Advertisement
Guest User

Untitled

a guest
May 31st, 2017
525
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.31 KB | None | 0 0
  1. namespace BlackCipher
  2. {
  3.     #define STATUS_SUCCESS       ((NTSTATUS)0x00000000)
  4.     #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022)
  5.  
  6.     typedef struct _CLIENT_ID
  7.     {
  8.         ULONG UniqueProcess;
  9.         ULONG UniqueThread;
  10.     } CLIENT_ID, *PCLIENT_ID;
  11.  
  12.     typedef enum _MEMORY_INFORMATION_CLASS
  13.     {
  14.         MemoryBasicInformation,
  15.         MemoryWorkingSetInformation,
  16.         MemoryMappedFilenameInformation,
  17.         MemoryRegionInformation,
  18.         MemoryWorkingSetExInformation,
  19.         MemorySharedCommitInformation,
  20.         MemoryImageInformation,
  21.         MemoryRegionInformationEx,
  22.         MemoryPrivilegedBasicInformation
  23.     } MEMORY_INFORMATION_CLASS;
  24.  
  25.     typedef struct _PROCESS_BASIC_INFORMATION {
  26.         ULONG ExitStatus;
  27.         PPEB PebBaseAddress;
  28.         ULONG AffinityMask;
  29.         ULONG BasePriority;
  30.         ULONG UniqueProcessId;
  31.         ULONG ParentUniqueProcessId;
  32.     } PROCESS_BASIC_INFORMATION;
  33.  
  34.     typedef struct _module_entry
  35.     {
  36.         unsigned int id;
  37.         std::string const name;
  38.  
  39.         unsigned char* base_address;
  40.         unsigned int base_size;
  41.  
  42.         HMODULE handle;
  43.     } module_entry;
  44.  
  45.     unsigned char* game_base_address = 0;
  46.     std::vector<module_entry> game_modules;
  47.  
  48.     NTSTATUS NTAPI NtOpenProcess_Hook(PHANDLE ProcessHandle, ACCESS_MASK AccessMask, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
  49.     {
  50.         if (ClientId->UniqueProcess != NULL)
  51.         {
  52.             PROCESS_BASIC_INFORMATION pbi;
  53.             memset(&pbi, 0, sizeof(PROCESS_BASIC_INFORMATION));
  54.             ULONG return_length = 0;
  55.  
  56.             if ((NtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), &return_length) == STATUS_SUCCESS) &&
  57.                 (pbi.ParentUniqueProcessId == ClientId->UniqueProcess))
  58.             {
  59.                 game_base_address = reinterpret_cast<unsigned char*>(pbi.PebBaseAddress->Reserved3[1]);
  60.  
  61.                 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ClientId->UniqueProcess);
  62.  
  63.                 if (hSnapshot != INVALID_HANDLE_VALUE)
  64.                 {
  65.                     MODULEENTRY32 module_entry;
  66.                     memset(&module_entry, 0, sizeof(MODULEENTRY32));
  67.  
  68.                     module_entry.dwSize = sizeof(MODULEENTRY32);
  69.  
  70.                     if (Module32First(hSnapshot, &module_entry))
  71.                     {
  72.                         game_modules.clear();
  73.  
  74.                         do
  75.                         {
  76.                             game_modules.push_back({ module_entry.th32ProcessID, std::string((const char*)module_entry.szModule), module_entry.modBaseAddr, module_entry.modBaseSize, module_entry.hModule });
  77.                         } while (Module32Next(hSnapshot, &module_entry));
  78.                     }
  79.  
  80.                     CloseHandle(hSnapshot);
  81.                 }
  82.             }
  83.             else
  84.             {
  85.                 CloseHandle(*ProcessHandle);
  86.                 *ProcessHandle = NULL;
  87.  
  88.                 return STATUS_ACCESS_DENIED;
  89.             }
  90.         }
  91.  
  92.         return STATUS_SUCCESS;
  93.     }
  94.  
  95.     NTSTATUS NTAPI NtQueryVirtualMemory_Hook(HANDLE ProcessHandle, LPBYTE BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID MemoryInformation, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength)
  96.     {
  97.         switch (MemoryInformationClass)
  98.         {
  99.         case MemoryBasicInformation:
  100.             memset(MemoryInformation, 0, MemoryInformationLength);
  101.  
  102.             if (ReturnLength != NULL)
  103.                 *ReturnLength = 0;
  104.  
  105.             return STATUS_SUCCESS;
  106.  
  107.         case MemoryWorkingSetInformation:
  108.         case MemoryMappedFilenameInformation:
  109.             memset(MemoryInformation, 0, MemoryInformationLength);
  110.  
  111.             if (ReturnLength != NULL)
  112.                 *ReturnLength = 0;
  113.  
  114.             return STATUS_ACCESS_VIOLATION;
  115.  
  116.         default:
  117.             break;
  118.         }
  119.  
  120.         return STATUS_SUCCESS;
  121.     }
  122.  
  123.     NTSTATUS NTAPI NtReadVirtualMemory_Game_Hook(HANDLE ProcessHandle, LPBYTE BaseAddress, PVOID Buffer, ULONG NumberOfBytesToRead, PULONG NumberOfBytesReaded)
  124.     {
  125.         std::vector<module_entry>::iterator iter = std::find_if(game_modules.begin(), game_modules.end(), [&](const module_entry& a) -> bool
  126.         {
  127.             return (BaseAddress >= a.base_address && BaseAddress < (a.base_address + a.base_size));
  128.         });
  129.  
  130.         if (iter != game_modules.end())
  131.         {
  132.             if (iter->base_address == game_base_address)
  133.             {
  134.                 std::string mapping_name = "Global\\NexonGameClient" + std::to_string(GetProcessId(ProcessHandle));
  135.                 HANDLE game_mapping = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, mapping_name.c_str());
  136.  
  137.                 if (game_mapping != NULL)
  138.                 {
  139.                     void* game_mapping_view = MapViewOfFile(game_mapping, FILE_MAP_READ, 0, 0, 0);
  140.  
  141.                     if (game_mapping_view != NULL)
  142.                     {
  143.                         memcpy(Buffer, reinterpret_cast<unsigned char*>(game_mapping_view) + (BaseAddress - iter->base_address), NumberOfBytesToRead);
  144.  
  145.                         if (NumberOfBytesReaded)
  146.                             *NumberOfBytesReaded = NumberOfBytesToRead;
  147.  
  148.                         UnmapViewOfFile(game_mapping_view);
  149.                         CloseHandle(game_mapping);
  150.                         return STATUS_SUCCESS;
  151.                     }
  152.                     else
  153.                     {
  154.                         CloseHandle(game_mapping);
  155.                     }
  156.                 }
  157.             }
  158.             else if (!strstr(iter->name.c_str(), "BlackCall.aes") && !strstr(iter->name.c_str(), "NGClient.aes"))
  159.             {
  160.                 return STATUS_ACCESS_DENIED;
  161.             }
  162.         }
  163.         else
  164.         {
  165.  
  166.         }
  167.  
  168.         return STATUS_SUCCESS;
  169.     }
  170.  
  171.     NTSTATUS NTAPI NtReadVirtualMemory_Hook(HANDLE ProcessHandle, LPBYTE BaseAddress, PVOID Buffer, ULONG NumberOfBytesToRead, PULONG NumberOfBytesReaded)
  172.     {
  173.         if (ProcessHandle == GetCurrentProcess())
  174.         {
  175.             return STATUS_ACCESS_DENIED;
  176.         }
  177.  
  178.         return NtReadVirtualMemory_Game_Hook(ProcessHandle, BaseAddress, Buffer, NumberOfBytesToRead, NumberOfBytesReaded);
  179.     }
  180.  
  181.     DWORD_PTR dwWow64Address = 0;
  182.     LPVOID lpJmpRealloc = nullptr;
  183.  
  184.     void __declspec(naked) NtOpenProcessHook()
  185.     {
  186.         __asm
  187.         {
  188.             push eax
  189.             push [ebp+0x14] // ClientId
  190.             push [ebp+0x10] // ObjectAttributes
  191.             push [ebp+0x0C] // DesiredAccess
  192.             push [ebp+0x08] // ProcessHandle
  193.             call NtOpenProcess_Hook
  194.             test eax, eax
  195.             jz NtOpenProcess_End
  196.             mov dword ptr [esp], eax
  197.             mov esp, ebp
  198.             pop ebp
  199.             ret 0x0010
  200.  
  201.             NtOpenProcess_End:
  202.             pop eax
  203.             jmp lpJmpRealloc
  204.         }
  205.     }
  206.  
  207.     void __declspec(naked) NtQueryVirtualMemoryHook()
  208.     {
  209.         __asm
  210.         {
  211.             push [ebp+0x1C] // ReturnLength
  212.             push [ebp+0x18] // MemoryInformationLength
  213.             push [ebp+0x14] // MemoryInformation
  214.             push [ebp+0x10] // MemoryInformationClass
  215.             push [ebp+0x0C] // BaseAddress
  216.             push [ebp+0x08] // ProcessHandle
  217.             call NtQueryVirtualMemory_Hook
  218.             mov esp, ebp
  219.             pop ebp
  220.             ret 0x0018
  221.         }
  222.     }
  223.  
  224.     void __declspec(naked) NtReadVirtualMemoryHook()
  225.     {
  226.         __asm
  227.         {
  228.             push eax
  229.             push [ebp+0x18] // NumberOfBytesReaded
  230.             push [ebp+0x14] // nSize
  231.             push [ebp+0x10] // lpBuffer
  232.             push [ebp+0x0C] // lpBaseAddress
  233.             push [ebp+0x08] // hProcess
  234.             call NtReadVirtualMemory_Hook
  235.             test eax, eax
  236.             jz NtReadVirtualMemory_End
  237.             mov dword ptr [esp], eax
  238.             mov esp, ebp
  239.             pop ebp
  240.             ret 0x0014
  241.  
  242.             NtReadVirtualMemory_End:
  243.             pop eax
  244.             jmp lpJmpRealloc
  245.         }
  246.     }
  247.  
  248.     const DWORD_PTR __declspec(naked) GetWow64Address()
  249.     {
  250.         __asm
  251.         {
  252.             mov eax, dword ptr fs: [0xC0]
  253.             ret
  254.         }
  255.     }
  256.  
  257.     void __declspec(naked) Wow64Trampoline()
  258.     {
  259.         __asm
  260.         {
  261.             cmp eax, 0x26
  262.             jz NtOpenProcessHook
  263.             cmp eax, 0x23
  264.             jz NtQueryVirtualMemoryHook
  265.             cmp eax, 0x3F
  266.             jz NtReadVirtualMemoryHook
  267.             jmp lpJmpRealloc
  268.         }
  269.     }
  270.  
  271.     const LPVOID CreateNewJump(const DWORD_PTR dwWow64Address)
  272.     {
  273.         lpJmpRealloc = VirtualAlloc(nullptr, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  274.  
  275.         (void)memcpy(lpJmpRealloc, (const void *)dwWow64Address, 9);
  276.  
  277.         return lpJmpRealloc;
  278.     }
  279.  
  280.     const void WriteJump(const DWORD_PTR dwWow64Address, const void *pBuffer, size_t ulSize)
  281.     {
  282.         DWORD dwOldProtect = 0;
  283.         (void)VirtualProtect((LPVOID)dwWow64Address, 4096, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  284.         (void)memcpy((void *)dwWow64Address, pBuffer, ulSize);
  285.         (void)VirtualProtect((LPVOID)dwWow64Address, 4096, dwOldProtect, &dwOldProtect);
  286.     }
  287.  
  288.     const void EnableWow64Redirect(const DWORD_PTR dwWow64Address, const LPVOID lpNewJumpLocation)
  289.     {
  290.         unsigned char trampolineBytes[] =
  291.         {
  292.             0x68, 0xDD, 0xCC, 0xBB, 0xAA,       // push 0xAABBCCDD
  293.             0xC3,                               // ret
  294.             0xCC, 0xCC, 0xCC                    // padding
  295.         };
  296.         memcpy(&trampolineBytes[1], &lpNewJumpLocation, sizeof(DWORD_PTR));
  297.  
  298.         WriteJump(dwWow64Address, trampolineBytes, sizeof(trampolineBytes));
  299.     }
  300.  
  301.     void Wow32Reserved_Hook()
  302.     {
  303.         dwWow64Address = GetWow64Address();
  304.  
  305.         const LPVOID lpNewJumpLocation = CreateNewJump(dwWow64Address);
  306.         EnableWow64Redirect(dwWow64Address, (LPVOID)Wow64Trampoline);
  307.     }
  308.  
  309.     bool Hook_GetCommandLineW(bool enable)
  310.     {
  311.         static decltype(&GetCommandLineW) _GetCommandLineW = decltype(&GetCommandLineW)(GetProcAddress(GetModuleHandleA("Kernel32"), "GetCommandLineW"));
  312.  
  313.         decltype(&GetCommandLineW) GetCommandLineW_Hook = []() -> LPWSTR
  314.         {
  315.             static bool is_detoured = false;
  316.  
  317.             if (!is_detoured)
  318.             {
  319.                 Wow32Reserved_Hook();
  320.                 is_detoured = true;
  321.             }
  322.  
  323.             return _GetCommandLineW();
  324.         };
  325.  
  326.         return DetourFunction(enable, reinterpret_cast<void**>(&_GetCommandLineW), GetCommandLineW_Hook);
  327.     }
  328.  
  329.     bool Hook_CopyFileW(bool enable)
  330.     {
  331.         static decltype(&CopyFileW) _CopyFileW = &CopyFileW;
  332.  
  333.         decltype(&CopyFileW) CopyFileW_hook = [](LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists) -> BOOL
  334.         {
  335.             LPCWSTR lpExistingFileNameEnd = lpExistingFileName + wcslen(lpExistingFileName);
  336.  
  337.             if (!lstrcmpiW(lpExistingFileNameEnd - wcslen(L"ntdll.dll"), L"ntdll.dll") || !lstrcmpiW(lpExistingFileNameEnd - wcslen(L"kernelbase.dll"), L"kernelbase.dll"))
  338.             {
  339.                 LPCWSTR lpNewFileNameEnd = lpNewFileName + wcslen(lpNewFileName);
  340.                 return FALSE;
  341.             }
  342.  
  343.             return _CopyFileW(lpExistingFileName, lpNewFileName, bFailIfExists);
  344.         };
  345.  
  346.         return DetourFunction(enable, reinterpret_cast<void**>(&_CopyFileW), CopyFileW_hook);
  347.     }
  348. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement