Advertisement
Guest User

Rage2Hook 0.3

a guest
May 25th, 2019
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.00 KB | None | 0 0
  1. // Use https://github.com/emoose/DQXIHook as a base, and replace dllmain.cpp with below:
  2.  
  3. #include "stdafx.h"
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <unordered_set>
  7. #include <filesystem>
  8. #include <fstream>
  9.  
  10. #include "MinHook/MinHook.h"
  11. #include "proxy.h"
  12.  
  13. std::unordered_set<std::string> extensions = {
  14.   "ddsc", "inputkeymapdefsc", "inputc", "gtoc", "bl", "bin", "stringlookup",
  15.   "gfx", "worldaudioinfo_xmlc", "vegetationinfo", "gadfc", "rawc", "fmod_bankc",
  16.   "roadgraphc", "routec", "aicoversettingsc", "aisystunec", "vocals_settingsc",
  17.   "intentstablec", "gameregionsc", "light_infoc", "meproc", "hrmeshc", "atx1",
  18.   "bmpc", "world", "terrainsystemc", "ee", "asb", "meshc", "brdd", "json",
  19.   "featuresc", "streampatch", "bikc", "ogg", "nl", "fl", "navmeshc", "wavc",
  20.   "ban", "physicsc", "stoc", "atx2", "resourcesetsc", "fmod_sbankc", "uitunec",
  21.   "environc", "hikcc", "vocalsc", "graphc"
  22. };
  23.  
  24. bool FileExists(const char* path)
  25. {
  26.   DWORD dwAttrib = GetFileAttributesA(path);
  27.   return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
  28. }
  29.  
  30. bool DirectoryExists(const char* path)
  31. {
  32.   DWORD dwAttrib = GetFileAttributesA(path);
  33.   return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
  34. }
  35.  
  36. void dbglog(const char *format, ...)
  37. {
  38.   char str[4096];
  39.   va_list ap;
  40.   va_start(ap, format);
  41.  
  42.   vsnprintf(str, 4096, format, ap);
  43.   va_end(ap);
  44.  
  45.   FILE* file;
  46.  
  47.   if (fopen_s(&file, "rage2hook.log", "a") != 0)
  48.     return;
  49.  
  50.   fwrite(str, strlen(str), 1, file);
  51.   fwrite("\n", 1, 1, file);
  52.   fclose(file);
  53. }
  54.  
  55. void strlog(const char* buffer, size_t size)
  56. {
  57.   FILE* file;
  58.  
  59.   if (fopen_s(&file, "rage2hook.log", "a") != 0)
  60.     return;
  61.  
  62.   fwrite(buffer, size, 1, file);
  63.   fwrite("\n", 1, 1, file);
  64.   fclose(file);
  65. }
  66.  
  67. bool StringValid(const char* buffer, size_t size)
  68. {
  69.   for (size_t i = 0; i < size; i++)
  70.   {
  71.     if (!isprint(buffer[i]))
  72.       return false;
  73.   }
  74.   return true;
  75. }
  76.  
  77. bool StringContains(const char* buffer, size_t size, char c)
  78. {
  79.   for (size_t i = 0; i < size; i++)
  80.   {
  81.     if (buffer[i] == c)
  82.       return true;
  83.   }
  84.   return false;
  85. }
  86.  
  87. char* exe_base = nullptr;
  88.  
  89. typedef uint64_t(*Murmur3Hash_ptr)(const char* buffer, size_t size, size_t seed);
  90. Murmur3Hash_ptr Murmur3Hash_orig;
  91.  
  92. size_t Murmur3Hash_addrs[] = {
  93.   0x107F3B0, // 1.2?
  94.   0x107EF10, // 1.1?
  95.   0x107ABF0, // 1.0?
  96. };
  97.  
  98. size_t Murmur3Hash_addr = 0;
  99.  
  100. std::unordered_set<uint64_t> known_hashes;
  101.  
  102. char newbuf[1024];
  103.  
  104. uint64_t Murmur3Hash_Hook(const char* buffer, size_t size, size_t seed)
  105. {
  106.   uint64_t hash = Murmur3Hash_orig(buffer, size, seed);
  107.  
  108.   if (StringValid(buffer, size))
  109.   {
  110.     // Murmur3 is used for lots of things, so check if this is a path (contains /) or ends with a known extension
  111.  
  112.     memcpy(newbuf, buffer, size);
  113.     newbuf[size] = '\0';
  114.     std::string buf = newbuf;
  115.  
  116.     auto pos = buf.find_last_of(".");
  117.     bool known_extension = pos != std::string::npos && extensions.find(buf.substr(pos + 1)) != extensions.end();
  118.  
  119.     if (known_extension || StringContains(buffer, size, '/'))
  120.     {
  121.       if (known_hashes.find(hash) == known_hashes.end())
  122.       {
  123.         strlog(buffer, size);
  124.         known_hashes.insert(hash);
  125.       }
  126.     }
  127.   }
  128.  
  129.   return hash;
  130. }
  131.  
  132. bool LoadFileList(const std::string& list_path)
  133. {
  134.   if (!FileExists(list_path.c_str()) || !Murmur3Hash_addr)
  135.     return false;
  136.  
  137.   Murmur3Hash_ptr hasher = (Murmur3Hash_ptr)(exe_base + Murmur3Hash_addr);
  138.  
  139.   std::ifstream infile(list_path);
  140.   std::string line;
  141.   while (std::getline(infile, line))
  142.   {
  143.     if (line.length() <= 0)
  144.       continue;
  145.     if (line.at(0) == ';')
  146.       continue;
  147.  
  148.     auto hash = hasher(line.c_str(), line.length(), 0);
  149.  
  150.     if (known_hashes.find(hash) == known_hashes.end())
  151.       known_hashes.insert(hash);
  152.   }
  153.  
  154.   return true;
  155. }
  156.  
  157. bool LoadFileLists(const std::string& dir)
  158. {
  159.   if (!DirectoryExists(dir.c_str()))
  160.     return false;
  161.  
  162.   std::experimental::filesystem::directory_iterator end_itr;
  163.   for (std::experimental::filesystem::directory_iterator i(dir); i != end_itr; ++i)
  164.   {
  165.     if (std::experimental::filesystem::is_regular_file(i->status()))
  166.     {
  167.       if (i->path().extension() == ".filelist")
  168.         LoadFileList(i->path().string());
  169.  
  170.       continue;
  171.     }
  172.  
  173.     if (std::experimental::filesystem::is_directory(i->status()))
  174.     {
  175.       LoadFileLists(i->path().string());
  176.     }
  177.   }
  178.  
  179.   return true;
  180. }
  181.  
  182. bool IsMurmur3Func(BYTE* addr)
  183. {
  184.   return addr[0] == 0x48 && addr[1] == 0x89 && addr[2] == 0x5C && addr[3] == 0x24;
  185. }
  186.  
  187. bool HookHashFuncs()
  188. {
  189.   BYTE* Murmur3Hash = 0;
  190.   for (auto addr : Murmur3Hash_addrs)
  191.   {
  192.     auto* funcdata = (BYTE*)(exe_base + addr);
  193.     if (IsMurmur3Func(funcdata))
  194.     {
  195.       Murmur3Hash = funcdata;
  196.       Murmur3Hash_addr = addr;
  197.       break;
  198.     }
  199.   }
  200.  
  201.   if (!Murmur3Hash)
  202.     return false;
  203.  
  204.   // Load previous names from log if it exists
  205.   LoadFileList("rage2hook.log");
  206.  
  207.   // Load Rage2Unpack filelists if they exist, so we won't log already known names
  208.   LoadFileLists("projects\\RAGE 2\\");
  209.  
  210.   // Hook Murmur3 function!
  211.   MH_Initialize();
  212.  
  213.   MH_CreateHook((void*)Murmur3Hash, Murmur3Hash_Hook, (LPVOID*)&Murmur3Hash_orig);
  214.   MH_EnableHook((void*)Murmur3Hash);
  215.  
  216.   return true;
  217. }
  218.  
  219. void InitHooks()
  220. {
  221.   if (exe_base)
  222.     return;
  223.  
  224.   exe_base = (char*)GetModuleHandleA("RAGE2.exe");
  225.   if (!exe_base)
  226.   {
  227.     MessageBoxA(0, "Rage2Hook: Failed to get handle for \"RAGE2.exe\" process? :(", "Rage2Hook", 0);
  228.     return;
  229.   }
  230.  
  231.   if (!HookHashFuncs())
  232.   {
  233.     MessageBoxA(0, "Rage2Hook: unsupported Rage2 version, Rage2Hook features disabled.\r\nPlease check for a new Rage2Hook build!", "Rage2Hook", 0);
  234.     return;
  235.   }
  236. }
  237.  
  238. HMODULE ourModule = 0;
  239.  
  240. BOOL APIENTRY DllMain(HMODULE hModule, int ul_reason_for_call, LPVOID lpReserved)
  241. {
  242.   if (ul_reason_for_call == DLL_PROCESS_ATTACH)
  243.   {
  244.     ourModule = hModule;
  245.     Proxy_Attach();
  246.  
  247.     InitHooks();
  248.   }
  249.   if (ul_reason_for_call == DLL_PROCESS_DETACH)
  250.     Proxy_Detach();
  251.  
  252.   return TRUE;
  253. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement