Created
October 22, 2012 22:10
-
-
Save leegao/3934918 to your computer and use it in GitHub Desktop.
Context-aware Hot Patching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <stdio.h> | |
//68 BE BA FE CA | |
const unsigned char OP_PUSH = 0x68; | |
const unsigned char OP_JMP = 0xE9; | |
static DWORD rets[10000]; | |
static PDWORD r = NULL; | |
struct patchwork{ | |
PBYTE dst; | |
PBYTE src; | |
DWORD offset; | |
BYTE A; | |
DWORD B; | |
BYTE C; | |
DWORD D; | |
}; | |
__declspec( naked ) void get_eip() { | |
__asm{ | |
mov eax, [esp]; | |
ret | |
} | |
} | |
void* patcher() | |
{ | |
struct patchwork* patch; | |
PBYTE d; DWORD d2, r_eax; | |
__asm{mov patch, ecx}; | |
d = patch->dst; | |
if(!VirtualProtect(d, 10, PAGE_EXECUTE_READWRITE, &d2)) return NULL; | |
//patch->A = *d; | |
//patch->B = *((PDWORD)(d+1)); | |
//patch->C = *(d+5); | |
//patch->D = *((PDWORD)(d+6)); | |
*d = patch->A; | |
*((PDWORD)(d + 1)) = patch->B; | |
*(d+5) = patch->C; | |
*((PDWORD)(d + 6)) = patch->D; | |
VirtualProtect(d, 10, d2, &d2); | |
d2 = (DWORD)patch->src; | |
// use two more items in stack | |
__asm{ | |
mov ecx, dword ptr[ebp] | |
mov d, ecx ; *r = return addr | |
}; | |
*r++ = (DWORD)d; | |
__asm{ | |
mov ecx, dword ptr[ebp+4] | |
mov d, ecx ; *r = return addr | |
}; | |
*r++ = (DWORD)d; | |
__asm{ | |
mov ecx, patch | |
mov d, ecx ; *r+4 = patch | |
} | |
*r++ = (DWORD)d; | |
__asm{ | |
call get_eip; | |
add eax, 12; | |
add esp, 20h; | |
mov dword ptr[ebp+4], eax; | |
jmp d2 | |
label_done: | |
} | |
// reset stack, we're no longer guaranteed that our locals are preserved | |
// let's just start over, since RTC keeps on complaining about stack corruption | |
__asm{ | |
sub esp, 24h; | |
} | |
__asm{ | |
mov eax,0CCCCCCCCh | |
mov dword ptr [ebp-18h],eax | |
mov dword ptr [ebp-14h],eax | |
mov dword ptr [ebp-10h],eax | |
mov dword ptr [ebp-0Ch],eax | |
mov dword ptr [ebp-8],eax | |
mov dword ptr [ebp-4],eax | |
} | |
d = (PBYTE)*--r; | |
__asm{ | |
mov ecx, d; | |
mov patch, ecx | |
} | |
d = (PBYTE)*--r; | |
__asm{ | |
mov ecx, d; | |
mov dword ptr[ebp+4], ecx | |
} | |
d = (PBYTE)*--r; | |
__asm{ | |
mov ecx, d; | |
mov dword ptr[ebp], ecx | |
} | |
d = patch->dst; | |
if(!VirtualProtect(d, 10, PAGE_EXECUTE_READWRITE, &d2)) return NULL; | |
patch->A = *d; | |
patch->B = *((PDWORD)(d+1)); | |
patch->C = *(d+5); | |
patch->D = *((PDWORD)(d+6)); | |
*d = OP_PUSH; | |
*((PDWORD)(d + 1)) = (DWORD)patch; | |
*(d+5) = OP_JMP; | |
*((PDWORD)(d + 6)) = (PBYTE)(patcher)-d-11; | |
VirtualProtect(d, 10, d2, &d2); | |
return; | |
} | |
struct patchwork* patch(void* dst, void* src){ | |
DWORD old_protection, dummy; | |
PBYTE d = (PBYTE)(dst), s = (PBYTE)src, p = (PBYTE)(patcher)-1; | |
BOOL res; | |
DWORD offset = p - d - 10; | |
struct patchwork* patch; | |
if (!r){ | |
// POP to eax first | |
res = VirtualProtect(p, 1, PAGE_EXECUTE_READWRITE, &old_protection); | |
if (!res){ | |
return NULL; | |
} | |
*p = 0x59; | |
VirtualProtect(p, 1, old_protection, &dummy); | |
r = (PDWORD)&rets; | |
} | |
// initialize | |
patch = (struct patchwork*)malloc(sizeof(struct patchwork)); | |
patch->dst = d; | |
patch->src = s; | |
patch->offset = offset; | |
// start patching, we'll use a poor man's jump table | |
res = VirtualProtect(d, 10, PAGE_EXECUTE_READWRITE, &old_protection); | |
if (!res){ | |
free(patch); | |
return NULL; | |
} | |
patch->A = *d; | |
patch->B = *((PDWORD)(d+1)); | |
patch->C = *(d+5); | |
patch->D = *((PDWORD)(d+6)); | |
*d = OP_PUSH; | |
*((PDWORD)(d + 1)) = (DWORD)patch; | |
*(d+5) = OP_JMP; | |
*((PDWORD)(d + 6)) = offset; | |
VirtualProtect(d, 10, old_protection, &dummy); | |
return patch; | |
} | |
void f(){ | |
printf("Hello World from f\n"); | |
} | |
void* g(char* fmt, ...){ | |
printf("Hello World from g\n"); | |
f(); | |
printf(fmt); | |
} | |
int main() | |
{ | |
struct patchwork* p; | |
p = patch(printf, g); | |
f(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment