Nikolay Igotti
Overriding symbols on Win32
Today I was asked it it's possible to implement something similar to Linux'sLD_PRELOAD for Windows, to allow override of particular symbol.
I answered yes, and here's how I did it (some dynamic code generation involved :)).
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char* address;
class Code {
address buf;
int size;
int idx;
enum reg {
ax=0, cx, dx, bx, sp, bp, si, di
};
void init_sys();
void generate(void* where, void* new_where);
bool put_byte(unsigned char b) {
if (idx >= size) {
return false;
}
buf[idx++] = b;
return true;
}
bool put_int(int i) {
if (idx >= size-4) {
return false;
}
*(int*)(buf+idx) = i;
idx +=4;
return true;
}
void pop(reg r) {
put_byte(0x58 | r);
}
void push(reg r) {
put_byte(0x50 | r);
}
void add(reg r, int imm8) {
put_byte(0x83);
put_byte(0xc0 | r);
put_byte(imm8 & 0xff);
}
void jmp(reg r) {
put_byte(0xff);
put_byte(0xe0 | r);
}
void jmp(address where) {
int off = buf_rel(where);
put_byte(0xe9);
put_int(off);
}
void call(address where) {
int off = buf_rel(where);
put_byte(0xe8);
put_int(off);
}
static address abs(address base, int off) {
return base+off+5;
}
static int rel(address dest, address cur) {
return (int)(dest - cur - 5);
}
int buf_rel(address w) {
return rel(w, buf+idx);
}
public:
Code(void* sym, void* new_where);
~Code();
};
void Code::init_sys() {
SYSTEM_INFO si;
GetSystemInfo(&si);
size = si.dwPageSize;
}
Code::Code(void* sym, void* new_where) : buf(NULL), size(-1), idx(0) {
init_sys();
buf = (address) VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
// compute address
int off = *(int*)((address)sym+1);
address real_sym = abs((address)sym, off);
generate(real_sym, new_where);
off = rel(buf, (address)sym);
// and patch jumptable
DWORD old = 0;
VirtualProtect(sym, 5, PAGE_READWRITE, &old);
*(int*)((address)sym+1) = off;
VirtualProtect(sym, 5, old, &old);
}
Code::~Code() {
VirtualFree(buf, size, MEM_RELEASE);
buf = NULL;
size = 0;
}
void Code::generate(void* old, void* new_where) {
call((address)new_where);
jmp((address)old);
FlushInstructionCache(GetCurrentProcess(), buf, size);
}
// must be void/void to not corrupt stack
void my_exit(void) {
printf("custom exit\n");
getchar();
}
int main(int argc, char* argv[])
{
// intentional leak, to avoid execution of code in unmapped area
new Code(&exit, &my_exit);
printf("OK\n");
//exit(0);
return 0;
}
Posted at 05:08PM Jun 26, 2007 by nike in Sun | Comments[2]
Tuesday Jun 26, 2007
ORED JAVA
Posted by JUSTSTR60 on November 05, 2007 at 09:06 PM MSK #
ORED JAVA
Posted by JUSTSTR60 on November 05, 2007 at 09:07 PM MSK #