Ok, found it. Need to hook NtCreateUserProcess in ntdll.dll as well, since 
cmd.exe apparently uses this instead of the normal CreateProcess family for 
creating processes.
Attached is a diff with this hook implemented, have tested it and it works 
well, even with command chaining.

--
Robert


On Monday, November 3, 2014 3:59:37 PM UTC+1, Robert Pettersen wrote:
>
> Small followup, seems it doesnt matter if I chain commands or not, using 
> cmd.exe to invoke commands will fail to detect output, even tho they 
> execute correctly.
>
> * 1) cmd /C gcc -c -o test.o test.c
>
>  *** tup errors ***
>
> tup error: Expected to write to file 'test.o' from cmd 20 but didn't
>
>
> Perhaps cmd.exe starts sub-processes in a way we haven't hooked for...
>
>
> And just noticed that one of the debug hooks provide erronous information 
> in tup_inject_dll:
>
> DEBUG_HOOK("%s is WOW64: %i\n", GetCommandLineA(), bWow64);
>>
>
> gives you the calling process, witch in most cases is tup.exe, to get the 
> name of the process that tup starts up we need
>
> TCHAR buffer[1024];
>
> if (GetModuleFileNameEx(lpProcessInformation->hProcess,0,buffer,1024)){
>
>         DEBUG_HOOK("Executable: %s\n", buffer);
>
> }
>
>
>
>
> On Monday, November 3, 2014 2:51:21 PM UTC+1, Robert Pettersen wrote:
>>
>> Hi Mike,
>>
>> 1) See 2)
>>
>> 2) 32bit processes can not inject into 64bit processes. cmd.exe on 64bit 
>> windows is a bit of magic, haven't really figured it out. But that was the 
>> reason I put have_shell=1 yes. We have a special case where we chain a 
>> 32bit compiler with a 64bit compiler, and tup fails to detect output 
>> written. But the expected behaviour is achieved.
>>
>> 3) You are right, compiling with the 64bit compiler with the -m32 flag 
>> seem to produce the expected output.
>>
>> 4) Think we have to ifdef the entire function, or atleast pepper it 
>> somewhat. Wow64 is loading 32bit binaries from 64bit host (yeah, naming is 
>> a bit confusing), and the other case is 64bit from 64bit, but as you have 
>> seen, the function does not contain a proper loading of 32bit from 32bit. 
>> See the attached patch-diff for a suggestion. Have tested it and it seems 
>> to work, with the exception of the cmd chaining. Maybe you have better luck 
>> now that you know more about it.
>>
>> --
>> Robert
>>
>> On Saturday, November 1, 2014 4:25:22 PM UTC+1, [email protected] wrote:
>>>
>>> Hi Robert, thanks so much for working on this! I think we are fairly 
>>> close.
>>>
>>> I've tried to incorporate this patch and produce both the 
>>> tup-dllinject.dll (64-bit) and tup-dllinject32.dll from the same tree. To 
>>> build binaries from Linux, you'll need both a CONFIG_TUP_MINGW and 
>>> CONFIG_TUP_MINGW32 in tup.config:
>>>
>>> CONFIG_TUP_MINGW=x86_64-w64-mingw32
>>> CONFIG_TUP_MINGW32=i686-w64-mingw32
>>>
>>> I have a few questions so far, all pretty inter-related:
>>>
>>> 1) Why did you want to force have_shell=1 in windepfile.c? That causes 
>>> many of the tests to fail, so if it is truly necessary I'll have to find a 
>>> way to fix those tests (there are many). Or if there is some particular 
>>> case that doesn't work without it, I'll want to add a test to check for it 
>>> (and possibly fix it a different way)
>>>
>>> 2) Should it be possible to inject the 64-bit DLL into a 64-bit process 
>>> from a 32-bit process? For example, if I run "sh -c './64-test.exe'", then 
>>> sh (a 32-bit process) gets injected with a 32-bit dll, but 64-test.exe (a 
>>> 64-bit process) doesn't get injected. (Whereas if I just run 64-test.exe 
>>> directly, it gets injected fine since tup.exe is 64-bit). Is this why you 
>>> added have_shell=1 above?
>>>
>>> 3) Am I compiling the dllinjection code correctly? I left in the 
>>> @(TUP_32_BIT) code that you had commented out. (To be honest I'm not sure 
>>> what it's used for - I can't find the email thread or issue that talks 
>>> about it). Specifically, do I need to use both x86_64-w64-mingw32 and 
>>> i686-w64-mingw32? Or is there some way with -m64 / -m32 / -somethingelse 
>>> that we can just use x86_64-w64-mingw32?
>>>
>>> 4) The 64-bit DLL injection code won't compile with the 32-bit compiler, 
>>> since the CONTEXT structure no longer has the .Rip field. I put an #ifdef 
>>> around it, but I hit the "Error: Shouldn't be hooking here for the 32-bit 
>>> dll" message (something I added to your patch) when using sh -c 
>>> './64-test.exe' from question 2). Is there a better way to handle that?
>>>
>>> Hopefully we can get these sorted out & in the master branch soon.
>>>
>>> Thanks again,
>>> -Mike
>>>
>>> On Wed, Aug 6, 2014 at 5:40 AM, Robert Pettersen <[email protected]> 
>>> wrote:
>>>
>>>> Hi, 
>>>>
>>>> Really sorry about not posting any updates, been swamped with work and 
>>>> just got back from vacation. I don't have time to setup a git repo and 
>>>> commit the code, means I'll actually have to clean-up and comment the 
>>>> code. 
>>>> But I have attached a diff between the current origin/HEAD and the changes 
>>>> I made to get it working on 64bit host windows. Haven't made any changes 
>>>> since the initial work, since it has been stable for our use. Be warned 
>>>> tho, I have not tested this on a 32bit host system, it will however 
>>>> execute 
>>>> 32bit binaries on a 64bit host system.
>>>>
>>>> ~/tup64$ cat tup.config
>>>>
>>>> CONFIG_TUP_MINGW=x86_64-w64-mingw32 
>>>>
>>>>
>>>> I can probably answer some questions about the code and help out some 
>>>> here on the forum, but I can't guarantee their timelyness. Really swamped 
>>>> with work. 
>>>>
>>>> Again, really sorry for not posting responses here sooner!
>>>>
>>>> On Monday, March 17, 2014 8:46:22 PM UTC+1, [email protected] wrote:
>>>>
>>>>> On Mon, Mar 17, 2014 at 8:51 AM, Tristan Rybak <[email protected]> 
>>>>> wrote:
>>>>>
>>>>>> Hi Mike, Robert,
>>>>>> Any news on a patch for 64bit windows?
>>>>>> I am using the executable attached to first post and it's working 
>>>>>> great (very big thanks for that Robert!)
>>>>>> but I'd like to have new features and bugfixes introduced later too 
>>>>>> please.
>>>>>> Maybe I could help with integrating the fix into repository somehow?
>>>>>> Regards,
>>>>>> Tristan
>>>>>>
>>>>>
>>>>> Hi Tristan,
>>>>>
>>>>> I don't think I've seen the patch from Robert yet, though maybe I've 
>>>>> missed it. I'd be happy to get it included if he's interested in getting 
>>>>> it 
>>>>> upstream.
>>>>>
>>>>> Thanks,
>>>>> -Mike
>>>>>
>>>>  -- 
>>>> -- 
>>>> tup-users mailing list
>>>> email: [email protected]
>>>> unsubscribe: [email protected]
>>>> options: http://groups.google.com/group/tup-users?hl=en
>>>> --- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "tup-users" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to [email protected].
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>>

-- 
-- 
tup-users mailing list
email: [email protected]
unsubscribe: [email protected]
options: http://groups.google.com/group/tup-users?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"tup-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/Tuprules.tup b/Tuprules.tup
index 668222d..665457e 100644
--- a/Tuprules.tup
+++ b/Tuprules.tup
@@ -63,7 +63,7 @@ ifeq (@(TUP_MINGW),)
 !mingwar = |> |>
 else
 !mingwcc = |> ^ MINGWCC %f^ @(TUP_MINGW)-gcc -c %f -o %o $(CFLAGS) $(CFLAGS_%f) $(MINGWCFLAGS) |> %B.omingw
-!mingwcc32 = |> ^ MINGW32CC %f^ @(TUP_MINGW32)-gcc -c %f -o %o $(CFLAGS) $(CFLAGS_%f) $(MINGWCFLAGS) |> %B.omingw32
+!mingwcc32 = |> ^ MINGW32CC %f^ @(TUP_MINGW)-gcc -m32 -c %f -o %o $(CFLAGS) $(CFLAGS_%f) $(MINGWCFLAGS) |> %B.omingw32
 !mingwar = |> ^ MINGWAR %o^ @(TUP_MINGW)-ar crs %o %f |>
 endif
 
diff --git a/src/compat/win32/wow64.h b/src/compat/win32/wow64.h
index 6ee276c..b213ba0 100644
--- a/src/compat/win32/wow64.h
+++ b/src/compat/win32/wow64.h
@@ -3,7 +3,54 @@
 #define WOW64_CONTEXT_i386 0x00010000
 #define WOW64_CONTEXT_CONTROL (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000001))
 
+#define WOW64_MAXIMUM_SUPPORTED_EXTENSION 512
+#define WOW64_SIZE_OF_80387_REGISTERS 80
+
+#ifdef _WIN64
+typedef struct _WOW64_FLOATING_SAVE_AREA {
+  DWORD   ControlWord;
+  DWORD   StatusWord;
+  DWORD   TagWord;
+  DWORD   ErrorOffset;
+  DWORD   ErrorSelector;
+  DWORD   DataOffset;
+  DWORD   DataSelector;
+  BYTE    RegisterArea[WOW64_SIZE_OF_80387_REGISTERS];
+  DWORD   Cr0NpxState;
+} WOW64_FLOATING_SAVE_AREA, *PWOW64_FLOATING_SAVE_AREA;
+
+typedef struct _WOW64_CONTEXT {
+  DWORD ContextFlags;
+  DWORD Dr0;
+  DWORD Dr1;
+  DWORD Dr2;
+  DWORD Dr3;
+  DWORD Dr6;
+  DWORD Dr7;
+  WOW64_FLOATING_SAVE_AREA FloatSave;
+  DWORD SegGs;
+  DWORD SegFs;
+  DWORD SegEs;
+  DWORD SegDs;
+  DWORD Edi;
+  DWORD Esi;
+  DWORD Ebx;
+  DWORD Edx;
+  DWORD Ecx;
+  DWORD Eax;
+  DWORD Ebp;
+  DWORD Eip;
+  DWORD SegCs;
+  DWORD EFlags;
+  DWORD Esp;
+  DWORD SegSs;
+  BYTE ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION];
+} WOW64_CONTEXT, *PWOW64_CONTEXT;
+
 BOOL WINAPI Wow64GetThreadContext(HANDLE hThread, PWOW64_CONTEXT lpContext);
 BOOL WINAPI Wow64SetThreadContext(HANDLE hThread, const WOW64_CONTEXT *lpContext);
 
 #endif
+
+
+#endif
diff --git a/src/dllinject/dllinject.c b/src/dllinject/dllinject.c
index 3b7be54..98a1ec4 100644
--- a/src/dllinject/dllinject.c
+++ b/src/dllinject/dllinject.c
@@ -33,6 +33,7 @@
 #ifndef STATUS_SUCCESS
 #include <ntstatus.h>
 #endif
+#include <winternl.h>
 #include <psapi.h>
 #include <stdio.h>
 #include <string.h>
@@ -329,7 +330,6 @@ typedef BOOL (WINAPI *CreateProcessWithTokenW_t)(
     __in        LPSTARTUPINFOW lpStartupInfo,
     __out       LPPROCESS_INFORMATION lpProcessInformation);
 
-typedef void *PIO_STATUS_BLOCK;
 typedef NTSTATUS (WINAPI *NtOpenFile_t)(
     __out  PHANDLE FileHandle,
     __in   ACCESS_MASK DesiredAccess,
@@ -351,6 +351,21 @@ typedef NTSTATUS (WINAPI *NtCreateFile_t)(
     __in      PVOID EaBuffer,
     __in      ULONG EaLength);
 
+typedef NTSTATUS (WINAPI *NtCreateUserProcess_t)(
+PHANDLE ProcessHandle,
+PHANDLE ThreadHandle,
+ACCESS_MASK ProcessDesiredAccess,
+ACCESS_MASK ThreadDesiredAccess,
+POBJECT_ATTRIBUTES ProcessObjectAttributes,
+POBJECT_ATTRIBUTES ThreadObjectAttributes,
+ULONG ProcessFlags,
+ULONG ThreadFlags,
+PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
+ULONG_PTR CreateInfo,
+ULONG_PTR AttributeList
+);
+
+
 typedef int (*access_t)(const char *pathname, int mode);
 typedef FILE *(*fopen_t)(const char *path, const char *mode);
 typedef int (*rename_t)(const char *oldpath, const char *newpath);
@@ -397,6 +412,7 @@ static CreateProcessWithLogonW_t	CreateProcessWithLogonW_orig;
 static CreateProcessWithTokenW_t	CreateProcessWithTokenW_orig;
 static NtCreateFile_t			NtCreateFile_orig;
 static NtOpenFile_t			NtOpenFile_orig;
+static NtCreateUserProcess_t		NtCreateUserProcess_orig;
 static access_t				_access_orig;
 static fopen_t				fopen_orig;
 static rename_t				rename_orig;
@@ -725,6 +741,53 @@ out_free:
 	return rc;
 }
 
+NTSTATUS WINAPI NtCreateUserProcess_hook(PHANDLE ProcessHandle,
+PHANDLE ThreadHandle,
+ACCESS_MASK ProcessDesiredAccess,
+ACCESS_MASK ThreadDesiredAccess,
+POBJECT_ATTRIBUTES ProcessObjectAttributes,
+POBJECT_ATTRIBUTES ThreadObjectAttributes,
+ULONG ProcessFlags,
+ULONG ThreadFlags,
+PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
+ULONG_PTR CreateInfo,
+ULONG_PTR AttributeList)
+{
+
+	NTSTATUS rc = NtCreateUserProcess_orig(ProcessHandle,
+		ThreadHandle, ProcessDesiredAccess,
+		ThreadDesiredAccess,
+		ProcessObjectAttributes,
+		ThreadObjectAttributes,
+		ProcessFlags, ThreadFlags,
+		ProcessParameters,CreateInfo, AttributeList);
+
+        if (rc != STATUS_SUCCESS) {
+                return rc;
+        }
+
+        TCHAR buffer[1024];
+        if (GetModuleFileNameEx(*ProcessHandle,0,buffer,1024)){
+		char *exec = strrchr(buffer, '\\');
+		if (exec == NULL) return rc;
+
+		exec++;
+		if (strncasecmp(exec, "tup32detect.exe", 15) == 0 ||
+			strncasecmp(exec, "mspdbsrv.exe", 12) == 0)
+			return rc;
+
+                DEBUG_HOOK("NtCreateUser: %s\n", buffer);
+
+		PROCESS_INFORMATION processInformation;
+		processInformation.hProcess = *ProcessHandle;
+		processInformation.hThread = *ThreadHandle;
+
+		tup_inject_dll(&processInformation, s_depfilename, s_vardict_file);
+        }
+
+	return rc;
+}
+
 BOOL WINAPI DeleteFileA_hook(
     __in LPCSTR lpFileName)
 {
@@ -1481,6 +1544,7 @@ static struct patch_entry patch_table[] = {
 #define MODULE_NAME "ntdll.dll"
 	HOOK(NtCreateFile),
 	HOOK(NtOpenFile),
+	HOOK(NtCreateUserProcess),
 #undef MODULE_NAME
 #define MODULE_NAME "msvcrt.dll"
 	HOOK(_access),
@@ -2126,12 +2190,18 @@ int tup_inject_dll(
 	size_t code_size;
 	DWORD old_protect;
 	HANDLE process;
-	BOOL bWow64 = 0;
 
+#ifdef _WIN64
+	BOOL bWow64 = 0;
 	IsWow64Process(lpProcessInformation->hProcess, &bWow64);
 
+
+	TCHAR buffer[1024];
+	if (GetModuleFileNameEx(lpProcessInformation->hProcess,0,buffer,1024)){
+		DEBUG_HOOK("%s is WOW64: %i\n", buffer, bWow64);
+	}
+
 	// WOW64
-	DEBUG_HOOK("%s is WOW64: %i\n", GetCommandLineA(), bWow64);
 	if (bWow64) {
 		remote_thread32_t remote;
 
@@ -2211,7 +2281,7 @@ int tup_inject_dll(
 		if( !Wow64SetThreadContext( lpProcessInformation->hThread, &ctx ) )
 			return -1;
 	} else {
-#ifdef _WIN64
+#endif
 		HMODULE kernel32;
 		remote_thread_t remote;
 
@@ -2224,7 +2294,11 @@ int tup_inject_dll(
 		strcat(remote.execdir, execdir);
 		strcat(remote.dll_name, execdir);
 		strcat(remote.dll_name, "\\");
+#ifdef _WIN64
 		strcat(remote.dll_name, "tup-dllinject.dll");
+#else
+		strcat(remote.dll_name, "tup-dllinject32.dll");
+#endif
 		strcat(remote.func_name, "tup_inject_init");
 
 		CONTEXT ctx;
@@ -2233,9 +2307,13 @@ int tup_inject_dll(
 			return -1;
 
 		/* Align code_size to a 16 byte boundary */
+#ifdef _WIN64
 		code_size = (  (uintptr_t) &remote_end
 			     - (uintptr_t) &remote_stub + 0x0F)
 			  & ~0x0F;
+#else
+    code_size = (sizeof(remote_stub32) + 0x0F) & ~0x0F;
+#endif
 
 
 		DEBUG_HOOK("Injecting dll '%s' '%s' %s' '%s'\n",
@@ -2265,11 +2343,19 @@ int tup_inject_dll(
 
 		unsigned char code[code_size];
 
+#ifdef _WIN64
 		memcpy( code, &remote_stub, code_size );
 		*(DWORD*)(code + 0x7) = low32(ctx.Rip);
 		*(DWORD*)(code + 0xf) = high32(ctx.Rip);
 		*(DWORD64*)(code + 0x30) = (long long unsigned int)(remote_data + code_size);
 		*(DWORD64*)(code + 0x3d) = (long long unsigned int)(DWORD_PTR)remote_data + ((DWORD_PTR)&remote_init - (DWORD_PTR)&remote_stub);
+#else
+		memcpy( code, &remote_stub32, code_size );
+		*(DWORD*)(code + 0x1) = ctx.Eip;											// Return addr
+		*(DWORD*)(code + 0x8) = (DWORD)((DWORD_PTR)remote_data + code_size);							// Arg (ptr to remote (TCB))
+		*(DWORD*)(code + 0xd) = (DWORD)((DWORD_PTR)remote_data + ((DWORD_PTR)&remote_stub32.remote_init - (DWORD_PTR)&remote_stub32));	// Func (ptr to remote_init)
+#endif
+
 
 		if (!WriteProcessMemory(process, remote_data, code, code_size, NULL))
 			return -1;
@@ -2283,15 +2369,18 @@ int tup_inject_dll(
 		if (!FlushInstructionCache(process, remote_data, code_size + sizeof(remote)))
 			return -1;
 
+#ifdef _WIN64
 		ctx.Rip = (DWORD_PTR)remote_data;
+#else
+		ctx.Eip = (DWORD_PTR)remote_data;
+#endif
+
 		ctx.ContextFlags = CONTEXT_CONTROL;
 		if( !SetThreadContext( lpProcessInformation->hThread, &ctx ) )
 			return -1;
-#else
-		DEBUG_HOOK("Error: Shouldn't be hooking here for the 32-bit dll.\n");
-		return -1;
-#endif
+#ifdef _WIN64
 	}
+#endif
 
 	return 0;
 }

Reply via email to