Advertisement
Leystryku

vfunc generation independent of args/index custom pro/epilog

Apr 7th, 2017
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.76 KB | None | 0 0
  1. //new? way of hooking
  2. //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
  3. //you could kinda call it a real
  4. //Its code is position independent and it works regardless of the arguments passed to the virtual functions
  5. //The registers before/after calling this are exactly the same, unless the original vfunc decides to modify them :)
  6.  
  7. #ifndef VMT_PROLOG_EPILOG_REPLACEMENT_HPP
  8. #define VMT_PROLOG_EPILOG_REPLACEMENT_HPP
  9.  
  10.  
  11. #pragma optimize("", off)
  12.  
  13. //globals because, naked function
  14. extern int iproxyvmt;
  15. extern int irealvmt;
  16.  
  17. //functions we need
  18. extern int iprintf;
  19. extern int iGETEIP;
  20. extern int iJMPBACK;
  21.  
  22. #define vfuncamount 200
  23.  
  24. /*
  25. somewhere in your CPP
  26.     iJMPBACK = (int)JMPBACK;
  27.     iGETEIP = (int)iGETEIP;
  28.     iprintf = (int)iprintf;
  29.  
  30.    
  31.     //these 2 global
  32.     void* real_funcs[1024] = { 0 };
  33.     void* proxyvmt_funcs[1024] = { 0 };
  34.  
  35.     //rest in some func
  36.    
  37.     //give it 2 examples
  38.     void** real_vmt = *(void***)programm->GetSomeClass();
  39.     real_funcs[0] = real_vmt[0];
  40.     real_funcs[1] = real_vmt[1];
  41.    
  42.     size_t vfuncmaxsize = 400;
  43.     size_t vtable_copyfrom = 1;
  44.    
  45.     void *object = new CopyClass;
  46.     void **proxyvmt = *(void***)object;
  47.     void **newvmt = new void*[vfuncamount];
  48.  
  49.     //hack, class functions for whatever fucking reason can't be naked in MSVC
  50.     int beginning = 0;
  51.     for (int i = 1; i < 100; i++)
  52.     {
  53.         if (*((char*)proxyvmt[0] + i) != '\x90' || *((char*)proxyvmt[0] + i + 1) != '\xCC')
  54.             continue;
  55.  
  56.         beginning = i + 2; //strip the fucking prolog
  57.         break;
  58.     }
  59.    
  60.     printf("Beg: %d\n", beginning);
  61.  
  62.     //generate the vfuncs
  63.     for (int i = 0; i < vfuncamount; i++)
  64.     {
  65.         newvmt[i] = VirtualAlloc(0, vfuncmaxsize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  66.         memset(newvmt[i], 0x90, vfuncmaxsize);
  67.         memcpy(newvmt[i], (char*)proxyvmt[0] + beginning, vfuncmaxsize);//fuck your size
  68.     }
  69.  
  70.     //set the vmt
  71.     *(void***)object = newvmt;
  72.     proxyvmt = newvmt;
  73.  
  74.     //tell the vfuncs where our vmt is
  75.    
  76.     iproxyvmt = (int)proxyvmt_funcs;
  77.     irealvmt = (int)real_funcs;
  78.  
  79.     //fill in the array with our vfuncs
  80.     for (int i = 0; i < vfuncamount; i++)
  81.     {
  82.         proxyvmt_funcs[i] = proxyvmt[i];
  83.  
  84.         if (!proxyvmt[i]) break;
  85.     }
  86.  
  87.  
  88.     intptr_t replacevmts[30] = { 0 };
  89.     size_t replacevmts_size = 0;
  90.  
  91.     char*modulename = "epic.dll";
  92.     int modulesize = 13377331;
  93.    
  94.     //we need to copy the original functions and we want to know the vmts of classes deriving from us too
  95.    
  96.     for (intptr_t i = (intptr_t)GetModuleHandle(modulename); i < (intptr_t)GetModuleHandle(modulename) + (modulesize-20); i++)
  97.     {
  98.         if (*(intptr_t*)i != (intptr_t)real_funcs[0] || *(intptr_t*)(i + 4) != (intptr_t)real_funcs[1])
  99.             continue;
  100.  
  101.         if (replacevmts_l == vtable_copyfrom) // is this the vtable we want to copy from?
  102.         {
  103.             for (int a = 0; a < vfuncamount; a++)//then copy everything
  104.             {
  105.                 intptr_t fn = *(intptr_t*)(i + (a*4));
  106.                 real_funcs[a] = (void*)fn;
  107.  
  108.                 if (!real_funcs[a]) // end once we encounter a null pointer, kinda hacky
  109.                 {
  110.                     printf("END: %d\n", a);
  111.                     break;
  112.                 }
  113.  
  114.             }
  115.  
  116.             printf("peropero\n");
  117.         }
  118.  
  119.         printf("1FOUND VMT OUTSIDE .TEXT %d\n", replacevmts_size);
  120.  
  121.         replacevmts[replacevmts_size] = i;
  122.         replacevmts_size += 1;
  123.  
  124.     }
  125.  
  126.  
  127.     printf("done scanning\n");
  128.  
  129.     unsigned long oldprotection = 0;
  130.  
  131.     //now we replace the vmts with our custom built one
  132.    
  133.     for (intptr_t i = (intptr_t)GetModuleHandle(modulename); i < (intptr_t)GetModuleHandle(modulename) + modulesize; i++)
  134.     {
  135.         for (int j = 0; j < replacevmts_size; j++)
  136.         {
  137.             if(!replacevmts[j] || *(intptr_t*)i != (intptr_t)replacevmts[j])
  138.                 continue;
  139.            
  140.  
  141.             printf("2FOUND VMT\n");
  142.             VirtualProtect((void*)(intptr_t*)i, 0x100, PAGE_EXECUTE_READWRITE, &oldprotection);
  143.  
  144.             *(intptr_t*)i = (intptr_t)proxyvmt_funcs;
  145.             unsigned long shit = 0;
  146.             VirtualProtect((void*)(intptr_t*)i, 0x100, oldprotection, &shit);
  147.  
  148.         }
  149.     }
  150.    
  151. */
  152.  
  153. //printmask for logging shit
  154. char *printmask = 0;
  155. int grobset = 0;
  156. int ouraddr = 0;
  157. int curretnaddr = 0;
  158.  
  159. int oldeax = 0;
  160.  
  161.  
  162. //stack for returns
  163. int jmpbacks[0xFFF] = { 0 }; // max calls into this shit = 0xFFF
  164. int jmpbacks_i = 0;
  165.  
  166.  
  167. __declspec(naked) void JMPBACK()
  168. {
  169.  
  170.     //HE RETURNED TO US; AFTER THIS PAINFUL JOURNEY
  171.     __asm pushad;
  172.  
  173.     //custom global epilog here
  174.  
  175.     jmpbacks_i -= 1;
  176.     curretnaddr = jmpbacks[jmpbacks_i];
  177.     jmpbacks[jmpbacks_i] = 0;
  178.     printf("Return to caller func!\n");
  179.  
  180.     __asm {
  181.         popad;
  182.         push curretnaddr
  183.         retn; // AND THUS WE RETURN TO OUR LORD AND SAVIOR
  184.     }
  185.  
  186. };
  187.  
  188. // function for getting the EIP
  189.  
  190. __declspec(naked) void GETEIP()
  191. {
  192.     __asm
  193.     {
  194.         pop eax;
  195.         mov ouraddr, eax;
  196.         jmp eax
  197.     }
  198.  
  199. }
  200.  
  201. class CopyClass
  202. {
  203. public:
  204.  
  205.     inline CopyClass::CopyClass()
  206.     {
  207.         printf("[Warning][CopyClass] Default constructor called!\n");
  208.        
  209.         if(proxyvmt)
  210.         {
  211.             *(void**)this = (void*)proxyvmt; // we always have to set our VMT to the right one
  212.         }
  213.        
  214.     }
  215.  
  216.  
  217.     inline CopyClass::~CopyClass()
  218.     {
  219.         printf("[Warning][CopyClass] Default deconstructor called!\n");
  220.     }
  221.  
  222.  
  223.     virtual void* __cdecl copyfunc()
  224.     {
  225.         __asm
  226.         {
  227.             //the nops at the beginning are our markers
  228.             nop;
  229.             int 3;
  230.             nop;
  231.             nop;
  232.            
  233.             //get the current EIP
  234.             mov eax, iGETEIP;
  235.             call eax;
  236.  
  237.             //default prolog
  238.             push ebp;
  239.             mov ebp, esp;
  240.            
  241.             //backup the EAX, we'll be using it for our operations
  242.             mov oldeax, eax;
  243.            
  244.             //get the current return address
  245.             mov eax, ebp;
  246.             mov eax, [eax + 4];
  247.             mov curretnaddr, eax;
  248.  
  249.             //overwrite the return address with our jmp back function
  250.             mov eax, iJMPBACK;
  251.             mov[ebp + 4], eax;
  252.  
  253.             //default prolog
  254.             mov esp, ebp;
  255.             pop ebp;
  256.  
  257.             //push all registers on the stack, we'll write C/C++ code now
  258.             pushad;
  259.  
  260.         }
  261.  
  262.        
  263.         //put the return address in our return address stack
  264.         jmpbacks[jmpbacks_i] = curretnaddr;
  265.         jmpbacks_i += 1;
  266.  
  267.         //get the beginning of our function
  268.         while (*(char*)ouraddr != '\x90' || *(char*)(ouraddr+1) != '\x90')
  269.             ouraddr--;
  270.  
  271.         //custom global prolog here
  272.  
  273.         //find out what index we're at
  274.         for (grobset = 0; grobset < vfuncamount; grobset++)
  275.             if (((void**)iproxyvmt)[grobset] == (void*)ouraddr)
  276.                 break;
  277.  
  278.         //if our printmask isn't set yet, set it!
  279.         if (!printmask)
  280.             printmask = "[CopyClass] [%d] __ %x\n";
  281.  
  282.        
  283.         //call printf
  284.         __asm
  285.         {
  286.             mov eax, iprintf;
  287.             push curretnaddr;
  288.             push grobset;
  289.             push printmask;
  290.             call eax;
  291.             add ESP, 0x0C;
  292.         }
  293.  
  294.         //we want to call a vfunc after all
  295.         grobset = grobset * 4;
  296.  
  297.         __asm
  298.         {
  299.             //we're done with C, fix the registers!
  300.             popad;
  301.  
  302.             //calculate the address of the current vfunc and call it
  303.             mov eax, 0;
  304.             add eax, grobset;
  305.             add eax, irealvmt;
  306.             mov eax, [eax];
  307.             push eax;
  308.             mov eax, oldeax;
  309.             retn;
  310.  
  311.         }
  312.     };
  313.  
  314.  
  315.     char dick[0x300];
  316. };
  317.  
  318. #pragma optimize("", on)
  319. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement