Advertisement
Guest User

Untitled

a guest
Mar 14th, 2016
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.12 KB | None | 0 0
  1. /*
  2. * This file is part of the CitizenFX project - http://citizen.re/
  3. *
  4. * See LICENSE and MENTIONS in the root of the source tree for information
  5. * regarding licensing.
  6. */
  7.  
  8. #pragma once
  9.  
  10. #include <stdint.h>
  11. #include <jitasm.h>
  12.  
  13. #include <memory>
  14. #include <functional>
  15.  
  16. namespace hook
  17. {
  18. // for link /DYNAMICBASE executables
  19. static ptrdiff_t baseAddressDifference;
  20.  
  21. // sets the base address difference based on an obtained pointer
  22. inline void set_base(uintptr_t address)
  23. {
  24. #ifdef _M_IX86
  25. uintptr_t addressDiff = (address - 0x400000);
  26. #elif defined(_M_AMD64)
  27. uintptr_t addressDiff = (address - 0x140000000);
  28. #endif
  29.  
  30. // pointer-style cast to ensure unsigned overflow ends up copied directly into a signed value
  31. baseAddressDifference = *(ptrdiff_t*)&addressDiff;
  32. }
  33.  
  34. // sets the base to the process main base
  35. inline void set_base()
  36. {
  37. set_base((uintptr_t)GetModuleHandle(NULL));
  38. }
  39.  
  40. // adjusts the address passed to the base as set above
  41. template<typename T>
  42. inline void adjust_base(T& address)
  43. {
  44. *(uintptr_t*)&address += baseAddressDifference;
  45. }
  46.  
  47. // returns the adjusted address to the stated base
  48. template<typename T>
  49. inline uintptr_t get_adjusted(T address)
  50. {
  51. return (uintptr_t)address + baseAddressDifference;
  52. }
  53.  
  54. struct pass
  55. {
  56. template<typename ...T> pass(T...) {}
  57. };
  58.  
  59. #pragma region assembly generator
  60. class FunctionAssembly
  61. {
  62. private:
  63. void* m_code;
  64.  
  65. public:
  66. inline FunctionAssembly(jitasm::Frontend& frontend)
  67. {
  68. frontend.Assemble();
  69.  
  70. void* code;
  71. code = VirtualAlloc(0, frontend.GetCodeSize(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  72.  
  73. memcpy(code, frontend.GetCode(), frontend.GetCodeSize());
  74.  
  75. m_code = code;
  76. }
  77.  
  78. inline ~FunctionAssembly()
  79. {
  80. VirtualFree(m_code, 0, MEM_RELEASE);
  81. }
  82.  
  83. inline void* GetCode()
  84. {
  85. return m_code;
  86. }
  87. };
  88. #pragma endregion
  89.  
  90. template<typename ValueType, typename AddressType>
  91. inline void put(AddressType address, ValueType value)
  92. {
  93. adjust_base(address);
  94.  
  95. memcpy((void*)address, &value, sizeof(value));
  96. }
  97.  
  98. template<typename ValueType, typename AddressType>
  99. inline void putVP(AddressType address, ValueType value)
  100. {
  101. adjust_base(address);
  102.  
  103. DWORD oldProtect;
  104. VirtualProtect((void*)address, sizeof(value), PAGE_EXECUTE_READWRITE, &oldProtect);
  105.  
  106. memcpy((void*)address, &value, sizeof(value));
  107.  
  108. VirtualProtect((void*)address, sizeof(value), oldProtect, &oldProtect);
  109. }
  110.  
  111. template<typename AddressType>
  112. inline void nop(AddressType address, size_t length)
  113. {
  114. adjust_base(address);
  115.  
  116. memset((void*)address, 0x90, length);
  117. }
  118.  
  119. template<typename AddressType>
  120. inline void return_function(AddressType address, uint16_t stackSize = 0)
  121. {
  122. if (stackSize == 0)
  123. {
  124. put<uint8_t>(address, 0xC3);
  125. }
  126. else
  127. {
  128. put<uint8_t>(address, 0xC2);
  129. put<uint16_t>((uintptr_t)address + 1, stackSize);
  130. }
  131. }
  132.  
  133. template<typename T>
  134. inline T* getRVA(uintptr_t rva)
  135. {
  136. #ifdef _M_IX86
  137. return (T*)(baseAddressDifference + 0x400000 + rva);
  138. #elif defined(_M_AMD64)
  139. return (T*)(0x140000000 + rva);
  140. #endif
  141. }
  142.  
  143. namespace
  144. {
  145. template<typename TOrdinal>
  146. inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, TOrdinal ordinal)
  147. {
  148.  
  149. }
  150.  
  151. template<>
  152. inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, int ordinal)
  153. {
  154. if (IMAGE_SNAP_BY_ORDINAL(*nameTableEntry))
  155. {
  156. return IMAGE_ORDINAL(*nameTableEntry) == ordinal;
  157. }
  158.  
  159. return false;
  160. }
  161.  
  162. template<>
  163. inline bool iat_matches_ordinal(uintptr_t* nameTableEntry, const char* ordinal)
  164. {
  165. if (!IMAGE_SNAP_BY_ORDINAL(*nameTableEntry))
  166. {
  167. auto import = getRVA<IMAGE_IMPORT_BY_NAME>(*nameTableEntry);
  168.  
  169. return !_stricmp(import->Name, ordinal);
  170. }
  171.  
  172. return false;
  173. }
  174. }
  175.  
  176. template<typename T, typename TOrdinal>
  177. T iat(const char* moduleName, T function, TOrdinal ordinal)
  178. {
  179. #ifdef _M_IX86
  180. IMAGE_DOS_HEADER* imageHeader = (IMAGE_DOS_HEADER*)(baseAddressDifference + 0x400000);
  181. #elif defined(_M_AMD64)
  182. IMAGE_DOS_HEADER* imageHeader = (IMAGE_DOS_HEADER*)(baseAddressDifference + 0x140000000);
  183. #endif
  184. IMAGE_NT_HEADERS* ntHeader = getRVA<IMAGE_NT_HEADERS>(imageHeader->e_lfanew);
  185.  
  186. IMAGE_IMPORT_DESCRIPTOR* descriptor = getRVA<IMAGE_IMPORT_DESCRIPTOR>(ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  187.  
  188. while (descriptor->Name)
  189. {
  190. const char* name = getRVA<char>(descriptor->Name);
  191.  
  192. if (_stricmp(name, moduleName))
  193. {
  194. descriptor++;
  195.  
  196. continue;
  197. }
  198.  
  199. auto nameTableEntry = getRVA<uintptr_t>(descriptor->OriginalFirstThunk);
  200. auto addressTableEntry = getRVA<uintptr_t>(descriptor->FirstThunk);
  201.  
  202. while (*nameTableEntry)
  203. {
  204. if (iat_matches_ordinal(nameTableEntry, ordinal))
  205. {
  206. T origEntry = (T)*addressTableEntry;
  207. *addressTableEntry = (uintptr_t)function;
  208.  
  209. return origEntry;
  210. }
  211.  
  212. nameTableEntry++;
  213. addressTableEntry++;
  214. }
  215.  
  216. return nullptr;
  217. }
  218.  
  219. return nullptr;
  220. }
  221.  
  222. #ifndef _M_AMD64
  223. // a context for the hook function to party on
  224. struct HookContext
  225. {
  226. uint32_t m_jumpRet;
  227. uint32_t m_edi, m_esi, m_ebp, m_esp, m_ebx, m_edx, m_ecx, m_eax; // matches pushad format
  228. };
  229.  
  230. class inject_hook
  231. {
  232. friend struct inject_hook_frontend;
  233.  
  234. private:
  235. HookContext* m_curContext;
  236. std::shared_ptr<FunctionAssembly> m_assembly;
  237. uintptr_t m_address;
  238.  
  239. public:
  240. // return value type container
  241. typedef int ReturnType;
  242.  
  243. private:
  244. // set context and run
  245. ReturnType do_run(HookContext* context)
  246. {
  247. m_curContext = context;
  248.  
  249. return run();
  250. }
  251.  
  252. protected:
  253. // return type values for use in return;
  254.  
  255. // return without jumping anywhere
  256. inline ReturnType DoNowt()
  257. {
  258. return ReturnType(0);
  259. }
  260.  
  261. // jump to this place after the hook
  262. inline ReturnType JumpTo(uint32_t address)
  263. {
  264. m_curContext->m_eax = address;
  265.  
  266. return ReturnType(1);
  267. }
  268.  
  269. // accessors for context registers
  270. inline uint32_t Eax() { return m_curContext->m_eax; }
  271. inline void Eax(uint32_t a) { m_curContext->m_eax = a; }
  272.  
  273. inline uint32_t Ebx() { return m_curContext->m_ebx; }
  274. inline void Ebx(uint32_t a) { m_curContext->m_ebx = a; }
  275.  
  276. inline uint32_t Ecx() { return m_curContext->m_ecx; }
  277. inline void Ecx(uint32_t a) { m_curContext->m_ecx = a; }
  278.  
  279. inline uint32_t Edx() { return m_curContext->m_edx; }
  280. inline void Edx(uint32_t a) { m_curContext->m_edx = a; }
  281.  
  282. inline uint32_t Esi() { return m_curContext->m_esi; }
  283. inline void Esi(uint32_t a) { m_curContext->m_esi = a; }
  284.  
  285. inline uint32_t Edi() { return m_curContext->m_edi; }
  286. inline void Edi(uint32_t a) { m_curContext->m_edi = a; }
  287.  
  288. inline uint32_t Esp() { return m_curContext->m_esp; }
  289. inline void Esp(uint32_t a) { m_curContext->m_esp = a; }
  290.  
  291. inline uint32_t Ebp() { return m_curContext->m_ebp; }
  292. inline void Ebp(uint32_t a) { m_curContext->m_ebp = a; }
  293.  
  294. public:
  295. virtual ReturnType run() = 0;
  296.  
  297. inject_hook(uint32_t address)
  298. {
  299. m_address = address;
  300. }
  301.  
  302. void inject();
  303. void injectCall();
  304. };
  305.  
  306. struct inject_hook_frontend : jitasm::Frontend
  307. {
  308. private:
  309. inject_hook* m_hook;
  310.  
  311. static inject_hook::ReturnType CallHookFunction(inject_hook* hook, HookContext* context)
  312. {
  313. return hook->do_run(context);
  314. }
  315.  
  316. public:
  317. inject_hook_frontend(inject_hook* hook)
  318. {
  319. m_hook = hook;
  320. }
  321.  
  322. void InternalMain()
  323. {
  324. // set up the context stack frame
  325. pushad(); // registers
  326. sub(esp, 4); // jump target area
  327. mov(dword_ptr[esp], 0);
  328.  
  329. // load the context address into eax
  330. lea(eax, dword_ptr[esp]);
  331.  
  332. // push eax (second argument to our call)
  333. push(eax);
  334.  
  335. // push the (softcoded, heh) hook function
  336. push((uint32_t)m_hook);
  337.  
  338. // call the call stub
  339. mov(eax, (uint32_t)CallHookFunction);
  340. call(eax);
  341.  
  342. // remove garbage from the stack
  343. add(esp, 8);
  344.  
  345. // do we want to jump somewhere?
  346. test(eax, eax);
  347. jnz("actuallyJump");
  348.  
  349. // guess not, remove jump target area and popad
  350. add(esp, 4);
  351. popad();
  352.  
  353. // get esp back from the context bit
  354. mov(esp, dword_ptr[esp - 20]);
  355.  
  356. ret();
  357.  
  358. L("actuallyJump");
  359.  
  360. add(esp, 4);
  361. popad();
  362.  
  363. mov(esp, dword_ptr[esp - 20]);
  364.  
  365. AppendInstr(jitasm::I_CALL, 0xFF, 0, jitasm::Imm8(4), R(eax));
  366. }
  367. };
  368.  
  369. #define DEFINE_INJECT_HOOK(hookName, hookAddress) class _zz_inject_hook_##hookName : public hook::inject_hook { public: _zz_inject_hook_##hookName(uint32_t address) : hook::inject_hook(address) {}; ReturnType run(); }; \
  370. static _zz_inject_hook_##hookName hookName(hookAddress); \
  371. _zz_inject_hook_##hookName::ReturnType _zz_inject_hook_##hookName::run()
  372.  
  373.  
  374. #if 0
  375. struct AsmHookStub : jitasm::Frontend
  376. {
  377. private:
  378. hook_function* m_safeFunction;
  379.  
  380. static bool CallHookFunction(hook_function* function, HookContext& context)
  381. {
  382. return (*function)(context);
  383. }
  384.  
  385. public:
  386. AsmHookStub(hook_function* function)
  387. {
  388. m_safeFunction = function;
  389. }
  390.  
  391. void InternalMain()
  392. {
  393. // set up the context stack frame
  394. pushad(); // registers
  395. sub(esp, 4); // jump target area
  396. mov(dword_ptr[esp], 0);
  397.  
  398. // load the jump target into eax
  399. lea(eax, dword_ptr[esp]);
  400.  
  401. // push eax (second argument to our call)
  402. push(eax);
  403.  
  404. // push the (softcoded, heh) hook function
  405. push((uint32_t)m_safeFunction);
  406.  
  407. // call the call stub
  408. mov(eax, (uint32_t)CallHookFunction);
  409. call(eax);
  410.  
  411. // remove garbage from the stack
  412. add(esp, 8);
  413.  
  414. // check if we want to execute the original trampoline
  415. test(al, al);
  416. jnz("noTrampolineReturn");
  417.  
  418.  
  419.  
  420. L("noTrampolineReturn");
  421.  
  422.  
  423. }
  424. };
  425. #endif
  426.  
  427. template<typename T, typename AT>
  428. inline void jump(AT address, T func)
  429. {
  430. put<uint8_t>(address, 0xE9);
  431. put<int>((uintptr_t)address + 1, (intptr_t)func - (intptr_t)get_adjusted(address) - 5);
  432. }
  433.  
  434. template<typename T, typename AT>
  435. inline void call(AT address, T func)
  436. {
  437. put<uint8_t>(address, 0xE8);
  438. put<int>((uintptr_t)address + 1, (intptr_t)func - (intptr_t)get_adjusted(address) - 5);
  439. }
  440.  
  441. template<typename T>
  442. inline T get_call(T address)
  443. {
  444. intptr_t target = *(uintptr_t*)(get_adjusted(address) + 1);
  445. target += (get_adjusted(address) + 5);
  446.  
  447. return (T)target;
  448. }
  449.  
  450. template<typename TTarget, typename T>
  451. inline void set_call(TTarget* target, T address)
  452. {
  453. *(T*)target = get_call(address);
  454. }
  455.  
  456. namespace vp
  457. {
  458. template<typename T, typename AT>
  459. inline void jump(AT address, T func)
  460. {
  461. putVP<uint8_t>(address, 0xE9);
  462. putVP<int>((uintptr_t)address + 1, (intptr_t)func - (intptr_t)get_adjusted(address) - 5);
  463. }
  464.  
  465. template<typename T, typename AT>
  466. inline void call(AT address, T func)
  467. {
  468. putVP<uint8_t>(address, 0xE8);
  469. putVP<int>((uintptr_t)address + 1, (intptr_t)func - (intptr_t)get_adjusted(address) - 5);
  470. }
  471. }
  472.  
  473. #pragma region inject call: call stub
  474. template<typename R, typename... Args>
  475. struct CallStub : jitasm::function<void, CallStub<R, Args...>>
  476. {
  477. private:
  478. void* m_target;
  479.  
  480. public:
  481. CallStub(void* target)
  482. : m_target(target)
  483. {
  484. }
  485.  
  486. void main()
  487. {
  488. uint32_t stackOffset = 0;
  489. uint32_t argOffset = sizeof(uintptr_t) * 2; // as frame pointers are also kept here
  490. uint32_t argCleanup = 0;
  491.  
  492. pass{([&]
  493. {
  494. int size = min(sizeof(Args), sizeof(uintptr_t));
  495.  
  496. argOffset += size;
  497. }(), 1)...};
  498.  
  499. // as this is the end, and the last argument isn't past the end
  500. argOffset -= 4;
  501.  
  502. pass{([&]
  503. {
  504. mov(eax, dword_ptr[esp + stackOffset + argOffset]);
  505. push(eax);
  506.  
  507. int size = max(sizeof(Args), sizeof(uintptr_t));
  508.  
  509. stackOffset += size;
  510. argCleanup += size;
  511. argOffset -= size;
  512. }(), 1)...};
  513.  
  514. mov(eax, (uintptr_t)m_target);
  515. call(eax);
  516.  
  517. add(esp, argCleanup);
  518. }
  519. };
  520. #pragma endregion
  521.  
  522. #pragma region inject call
  523. template<typename R, typename... Args>
  524. class inject_call
  525. {
  526. private:
  527. R (*m_origAddress)(Args...);
  528.  
  529. uintptr_t m_address;
  530.  
  531. std::shared_ptr<FunctionAssembly> m_assembly;
  532.  
  533. public:
  534. inject_call(uintptr_t address)
  535. {
  536. if (*(uint8_t*)address != 0xE8)
  537. {
  538. FatalError("inject_call attempted on something that was not a call. Are you sure you have a compatible version of the game executable? You might need to try poking the guru.");
  539. }
  540.  
  541. m_address = address;
  542. }
  543.  
  544. void inject(R (*target)(Args...))
  545. {
  546. CallStub<R, Args...> stub(target);
  547.  
  548. m_assembly = std::make_shared<FunctionAssembly>(stub);
  549.  
  550. // store original
  551. int origAddress = *(int*)(m_address + 1);
  552. origAddress += 5;
  553. origAddress += m_address;
  554.  
  555. m_origAddress = (R(*)(Args...))origAddress;
  556.  
  557. // and patch
  558. put<int>(m_address + 1, (uintptr_t)m_assembly->GetCode() - (uintptr_t)get_adjusted(m_address) - 5);
  559. }
  560.  
  561. R call()
  562. {
  563. return ((R(*)())m_origAddress)();
  564. }
  565.  
  566. R call(Args... args)
  567. {
  568. return m_origAddress(args...);
  569. }
  570. };
  571. #pragma endregion
  572. #else
  573. void* AllocateFunctionStub(void* ptr, int type = 0);
  574.  
  575. template<typename T, typename AT>
  576. inline void jump(AT address, T func)
  577. {
  578. LPVOID funcStub = AllocateFunctionStub((void*)func);
  579.  
  580. put<uint8_t>(address, 0xE9);
  581. put<int>((uintptr_t)address + 1, (intptr_t)funcStub- (intptr_t)get_adjusted(address) - 5);
  582. }
  583.  
  584. template<typename T, typename AT>
  585. inline void jump_rcx(AT address, T func)
  586. {
  587. LPVOID funcStub = AllocateFunctionStub((void*)func, 1);
  588.  
  589. put<uint8_t>(address, 0xE9);
  590. put<int>((uintptr_t)address + 1, (intptr_t)funcStub - (intptr_t)get_adjusted(address) - 5);
  591. }
  592.  
  593. template<typename T, typename AT>
  594. inline void call(AT address, T func)
  595. {
  596. LPVOID funcStub = AllocateFunctionStub((void*)func);
  597.  
  598. put<uint8_t>(address, 0xE8);
  599. put<int>((uintptr_t)address + 1, (intptr_t)funcStub - (intptr_t)get_adjusted(address) - 5);
  600. }
  601.  
  602. template<typename T, typename AT>
  603. inline void call_rcx(AT address, T func)
  604. {
  605. LPVOID funcStub = AllocateFunctionStub((void*)func, 1);
  606.  
  607. put<uint8_t>(address, 0xE8);
  608. put<int>((uintptr_t)address + 1, (intptr_t)funcStub - (intptr_t)get_adjusted(address) - 5);
  609. }
  610.  
  611. template<typename T>
  612. inline T get_call(T address)
  613. {
  614. intptr_t target = *(int32_t*)(get_adjusted(address) + 1);
  615. target += (get_adjusted(address) + 5);
  616.  
  617. return (T)target;
  618. }
  619.  
  620. template<typename TTarget, typename T>
  621. inline void set_call(TTarget* target, T address)
  622. {
  623. *(T*)target = get_call(address);
  624. }
  625.  
  626. inline uintptr_t get_member_internal(void* function)
  627. {
  628. return *(uintptr_t*)function;
  629. }
  630.  
  631. template<typename T>
  632. inline uintptr_t get_member(T function)
  633. {
  634. return ((uintptr_t(*)(T))get_member_internal)(function);
  635. }
  636. #endif
  637. }
  638.  
  639. #include "Hooking.Invoke.h"
  640. #include "Hooking.Patterns.h"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement