win32: clean up some Windows code.

This commit is contained in:
Sam Hocevar
2015-01-29 03:12:36 +01:00
parent bad2925778
commit 923fffb27f
2 changed files with 77 additions and 59 deletions
+73 -59
View File
@@ -418,8 +418,9 @@ static int dll_inject(PROCESS_INFORMATION *pinfo, char const *lib)
# define LoaderRegister Rcx
# define LoadLibraryAOffset 0x15
/* This payload allows us to load arbitrary module located at the end of this buffer */
static uint8_t const ldr[] =
/* This payload allows us to load arbitrary module located
* at the end of this buffer */
static uint8_t const loader[] =
{
"\x55" /* push rbp */
"\x48\x89\xE5" /* mov rbp,rsp */
@@ -440,11 +441,12 @@ static int dll_inject(PROCESS_INFORMATION *pinfo, char const *lib)
# define StackPointer Esp
# define LoaderRegister Eax /* It seems the Windows loader store the oep as the first param
* but by a side effect it's also contained in eax register */
# define ldr ldr32
# define loader loader32
# define LoadLibraryAOffset 0x04
/* This payload allows us to load arbitrary module located at the end of this buffer */
static uint8_t const ldr[] =
/* This payload allows us to load arbitrary module located
* at the end of this buffer */
static uint8_t const loader[] =
{
"\x60" /* pushad */
"\xEB\x0E" /* jmp short 0x11 */
@@ -461,102 +463,114 @@ static int dll_inject(PROCESS_INFORMATION *pinfo, char const *lib)
# error Unimplemented architecture !
#endif
int res = -1;
/* We use this code to make the targeted process waits for us */
/* We use this code to make the targeted process wait for us */
static uint8_t const wait[] = "\xeb\xfe"; /* jmp $-1 */
size_t wait_len = sizeof(wait) - 1;
uint8_t orig_data[2];
void *process = pinfo->hProcess;
void *thread = pinfo->hThread;
DWORD pid = pinfo->dwProcessId;
void *rldlib = NULL;
SIZE_T written = 0;
void *process = pinfo->hProcess;
void *thread = pinfo->hThread;
SIZE_T written = 0;
BOOL tmp;
/* Payload */
void *rpl = NULL;
uint8_t *pl = NULL;
size_t pl_len = sizeof(ldr) - 1 + strlen(lib) + 1;
CONTEXT ctxt;
DWORD_PTR oep; /* Original Entry Point */
size_t payload_len = sizeof(loader) - 1 + strlen(lib) + 1;
uint8_t *payload = malloc(payload_len);
if (payload == NULL)
goto error;
/* Use the main thread to inject our library */
CONTEXT ctxt;
ctxt.ContextFlags = CONTEXT_FULL;
if (!GetThreadContext(thread, &ctxt))
goto _return;
goto error;
/* Make the target program waits when it reachs the original entry point, because we can't do many thing from the windows loader */
oep = ctxt.LoaderRegister;
if (!ReadProcessMemory(process, (LPVOID)oep, orig_data, sizeof(orig_data), &written) || written != sizeof(orig_data))
goto _return; /* save original opcode */
if (!WriteProcessMemory(process, (LPVOID)oep, wait, wait_len , &written) || written != wait_len)
goto _return; /* write jmp short $-1 */
/* Make the target program wait when it reaches the original entry
* point, because we can't do many thing from the Windows loader */
DWORD_PTR oep = ctxt.LoaderRegister; /* Original Entry Point */
uint8_t orig_data[2];
tmp = ReadProcessMemory(process, (LPVOID)oep, orig_data,
sizeof(orig_data), &written);
if (!tmp || written != sizeof(orig_data))
goto error; /* save original opcode */
tmp = WriteProcessMemory(process, (LPVOID)oep, wait, wait_len, &written);
if (!tmp || written != wait_len)
goto error; /* write jmp short $-1 */
if (!FlushInstructionCache(process, (LPVOID)oep, wait_len))
goto _return;
goto error;
if (ResumeThread(thread) == (DWORD)-1)
goto _return;
goto error;
/* Stop when the program reachs the oep */
/* Stop when the program reachse the oep */
while (oep != ctxt.InstructionPointer)
{
if (!GetThreadContext(thread, &ctxt))
goto _return;
goto error;
Sleep(10);
}
if (SuspendThread(thread) == (DWORD)-1)
goto _return;
goto error;
/* Resolve LoadLibraryA from the target process memory context */
if ((rldlib = get_proc_address(process, pid, "LoadLibraryA")) == NULL)
goto _return;
DWORD pid = pinfo->dwProcessId;
void *rldlib = get_proc_address(process, pid, "LoadLibraryA");
if (rldlib == NULL)
goto error;
if ((rpl = VirtualAllocEx(process, NULL, pl_len, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == NULL)
goto _return;
void *rpl = VirtualAllocEx(process, NULL, payload_len,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (rpl == NULL)
goto error;
/* Emulate a call to the ldr code, thus the ret instruction from ldr will get (e|r)ip back to the original entry point */
/* Emulate a call to the loader code, thus the ret instruction from
* loader will get (e|r)ip back to the original entry point */
ctxt.StackPointer -= sizeof(oep);
if (!WriteProcessMemory(process, (LPVOID)ctxt.StackPointer, &oep, sizeof(oep), &written) || written != sizeof(oep))
goto _return;
tmp = WriteProcessMemory(process, (LPVOID)ctxt.StackPointer,
&oep, sizeof(oep), &written);
if (!tmp || written != sizeof(oep))
goto error;
ctxt.InstructionPointer = (DWORD_PTR)rpl;
if (!SetThreadContext(thread, &ctxt))
goto _return;
goto error;
/* Forge the payload */
if ((pl = (uint8_t *)malloc(pl_len)) == NULL)
goto _return;
memcpy(pl, ldr, sizeof(ldr) - 1);
memcpy(pl + LoadLibraryAOffset, &rldlib, sizeof(rldlib)); /* Write the address of LoadLibraryA */
strcpy((char *)(pl + sizeof(ldr) - 1), lib); /* Write the first parameter of LoadLibraryA */
memcpy(payload, loader, sizeof(loader) - 1);
/* Write the address of LoadLibraryA */
memcpy(payload + LoadLibraryAOffset, &rldlib, sizeof(rldlib));
/* Write the first parameter of LoadLibraryA */
strcpy((char *)(payload + sizeof(loader) - 1), lib);
if (!WriteProcessMemory(process, rpl, pl, pl_len, &written) || written != pl_len)
goto _return;
tmp = WriteProcessMemory(process, rpl, payload, payload_len, &written);
if (!tmp || written != payload_len)
goto error;
/* Restore original opcode */
if (!WriteProcessMemory(process, (LPVOID)oep, orig_data, sizeof(orig_data), &written) || written != sizeof(orig_data))
goto _return;
tmp = WriteProcessMemory(process, (LPVOID)oep, orig_data,
sizeof(orig_data), &written);
if (!tmp || written != sizeof(orig_data))
goto error;
if (!FlushInstructionCache(process, rpl, pl_len))
goto _return;
if (!FlushInstructionCache(process, rpl, payload_len))
goto error;
if (!FlushInstructionCache(process, (LPVOID)oep, sizeof(orig_data)))
goto _return;
res = 0;
_return:
if (pl != NULL)
free(pl);
goto error;
/* We must not free remote allocated memory since they will be used
* after the process will be resumed */
return res;
free(payload);
return 0;
error:
free(payload);
return -1;
}
#undef InstructionPointer
#undef StackPointer
#undef LoaderRegister
#undef LoadLibraryAOffset
}
static void *get_proc_address(void *process, DWORD pid, const char *func)
{
+4
View File
@@ -14,6 +14,10 @@
* mutex.h: very simple spinlock routines
*/
#if HAVE_WINDOWS_H
# include <windows.h>
#endif
#if _WIN32
typedef volatile LONG zzuf_mutex_t;
#elif __GNUC__ || __clang__