Advertisement
Guest User

sku/thesku

a guest
Sep 14th, 2011
1,455
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.89 KB | None | 0 0
  1. /*
  2.     AUTHOR:         sku/thesku [http://www.ownedcore.com/forums/members/69674-sku.html]
  3.  
  4.     CREDITS:        shadowdancer_ on irc.synirc.net#d3dev
  5.                   #d3dev [irc.synirc.net]
  6.                   #d3se [irc.rizon.net]
  7.  
  8.     DESCRIPTION:    Logs all login-relevant protobuf message constructor calls [x86 only]
  9.  
  10.     VERSION:        1.2
  11.  
  12.     DEPENDENCIES:   Boost [http://www.boost.org]
  13.                   HadesMem [http://code.google.com/p/hadesmem/]
  14.                   AsmJit [http://code.google.com/p/asmjit/]
  15.                   BeaEngine [http://www.beaengine.org/]
  16.  
  17.     TODO:           Add all constructors
  18.                   Detour WSARecv/WSASend
  19.  
  20.     LEGAL:          Code released to public domain by sku, no copyright
  21.                   Dependencies are copyrighted and licensed by their respective owners
  22.                   Use at your own risk
  23.  
  24.     CHANGELOG:      1.1 Added timestamps to log messages.
  25.                   1.2   Removed duplicate code
  26. */
  27.  
  28. // Windows.
  29. #include <Windows.h>
  30.  
  31. // Standard.
  32. #include <algorithm>
  33. #include <ctime>
  34. #include <fstream>
  35. #include <memory>
  36. #include <stdexcept>
  37. #include <tuple>
  38. #include <vector>
  39.  
  40. // Boost.
  41. #include <boost/exception/all.hpp>
  42. #include <boost/format.hpp>
  43.  
  44. // HadesMem (v3, old).
  45. #define ASMJIT_API
  46. #include <HadesMemory/MemoryMgr.hpp>
  47. #include <HadesMemory/Patcher.hpp>
  48.  
  49. // Link libraries.
  50. #pragma comment(lib, "libAsmJit")
  51. #pragma comment(lib, "libBeaEngine")
  52. #pragma comment(lib, "libMemory")
  53. #pragma comment(lib, "psapi")
  54.  
  55. // Forward declarations.
  56. void __stdcall Log(std::string const& message);
  57. void __stdcall Log(boost::format const& fmt);
  58. void __cdecl AddConstructorAddresses();
  59. void __cdecl CtorTrampoline();
  60. DWORD __stdcall CtorHandler(DWORD messagePtr, DWORD ctorAddress);
  61.  
  62. // Constants.
  63. DWORD const kIDA_BASE = 0x3C910000;
  64. std::string const kLOG_FILE_PATH = "dump-msg-ctor-calls.log";
  65.  
  66. // Typedefs.
  67. typedef std::tuple<std::shared_ptr<Hades::Memory::PatchRaw>, DWORD> PatchTuple;
  68. typedef std::tuple<DWORD, std::string> CtorTuple;
  69. typedef std::runtime_error Error;
  70.  
  71. // Globals.
  72. std::ofstream g_logFile;
  73. std::vector<PatchTuple> g_patches;
  74. std::vector<CtorTuple> g_messageCtors;
  75. Hades::Memory::MemoryMgr g_memory(GetCurrentProcessId());
  76.  
  77.  
  78. // Dll entry point.
  79. BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) {
  80.     return TRUE;
  81. }
  82.  
  83. // Dll injector initialize export.
  84. extern "C" __declspec(dllexport) void Initialize() {
  85.     try {
  86.         try {
  87.             // Delete log file if it exists already.
  88.             std::remove(kLOG_FILE_PATH.c_str());
  89.         } catch (...) {
  90.             // Exception may be ignored.
  91.         }
  92.  
  93.         // For debugging purposes.
  94.         Log("Initialize called.");
  95.  
  96.         // Type 1 constructors.
  97.         Log("Adding constructors.");
  98.         AddConstructorAddresses();
  99.  
  100.         // Get the battle.net.dll base address.
  101.         Log("Getting module handle of battle.net.dll");
  102.         HMODULE const hBattlenetDll = GetModuleHandleA("battle.net.dll");
  103.         if (!hBattlenetDll) {
  104.             throw Error("Could not get battle.net.dll module handle.");
  105.         }
  106.  
  107.         // Use base address for arithmetics.
  108.         DWORD const battlenetBase =
  109.             reinterpret_cast<DWORD>(hBattlenetDll);
  110.  
  111.         // Rebase function.
  112.         auto const Rebaser = [&](CtorTuple& ctor) {
  113.             std::get<0>(ctor) += (battlenetBase - kIDA_BASE);
  114.         };
  115.  
  116.         // Rebase constructors.
  117.         Log("Rebasing constructor pointers.");
  118.         std::for_each(g_messageCtors.begin(), g_messageCtors.end(), Rebaser);
  119.  
  120.         // Detour function.
  121.         auto const MakeDetour = [&](CtorTuple& ctor) {
  122.             // Get the constructor address.
  123.             DWORD const address = std::get<0>(ctor);
  124.             Log(boost::format("Detouring 0x%08x.") % address);
  125.  
  126.             // Build detour code.
  127.             Log("Building AsmJit code.");
  128.             AsmJit::Assembler a;
  129.             AsmJit::Label L_getEip = a.newLabel();
  130.             a.call(L_getEip);
  131.             a.bind(L_getEip);
  132.             DWORD trampolineAddr =
  133.                 reinterpret_cast<DWORD>(&CtorTrampoline);
  134.             a.push(trampolineAddr);
  135.             a.ret();
  136.  
  137.             // Get them bytes.
  138.             Log("Compiling AsmJit code.");
  139.             BYTE* detourCode = static_cast<BYTE*>(a.make());
  140.             if (!detourCode) {
  141.                 throw Error("AsmJit::Compiler::make failed.");
  142.             }
  143.  
  144.             // Patch memory.
  145.             Log("Creating raw patch.");
  146.             std::vector<BYTE> data(detourCode, detourCode + a.getCodeSize());
  147.             auto patch = new Hades::Memory::PatchRaw(g_memory,
  148.                 reinterpret_cast<PVOID>(address), data);
  149.             Log("Applying patch.");
  150.             patch->Apply();
  151.  
  152.             // Keep pointer to the patch.
  153.             Log("Adding patch to list.");
  154.             g_patches.push_back(PatchTuple(
  155.                 std::shared_ptr<Hades::Memory::PatchRaw>(patch),
  156.                 address));
  157.         };
  158.  
  159.         // Detour constructors.
  160.         Log("Creating and applying constructor detours.");
  161.         std::for_each(g_messageCtors.begin(), g_messageCtors.end(), MakeDetour);
  162.  
  163.         // Initialization done.
  164.         Log("Completed initialization.");
  165.     } catch (std::exception const& ex) {
  166.         Log(boost::diagnostic_information(ex));
  167.     } catch (...) {
  168.         Log("Unknown error.");
  169.     }
  170. }
  171.  
  172. void __stdcall Log(std::string const& message) {
  173.     if (!message.empty()) {
  174.         // Send debug message.
  175.         OutputDebugStringA(("*** msg-ctor-calls-log: " + message).c_str());
  176.  
  177.         // Open file.
  178.         if (!g_logFile.is_open()) {
  179.             g_logFile.open(kLOG_FILE_PATH, std::ofstream::app | std::ofstream::out);
  180.         }
  181.  
  182.         // Write to file.
  183.         g_logFile << boost::str(boost::format("[%08x] %s\n") % std::time(nullptr) % message);
  184.         g_logFile.close();
  185.     }
  186. }
  187.  
  188. void __stdcall Log(boost::format const& fmt) {
  189.     Log(boost::str(fmt));
  190. }
  191.  
  192. void __declspec(naked) __cdecl CtorTrampoline() {
  193.     __asm {
  194.         push ebp
  195.         mov ebp, esp
  196.         push edx
  197.         mov edx, [ebp+0x04]
  198.         sub edx, 0x05
  199.         push edx
  200.         push ecx
  201.         call CtorHandler
  202.         pop edx
  203.         leave
  204.         add esp, 0x04
  205.         retn
  206.     }
  207. }
  208.  
  209. DWORD __stdcall CtorHandler(DWORD messagePtr, DWORD ctorAddress) {
  210.     // Find the patch that belongs to this constructor address.
  211.     // TODO: Use a map instead..
  212.     for (size_t i = 0; i < g_patches.size(); ++i) {
  213.         if (std::get<1>(g_patches[i]) == ctorAddress) {
  214.             // Log call.
  215.             Log(boost::format("0x%08x: %s constructor called.")
  216.                 % ctorAddress % std::get<1>(g_messageCtors[i]));
  217.  
  218.             // Remove patch temporarily.
  219.             std::get<0>(g_patches[i])->Remove();
  220.  
  221.             // Call original constructor.
  222.             auto const origCtor = reinterpret_cast<DWORD (__thiscall*)(DWORD)>(
  223.                 ctorAddress);
  224.             DWORD const result = origCtor(messagePtr);
  225.  
  226.             // Reapply patch.
  227.             std::get<0>(g_patches[i])->Apply();
  228.  
  229.             // Return original value.
  230.             return result;
  231.         }
  232.     }
  233.  
  234.     // This is bad.
  235.     Log(boost::format("Fatal error: Unknown constructor address 0x%08x.") % ctorAddress);
  236.     return 0;
  237. }
  238.  
  239. void __cdecl AddConstructorAddresses() {
  240.     // Note: This list is not complete.
  241.     g_messageCtors.push_back(CtorTuple(0x3cc26de0, "ModuleLoadRequest"));
  242.     g_messageCtors.push_back(CtorTuple(0x3cc27130, "ModuleLoadResponse"));
  243.     g_messageCtors.push_back(CtorTuple(0x3cc27530, "ModuleMessageRequest"));
  244.     g_messageCtors.push_back(CtorTuple(0x3cc27a00, "LogonRequest"));
  245.     g_messageCtors.push_back(CtorTuple(0x3cc28360, "LogonResponse"));
  246.     g_messageCtors.push_back(CtorTuple(0x3cc28770, "AuthModuleVariant"));
  247.     g_messageCtors.push_back(CtorTuple(0x3cc28d10, "AuthAgreementLocale"));
  248.     g_messageCtors.push_back(CtorTuple(0x3cc2a410, "AuthenticationConfig"));
  249.     g_messageCtors.push_back(CtorTuple(0x3cc2af40, "AuthModuleConfig"));
  250.     g_messageCtors.push_back(CtorTuple(0x3cc2b260, "AuthAgreement"));
  251.     g_messageCtors.push_back(CtorTuple(0x3ccc4d80, "GetLoadRequest"));
  252.     g_messageCtors.push_back(CtorTuple(0x3ccc4df0, "GetLoadRequest2"));
  253.     g_messageCtors.push_back(CtorTuple(0x3ccc50b0, "ServerState"));
  254.     g_messageCtors.push_back(CtorTuple(0x3ccc5120, "ServerState2"));
  255.     g_messageCtors.push_back(CtorTuple(0x3ccc5610, "PoolStateRequest"));
  256.     g_messageCtors.push_back(CtorTuple(0x3ccc5680, "PoolStateRequest2"));
  257.     g_messageCtors.push_back(CtorTuple(0x3ccc5b80, "ServerInfo"));
  258.     g_messageCtors.push_back(CtorTuple(0x3ccc5c00, "ServerInfo2"));
  259.     g_messageCtors.push_back(CtorTuple(0x3ccc6460, "PoolStateResponse"));
  260.     g_messageCtors.push_back(CtorTuple(0x3ccc64e0, "PoolStateResponse2"));
  261.     g_messageCtors.push_back(CtorTuple(0x3ccf26b0, "NO_RESPONSE"));
  262.     g_messageCtors.push_back(CtorTuple(0x3ccf2720, "NO_RESPONSE2"));
  263.     g_messageCtors.push_back(CtorTuple(0x3ccf29e0, "Address"));
  264.     g_messageCtors.push_back(CtorTuple(0x3ccf2cf0, "ProcessId"));
  265.     g_messageCtors.push_back(CtorTuple(0x3ccf2d50, "ProcessId2"));
  266.     g_messageCtors.push_back(CtorTuple(0x3ccf3170, "ObjectAddress"));
  267.     g_messageCtors.push_back(CtorTuple(0x3ccf31e0, "ObjectAddress2"));
  268.     g_messageCtors.push_back(CtorTuple(0x3ccf3340, "NoData"));
  269.     g_messageCtors.push_back(CtorTuple(0x3ccf33b0, "NoData2"));
  270.     g_messageCtors.push_back(CtorTuple(0x3ccf39f0, "Address2"));
  271.     g_messageCtors.push_back(CtorTuple(0x3cd10aa0, "ConnectRequest"));
  272.     g_messageCtors.push_back(CtorTuple(0x3cd10e20, "ConnectResponse"));
  273.     g_messageCtors.push_back(CtorTuple(0x3cd10e90, "ConnectResponse2"));
  274.     g_messageCtors.push_back(CtorTuple(0x3cd11230, "BoundService"));
  275.     g_messageCtors.push_back(CtorTuple(0x3cd11290, "BoundService2"));
  276.     g_messageCtors.push_back(CtorTuple(0x3cd11690, "BindResponse"));
  277.     g_messageCtors.push_back(CtorTuple(0x3cd11710, "BindResponse2"));
  278.     g_messageCtors.push_back(CtorTuple(0x3cd119e0, "EchoRequest"));
  279.     g_messageCtors.push_back(CtorTuple(0x3cd11ea0, "EchoResponse"));
  280.     g_messageCtors.push_back(CtorTuple(0x3cd12360, "DisconnectRequest"));
  281.     g_messageCtors.push_back(CtorTuple(0x3cd12740, "DisconnectNotification"));
  282.     g_messageCtors.push_back(CtorTuple(0x3cd12c60, "NullRequest"));
  283.     g_messageCtors.push_back(CtorTuple(0x3cd12f90, "EncryptRequest"));
  284.     g_messageCtors.push_back(CtorTuple(0x3cd148c0, "BindRequest"));
  285.     g_messageCtors.push_back(CtorTuple(0x3cd387a0, "Var"));
  286.     g_messageCtors.push_back(CtorTuple(0x3cd38c90, "Resource"));
  287.     g_messageCtors.push_back(CtorTuple(0x3cd38d00, "Resource2"));
  288.     g_messageCtors.push_back(CtorTuple(0x3cd39230, "ServerAddress"));
  289.     g_messageCtors.push_back(CtorTuple(0x3cd392a0, "ServerAddress2"));
  290.     g_messageCtors.push_back(CtorTuple(0x3cd396e0, "SupplementalService"));
  291.     g_messageCtors.push_back(CtorTuple(0x3cd39740, "SupplementalService2"));
  292.     g_messageCtors.push_back(CtorTuple(0x3cd39be0, "ServiceShard"));
  293.     g_messageCtors.push_back(CtorTuple(0x3cd39c50, "ServiceShard2"));
  294.     g_messageCtors.push_back(CtorTuple(0x3cd3ab20, "Var2"));
  295.     g_messageCtors.push_back(CtorTuple(0x3cd3b130, "ProgramResources"));
  296.     g_messageCtors.push_back(CtorTuple(0x3cd3b1b0, "ProgramResources2"));
  297.     g_messageCtors.push_back(CtorTuple(0x3cd3b450, "ServerSet"));
  298.     g_messageCtors.push_back(CtorTuple(0x3cd3b4e0, "ServerSet2"));
  299.     g_messageCtors.push_back(CtorTuple(0x3cd3ba30, "ListenPoint"));
  300.     g_messageCtors.push_back(CtorTuple(0x3cd3bab0, "ListenPoint2"));
  301.     g_messageCtors.push_back(CtorTuple(0x3cd3bd00, "ServiceConfig"));
  302.     g_messageCtors.push_back(CtorTuple(0x3cd3bd80, "ServiceConfig2"));
  303.     g_messageCtors.push_back(CtorTuple(0x3cd3c260, "RPCServerConfig"));
  304.     g_messageCtors.push_back(CtorTuple(0x3cd3c2e0, "RPCServerConfig2"));
  305.     g_messageCtors.push_back(CtorTuple(0x3cd3c590, "ProcessConfig"));
  306.     g_messageCtors.push_back(CtorTuple(0x3cd3c670, "ProcessConfig2"));
  307. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement