Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace BlackCipher
- {
- #define STATUS_SUCCESS ((NTSTATUS)0x00000000)
- #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022)
- typedef struct _CLIENT_ID
- {
- ULONG UniqueProcess;
- ULONG UniqueThread;
- } CLIENT_ID, *PCLIENT_ID;
- typedef enum _MEMORY_INFORMATION_CLASS
- {
- MemoryBasicInformation,
- MemoryWorkingSetInformation,
- MemoryMappedFilenameInformation,
- MemoryRegionInformation,
- MemoryWorkingSetExInformation,
- MemorySharedCommitInformation,
- MemoryImageInformation,
- MemoryRegionInformationEx,
- MemoryPrivilegedBasicInformation
- } MEMORY_INFORMATION_CLASS;
- typedef struct _PROCESS_BASIC_INFORMATION {
- ULONG ExitStatus;
- PPEB PebBaseAddress;
- ULONG AffinityMask;
- ULONG BasePriority;
- ULONG UniqueProcessId;
- ULONG ParentUniqueProcessId;
- } PROCESS_BASIC_INFORMATION;
- typedef struct _module_entry
- {
- unsigned int id;
- std::string const name;
- unsigned char* base_address;
- unsigned int base_size;
- HMODULE handle;
- } module_entry;
- unsigned char* game_base_address = 0;
- std::vector<module_entry> game_modules;
- NTSTATUS NTAPI NtOpenProcess_Hook(PHANDLE ProcessHandle, ACCESS_MASK AccessMask, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
- {
- if (ClientId->UniqueProcess != NULL)
- {
- PROCESS_BASIC_INFORMATION pbi;
- memset(&pbi, 0, sizeof(PROCESS_BASIC_INFORMATION));
- ULONG return_length = 0;
- if ((NtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), &return_length) == STATUS_SUCCESS) &&
- (pbi.ParentUniqueProcessId == ClientId->UniqueProcess))
- {
- game_base_address = reinterpret_cast<unsigned char*>(pbi.PebBaseAddress->Reserved3[1]);
- HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ClientId->UniqueProcess);
- if (hSnapshot != INVALID_HANDLE_VALUE)
- {
- MODULEENTRY32 module_entry;
- memset(&module_entry, 0, sizeof(MODULEENTRY32));
- module_entry.dwSize = sizeof(MODULEENTRY32);
- if (Module32First(hSnapshot, &module_entry))
- {
- game_modules.clear();
- do
- {
- game_modules.push_back({ module_entry.th32ProcessID, std::string((const char*)module_entry.szModule), module_entry.modBaseAddr, module_entry.modBaseSize, module_entry.hModule });
- } while (Module32Next(hSnapshot, &module_entry));
- }
- CloseHandle(hSnapshot);
- }
- }
- else
- {
- CloseHandle(*ProcessHandle);
- *ProcessHandle = NULL;
- return STATUS_ACCESS_DENIED;
- }
- }
- return STATUS_SUCCESS;
- }
- NTSTATUS NTAPI NtQueryVirtualMemory_Hook(HANDLE ProcessHandle, LPBYTE BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID MemoryInformation, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength)
- {
- switch (MemoryInformationClass)
- {
- case MemoryBasicInformation:
- memset(MemoryInformation, 0, MemoryInformationLength);
- if (ReturnLength != NULL)
- *ReturnLength = 0;
- return STATUS_SUCCESS;
- case MemoryWorkingSetInformation:
- case MemoryMappedFilenameInformation:
- memset(MemoryInformation, 0, MemoryInformationLength);
- if (ReturnLength != NULL)
- *ReturnLength = 0;
- return STATUS_ACCESS_VIOLATION;
- default:
- break;
- }
- return STATUS_SUCCESS;
- }
- NTSTATUS NTAPI NtReadVirtualMemory_Game_Hook(HANDLE ProcessHandle, LPBYTE BaseAddress, PVOID Buffer, ULONG NumberOfBytesToRead, PULONG NumberOfBytesReaded)
- {
- std::vector<module_entry>::iterator iter = std::find_if(game_modules.begin(), game_modules.end(), [&](const module_entry& a) -> bool
- {
- return (BaseAddress >= a.base_address && BaseAddress < (a.base_address + a.base_size));
- });
- if (iter != game_modules.end())
- {
- if (iter->base_address == game_base_address)
- {
- std::string mapping_name = "Global\\NexonGameClient" + std::to_string(GetProcessId(ProcessHandle));
- HANDLE game_mapping = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, mapping_name.c_str());
- if (game_mapping != NULL)
- {
- void* game_mapping_view = MapViewOfFile(game_mapping, FILE_MAP_READ, 0, 0, 0);
- if (game_mapping_view != NULL)
- {
- memcpy(Buffer, reinterpret_cast<unsigned char*>(game_mapping_view) + (BaseAddress - iter->base_address), NumberOfBytesToRead);
- if (NumberOfBytesReaded)
- *NumberOfBytesReaded = NumberOfBytesToRead;
- UnmapViewOfFile(game_mapping_view);
- CloseHandle(game_mapping);
- return STATUS_SUCCESS;
- }
- else
- {
- CloseHandle(game_mapping);
- }
- }
- }
- else if (!strstr(iter->name.c_str(), "BlackCall.aes") && !strstr(iter->name.c_str(), "NGClient.aes"))
- {
- return STATUS_ACCESS_DENIED;
- }
- }
- else
- {
- }
- return STATUS_SUCCESS;
- }
- NTSTATUS NTAPI NtReadVirtualMemory_Hook(HANDLE ProcessHandle, LPBYTE BaseAddress, PVOID Buffer, ULONG NumberOfBytesToRead, PULONG NumberOfBytesReaded)
- {
- if (ProcessHandle == GetCurrentProcess())
- {
- return STATUS_ACCESS_DENIED;
- }
- return NtReadVirtualMemory_Game_Hook(ProcessHandle, BaseAddress, Buffer, NumberOfBytesToRead, NumberOfBytesReaded);
- }
- DWORD_PTR dwWow64Address = 0;
- LPVOID lpJmpRealloc = nullptr;
- void __declspec(naked) NtOpenProcessHook()
- {
- __asm
- {
- push eax
- push [ebp+0x14] // ClientId
- push [ebp+0x10] // ObjectAttributes
- push [ebp+0x0C] // DesiredAccess
- push [ebp+0x08] // ProcessHandle
- call NtOpenProcess_Hook
- test eax, eax
- jz NtOpenProcess_End
- mov dword ptr [esp], eax
- mov esp, ebp
- pop ebp
- ret 0x0010
- NtOpenProcess_End:
- pop eax
- jmp lpJmpRealloc
- }
- }
- void __declspec(naked) NtQueryVirtualMemoryHook()
- {
- __asm
- {
- push [ebp+0x1C] // ReturnLength
- push [ebp+0x18] // MemoryInformationLength
- push [ebp+0x14] // MemoryInformation
- push [ebp+0x10] // MemoryInformationClass
- push [ebp+0x0C] // BaseAddress
- push [ebp+0x08] // ProcessHandle
- call NtQueryVirtualMemory_Hook
- mov esp, ebp
- pop ebp
- ret 0x0018
- }
- }
- void __declspec(naked) NtReadVirtualMemoryHook()
- {
- __asm
- {
- push eax
- push [ebp+0x18] // NumberOfBytesReaded
- push [ebp+0x14] // nSize
- push [ebp+0x10] // lpBuffer
- push [ebp+0x0C] // lpBaseAddress
- push [ebp+0x08] // hProcess
- call NtReadVirtualMemory_Hook
- test eax, eax
- jz NtReadVirtualMemory_End
- mov dword ptr [esp], eax
- mov esp, ebp
- pop ebp
- ret 0x0014
- NtReadVirtualMemory_End:
- pop eax
- jmp lpJmpRealloc
- }
- }
- const DWORD_PTR __declspec(naked) GetWow64Address()
- {
- __asm
- {
- mov eax, dword ptr fs: [0xC0]
- ret
- }
- }
- void __declspec(naked) Wow64Trampoline()
- {
- __asm
- {
- cmp eax, 0x26
- jz NtOpenProcessHook
- cmp eax, 0x23
- jz NtQueryVirtualMemoryHook
- cmp eax, 0x3F
- jz NtReadVirtualMemoryHook
- jmp lpJmpRealloc
- }
- }
- const LPVOID CreateNewJump(const DWORD_PTR dwWow64Address)
- {
- lpJmpRealloc = VirtualAlloc(nullptr, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- (void)memcpy(lpJmpRealloc, (const void *)dwWow64Address, 9);
- return lpJmpRealloc;
- }
- const void WriteJump(const DWORD_PTR dwWow64Address, const void *pBuffer, size_t ulSize)
- {
- DWORD dwOldProtect = 0;
- (void)VirtualProtect((LPVOID)dwWow64Address, 4096, PAGE_EXECUTE_READWRITE, &dwOldProtect);
- (void)memcpy((void *)dwWow64Address, pBuffer, ulSize);
- (void)VirtualProtect((LPVOID)dwWow64Address, 4096, dwOldProtect, &dwOldProtect);
- }
- const void EnableWow64Redirect(const DWORD_PTR dwWow64Address, const LPVOID lpNewJumpLocation)
- {
- unsigned char trampolineBytes[] =
- {
- 0x68, 0xDD, 0xCC, 0xBB, 0xAA, // push 0xAABBCCDD
- 0xC3, // ret
- 0xCC, 0xCC, 0xCC // padding
- };
- memcpy(&trampolineBytes[1], &lpNewJumpLocation, sizeof(DWORD_PTR));
- WriteJump(dwWow64Address, trampolineBytes, sizeof(trampolineBytes));
- }
- void Wow32Reserved_Hook()
- {
- dwWow64Address = GetWow64Address();
- const LPVOID lpNewJumpLocation = CreateNewJump(dwWow64Address);
- EnableWow64Redirect(dwWow64Address, (LPVOID)Wow64Trampoline);
- }
- bool Hook_GetCommandLineW(bool enable)
- {
- static decltype(&GetCommandLineW) _GetCommandLineW = decltype(&GetCommandLineW)(GetProcAddress(GetModuleHandleA("Kernel32"), "GetCommandLineW"));
- decltype(&GetCommandLineW) GetCommandLineW_Hook = []() -> LPWSTR
- {
- static bool is_detoured = false;
- if (!is_detoured)
- {
- Wow32Reserved_Hook();
- is_detoured = true;
- }
- return _GetCommandLineW();
- };
- return DetourFunction(enable, reinterpret_cast<void**>(&_GetCommandLineW), GetCommandLineW_Hook);
- }
- bool Hook_CopyFileW(bool enable)
- {
- static decltype(&CopyFileW) _CopyFileW = &CopyFileW;
- decltype(&CopyFileW) CopyFileW_hook = [](LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists) -> BOOL
- {
- LPCWSTR lpExistingFileNameEnd = lpExistingFileName + wcslen(lpExistingFileName);
- if (!lstrcmpiW(lpExistingFileNameEnd - wcslen(L"ntdll.dll"), L"ntdll.dll") || !lstrcmpiW(lpExistingFileNameEnd - wcslen(L"kernelbase.dll"), L"kernelbase.dll"))
- {
- LPCWSTR lpNewFileNameEnd = lpNewFileName + wcslen(lpNewFileName);
- return FALSE;
- }
- return _CopyFileW(lpExistingFileName, lpNewFileName, bFailIfExists);
- };
- return DetourFunction(enable, reinterpret_cast<void**>(&_CopyFileW), CopyFileW_hook);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement