Overriding symbols on Win32

Today I was asked it it's possible to implement something similar to Linux's LD_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;
}
Comments:

ORED JAVA

Posted by JUSTSTR60 on November 05, 2007 at 01:06 PM MSK #

ORED JAVA

Posted by JUSTSTR60 on November 05, 2007 at 01:07 PM MSK #

Post a Comment:
  • HTML Syntax: NOT allowed
About

nike

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today