Guest User

Rage2Hook 0.3

a guest
May 23rd, 2019
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.93 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 <vector>
  7. #include <filesystem>
  8. #include <fstream>
  9.  
  10. #include "MinHook/MinHook.h"
  11. #include "proxy.h"
  12.  
  13. std::vector<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(LPCWSTR path)
  25. {
  26.     DWORD dwAttrib = GetFileAttributesW(path);
  27.     return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
  28. }
  29.  
  30. void dbglog(const char *format, ...)
  31. {
  32.   char str[4096];
  33.   va_list ap;
  34.   va_start(ap, format);
  35.  
  36.   vsnprintf(str, 4096, format, ap);
  37.   va_end(ap);
  38.  
  39.   FILE* file;
  40.  
  41.   if (fopen_s(&file, "rage2hook.log", "a") != 0)
  42.     return;
  43.  
  44.   fwrite(str, strlen(str), 1, file);
  45.   fwrite("\n", 1, 1, file);
  46.   fclose(file);
  47. }
  48.  
  49. void strlog(const char* buffer, size_t size)
  50. {
  51.   FILE* file;
  52.  
  53.   if (fopen_s(&file, "rage2hook.log", "a") != 0)
  54.     return;
  55.  
  56.   fwrite(buffer, size, 1, file);
  57.   fwrite("\n", 1, 1, file);
  58.   fclose(file);
  59. }
  60.  
  61. bool StringValid(const char* buffer, size_t size)
  62. {
  63.   for (size_t i = 0; i < size; i++)
  64.   {
  65.     if (!isprint(buffer[i]))
  66.       return false;
  67.   }
  68.   return true;
  69. }
  70.  
  71. bool StringContains(const char* buffer, size_t size, char c)
  72. {
  73.   for (size_t i = 0; i < size; i++)
  74.   {
  75.     if (buffer[i] == c)
  76.       return true;
  77.   }
  78.   return false;
  79. }
  80.  
  81. char* exe_base = nullptr;
  82.  
  83. typedef uint64_t(*Murmur3Hash_ptr)(const char* buffer, size_t size, size_t seed);
  84. Murmur3Hash_ptr Murmur3Hash_orig;
  85.  
  86. size_t Murmur3Hash_addr_10 = 0x107ABF0; // 1.0?
  87. size_t Murmur3Hash_addr_11 = 0x107EF10; // 1.1?
  88.  
  89. size_t Murmur3Hash_addr = Murmur3Hash_addr_11; // todo: detect version based on what bytes we read at the addr...
  90.  
  91. std::vector<uint64_t> known_hashes;
  92.  
  93. char newbuf[1024];
  94.  
  95. uint64_t Murmur3Hash_Hook(const char* buffer, size_t size, size_t seed)
  96. {
  97.   uint64_t hash = Murmur3Hash_orig(buffer, size, seed);
  98.  
  99.   if (StringValid(buffer, size))
  100.   {
  101.     bool is_valid = false;
  102.  
  103.     memcpy(newbuf, buffer, size);
  104.     newbuf[size] = '\0';
  105.  
  106.     std::string buf = newbuf;
  107.  
  108.     auto pos = buf.find_last_of(".");
  109.     if (pos != std::string::npos)
  110.     {
  111.       auto ext = buf.substr(pos + 1);
  112.       for(auto known_ext : extensions)
  113.       {
  114.         if (ext == known_ext)
  115.         {
  116.           is_valid = true;
  117.           break;
  118.         }
  119.       }
  120.     }
  121.  
  122.     if(is_valid || StringContains(buffer, size, '/')) // lots of other stuff uses Murmur3, so filter out only the paths
  123.     {
  124.       bool hash_isknown = false;
  125.       for (auto known_hash : known_hashes)
  126.       {
  127.         if (known_hash == hash)
  128.         {
  129.           hash_isknown = true;
  130.           break;
  131.         }
  132.       }
  133.  
  134.       if (!hash_isknown)
  135.       {
  136.         strlog(buffer, size);
  137.         known_hashes.push_back(hash);
  138.       }
  139.     }
  140.   }
  141.  
  142.   return hash;
  143. }
  144.  
  145. bool HookHashFuncs()
  146. {
  147.   BYTE* Murmur3Hash = (BYTE*)(exe_base + Murmur3Hash_addr);
  148.  
  149.   // Make sure murmur function begins how we expect...
  150.   if (Murmur3Hash[0] != 0x48 || Murmur3Hash[1] != 0x89 || Murmur3Hash[2] != 0x5C || Murmur3Hash[3] != 0x24)
  151.     return false;
  152.  
  153.   MH_Initialize();
  154.  
  155.   MH_CreateHook((void*)Murmur3Hash, Murmur3Hash_Hook, (LPVOID*)&Murmur3Hash_orig);
  156.   MH_EnableHook((void*)Murmur3Hash);
  157.  
  158.   return true;
  159. }
  160.  
  161. void LoadFileList(const std::string& list_path)
  162. {
  163.   Murmur3Hash_ptr hasher = (Murmur3Hash_ptr)(exe_base + Murmur3Hash_addr);
  164.  
  165.   std::ifstream infile(list_path);
  166.   std::string line;
  167.   while (std::getline(infile, line))
  168.   {
  169.     if (line.length() <= 0)
  170.       continue;
  171.     if (line.at(0) == ';')
  172.       continue;
  173.  
  174.     auto hash = hasher(line.c_str(), line.length(), 0);
  175.  
  176.     bool hash_isknown = false;
  177.     for (auto known_hash : known_hashes)
  178.     {
  179.       if (known_hash == hash)
  180.       {
  181.         hash_isknown = true;
  182.         break;
  183.       }
  184.     }
  185.  
  186.     if (!hash_isknown)
  187.       known_hashes.push_back(hash);
  188.   }
  189. }
  190.  
  191. void LoadFileLists(const std::string& dir)
  192. {
  193.   std::experimental::filesystem::directory_iterator end_itr;
  194.   for (std::experimental::filesystem::directory_iterator i(dir); i != end_itr; ++i)
  195.   {
  196.     if (std::experimental::filesystem::is_regular_file(i->status()))
  197.     {
  198.       if (i->path().extension() == ".filelist")
  199.         LoadFileList(i->path().string());
  200.  
  201.       continue;
  202.     }
  203.  
  204.     if (std::experimental::filesystem::is_directory(i->status()))
  205.     {
  206.       LoadFileLists(i->path().string());
  207.     }
  208.   }
  209. }
  210.  
  211. void InitHooks()
  212. {
  213.   if (exe_base)
  214.     return;
  215.  
  216.   exe_base = (char*)GetModuleHandleA("RAGE2.exe");
  217.   if (!exe_base)
  218.   {
  219.     MessageBoxA(0, "Rage2Hook: Failed to get handle for \"RAGE2.exe\" process? :(", "Rage2Hook", 0);
  220.     return;
  221.   }
  222.  
  223.   // Load previous names from log if it exists
  224.   LoadFileList("rage2hook.log");
  225.  
  226.   // Load Rage2Unpack filelists if they exist, so we won't log any already known names
  227.   LoadFileLists("projects\\RAGE 2\\");
  228.  
  229.   if (!HookHashFuncs())
  230.   {
  231.     MessageBoxA(0, "Rage2Hook: unsupported Rage2 version, Rage2Hook features disabled.\r\nPlease check for a new Rage2Hook build!", "Rage2Hook", 0);
  232.     return;
  233.   }
  234. }
  235.  
  236. HMODULE ourModule = 0;
  237.  
  238. BOOL APIENTRY DllMain(HMODULE hModule, int ul_reason_for_call, LPVOID lpReserved)
  239. {
  240.     if (ul_reason_for_call == DLL_PROCESS_ATTACH)
  241.     {
  242.         ourModule = hModule;
  243.         Proxy_Attach();
  244.  
  245.         InitHooks();
  246.     }
  247.     if (ul_reason_for_call == DLL_PROCESS_DETACH)
  248.         Proxy_Detach();
  249.  
  250.     return TRUE;
  251. }
Add Comment
Please, Sign In to add comment