Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //new? way of hooking
- //this is a relatively handy class, which allows you to copy vmts and have a globally working own custom epilog/prolog for every single function in the VMT
- //you could kinda call it a real
- //Its code is position independent and it works regardless of the arguments passed to the virtual functions
- //The registers before/after calling this are exactly the same, unless the original vfunc decides to modify them :)
- #ifndef VMT_PROLOG_EPILOG_REPLACEMENT_HPP
- #define VMT_PROLOG_EPILOG_REPLACEMENT_HPP
- #pragma optimize("", off)
- //globals because, naked function
- extern int iproxyvmt;
- extern int irealvmt;
- //functions we need
- extern int iprintf;
- extern int iGETEIP;
- extern int iJMPBACK;
- #define vfuncamount 200
- /*
- somewhere in your CPP
- iJMPBACK = (int)JMPBACK;
- iGETEIP = (int)iGETEIP;
- iprintf = (int)iprintf;
- //these 2 global
- void* real_funcs[1024] = { 0 };
- void* proxyvmt_funcs[1024] = { 0 };
- //rest in some func
- //give it 2 examples
- void** real_vmt = *(void***)programm->GetSomeClass();
- real_funcs[0] = real_vmt[0];
- real_funcs[1] = real_vmt[1];
- size_t vfuncmaxsize = 400;
- size_t vtable_copyfrom = 1;
- void *object = new CopyClass;
- void **proxyvmt = *(void***)object;
- void **newvmt = new void*[vfuncamount];
- //hack, class functions for whatever fucking reason can't be naked in MSVC
- int beginning = 0;
- for (int i = 1; i < 100; i++)
- {
- if (*((char*)proxyvmt[0] + i) != '\x90' || *((char*)proxyvmt[0] + i + 1) != '\xCC')
- continue;
- beginning = i + 2; //strip the fucking prolog
- break;
- }
- printf("Beg: %d\n", beginning);
- //generate the vfuncs
- for (int i = 0; i < vfuncamount; i++)
- {
- newvmt[i] = VirtualAlloc(0, vfuncmaxsize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- memset(newvmt[i], 0x90, vfuncmaxsize);
- memcpy(newvmt[i], (char*)proxyvmt[0] + beginning, vfuncmaxsize);//fuck your size
- }
- //set the vmt
- *(void***)object = newvmt;
- proxyvmt = newvmt;
- //tell the vfuncs where our vmt is
- iproxyvmt = (int)proxyvmt_funcs;
- irealvmt = (int)real_funcs;
- //fill in the array with our vfuncs
- for (int i = 0; i < vfuncamount; i++)
- {
- proxyvmt_funcs[i] = proxyvmt[i];
- if (!proxyvmt[i]) break;
- }
- intptr_t replacevmts[30] = { 0 };
- size_t replacevmts_size = 0;
- char*modulename = "epic.dll";
- int modulesize = 13377331;
- //we need to copy the original functions and we want to know the vmts of classes deriving from us too
- for (intptr_t i = (intptr_t)GetModuleHandle(modulename); i < (intptr_t)GetModuleHandle(modulename) + (modulesize-20); i++)
- {
- if (*(intptr_t*)i != (intptr_t)real_funcs[0] || *(intptr_t*)(i + 4) != (intptr_t)real_funcs[1])
- continue;
- if (replacevmts_l == vtable_copyfrom) // is this the vtable we want to copy from?
- {
- for (int a = 0; a < vfuncamount; a++)//then copy everything
- {
- intptr_t fn = *(intptr_t*)(i + (a*4));
- real_funcs[a] = (void*)fn;
- if (!real_funcs[a]) // end once we encounter a null pointer, kinda hacky
- {
- printf("END: %d\n", a);
- break;
- }
- }
- printf("peropero\n");
- }
- printf("1FOUND VMT OUTSIDE .TEXT %d\n", replacevmts_size);
- replacevmts[replacevmts_size] = i;
- replacevmts_size += 1;
- }
- printf("done scanning\n");
- unsigned long oldprotection = 0;
- //now we replace the vmts with our custom built one
- for (intptr_t i = (intptr_t)GetModuleHandle(modulename); i < (intptr_t)GetModuleHandle(modulename) + modulesize; i++)
- {
- for (int j = 0; j < replacevmts_size; j++)
- {
- if(!replacevmts[j] || *(intptr_t*)i != (intptr_t)replacevmts[j])
- continue;
- printf("2FOUND VMT\n");
- VirtualProtect((void*)(intptr_t*)i, 0x100, PAGE_EXECUTE_READWRITE, &oldprotection);
- *(intptr_t*)i = (intptr_t)proxyvmt_funcs;
- unsigned long shit = 0;
- VirtualProtect((void*)(intptr_t*)i, 0x100, oldprotection, &shit);
- }
- }
- */
- //printmask for logging shit
- char *printmask = 0;
- int grobset = 0;
- int ouraddr = 0;
- int curretnaddr = 0;
- int oldeax = 0;
- //stack for returns
- int jmpbacks[0xFFF] = { 0 }; // max calls into this shit = 0xFFF
- int jmpbacks_i = 0;
- __declspec(naked) void JMPBACK()
- {
- //HE RETURNED TO US; AFTER THIS PAINFUL JOURNEY
- __asm pushad;
- //custom global epilog here
- jmpbacks_i -= 1;
- curretnaddr = jmpbacks[jmpbacks_i];
- jmpbacks[jmpbacks_i] = 0;
- printf("Return to caller func!\n");
- __asm {
- popad;
- push curretnaddr
- retn; // AND THUS WE RETURN TO OUR LORD AND SAVIOR
- }
- };
- // function for getting the EIP
- __declspec(naked) void GETEIP()
- {
- __asm
- {
- pop eax;
- mov ouraddr, eax;
- jmp eax
- }
- }
- class CopyClass
- {
- public:
- inline CopyClass::CopyClass()
- {
- printf("[Warning][CopyClass] Default constructor called!\n");
- if(proxyvmt)
- {
- *(void**)this = (void*)proxyvmt; // we always have to set our VMT to the right one
- }
- }
- inline CopyClass::~CopyClass()
- {
- printf("[Warning][CopyClass] Default deconstructor called!\n");
- }
- virtual void* __cdecl copyfunc()
- {
- __asm
- {
- //the nops at the beginning are our markers
- nop;
- int 3;
- nop;
- nop;
- //get the current EIP
- mov eax, iGETEIP;
- call eax;
- //default prolog
- push ebp;
- mov ebp, esp;
- //backup the EAX, we'll be using it for our operations
- mov oldeax, eax;
- //get the current return address
- mov eax, ebp;
- mov eax, [eax + 4];
- mov curretnaddr, eax;
- //overwrite the return address with our jmp back function
- mov eax, iJMPBACK;
- mov[ebp + 4], eax;
- //default prolog
- mov esp, ebp;
- pop ebp;
- //push all registers on the stack, we'll write C/C++ code now
- pushad;
- }
- //put the return address in our return address stack
- jmpbacks[jmpbacks_i] = curretnaddr;
- jmpbacks_i += 1;
- //get the beginning of our function
- while (*(char*)ouraddr != '\x90' || *(char*)(ouraddr+1) != '\x90')
- ouraddr--;
- //custom global prolog here
- //find out what index we're at
- for (grobset = 0; grobset < vfuncamount; grobset++)
- if (((void**)iproxyvmt)[grobset] == (void*)ouraddr)
- break;
- //if our printmask isn't set yet, set it!
- if (!printmask)
- printmask = "[CopyClass] [%d] __ %x\n";
- //call printf
- __asm
- {
- mov eax, iprintf;
- push curretnaddr;
- push grobset;
- push printmask;
- call eax;
- add ESP, 0x0C;
- }
- //we want to call a vfunc after all
- grobset = grobset * 4;
- __asm
- {
- //we're done with C, fix the registers!
- popad;
- //calculate the address of the current vfunc and call it
- mov eax, 0;
- add eax, grobset;
- add eax, irealvmt;
- mov eax, [eax];
- push eax;
- mov eax, oldeax;
- retn;
- }
- };
- char dick[0x300];
- };
- #pragma optimize("", on)
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement