çç±ãå°ããŸããïŒ
32ãããã¢ããªã±ãŒã·ã§ã³ã®å ŽåãAWEã䜿çšããªããš2ã3ã®ã¬ãã€ããè¶ ããããšã¯ã§ããŸããããããã§ãèªåã®ãªãœãŒã¹ãå¶åŸ¡ããããšãæãŸããã§ãã ããããããããªããŠããåã«ãããææ¡ããããã«...
以åã®èšäºã§ããããã°äžã®ã¢ããªã±ãŒã·ã§ã³ã®ã¡ã¢ãªãå€æŽããããããã¬ãŒã®åäœã«ã€ããŠèª¬æããŸããã ãã®èšäºã¯ããã®è³æã®ç¶ãã§ãã ãããŠãããã¯ãããã¬ãšã¯é¢ä¿ãããŸãããããããã°ããã»ã¹ã¯æãçŽæ¥çã§ã...
ããã°ã©ããŒããããã°äžã«ã¡ã¢ãªãæäœããæ¹æ³ãèŠãŠã¿ãŸãããïŒç¹ã«ããµãŒãããŒãã£ã®ã¢ããªã±ãŒã·ã§ã³ããããã°ãããšããèšãæãããšããªããŒã¹ãããšãïŒã
1.ååãšããŠãæãé »ç¹ã«è¡ãããæäœã¯ãã¢ããªã±ãŒã·ã§ã³ã¡ã¢ãªå ã®å€ãæ€çŽ¢ããããšã§ããæ®å¿µãªããããã®æ©èœã¯äœããã®çç±ã§Delphiãããã¬ãŒã§ã¯æäŸãããŸããïŒå®éãMS VC ++ãªã©ïŒã
2.ã·ã¹ãã æ§é ïŒPEB / TEB / SEHChain / Unwind / PEãã¡ã€ã«ã®ãã£ã¬ã¯ããªãªã©ïŒã®å€æŽã¯ãæ§é ã®ãã£ãŒã«ããå æããèªã¿åãå¯èœãªåœ¢åŒã§è¡šç€ºãããã¢ãã¬ã¹ã«ãããã³ã°è§£é€ããããšãã¯ããã«ç°¡åã«ãªããŸãã
3.ããã»ã¹ã¡ã¢ãªã®å€æŽã®è¿œè·¡ïŒã»ãšãã©ã®æ©èœã¯æäŸããããäžè¬çãªãããã¬ãŒã®ãã©ã°ã€ã³ãšããŠå®è£ ãããŸãïŒã å®éãå¿ èŠãªããŒã¿å€æŽãããã§è¡ãããŠãããã©ãããç解ããããã«ãã¡ã¢ãªã«ãŒãã®2ã€ã®ç»åãæ¯èŒããã ãã§ååãªã®ã«ããªãéã¿ããã£ãè²ã«ãã¬ãŒã¹ããã®ã§ããããã
ã¯ããå®éãå€ãã®ãŠãŒã¹ã±ãŒã¹ããããŸãã
ãã ããæè©ããªãå Žåããããã°ã«äœ¿çšã§ããããã»ã¹ã¡ã¢ãªã«ãŒãã«é¢ããå€å°ã®æ£æ°ãªæ å ±ã衚瀺ãããŠãŒãã£ãªãã£ã¯ã»ãšãã©ãããŸããã
æã䟿å©ãªå®è£ ã¯OllyDebug 2ããã§ãããæ®å¿µãªããã64ãããã§ããŒã¿ã衚瀺ããŸããïŒãŸã åŸ ã£ãŠããŸãïŒã
Mark Russinovichã®VMMapã¯ãMicrosoftã«ãã£ãŠçœ²åãããçŽç²ã«è£ 食çãªããããã£ãå®è¡ããŸããã衚瀺ãããããŒã¿ãå®éã«é©çšããããšã¯å°é£ã§ãã
ProcessHackerã¯åªããããŒã«ã§ããããã®äœæè ã¯ã¡ã¢ãªããŒã¿ã®åºåãæäœããã¿ã¹ã¯ãèšå®ããŠããªãã£ãããã圌ã衚瀺ããæ å ±ã¯äžè¬çã«æãåçŽã§ãããšèšããŸãã
ãŸããç§ã¯IDA Proã®ã¡ã¢ãªãŒã«ãŒããé·å¹Žäœ¿ã£ãŠããã®ã«æ £ããŠããŸããïŒç§ã¯å¿«é©ã§ã¯ãããŸããïŒ:)
ãã ããæå¹ãªã¡ã¢ãªã«ãŒãã圹ã«ç«ã€ã®ã¯ããããã°ã ãã§ã¯ãããŸããã ç¹ã«ãä»äºã§ã¯ãã¡ã¢ãªã«ãŒãã䜿çšããŠããŠãŒã¶ãŒããéä¿¡ããããšã©ãŒãã°ãšéèŠãªã»ã¯ã·ã§ã³ã®ãã³ããåæããããã«é¢ããæ å ±ãEurekaLogã«çµ±åããŸãã
ãã®èšäºã§ã¯ãããã»ã¹ã¡ã¢ãªã«ãŒããåå¥ã«äœæãããããã°ãšåæã«å¿ èŠãªããŒã¿ã«é¢ããæ å ±ããã®äžã«é 眮ããæ¹æ³ã段éçã«èª¬æããŸãã
1.å©çšå¯èœãªå°åã®ãªã¹ããååŸãã
ãã¹ãŠã®ä»®æ³ããã»ã¹ã¡ã¢ãªã¯ããŒãžã®åœ¢åŒã§è¡šç€ºãããŸãã
ããŒãžã¯å°ããïŒ4096ãã€ãïŒã倧ããã§ãã ïŒ MSDNã§è©³çŽ°ãã芧ãã ãã ïŒ
ã»ãšãã©ã®å Žåãé£ç¶ããããŒãžã«ã¯åãå±æ§ããããŸãã
å°åãšã¯äœã§ããïŒ
倧ãŸãã«ïŒ MSDNã«åºã¥ã㊠ïŒVirtualQueryé¢æ°ã«æž¡ãããã¢ãã¬ã¹ã§å§ãŸãåãå±æ§ãæã€ãã¹ãŠã®ããŒãžã®ã»ããã§ãã
æãç°¡åãªåœ¢åŒã§ã¯ã次ã®ã³ãŒãã䜿çšããŠããã»ã¹ã®é åã®ãªã¹ããååŸã§ããŸãã
program Project1; {$APPTYPE CONSOLE} {$R *.res} uses Windows, SysUtils; var MBI: TMemoryBasicInformation; dwLength: NativeUInt; Address: PByte; begin Address := nil; dwLength := SizeOf(TMemoryBasicInformation); while VirtualQuery(Address, MBI, dwLength) <> 0 do begin Writeln( 'AllocationBase: ', IntToHex(NativeUInt(MBI.AllocationBase), 8), ', BaseAddress: ', IntToHex(NativeUInt(MBI.BaseAddress), 8), ', RegionSize: ', MBI.RegionSize); Inc(Address, MBI.RegionSize); end; Readln; end.
ããšãã°ãæåã«ã¢ãã¬ã¹nilãæåã®ãã©ã¡ãŒã¿ãŒãšããŠæž¡ããŸããã é¢æ°ãåŒã³åºããåŸãMBIå€æ°ã¯æ¬¡ã®å€ãåããŸãã
- BaseAddress = nil
- AllocationBase = nil
- AllocationProtect = 0
- RegionSize = 10000ãã«
- å·= 10,000ãã«
- ä¿è·= 1
- Type_9 = 0
é åã®ãµã€ãºã¯10,000ãã«ïŒ64 kbïŒã§ããããã¯ãç¶æ ïŒStateïŒãMEM_FREEïŒ10,000ãã«ïŒã§ãããã»ãã¥ãªãã£å±æ§PAGE_NO_ACCESSïŒ1ïŒãProtectãã©ã¡ãŒã¿ãŒã§èšå®ãããŠããã¢ãã¬ã¹0ããå§ãŸã16ããŒãžã«çžåœããŸãã
次ã®ããã«ã³ãŒããæžãçŽããšïŒ
function ExtractAccessString(const Value: DWORD): string; const PAGE_WRITECOMBINE = $400; begin Result := 'Unknown access'; if (Value and PAGE_EXECUTE) = PAGE_EXECUTE then Result := 'E'; if (Value and PAGE_EXECUTE_READ) = PAGE_EXECUTE_READ then Result := 'RE'; if (Value and PAGE_EXECUTE_READWRITE) = PAGE_EXECUTE_READWRITE then Result := 'RWE'; if (Value and PAGE_EXECUTE_WRITECOPY) = PAGE_EXECUTE_WRITECOPY then Result := 'RE, Write copy'; if (Value and PAGE_NOACCESS) = PAGE_NOACCESS then Result := 'No access'; if (Value and PAGE_READONLY) = PAGE_READONLY then Result := 'R'; if (Value and PAGE_READWRITE) = PAGE_READWRITE then Result := 'RW'; if (Value and PAGE_WRITECOPY) = PAGE_WRITECOPY then Result := 'Write copy'; if (Value and PAGE_GUARD) = PAGE_GUARD then Result := Result + ', Guarded'; if (Value and PAGE_NOCACHE) = PAGE_NOCACHE then Result := Result + ', No cache'; if (Value and PAGE_WRITECOMBINE) = PAGE_WRITECOMBINE then Result := Result + ', Write Combine'; end; function ExtractRegionTypeString(Value: TMemoryBasicInformation): string; begin Result := ''; case Value.State of MEM_FREE: Result := 'Free'; MEM_RESERVE: Result := 'Reserved'; MEM_COMMIT: case Value.Type_9 of MEM_IMAGE: Result := 'Image'; MEM_MAPPED: Result := 'Mapped'; MEM_PRIVATE: Result := 'Private'; end; end; Result := Result + ', ' + ExtractAccessString(Value.Protect); end; var MBI: TMemoryBasicInformation; dwLength: NativeUInt; Address: PByte; begin Address := nil; dwLength := SizeOf(TMemoryBasicInformation); while VirtualQuery(Address, MBI, dwLength) <> 0 do begin Writeln( 'AllocationBase: ', IntToHex(NativeUInt(MBI.AllocationBase), 8), ', BaseAddress: ', IntToHex(NativeUInt(MBI.BaseAddress), 8), ' - ', ExtractRegionTypeString(MBI)); Inc(Address, MBI.RegionSize); end;
...次ã«ãVirtualAllocé¢æ°ã䜿çšããŠå°ååã®ååãæ確ã«ç¢ºèªã§ããŸãã
ããšãã°ã2çªç®ãš3çªç®ã®é åã®ã¢ã¯ã»ã¹å±æ§ïŒèªã¿åãã¬ã³ãŒãïŒã¯åãã§ãããAllocationBaseãç°ãªããŸãã AllocationBaseã¯ãVirtualAllocãä»ããŠã¡ã¢ãªãå²ãåœãŠããšãã«ããŒãžã«å²ãåœãŠããããããå¥ã®é åã§ããŒãžãçµåããŸãã
2.ãããŒã«é¢ããããŒã¿ãåéããŸã
åãåã£ãé åã«ãããããæ ŒçŽãããã®ã«é¢ããæ å ±ãèšå ¥ãå§ããæãæ¥ãŸããããããŠããããŒïŒã¹ã¬ããâ奜ããªãã®ã¯äœã§ãïŒããå§ããŸãã
ã¹ã¬ããã®ãªã¹ããååŸããããã®ã³ãŒãã¯ç°¡åã§ã-CreateToolhelp32Snapshotã䜿çšã
const THREAD_GET_CONTEXT = 8; THREAD_SUSPEND_RESUME = 2; THREAD_QUERY_INFORMATION = $40; ThreadBasicInformation = 0; ThreadQuerySetWin32StartAddress = 9; STATUS_SUCCESS = 0; var hSnap, hThread: THandle; ThreadEntry: TThreadEntry32; TBI: TThreadBasicInformation; TIB: NT_TIB; lpNumberOfBytesRead: NativeUInt; ThreadStartAddress: Pointer; begin // hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetCurrentProcessId); if hSnap <> INVALID_HANDLE_VALUE then try ThreadEntry.dwSize := SizeOf(TThreadEntry32); if Thread32First(hSnap, ThreadEntry) then repeat if ThreadEntry.th32OwnerProcessID <> GetCurrentProcessId then Continue; Writeln('ThreadID: ', ThreadEntry.th32ThreadID); // hThread := OpenThread(THREAD_GET_CONTEXT or THREAD_SUSPEND_RESUME or THREAD_QUERY_INFORMATION, False, ThreadEntry.th32ThreadID); if hThread <> 0 then try // ThreadProc() if NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, @ThreadStartAddress, SizeOf(ThreadStartAddress), nil) = STATUS_SUCCESS then Writeln('ThreadProcAddr: ', IntToHex(NativeUInt(ThreadStartAddress), 1)); // if NtQueryInformationThread(hThread, ThreadBasicInformation, @TBI, SizeOf(TThreadBasicInformation), nil) = STATUS_SUCCESS then begin Writeln('Thread Environment Block (TEB) Addr: ', IntToHex(NativeUInt(TBI.TebBaseAddress), 1)); // // TIB (Thread Information Block) if ReadProcessMemory(GetCurrentProcess, TBI.TebBaseAddress, @TIB, SizeOf(NT_TIB), lpNumberOfBytesRead) then begin Writeln('Thread StackBase Addr: ', IntToHex(NativeUInt(TIB.StackBase), 1)); Writeln('Thread StackLimit Addr: ', IntToHex(NativeUInt(TIB.StackLimit), 1)); end; end; finally CloseHandle(hThread); end; until not Thread32Next(hSnap, ThreadEntry); finally CloseHandle(hSnap); end; Readln; end.
æé ïŒ
- CreateToolhelp32Snapshot / Thread32First / Thread32Nextã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ããã¢ã¯ãã£ããªã¹ã¬ããã®ãªã¹ããååŸããŸãã
- 詳现ã«ã€ããŠã¯ãOpenThreadãåŒã³åºããŠååŸããã¹ã¬ãããžã®ãã³ãã«ãå¿ èŠã§ãã
- NtQueryInformationThreadã䜿çšããŠãäœæ¥ãéå§ããã¹ã¬ããããã·ãŒãžã£ã®ã¢ãã¬ã¹ãšãã¹ã¬ããã«é¢ããåºæ¬æ å ±ãTThreadBasicInformationæ§é ã®åœ¢åŒã§ååŸããŸãã
- ãã®æ§é ã®ãã¡ãé¢å¿ãããã®ã¯1ã€ã®ãã£ãŒã«ãã ãã§ã-TebBaseAddressã«ã¯ãã¹ããªãŒã ç°å¢ãããã¯ã®ã¢ãã¬ã¹ããããã TEBïŒã¹ã¬ããç°å¢ãããã¯ïŒã
- ReadProcessMemoryãåŒã³åºãããšã«ããïŒããã¯ã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠåé·ã§ããïŒãTEBã¢ãã¬ã¹ã®ããŒã¿ãã€ãŸããã®æåã®ãã©ã¡ãŒã¿ãŒã§ããNT_TIBæ§é äœãèªã¿åããŸãã
NT_TIB宣èšã¯æ¬¡ã®ããã«ãªããŸãã
PNT_TIB = ^_NT_TIB; _NT_TIB = record ExceptionList: Pointer; StackBase, StackLimit, SubSystemTib: Pointer; case Integer of 0: ( FiberData: Pointer ); 1: ( Version: ULONG; ArbitraryUserPointer: Pointer; Self: PNT_TIB; ) end; NT_TIB = _NT_TIB; PPNT_TIB = ^PNT_TIB;
ãŸãããŸãã¯ãã®ããã«ãããå°ã説æãããšïŒ
- ExceptionList-32ãããããã»ã¹ã§ã¯ãçŸåšã®SEHãã¬ãŒã ã®ã¢ãã¬ã¹ãžã®ãã€ã³ã¿ãŒïŒEXCEPTION_REGISTRATIONæ§é äœïŒã ãã®æ å ±ã«åºã¥ããŠãSEHãã¬ãŒã ã®ãã§ãŒã³å šäœã解ããŸãã
- TEBã32ãããã¢ããªã±ãŒã·ã§ã³ã§å®è¡ãããŠãã64ãããã¹ããªãŒã ã«å±ããŠããå Žåããã®ãã£ãŒã«ãã¯ãã®32ãããã¢ããã°ã®ExceptionListãã£ãŒã«ããæããŸãã
- 64ãããããã»ã¹ã§ã¯ããã®ãã£ãŒã«ãã¯åžžã«ç¡å¹ã«ãªããŸãã 64ãããã®å ŽåãSEHã¡ã«ããºã ã®ä»£ããã«ãããã«ç°ãªãã¡ã«ããºã ãæ©èœããŸãã
- StackBase-ã¹ã¿ãã¯ã®ããŒã¹ã StackLimitã®æ¹åã«ã¹ã¿ãã¯ãæé·ãå§ããã¢ãã¬ã¹ã
- StackLimitã¯çŸåšã®ã¹ã¿ãã¯ã®ãããã§ãã
- ArbitraryUserPointerã¯ãç¡æã®TLSã¹ãããã®ãããªãã®ã§ãã 倧ãŸãã«èšã£ãŠãããã°ã©ããèªåã®ããŒãºã«åãããŠå€ãä»»æã«å€æŽã§ããã¹ããªãŒã ã«å±ããå€æ°ã
- èªå·±-TEBã¢ãã¬ã¹ãå«ããã©ã¡ãŒã¿ãŒïŒã€ãŸããããèªäœïŒ
æ®ãã®ãã£ãŒã«ãã¯äžèŠã§ãã
ãŸããããããã©ã®ããã«å¿ èŠã§ã¯ãããŸãããïŒ
ãã¡ããå¿ èŠã§ãããä»ã®ãšãããããã¯ç§ãã¡ã«ãšã£ãŠåé·ã§ãã
ãšããã§ããã®æ§é ã®å°ãæ代é ãã®èª¬æãèŠãããšãã§ãããªã³ã¯ã¯ããã«ãããŸãïŒ ã¹ã¬ããç°å¢ããã㯠ã
ãã®ã³ãŒãã¯ã次ã®å³ã衚瀺ããŸãã
ãããŠãããã¯VMMapã§èŠãããã§ãããã
ãã®å³ã¯ãVMMapãTEBã«é¢ããæ å ±ã衚瀺ããªãã£ãããšã瀺ããŠããŸãã
ãšããã§ãäžèšã®ã³ãŒãã®äžéšã®é¢æ°ãšæ§é äœã¯ãæšæºã®DelphiãœãŒã¹ã§å®£èšãããŠããŸããããããã®å®£èšã¯ããã®èšäºã®äžéšã§ãããã¢äŸã§ç¢ºèªã§ããŸãã ããããããã¯MSDNã«ææžåãããŠããªããšããæå³ã§ã¯ãããŸãã:)
ã¹ããªãŒã ã®TEBã䜿çšããå ŽåãToolHelp32.dllé¢æ°ã䜿çšããå¿ èŠã¯ãªããFSã»ã°ã¡ã³ãã¬ãžã¹ã¿ïŒãŸãã¯x64ã®å Žåã¯GSïŒã䜿çšããå¿ èŠããããããã³ãŒãã¯å€§å¹ ã«ç°¡çŽ åãããŸãã
ããšãã°ããã®ãããªé¢æ°ã¯ãTEBã¢ãã¬ã¹ãååŸããããã«ããèŠã€ãããŸãã
function GetCurrentTEB: NativeUInt; asm {$IFDEF WIN64} // mov RAX, qword ptr GS:[30h] // , 64- DB $65, $48, $8B, $04, $25, $30, 0, 0, 0 // , mov RAX, qword ptr GS:[abs $30] {$ELSE} mov EAX, FS:[18h] {$ENDIF} end;
ãã®å ŽåãTEBæ§é äœã®ãã©ã¡ãŒã¿ãŒNtTIB.Selfã«ã¢ã¯ã»ã¹ããŸãããã®ãã©ã¡ãŒã¿ãŒã¯ãå é ãããªãã»ãã0x18ïŒ64ãããTEBã®å Žåã¯0x30ïŒã«ãããŸãã
ããããç§ãã¡ã¯ç¶ããŸã...
åä¿¡ããããŒã¿ã®äžéšã§ãããããã¯ç§ãã¡ãå ¥æã§ãããã¹ãŠã®æ å ±ã§ã¯ãããŸããã
åã¹ã¬ããã®ã¹ã¿ãã¯äžã«ã¯ãtry..finally / exceptãããã¯ãå ¥åãããšèªåçã«çæãããSEHãã¬ãŒã ãšãããã·ãŒãžã£ã³ãŒã«ã®ã¹ã¿ãã¯ããããŸãã ãããã®ããŒã¿ãæå ã«çšæããŠãå°åãåç §ããŠããèŠèŠçãªåœ¢åŒã§è¡šç€ºãããšããã§ãããã
ããã§ã¯ããã®ãããªç°¡åãªæé ã§SEHãã¬ãŒã ã®ããã¢ãŒã·ã§ã³ãæ±ããŸãã
procedure GetThreadSEHFrames(InitialAddr: Pointer); type EXCEPTION_REGISTRATION = record prev, handler: Pointer; end; var ER: EXCEPTION_REGISTRATION; lpNumberOfBytesRead: NativeUInt; begin while ReadProcessMemory(GetCurrentProcess, InitialAddr, @ER, SizeOf(EXCEPTION_REGISTRATION), lpNumberOfBytesRead) do begin Writeln('SEH Frame at Addr: ', IntToHex(NativeUInt(InitialAddr), 1), ', handler at addr: ', IntToHex(NativeUInt(ER.handler), 1)); InitialAddr := ER.prev; if DWORD(InitialAddr) <= 0 then Break; end; end;
ãã©ã¡ãŒã¿ãšããŠæåã®EXCEPTION_REGISTRATIONæ§é äœãæãTEB.TIB.ExceptionListå€ãåãåããšããããã®æ§é äœã®ãã§ãŒã³ã«æ²¿ã£ãŠå®è¡ããããã®æ§é äœã®prevå€ã«ã¬ã€ããããåã®EXCEPTION_REGISTRATIONæ§é äœã®ã¢ãã¬ã¹ãå«ãŸããŸãã ãŸããçªç¶çºçããå Žåããã³ãã©ãã©ã¡ãŒã¿ã«ã¯äŸå€ãã³ãã©ã®ã¢ãã¬ã¹ãå«ãŸããŸãã
次ã®ããã«ãªããŸãã
ããŠãCallStackã¯æ¬¡ã®æé ãåãåããŸãïŒ
procedure GetThreadCallStack(hThread: THandle); var StackFrame: TStackFrame; ThreadContext: PContext; MachineType: DWORD; begin // ThreadContext , VirtualAlloc // // ERROR_NOACCESS (998) ThreadContext := VirtualAlloc(nil, SizeOf(TContext), MEM_COMMIT, PAGE_READWRITE); try ThreadContext^.ContextFlags := CONTEXT_FULL; if not GetThreadContext(hThread, ThreadContext^) then Exit; ZeroMemory(@StackFrame, SizeOf(TStackFrame)); StackFrame.AddrPC.Mode := AddrModeFlat; StackFrame.AddrStack.Mode := AddrModeFlat; StackFrame.AddrFrame.Mode := AddrModeFlat; StackFrame.AddrPC.Offset := ThreadContext.Eip; StackFrame.AddrStack.Offset := ThreadContext.Esp; StackFrame.AddrFrame.Offset := ThreadContext.Ebp; MachineType := IMAGE_FILE_MACHINE_I386; while True do begin if not StackWalk(MachineType, GetCurrentProcess, hThread, @StackFrame, ThreadContext, nil, nil, nil, nil) then Break; if StackFrame.AddrPC.Offset <= 0 then Break; Writeln('CallStack Frame Addr: ', IntToHex(NativeUInt(StackFrame.AddrFrame.Offset), 1)); Writeln('CallStack Handler: ', IntToHex(NativeUInt(StackFrame.AddrPC.Offset), 1)); Writeln('CallStack Stack: ', IntToHex(NativeUInt(StackFrame.AddrStack.Offset), 1)); Writeln('CallStack Return: ', IntToHex(NativeUInt(StackFrame.AddrReturn.Offset), 1)); end; finally VirtualFree(ThreadContext, SizeOf(TContext), MEM_FREE); end; end;
確ãã«ãDelphiãããã¬ãŒãšã¯ç°ãªããã¹ã¿ãã¯ãã¬ãŒã ãçæãããããã·ãŒãžã£ã«é¢ããããŒã¿ãåºåããæ®ãã¯ã¹ãããããŸãã
StackWalkïŒãŸãã¯StackWalk64ïŒé¢æ°ã¯ãã¹ã¿ãã¯ãã¬ãŒã ã«é¢ããæ å ±ãäžèŠ§è¡šç€ºããŸãã
ããã§æ³šæç¹ïŒãã®ã³ãŒããèªåã§é©çšãããšã1ã€ã®ã¹ã¿ãã¯ãã¬ãŒã ã®ã¿ããã¬ãŒã¹ã§ãããã®åŸã«åºå£ããããŸãïŒ ãã¢ã¢ããªã±ãŒã·ã§ã³ã§ç¢ºèªã§ããŸã ïŒã
ããã¯æ¬¡ã®çç±ã§çºçããŸãïŒStackWalké¢æ°ãé©åã«ãã¬ãŒã¹ããã«ã¯ãçŸåšã®ã¹ã¿ãã¯ãã¬ãŒã ïŒx64ã®EBPããã³ESP / RBPããã³RSPïŒã®ãã©ã¡ãŒã¿ãŒãšãå®éã«ã¯çŸåšã®ã³ãŒãã¢ãã¬ã¹ïŒx64ã®EIPãŸãã¯RIPã¬ãžã¹ã¿ïŒãæå®ããå¿ èŠããããŸãã ãã®ããŒã¿ãèªåã§ååŸããå ŽåãGetThreadContexté¢æ°ãåŒã³åºãããšãã«ãããçºçãããã®é¢æ°ãçµäºããåŸã«ã¹ã¿ãã¯ã®ã¹ãã³ãéå§ããŸãããã®é¢æ°ã§ã¯ã3ã€ãã¹ãŠã®ãã©ã¡ãŒã¿ãŒãæå¹ã«ãªããŸãã ãã®ããããã®é¢æ°ãåŒã³åºããŠèªèº«ããã¬ãŒã¹ããããšã¯ã§ããŸããã
ãã®ç¹ãèæ ®ããããšãæãŸãã...
64ãããOSã®äžã§ã®32ãããããã»ã¹ã®ã¹ã¬ããã«é¢ããæ å ±ã®åä¿¡ã«ã€ããŠè©³ãã説æããŸãã32ãããããã³64ãããã®ããªã¢ã³ããå°ãåŸã§èª¬æããŸãã...
3.ããŒãã«é¢ããããŒã¿ãåéããŸã
Delphiã¢ããªã±ãŒã·ã§ã³èªäœã¯ãååãšããŠãããŒãã䜿çšããŸãããããã¯ãC ++ã¢ããªã±ãŒã·ã§ã³ã®ç¹æš©ã§ãããããŒãã¯ãŸã ååšããŠããŸãã éåžžããããã¯ãå¿ èŠã«å¿ããŠããŸããŸãªãµãŒãããŒãã£ã©ã€ãã©ãªã«ãã£ãŠäœæããã³äœ¿çšãããŸãã
ããŒãããŒã¿ãååŸããéã®ãã¥ã¢ã³ã¹ã¯ãåããŒããæ§æããHeapEntryèŠçŽ ãæ°åã«ãªãå¯èœæ§ãããããšã§ããã2çªç®ã®ãã¥ã¢ã³ã¹ã¯ãHeap32Nexté¢æ°ãååŒã³åºãã§ãªã¹ãå šäœãåæ§ç¯ããããªãææãªé 延ïŒæ倧ã§æ°åç§ïŒã
ãã®äžå¿«ãªæ©èœã«ã€ããŠã¯ãã§ã«æžããŠããŸãã
確ãã«ããã®èšäºã§ã¯ãååèªäœã瀺ãããã ãã«ã³ãŒãã¯ããªãèããç§ãã¡ã«ãšã£ãŠã¯ããŸããããŸããããããã³ãŒã ãããããŒãžã§ã³ãç§ãã¡ã«åã£ãŠããŸãïŒ
const RTL_HEAP_BUSY = 1; RTL_HEAP_SEGMENT = 2; RTL_HEAP_SETTABLE_VALUE = $10; RTL_HEAP_SETTABLE_FLAG1 = $20; RTL_HEAP_SETTABLE_FLAG2 = $40; RTL_HEAP_SETTABLE_FLAG3 = $80; RTL_HEAP_SETTABLE_FLAGS = $E0; RTL_HEAP_UNCOMMITTED_RANGE = $100; RTL_HEAP_PROTECTED_ENTRY = $200; RTL_HEAP_FIXED = (RTL_HEAP_BUSY or RTL_HEAP_SETTABLE_VALUE or RTL_HEAP_SETTABLE_FLAG2 or RTL_HEAP_SETTABLE_FLAG3 or RTL_HEAP_SETTABLE_FLAGS or RTL_HEAP_PROTECTED_ENTRY); STATUS_SUCCESS = 0; function CheckSmallBuff(Value: DWORD): Boolean; const STATUS_NO_MEMORY = $C0000017; STATUS_BUFFER_TOO_SMALL = $C0000023; begin Result := (Value = STATUS_NO_MEMORY) or (Value = STATUS_BUFFER_TOO_SMALL); end; function FlagToStr(Value: DWORD): string; begin case Value of LF32_FIXED: Result := 'LF32_FIXED'; LF32_FREE: Result := 'LF32_FREE'; LF32_MOVEABLE: Result := 'LF32_MOVEABLE'; else Result := ''; end; end; var I, A: Integer; pDbgBuffer: PRtlDebugInformation; pHeapInformation: PRtlHeapInformation; pHeapEntry: PRtrHeapEntry; dwAddr, dwLastSize: ULONG_PTR; hit_seg_count: Integer; BuffSize: NativeUInt; begin // .. Heap32ListFirst, Heap32ListNext, Heap32First, Heap32Next // , - // RtlQueryProcessDebugInformation , // // BuffSize := $400000; pDbgBuffer := RtlCreateQueryDebugBuffer(BuffSize, False); // while CheckSmallBuff(RtlQueryProcessDebugInformation(GetCurrentProcessId, RTL_QUERY_PROCESS_HEAP_SUMMARY or RTL_QUERY_PROCESS_HEAP_ENTRIES, pDbgBuffer)) do begin // , ... RtlDestroyQueryDebugBuffer(pDbgBuffer); BuffSize := BuffSize shl 1; pDbgBuffer := RtlCreateQueryDebugBuffer(BuffSize, False); end; if pDbgBuffer <> nil then try // if RtlQueryProcessDebugInformation(GetCurrentProcessId, RTL_QUERY_PROCESS_HEAP_SUMMARY or RTL_QUERY_PROCESS_HEAP_ENTRIES, pDbgBuffer) = STATUS_SUCCESS then begin // pHeapInformation := @pDbgBuffer^.Heaps^.Heaps[0]; // ... for I := 0 to pDbgBuffer^.Heaps^.NumberOfHeaps - 1 do begin // pHeapEntry := pHeapInformation^.Entries; dwAddr := DWORD(pHeapEntry^.u.s2.FirstBlock) + pHeapInformation^.EntryOverhead; dwLastSize := 0; A := 0; while A < Integer(pHeapInformation^.NumberOfEntries) do try hit_seg_count := 0; while (pHeapEntry^.Flags and RTL_HEAP_SEGMENT) = RTL_HEAP_SEGMENT do begin // RTL_HEAP_SEGMENT, // EntryOverhead dwAddr := DWORD(pHeapEntry^.u.s2.FirstBlock) + pHeapInformation^.EntryOverhead; Inc(pHeapEntry); Inc(A); Inc(hit_seg_count); // if A + hit_seg_count >= Integer(pHeapInformation^.NumberOfEntries - 1) then Continue; end; // , , // + if hit_seg_count = 0 then Inc(dwAddr, dwLastSize); // if pHeapEntry^.Flags and RTL_HEAP_FIXED <> 0 then pHeapEntry^.Flags := LF32_FIXED else if pHeapEntry^.Flags and RTL_HEAP_SETTABLE_FLAG1 <> 0 then pHeapEntry^.Flags := LF32_MOVEABLE else if pHeapEntry^.Flags and RTL_HEAP_UNCOMMITTED_RANGE <> 0 then pHeapEntry^.Flags := LF32_FREE; if pHeapEntry^.Flags = 0 then pHeapEntry^.Flags := LF32_FIXED; // Writeln('HeapID: ', I, ', entry addr: ', IntToHex(dwAddr, 8), ', size: ', IntToHex(pHeapEntry^.Size, 8), ' ', FlagToStr(pHeapEntry^.Flags)); // dwLastSize := pHeapEntry^.Size; // Inc(pHeapEntry); finally Inc(A); end; // Inc(pHeapInformation); end; end; finally RtlDestroyQueryDebugBuffer(pDbgBuffer); end; Readln; end.
ã€ãŸããRtlQueryProcessDebugInformationãRtlCreateQueryDebugBufferãããã³RtlQueryProcessDebugInformationé¢æ°ãåŒã³åºãããšã«ãããçŸåšã®ããã»ã¹ããŒãã«é¢ããæ å ±ãå«ããããã¡ãŒãäœæãããŸãã 次ã«ãæ ŒçŽãããŠããããŒã¿ã®æ§é ãããã£ãŠããã®ã§ããã®ããŒã¿ãã«ãŒãã§ååŸããŸãã
pDbgBuffer ^ .Heaps-ããŒããªã¹ãïŒTHeapList32ã®ã¢ããã°ïŒãä¿åããã¬ã³ãŒãèªäœã¯pDbgBuffer ^ .Heaps ^ .Heaps [N] .EntriesïŒTHeapEntry32ã®ã¢ããã°ïŒã«ä¿åãããŸãã
ãã®ã³ãŒãã¯æ¬¡ã®æ å ±ãåºåããŸãã
ååãšããŠããããã°æã«ããŒãã䜿çšããããšã¯ã»ãšãã©ãããŸãããããã®æ å ±ã圹ã«ç«ã€å ŽåããããŸãã
4.ããŠã³ããŒãããPEãã¡ã€ã«ã®ããŒã¿ãåéããŸã
次ã«ãããã»ã¹ã®ã¢ãã¬ã¹ç©ºéã«ããŒããããå®è¡å¯èœãã¡ã€ã«ãšã©ã€ãã©ãªã«é¢ããæ å ±ãååŸããŸãã ãããè¡ãã«ã¯ããã€ãã®æ¹æ³ããããŸããïŒããšãã°ãPEB.LoaderDataãåæããããšã«ãã£ãŠïŒããããç°¡åã«ããŸãããã
ååãšããŠãPEãã¡ã€ã«ã«ã¯å¥ã®é åãå²ãåœãŠãããŸãïŒå°ãªããšããç§ã¯PEãé åã®äžéšãšæŽåããã«ããŒããããããã«ééããããšã¯ãããŸããïŒããããã£ãŠãæåã®ç« ã®ã³ãŒãã䜿çšããé åã®æåã®ããŒãžã®ããŒã¿ã確èªããŸãPEãã¡ã€ã«ã«æºæ ããããã«ãããŒãããããã¹ãŠã®ã©ã€ãã©ãªãšå®è¡å¯èœãã¡ã€ã«ã®ãªã¹ããååŸããŸãã
次ã®ã³ãŒãã¯ãæå®ãããã¢ãã¬ã¹ã«æå¹ãªPEãã¡ã€ã«ã®ååšãæ€åºããŸãã
function CheckPEImage(hProcess: THandle; ImageBase: Pointer; var IsPEImage64: Boolean): Boolean; var ReturnLength: NativeUInt; IDH: TImageDosHeader; NT: TImageNtHeaders; begin Result := False; IsPEImage64 := False; if not ReadProcessMemory(hProcess, ImageBase, @IDH, SizeOf(TImageDosHeader), ReturnLength) then Exit; if IDH.e_magic <> IMAGE_DOS_SIGNATURE then Exit; ImageBase := Pointer(NativeInt(ImageBase) + IDH._lfanew); if not ReadProcessMemory(hProcess, ImageBase, @NT, SizeOf(TImageNtHeaders), ReturnLength) then Exit; Result := NT.Signature = IMAGE_NT_SIGNATURE; IsPEImage64 := (NT.FileHeader.Machine = IMAGE_FILE_MACHINE_IA64) or (NT.FileHeader.Machine = IMAGE_FILE_MACHINE_ALPHA64) or (NT.FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64); end;
ãã£ãšæ£ç¢ºã«èšããšã圌ã¯åã«ImageDosHeaderãšImageNTHeaderã®ååšããã§ãã¯ãã眲åã«çŠç¹ãåãããŸãã ååãšããŠã99ïŒ ã®ã±ãŒã¹ã§ããã§ååã§ãã
3çªç®ã®ãã©ã¡ãŒã¿ãŒã¯åãªãåèæ å ±ã§ãããPEãã¡ã€ã«ã64ããããã©ããã瀺ããŸãã
GetMappedFileNameé¢æ°ãåŒã³åºãããšã«ãããããŠã³ããŒããããã¡ã€ã«ãžã®ãã¹ãååŸã§ããŸãã
function GetFileAtAddr(hProcess: THandle; ImageBase: Pointer): string; begin SetLength(Result, MAX_PATH); SetLength(Result, GetMappedFileName(hProcess, ImageBase, @Result[1], MAX_PATH)); end;
ããã§ã¯ãéåžžã®ã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ã«äœãèªã¿èŸŒãã§ããããèŠãŠã¿ãŸãããã
var MBI: TMemoryBasicInformation; dwLength: NativeUInt; Address: PByte; IsPEImage64: Boolean; begin Address := nil; dwLength := SizeOf(TMemoryBasicInformation); while VirtualQuery(Address, MBI, dwLength) <> 0 do begin if CheckPEImage(GetCurrentProcess, MBI.BaseAddress, IsPEImage64) then begin Write(IntToHex(NativeUInt(MBI.BaseAddress), 8), ': ', GetFileAtAddr(GetCurrentProcess, MBI.BaseAddress)); if IsPEImage64 then Writeln(' (x64)') else Writeln(' (x32)'); end; Inc(Address, MBI.RegionSize); end; Readln; end.
次ã®å³ã衚瀺ãããŸãã
32ãããã¢ããªã±ãŒã·ã§ã³ã®64ãããã©ã€ãã©ãªïŒ ã¯ããããã¯ç°¡åã§ã:)
32ãããã¢ããªã±ãŒã·ã§ã³ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã Windows 7 x64ããããŸãã åçã«ç€ºãããŠããããšããå€æãããšã4ã€ã®64ãããã©ã€ãã©ãªã¯32ãããããã»ã¹ã§éãã«åäœããåäœããŸãããããã§ã¯çããããšã¯ãããŸãããããã¯ããããWow64ïŒ 64ãããWindowsã§ã®Win32ãšãã¥ã¬ãŒã·ã§ã³ ïŒã§ãã
ãããã32ãããã¹ããªãŒã ãšããŒãã®64ãããã¢ããã°ãã©ãããæ¥ããã¯ããã«æããã«ãªããŸãã
ããŠãè¯ãæ¹æ³ã§ãåPEãã¡ã€ã«ã®ã»ã¯ã·ã§ã³ã®ã¢ãã¬ã¹ãååŸããŠãããæ確ã«è¡šç€ºã§ããããã«ããå¿ èŠããããŸãã ãã¹ãŠã®ã»ã¯ã·ã§ã³ã¯ããŒãžã®å é ã«é 眮ãããäºãã«äº€å·®ããŸããã
ãã®ããã«ããŸãããïŒ
procedure GetInfoFromImage(const FileName: string; ImageBase: Pointer); var ImageInfo: TLoadedImage; ImageSectionHeader: PImageSectionHeader; I: Integer; begin if MapAndLoad(PAnsiChar(AnsiString(FileName)), nil, @ImageInfo, True, True) then try ImageSectionHeader := ImageInfo.Sections; for I := 0 to Integer(ImageInfo.NumberOfSections) - 1 do begin Write( IntToHex((NativeUInt(ImageBase) + ImageSectionHeader^.VirtualAddress), 8), ': ', string(PAnsiChar(@ImageSectionHeader^.Name[0]))); if IsExecute(ImageSectionHeader^.Characteristics) then Write(' Execute'); if IsWrite(ImageSectionHeader^.Characteristics) then Write(' Writable'); Writeln; Inc(ImageSectionHeader); end; finally UnMapAndLoad(@ImageInfo); end; Writeln; end;
ããã§ã¯ãMapAndLoadé¢æ°ã®åŒã³åºãã䜿çšããŸãããã®é¢æ°ã¯ããã¡ã€ã«ã®èªã¿èŸŒã¿ãšããããŒã®ç¢ºèªã«å ããŠãNtMapViewOfSectionãåŒã³åºããŠã»ã¯ã·ã§ã³ã®ã¢ã©ã€ã¡ã³ããå®è¡ããŸãã
ãã¡ãããç¬èªã®ããã»ã¹ã§ã¯ããã®é¢æ°ãåŒã³åºãããšã¯åé·ã§ãã å¿ èŠãªPEãã¡ã€ã«ã¯ãã§ã«ããã»ã¹ã®ã¢ãã¬ã¹ã¹ããŒã¹ã«ããŒããããŠããŸããã ä»ã®ããã»ã¹ãæäœããããã«ããæ±çšçãªã³ãŒããå¿ èŠãªå Žåããã®ã¢ãããŒãã䜿çšããŸãã
MapAndLoadã¯ã64ãããããã»ã¹ã32ãããPEãã¡ã€ã«ãèªã¿èŸŒãããšãã§ããããïŒããã¯32ãããããã»ã¹ã§ã¯æ©èœããŸãããïŒåªããŠããããã®æ©èœã¯åŸã§äŸ¿å©ã«ãªããŸãã
ã³ãŒãã®èŠç¹ã¯æ¬¡ã®ãšããã§ããMapAndLoadãå®è¡ãããšãTLoadedImageæ§é äœãæ ŒçŽããããã®Sectionsãã©ã¡ãŒã¿ãŒãTImageSectionHeaderæ§é äœã®é åãæããŸãã ãããã®åæ§é ã«ã¯ãã©ã€ãã©ãªã®ããŒãã¢ãã¬ã¹ããã®ãªãã»ããã§ããVirtualAddressãã£ãŒã«ãããããŸãã ãã®ãã£ãŒã«ãã®å€ãhInstanceã©ã€ãã©ãªã«è¿œå ãããšãã»ã¯ã·ã§ã³ã®ã¢ãã¬ã¹ãååŸãããŸãã
IsExecuteããã³IsWriteé¢æ°ã¯ãã»ã¯ã·ã§ã³ã®ç¹æ§ã確èªããã»ã¯ã·ã§ã³ã«å®è¡å¯èœã³ãŒãïŒIsExecuteïŒãŸãã¯å€æŽå¯èœãªããŒã¿ïŒIsWriteïŒãå«ãŸããŠããå Žåã«Trueãè¿ããŸãã 次ã®ããã«ãªããŸãã
function IsExecute(const Value: DWORD): Boolean; begin Result := False; if (Value and IMAGE_SCN_CNT_CODE) = IMAGE_SCN_CNT_CODE then Result := True; if (Value and IMAGE_SCN_MEM_EXECUTE) = IMAGE_SCN_MEM_EXECUTE then Result := True; end; function IsWrite(const Value: DWORD): Boolean; begin Result := False; if (Value and IMAGE_SCN_CNT_UNINITIALIZED_DATA) = IMAGE_SCN_CNT_UNINITIALIZED_DATA then Result := True; if (Value and IMAGE_SCN_MEM_WRITE) = IMAGE_SCN_MEM_WRITE then Result := True; end;
ãã®ã³ãŒãã®çµæã次ã®ããã«è¡šç€ºãããŸãã
確ãã«ããã®ã³ãŒãã«ã¯å¥ã®å°ããªãã¥ã¢ã³ã¹ããããŸãã
åã®å³ã«èŠãããããã«ãGetMappedFileNameé¢æ°ã¯ãããŠã³ããŒããããã¡ã€ã«ãžã®ãã¹ã次ã®åœ¢åŒã§è¿ããŸããã\ Device \ HarddiskVolume2 \ Windows \ System32 \ wow64cpu.dllããMapAndLoadé¢æ°ã«ã¯ãCïŒ\ Windows \ System32 \ wow64cpuãã®æ£èŠåãã¹ãå¿ èŠã§ãã dllã
次ã®ã³ãŒãã¯ã䜿ãæ £ããå€èŠ³ã«ãã¹ããããã圹å²ãæãããŸãã
function NormalizePath(const Value: string): string; const OBJ_CASE_INSENSITIVE = $00000040; STATUS_SUCCESS = 0; FILE_SYNCHRONOUS_IO_NONALERT = $00000020; FILE_READ_DATA = 1; ObjectNameInformation = 1; DriveNameSize = 4; VolumeCount = 26; DriveTotalSize = DriveNameSize * VolumeCount; var US: UNICODE_STRING; OA: OBJECT_ATTRIBUTES; IO: IO_STATUS_BLOCK; hFile: THandle; NTSTAT, dwReturn: DWORD; ObjectNameInfo: TOBJECT_NAME_INFORMATION; Buff, Volume: string; I, Count, dwQueryLength: Integer; lpQuery: array [0..MAX_PATH - 1] of Char; AnsiResult: AnsiString; begin Result := Value; // ZwOpenFile RtlInitUnicodeString(@US, StringToOleStr(Value)); // InitializeObjectAttributes FillChar(OA, SizeOf(OBJECT_ATTRIBUTES), #0); OA.Length := SizeOf(OBJECT_ATTRIBUTES); OA.ObjectName := @US; OA.Attributes := OBJ_CASE_INSENSITIVE; // ZwOpenFile , // , : // \SystemRoot\System32\ntdll.dll // \??\C:\Windows\System32\ntdll.dll // \Device\HarddiskVolume1\WINDOWS\system32\ntdll.dll // NTSTAT := ZwOpenFile(@hFile, FILE_READ_DATA or SYNCHRONIZE, @OA, @IO, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT); if NTSTAT = STATUS_SUCCESS then try // , NTSTAT := NtQueryObject(hFile, ObjectNameInformation, @ObjectNameInfo, MAX_PATH * 2, @dwReturn); if NTSTAT = STATUS_SUCCESS then begin SetLength(AnsiResult, MAX_PATH); WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length {$IFDEF WIN64} + 4{$ENDIF}], ObjectNameInfo.Name.Length, @AnsiResult[1], MAX_PATH, nil, nil); Result := string(PAnsiChar(AnsiResult)); // ZwOpenFile // \Device\HarddiskVolume\- // SetLength(Buff, DriveTotalSize); Count := GetLogicalDriveStrings(DriveTotalSize, @Buff[1]) div DriveNameSize; for I := 0 to Count - 1 do begin Volume := PChar(@Buff[(I * DriveNameSize) + 1]); Volume[3] := #0; // // QueryDosDevice(PChar(Volume), @lpQuery[0], MAX_PATH); dwQueryLength := Length(string(lpQuery)); if Copy(Result, 1, dwQueryLength) = string(lpQuery) then begin Volume[3] := '\'; if lpQuery[dwQueryLength - 1] <> '\' then Inc(dwQueryLength); Delete(Result, 1, dwQueryLength); Result := Volume + Result; Break; end; end; end; finally ZwClose(hFile); end; end;
ããã¯ãã§ã«éåžžã«å€ãã³ãŒãã§ãããéåžžã®ãã¹ã«äœ¿çšããããã«åžžã«äœ¿çšããŠããŸãããã®æ¬è³ªã¯ã次ã®ã¿ã€ãã®ãã¹ã®æ¬è³ªã§ãã
- \ SystemRoot \ System32 \ ntdll.dll
- \ ?? \ CïŒ\ Windows \ System32 \ ntdll.dll
- \ããã€ã¹\ HarddiskVolume1 \ WINDOWS \ system32 \ ntdll.dll
...ä¿®æ£ãããã\ Device \ HarddiskVolume1 \ WINDOWS \ system32 \ ntdll.dllããååŸããŸãã
ããã¯ãZwOpenFile + NtQueryObjectãåŒã³åºãããšã«ãã£ãŠå®è¡ãããŸãããã®åŸãã·ã¹ãã å ã®ãã¹ãŠã®ãã£ã¹ã¯ãåçŽã«ãœãŒããããããããã«å¯ŸããŠQueryDosDeviceãåŒã³åºãããåã圢åŒã§ãã¹ãè¿ãããŸãããã®åŸããã¹ãæ¯èŒããïŒäžèŽããå ŽåïŒã察å¿ãããã£ã¹ã¯ã©ãã«ã転éããããã¹ã«çœ®ãæããããŸãã
ããããããã¯æè©ã§ãã
èªåã«å®å šã«æºè¶³ããã«ã¯ãPEãã¡ã€ã«ã®ãã£ã¬ã¯ããªã衚瀺ããããšããå§ãããŸããããã«ãããã€ã³ããŒãããŒãã«ãUNWINDã眮ãããŠããå Žæãªã©ãããã«ç¢ºèªã§ããŸãã
ããã¯ããªãåçŽãªã³ãŒãã§è¡ãããŸãïŒ
procedure EnumDirectoryes(ImageBase: Pointer; ImageInfo: TLoadedImage; AddrStart, AddrEnd: NativeUInt); const DirectoryStr: array [0..14] of string = ('export', 'import', 'resource', 'exception', 'security', 'basereloc', 'debug', 'copyright', 'globalptr', 'tls', 'load_config', 'bound_import', 'iat', 'delay_import', 'com'); var I: Integer; dwDirSize: DWORD; DirAddr: Pointer; ReadlDirAddr: NativeUInt; begin for I := 0 to 14 do begin DirAddr := ImageDirectoryEntryToData(ImageInfo.MappedAddress, True, I, dwDirSize); if DirAddr = nil then Continue; ReadlDirAddr := NativeUint(ImageBase) + NativeUint(DirAddr) - NativeUint(ImageInfo.MappedAddress); if (ReadlDirAddr >= AddrStart) and (ReadlDirAddr < AddrEnd) then Writeln( IntToHex(ReadlDirAddr, 8), ': directory "', DirectoryStr[I], '"'); end; end;
TLoadedImageæ§é äœãæå ã«çœ®ããŠãImageDirectoryEntryToDataé¢æ°ãåŒã³åºãã ãã§ã¢ãã¬ã¹ãååŸã§ããŸãããPEãã¡ã€ã«ã衚瀺ãããã¢ãã¬ã¹ã«ãã€ã³ããããŸãããããå®éã®ã¢ãã¬ã¹ã«å€æããã«ã¯ãçŸåšã®ã¢ãã¬ã¹ããç»åã衚瀺ãããã¢ãã¬ã¹ãæžç®ãããã¡ã€ã«ã®å é ãããªãã»ãããååŸããŠãImageBaseã©ã€ãã©ãªã«æ¢ã«è¿œå ããå¿ èŠããããŸãã
çµæã¯ãã®åçã§ãïŒ
ããšãã°ãmsctf.dllã©ã€ãã©ãªã®ã.textãã»ã¯ã·ã§ã³ã«ã¯ãã€ã³ããŒã/ãšã¯ã¹ããŒã/ä¿çäžã®ã€ã³ããŒããã£ã¬ã¯ããªãªã©ãããããšãããã«ããããŸãã
ãªãœãŒã¹ãã£ã¬ã¯ããªã¯ã.rsrcãã»ã¯ã·ã§ã³ã«ãããŸãããŸããrelocã¯æ¬æ¥ããã¹ãå Žæã§ããããbound_importããã£ã¬ã¯ããªã¯ã¹ããŒã ããé€å€ãããŸãã
ã¯ãã確ãã«ããã®ãã£ã¬ã¯ããªã¯ã©ã€ãã©ãªã®ã©ã®ã»ã¯ã·ã§ã³ã«ãçŽæ¥é 眮ãããŠããŸãããéåžžãPEããããŒã®çŽåŸã«ãããŸãïŒãã ããã»ã¯ã·ã§ã³ã®éã«ããå ŽåããããŸãïŒããã®ãã£ã¬ã¯ããªã¯ãäž»ã«OSã®äžéšã§ããããã°ã©ã ãšã©ã€ãã©ãªã«ãããã¿ã€ãã€ã³ããŒããã®ã¡ã«ããºã ãæäŸããŸãã
ãã®æ¬è³ªã¯ãã€ã³ããŒããããé¢æ°ã®ãã¹ãŠã®ã¢ãã¬ã¹ãã³ã³ãã€ã«æ®µéã§å®è¡å¯èœãã¡ã€ã«ã«çž«ãä»ãããããããé¢æ°ã¢ãã¬ã¹ãæ€çŽ¢ããŠéåžžã®ã€ã³ããŒãããŒãã«ãå®è¡ããŠäžèŠãªãžã§ã¹ãã£ãŒãå®è¡ããå¿ èŠã¯ãããŸããã
ãã ãããªã³ã¯ãããã€ã³ããŒãã»ã¯ã·ã§ã³ã§å®£èšãããã©ã€ãã©ãªãå€æŽããããšããã«ãã¢ããªã±ãŒã·ã§ã³ãåã³ã³ãã€ã«ããå¿ èŠãããããããªãŒããŒããããé©åã§ãã
5.ããã»ã¹ç°å¢ãŠãããïŒPEBïŒ+ KUSER_SHARED_DATA
ã¹ããªãŒã ãããŒããå®è¡å¯èœãã¡ã€ã«ã®ããŒã¿ãæå ã«çœ®ããŠãæ å ±ãèªã¿åãå¯èœãªåœ¢åŒã§è¡šç€ºããå°ããªãŠãŒãã£ãªãã£ãäœæã§ããŸãããä»ã«äœãè¿œå ã§ããŸããïŒ
å°ãªããšããããã»ã¹ç°å¢ãããã¯ããæ å ±ãéåä¿¡ããããšã匷ããå§ãããŸãã
ProcessBasicInformationãã©ã°ïŒå®æ°0ïŒãæå®ããŠNtQueryInformationProcessé¢æ°ãåŒã³åºãããšã§ã¢ã¯ã»ã¹ã§ããŸãããã®å Žåãæã¯PROCESS_BASIC_INFORMATIONæ§é ãæã¡ãPebBaseAddressãã£ãŒã«ãã«ã¯PEBã¢ãã¬ã¹ãå«ãŸããŸãã
ãã ããããã¯ãããã»ã¹ã®ãããïŒèŠæ±å ãšæ å ±ã®èŠæ±å ïŒã®ããããäžèŽããå Žåã«ã®ã¿é¢é£ããŸãã 32ãããã¢ããªã±ãŒã·ã§ã³ã«é©çšãããŠãã64ãããã¢ããªã±ãŒã·ã§ã³ãããã®é¢æ°ãåŒã³åºããšããã€ãã£ã32ãããã¢ããªã±ãŒã·ã§ã³ã§ã¯ãªãã64ãããPEBã®ã¢ãã¬ã¹ãååŸãããŸãã
64ãããã¢ããªã±ãŒã·ã§ã³ããWow64PEBã«ã¢ã¯ã»ã¹ããã«ã¯ïŒãããåŒã³åºããŸãããïŒãProcessWow64Informationãã©ã¡ãŒã¿ãŒïŒå®æ°ã¯26ïŒãšãããã¡ãŒãµã€ãºãSizeOfïŒULONG_PTRïŒã«çããNtQueryInformationProcessé¢æ°ãåŒã³åºãå¿ èŠããããŸãããã®å ŽåãPROCESS_BASIC_INFORMATIONæ§é ã®ä»£ããã«ãé¢æ°ã¯32ãããPEBãžã®ãã€ã³ã¿ãŒãè¿ããããããReadProcessMemoryã䜿çšããŠå¿ èŠãªæ å ±ãèªã¿åããŸãã
PEBãšã¯äœã§ããïŒ
倧ãŸãã«èšã£ãŠãããã¯ååã«ææžåãããæ§é ã§ã¯ãªãããã®ã»ãšãã©ã¯ã·ã¹ãã ãçŽæ¥äœ¿çšããããŒã¿ãä¿åããããã«èšèšãããŠããŸããããããããã¯éåžžã®ã¢ããªã±ãŒã·ã§ã³ã®éçºè ã«ãšã£ãŠé¢çœããªããšããæå³ã§ã¯ãããŸãããç¹ã«ããã®æ§é ã«ã¯ä»¥äžã®ãããªå€ãã®èå³æ·±ããã£ãŒã«ããå«ãŸããŸãããããã¬ãããã»ã¹ã«æ¥ç¶ãããŠãããã©ããã瀺ãBeingDebuggedãã©ã°ãããã»ã¹ã«ããŒããããã¢ãžã¥ãŒã«ã«é¢ããæ å ±ãå«ãPEB_LDR_DATAãžã®ãã€ã³ã¿ãŒãæ®ãã®å€ãã¯ãããã°ã©ããŒã«ãšã£ãŠãç¹ã«èªåã®ç®çã§ããã䜿çšããæ¹æ³ãç¥ã£ãŠãã人ã«ãšã£ãŠéåžžã«æçšãªæ å ±ã§ã:)
ãã®æ§é ã¯æ¬¡ã®ããã«ãªããŸãïŒWindows7 x86 / 64ã®å®£èšïŒïŒ
PPEB = ^TPEB; TPEB = record InheritedAddressSpace: BOOLEAN; ReadImageFileExecOptions: BOOLEAN; BeingDebugged: BOOLEAN; BitField: BOOLEAN; { BOOLEAN ImageUsesLargePages : 1; BOOLEAN IsProtectedProcess : 1; BOOLEAN IsLegacyProcess : 1; BOOLEAN IsImageDynamicallyRelocated : 1; BOOLEAN SkipPatchingUser32Forwarders : 1; BOOLEAN IsPackagedProcess : 1; BOOLEAN IsAppContainer : 1; BOOLEAN SpareBits : 1; } Mutant: HANDLE; ImageBaseAddress: PVOID; LoaderData: PVOID; ProcessParameters: PRTL_USER_PROCESS_PARAMETERS; SubSystemData: PVOID; ProcessHeap: PVOID; FastPebLock: PRTLCriticalSection; AtlThunkSListPtr: PVOID; IFEOKey: PVOID; EnvironmentUpdateCount: ULONG; UserSharedInfoPtr: PVOID; SystemReserved: ULONG; AtlThunkSListPtr32: ULONG; ApiSetMap: PVOID; TlsExpansionCounter: ULONG; TlsBitmap: PVOID; TlsBitmapBits: array[0..1] of ULONG; ReadOnlySharedMemoryBase: PVOID; HotpatchInformation: PVOID; ReadOnlyStaticServerData: PPVOID; AnsiCodePageData: PVOID; OemCodePageData: PVOID; UnicodeCaseTableData: PVOID; KeNumberOfProcessors: ULONG; NtGlobalFlag: ULONG; CriticalSectionTimeout: LARGE_INTEGER; HeapSegmentReserve: SIZE_T; HeapSegmentCommit: SIZE_T; HeapDeCommitTotalFreeThreshold: SIZE_T; HeapDeCommitFreeBlockThreshold: SIZE_T; NumberOfHeaps: ULONG; MaximumNumberOfHeaps: ULONG; ProcessHeaps: PPVOID; GdiSharedHandleTable: PVOID; ProcessStarterHelper: PVOID; GdiDCAttributeList: ULONG; LoaderLock: PRTLCriticalSection; NtMajorVersion: ULONG; NtMinorVersion: ULONG; NtBuildNumber: USHORT; NtCSDVersion: USHORT; PlatformId: ULONG; Subsystem: ULONG; MajorSubsystemVersion: ULONG; MinorSubsystemVersion: ULONG; AffinityMask: ULONG_PTR; {$IFDEF WIN32} GdiHandleBuffer: array [0..33] of ULONG; {$ELSE} GdiHandleBuffer: array [0..59] of ULONG; {$ENDIF} PostProcessInitRoutine: PVOID; TlsExpansionBitmap: PVOID; TlsExpansionBitmapBits: array [0..31] of ULONG; SessionId: ULONG; AppCompatFlags: ULARGE_INTEGER; AppCompatFlagsUser: ULARGE_INTEGER; pShimData: PVOID; AppCompatInfo: PVOID; CSDVersion: UNICODE_STRING; ActivationContextData: PVOID; ProcessAssemblyStorageMap: PVOID; SystemDefaultActivationContextData: PVOID; SystemAssemblyStorageMap: PVOID; MinimumStackCommit: SIZE_T; FlsCallback: PPVOID; FlsListHead: LIST_ENTRY; FlsBitmap: PVOID; FlsBitmapBits: array [1..FLS_MAXIMUM_AVAILABLE div SizeOf(ULONG) * 8] of ULONG; FlsHighIndex: ULONG; WerRegistrationData: PVOID; WerShipAssertPtr: PVOID; pContextData: PVOID; pImageHeaderHash: PVOID; TracingFlags: ULONG; { ULONG HeapTracingEnabled : 1; ULONG CritSecTracingEnabled : 1; ULONG LibLoaderTracingEnabled : 1; ULONG SpareTracingBits : 29; } CsrServerReadOnlySharedMemoryBase: ULONGLONG; end;
ãšããã§ããã®æ§é ãMSDNã§å ¬åŒã«å ¥æå¯èœãªæ§é ãšæ¯èŒããŠãã ããã
Window 2000 / XP / 2003ã§ã¯ãå°ããªå€æŽããããŸãããããã»ã©é倧ã§ã¯ãããŸããã
ç§ã¯åãã£ãŒã«ãããã€ã³ãããŸãããPEBã§åã人ã¯ãã§ã«ç¥ã£ãŠããŸããïŒãŸãã«åœŒããå¿ èŠãšãããã®ã§ãããããã€ãã®åéã§ã¯ããªãã®æ³šæãåŒãã§ãããã
ã ããïŒ
- BeingDebuggedãã£ãŒã«ã- ãããã¬ãŒã«é¢ããèšäºã®ç¬¬3éšã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã¡ã¢ãªãããã䜿çšããŠãã®æ€åºããã€ãã¹ããããã®ãªãã·ã§ã³ã®1ã€ã瀺ããŸãããã¢ãããŒãã®æ¬è³ªã¯ãPEBã¢ãã¬ã¹ãæ£ç¢ºã«æ±ºå®ããBeingDebuggedãã©ã¡ãŒã¿ãŒã®å€ããŒãã«å€æŽããããšã§ããããã®åŸããã®ãã£ãŒã«ãã«å°ãããIsDebuggerPresenté¢æ°ã¯Falseãè¿ãå§ããŸããã圌女ã¯ãããã¬ãèŠã€ããããªãã£ãã
- ImageBaseAddress â hInstance ( ImageBase PE ).
- LoaderData â , , , , , . , :)
- ProcessParameters â ParamStr/GetCurrentDir .. ? . .
- , , CSDVersion. , , NtMajorVersion/NtMinorVersion/NtBuildNumber .
ãŸããªã©-ããªãã¯é·ãéç¶ããããšãã§ããŸãã
ãããã®ãã£ãŒã«ãã®ã»ãšãã©ã¯ãããã»ã¹ã®ã¢ãã¬ã¹ç©ºéã§ããŒãžãå æããŸããããšãã°ãProcessParametersã¯éåžžãããŒããŒã«ãã£ãŠäœæãããããŒãã®1ã€ã«é 眮ãããç°å¢å€æ°ããã®é åã®ã©ããã«é 眮ãããŸãã
ãã®ãã¹ãŠãèŠèŠåããå ŽåïŒãããŠãç§ã¯ããã«ã€ãªããïŒãæçµã¢ããªã±ãŒã·ã§ã³ã«è¡šç€ºãããã®ãããããã«ããã®ããŒã¿ãæå ã«çšæããå¿ èŠããããŸãã
åæããŸãããã€ããªããŒã¿ã®ç¹å®ã®ãããã¯ã§ã¯ãªãããã®åœ¢åŒã®äœããæã£ãŠããæ¹ãã¯ããã«å¿«é©ã§ãã
ãã ããKUSER_SHARED_DATAããããŸãã
ããã¯ã·ã¹ãã ã䜿çšããæ§é äœã§ããããåžžã«åãGetTickCountãŸãã¯IsProcessorFeaturePresentãåŒã³åºããŠããã«å¯Ÿå¿ããŸãã
ããšãã°ãNtSystemRootããã®äžã«ãããç¹°ãè¿ãã«ãªããŸããããã¹ãŠããªã¹ãããçç±ã¯ãèŠããããªã£ãŠããŸãã
- GetForegroundWindowãåŒã³åºããã«ã¢ã¯ãã£ããªããã»ã¹ãç¥ãããå Žåã¯ãConsoleSessionForegroundProcessIdãèªãã§ãã ããã
- 以åã®OSçšã«èšèšãããŠããªãä¿è·ã·ã¹ãã ã®äžéšãåæãããããã«ãWinã®å·ŠããŒãžã§ã³ãã¹ãªããããããšããŠããŸããïŒNtMajorVersion / NtMinorVersionãã£ãŒã«ãããçŸåšã®å€ãèªã¿åããŸã...
ãããããããããç§ãã¡ã¯ä»ã®ãšããããã§åæ¢ããŸã...
6. TRegionData
ããã§çè«çãªéšåã¯çµããããã¹ãŠãå®è·µããæãæ¥ãŸããã
ãŸããå°åã«é¢ããæ å ±ãä¿åããæ¹æ³ã決å®ããå¿ èŠããããŸããèšäºã®æºåãšããŠãå ±éã®åå空éãMemoryMapãã«å²ãåœãŠãããäžé£ã®ã¯ã©ã¹ãäœæããŸããããã¢äŸã®äžéšãšããŠããããèŠã€ããããšãã§ããŸãã
éèŠ!!!
ãã®ã¯ã©ã¹ã®ã»ããã¯ãDelphi XE4ã®é©æ°ãèæ ®ããŠéçºãããŸãã; Delphiã®å€ãããŒãžã§ã³ã§ã¯ãããã©ãŒãã³ã¹ã¯ãã¹ããããŠããããä¿èšŒãããŠããŸããã
åé åã®æ å ±ã¯ããMemoryMap.RegionData.pasãã¢ãžã¥ãŒã«ã«å®è£ ãããŠããTRegionDataã¯ã©ã¹ã«ãã£ãŠä¿åãããŸãã
ãããã次ã®ããã«ãªããŸãïŒãããžã§ã¯ãã®éçºéçšã§ãã¯ã©ã¹å®£èšãå€æŽãããå ŽåããããŸãïŒã
TRegionData = class private FParent: TRegionData; FRegionType: TRegionType; FMBI: TMemoryBasicInformation; FDetails: string; FRegionVisible: Boolean; FHiddenRegionCount: Integer; FTotalRegionSize: NativeUInt; FHeap: THeapData; FThread: TThreadData; FPEBData: TSystemData; FSection: TSection; FContains: TList; FDirectories: TList; FShared: Boolean; FSharedCount: Integer; FFiltered: Boolean; protected ... public constructor Create; destructor Destroy; override; property RegionType: TRegionType read FRegionType; property MBI: TMemoryBasicInformation read FMBI; property Details: string read FDetails; property RegionVisible: Boolean read FRegionVisible; property HiddenRegionCount: Integer read FHiddenRegionCount; property Parent: TRegionData read FParent; property TotalRegionSize: NativeUInt read FTotalRegionSize; property Heap: THeapData read FHeap; property Thread: TThreadData read FThread; property SystemData: TSystemData read FPEBData; property Section: TSection read FSection; property Directory: TList read FDirectories; property Contains: TList read FContains; end;
é åºïŒ
åå°åã¯ãååãšããŠã1ã€ã®ã¿ã€ãã®ããŒã¿ãããèªäœã«ä¿åããŸãã
ã€ãŸãããŒããã¹ããªãŒã ã®ã¹ã¿ãã¯ãPEãã¡ã€ã«ã«ã¯ãç¬èªã®ããŒãžé åãå²ãåœãŠãããŸãã
RegionTypeããããã£ã¯ããªãŒãžã§ã³ã¿ã€ãã®æ ŒçŽãæ åœããŸããããã¯ã次ã®ããã«å®£èšãããåæåã§ãã
// TRegionType = ( rtDefault, rtHeap, // rtThread, // TEB rtSystem, // (PEB/KUSER_SHARED_DATA ..) rtExecutableImage // PE );
VirtualQueryExãåŒã³åºããŠååŸããé åãã©ã¡ãŒã¿ãŒã¯ãMBIãã£ãŒã«ãã«ä¿åãããŸãã
å°åã®ç°¡åãªèª¬æã¯ã詳现ã«ä¿åãããŸãã衚瀺ãããŠããPEãã¡ã€ã«ãžã®ãã¹ïŒååšããå ŽåïŒãã¹ããªãŒã IDã®æååã®èª¬æãªã©ãäœã§ãä¿åã§ããŸã
ã以äžã®3ã€ã®ãã©ã¡ãŒã¿ãŒã¯ãããªãŒæ§é ãç·šæããããã«äœ¿çšãããŸãã
ãªãŒãžã§ã³ã®1ã€ã¯ã«ãŒãããŒãïŒã«ãŒãïŒã§ãæ®ãã¯åããŒãã§ãã
RegionVisibleãã©ã°ã¯ããªãŒãžã§ã³ãã«ãŒãããŒããã©ããã瀺ããŸãã
HiddenRegionCountããããã£ã«ã¯ããµããªãŒãžã§ã³ïŒAllocationBaseãBaseAddressã«ãŒãã«çããïŒã®æ°ãå«ãŸããŠããŸãã
ããŠãParentãã©ã¡ãŒã¿ãŒã«ã¯ã«ãŒããžã®ãªã³ã¯ãæ ŒçŽãããŸãã
æé©ãªæ¹æ³ã§ã¯ãããŸãããå€å žçãªããªãŒãæŽçããããšã¯å¯èœã§ãããçŸæç¹ã§ã¯ããçŽãããæéã¯ãããŸãããããããåŸã§ïŒ
TotalRegionSizeã«ã¯ãã«ãŒããå«ããã¹ãŠã®ãµããªãŒãžã§ã³ã®åèšãµã€ãºãå«ãŸããŸãã
é åã«ããŒããå«ãŸããå Žåããã®æåã®èŠçŽ ã«é¢ããããŒã¿ã¯ã次ã®æ§é ã§ããããŒããã©ã¡ãŒã¿ã«é 眮ãããŸãã
THeapEntry = record Address: ULONG_PTR; Size: SIZE_T; Flags: ULONG; end; THeapData = record ID: DWORD; Wow64: Boolean; Entry: THeapEntry; end;
é åå ã«ããæ®ãã®ããŒãèŠçŽ ã¯ã[å«ã]ãã£ãŒã«ãã«é 眮ãããŸãã
äžè¬ã«ãContainsãã£ãŒã«ãã«ã¯å€ãã®ã¿ã€ãã®ããŒã¿ãå«ããããšãã§ããŸãã
TContainItemType = (itHeapBlock, itThreadData, itStackFrame, itSEHFrame, itSystem); TContainItem = record ItemType: TContainItemType; function Hash: string; case Integer of 0: (Heap: THeapData); 1: (ThreadData: TThreadData); 2: (StackFrame: TThreadStackEntry); 3: (SEH: TSEHEntry); 4: (System: TSystemData); end;
次ã¯Threadãã£ãŒã«ãã§ãé åãç¬èªã®ããŒã¿ãä¿åããããã«äœ¿çšããã¹ã¬ããã«é¢ããæ å ±ãä¿åããŸãã
type TThreadInfo = (tiNoData, tiExceptionList, tiStackBase, tiStackLimit, tiTEB, tiThreadProc); type TThreadData = record Flag: TThreadInfo; ThreadID: Integer; Address: Pointer; Wow64: Boolean; end;
é åå ã«å€ãã®ãããŒããŒã¿ãããå ŽåïŒããšãã°ãSEHãã¬ãŒã ãŸãã¯CallStackãããŒã®ãªã¹ãïŒããããã¯[å«ã]ãã£ãŒã«ãã«ãé 眮ãããŸãã
ã·ã¹ãã æ§é ïŒPEB / TEBæ§é ã®ãã£ãŒã«ããªã©ïŒããã®ããŒã¿ã¯ãããŒã¿ã¢ãã¬ã¹ãšãã®èª¬æããã®ã¬ã³ãŒãã§ããSystemDataãã£ãŒã«ãã«é 眮ãããŸãã
ãŸãããã®ããŒã¿ã¯[å«ã]ãã£ãŒã«ãã«é 眮ã§ããŸãã
é åãPEãã¡ã€ã«ã®ã»ã¯ã·ã§ã³ã®ããããã«å±ããå Žåãã»ã¯ã·ã§ã³ããŒã¿ã¯Sectionãã©ã¡ãŒã¿ãŒã«é 眮ãããŸããããŠããã¡ã€ã«ãã£ã¬ã¯ããªã®ãªã¹ãã¯[ãã£ã¬ã¯ããª]ãã£ãŒã«ãã«é 眮ãããŸãã
äžèšã§èšãã°ããã®ãããªãã®ã§ãã次ã«ãããã»ã¹ã¡ã¢ãªã«ãŒãäžã®ããŒã¿ãè¡šãããã«ãé åã®ãªã¹ããååŸããåé åã®TRegionDataã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããäœæããããªããžã§ã¯ãã®ãã£ãŒã«ããå¿ èŠãªæ å ±ã§åæåããå¿ èŠããããŸãã
TMemoryMapã¯ã©ã¹ã¯ããã«è²¬ä»»ããããŸã...
7. TMemoryMap
ãã®ã¯ã©ã¹ã¯ãã¢ãžã¥ãŒã«ãMemoryMap.Core.pasãã«å®è£ ãããŠããŸãã
ãã®ã¿ã¹ã¯ã¯ãæåéã3ã€ã®äž»èŠãªæ®µéã«åæžãããŸãã
- æå®ãããã¢ããªã±ãŒã·ã§ã³ã®ã¡ã¢ãªå ã®éžæããããã¹ãŠã®é åã®ãªã¹ããã¹ã¬ãã/ããŒã/ããŒããããã€ã¡ãŒãžãªã©ã®ããŒã¿ãååŸããŸãã
- TRegionDataãªã¹ããäœæãããã®ãã£ãŒã«ãã«åä¿¡ããæ å ±ãå ¥åããŸãã
- ããŒã¿ã®ä¿å/èªã¿èŸŒã¿ãããŒã¿ã®ãã£ã«ã¿ãªã³ã°ã
å®éã«ã¯ããã¹ãŠãå°ãè€éã«èŠããŸãã
æ å ±ãåéããåºæ¬çãªæé ã¯æ¬¡ã®ãšããã§ãã
function TMemoryMap.InitFromProcess(PID: Cardinal; const ProcessName: string): Boolean; var ProcessLock: TProcessLockHandleList; begin Result := False; FRegions.Clear; FModules.Clear; FFilter := fiNone; ProcessLock := nil; // FProcess := OpenProcess( PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID); if FProcess = 0 then RaiseLastOSError; try FPID := PID; FProcessName := ProcessName; // FProcess64 := False; {$IFDEF WIN64} if not IsWow64(FProcess) then FProcess64 := True; {$ELSE} // 32 , 64- // if Is64OS and not IsWow64(FProcess) then raise Exception.Create('Can''t scan process.'); {$ENDIF} // if SuspendProcessBeforeScan then ProcessLock := SuspendProcess(PID); try FSymbols := TSymbols.Create(FProcess); try FPEImage := TPEImage.Create; try FWorkset := TWorkset.Create(FProcess);; try // GetAllRegions; finally FWorkset.Free; end; {$IFDEF WIN64} // 32 AddWow64HeapsData; {$ENDIF} // AddThreadsData; // AddHeapsData; // Process Environment Block AddPEBData; // PE AddImagesData; finally FPEImage.Free; end; finally FSymbols.Free; end; finally if SuspendProcessBeforeScan then ResumeProcess(ProcessLock); end; // SortAllContainsBlocks; // CalcTotal; // UpdateRegionFilters; finally CloseHandle(FProcess); end; end;
æåã®4ã€ã®ç« ã§GetAllRegions / AddThreadsData / AddHeapsDataããã³AddImagesDataããã·ãŒãžã£ã®ãµã³ãã«ã³ãŒããæäŸããŸããããããã«ã¯çŠç¹ãåœãŠãŸããããæ®ãã¯åŠçããããšæããŸãã
ããã»ã¹ãéããåŸã®æåã®ã¹ãããã¯ãããã»ã¹ã®ãããæ°ã決å®ããããšã§ãã
ããã¯ãããã»ã¹ã®ããããµã€ãºïŒçŸåšããã³æ å ±ãåãåãïŒãäžèŽããªãå Žåãããã€ãã®è¿œå æé ãå®è¡ããå¿ èŠãããããã§ãã
äžè¬çãªã¹ããŒã ã¯æ¬¡ã®ãšããã§ãã
- 32ãããããã»ã¹ã¯ã32ãããOSã§å®å šã«32ãããã§ããŒã¿ãåä¿¡ã§ããŸãã
- 64ãããããã»ã¹ã¯ã64ãããããã»ã¹ã§ããŒã¿ãå®å šã«åä¿¡ã§ããŸãã
- 32ãããããã»ã¹ã¯ã64 ãããããã»ã¹ã§ããŒã¿ãåä¿¡ã§ããŸããã
- 32- 32- 64- , .
- 64- 32-, .
æåã®2ã€ã®ãã€ã³ãã§ãã¹ãŠãæ確ãªå Žåãä»ã®3ã€ã®ãã€ã³ãããã詳现ã«æ€èšãããŸãã
32ãããããã»ã¹ã64ãããããã»ã¹ã§ããŒã¿ãåä¿¡ã§ããªãçç±ã¯ç°¡åã§ãããã€ã³ã¿ãŒã®ãµã€ãºã§ã¯èš±å¯ããããããã«ReadProcessMemoryã¯ãšã©ãŒERROR_PARTIAL_COPYãå®æçã«çæããŸãã
ãã ãã64ãããOSã®32ãããããã»ã¹ããããŒã¿ãååŸããã®ã¯ãã¯ããã«é£ããäœæ¥ã§ãã
åè¿°ããããã«ã32ãããã¢ããªã±ãŒã·ã§ã³ã§ã¯ã4ã€ã®64ãããã©ã€ãã©ãªãããŒããããããŒã/ã¹ã¬ãããäœæãããŸãã
32ãããã¢ããªã±ãŒã·ã§ã³ããããŒããšã¹ããªãŒã ã®ãªã¹ããååŸãããšã32ãããã«é¢é£ããããŒã¿ã®ã¿ã衚瀺ããã64ãããã¢ããã°ã®ããŒã¿ã¯ååŸã§ããŸããã
64ãããããã»ã¹ãã32ãããããã»ã¹ã«é¢ããããŒã¿ãèŠæ±ããå Žåãåæ§ã§ãã64ãããã«é¢é£ããããŒã¿ã®ã¿ãè¿ãããŸãããã®å Žåãããããéšåçã«ååŸãããªãã·ã§ã³ããããŸããã
ç¹ã«ã32ãããPEBãžã®ã¢ã¯ã»ã¹ã¯ã次ã®é¢æ°ãåŒã³åºãããšã«ãã£ãŠè¡ãããŸãã
const ProcessWow64Information = 26; ... NtQueryInformationProcess(FProcess, ProcessWow64Information, @FPebWow64BaseAddress, SizeOf(ULONG_PTR), @ReturnLength)
32ãããTEBãžã®ã¢ã¯ã»ã¹ã¯ãNtTIB.ExceptionListãã©ã¡ãŒã¿ãŒã«æ ŒçŽãããŠãã64ãããTEBããã¢ãã¬ã¹ãèªã¿åãããšã§ååŸã§ããŸãã
// 64 TEB TIB.ExceptionList Wow64TEB if not ReadProcessMemory(hProcess, TIB.ExceptionList, @WOW64_NT_TIB, SizeOf(TWOW64_NT_TIB), lpNumberOfBytesRead) then Exit;
次ã®ã³ãŒãã䜿çšããŠãCallStackããã¢ãŒã·ã§ã³ã®32ãããã¹ããªãŒã ã®ã³ã³ããã¹ããååŸã§ããŸãã
const ThreadWow64Context = 29; ... ThreadContext^.ContextFlags := CONTEXT_FULL; if NtQueryInformationThread(hThread, ThreadWow64Context, ThreadContext, SizeOf(TWow64Context), nil) <> STATUS_SUCCESS then Exit;
ãŸãã¯ãWow64GetThreadContexté¢æ°ãåŒã³åºããŸãã
ãããã64ãããããã»ã¹ãã32ãããããŒãã«é¢ããããŒã¿ãåæ³çã«ååŸããæ¹æ³ãããããŸãããçŸåšé©çšããŠããå¯äžã®ãªãã·ã§ã³ã¯ãã³ãã³ãã32ãããããã»ã¹ã«éä¿¡ããããšã§ãã32ãããããã»ã¹ã¯ã32ãããããŒãã«é¢ããããŒã¿ãåéãã64ãããã«éãè¿ããŸãïŒãããAddWow64HeapsDataé¢æ°ã®ãã³ãã©ãŒã§ãïŒã
ããã»ã¹ã®ãããæ°ã®å®çŸ©ãšããããå¿ èŠãªçç±ãããã£ãã®ã§ã次ã«SuspendProcessé¢æ°ã®åŒã³åºãã«ç§»ããŸãããã
è¯ãæ¹æ³ã§ã¯ãããã¯ããªã¢ãŒãããã»ã¹ã®ããŒã¿ãå€æŽãããŠèªã¿åããããšãã«ç¡é¢ä¿ã«ãªããªãããã«ããããã«ã®ã¿å¿ èŠã§ãããã ããéåžžããã®ã¯ã©ã¹ã®ã»ããã¯ãèªåã®ã¢ããªã±ãŒã·ã§ã³ãŸãã¯ãããã¬ãŒã®äžã®ã¢ããªã±ãŒã·ã§ã³ã®2ã€ã®å Žåã«äœ¿çšããŸããã©ã¡ãã®å Žåããã¹ã¬ãããããªãŒãºããå¿ èŠã¯ãããŸãããããµãŒãããŒãã£ã®ã¢ããªã±ãŒã·ã§ã³ãåæãããŠããå Žåããªãããã§ã¯ãªãã®ã§ããïŒ
ãªã¢ãŒãããã»ã¹ãããªãŒãºãããšã3ã€ã®ãã«ããŒã¯ã©ã¹ãäœæãããŸãã
- TSymbols-次ã®ç« ã§åœŒã«ã€ããŠè©±ããŸãã
- TPEImage-ãã®ã¯ã©ã¹ã«ã¯ã第4ç« ã§èª¬æãããŠããPEãã¡ã€ã«ã«é¢ããæ å ±ãååŸã§ããã¡ãœãããå«ãŸããŠããŸããå©äŸ¿æ§ã®ã¿ã®ããã«äœãããŸããã
- TWorksetã¯ãå ±æã¡ã¢ãªã«é¢ããæ å ±ãååŸããã¿ã¹ã¯ãæã€ãã«ããŒã¯ã©ã¹ã§ãã
æ¬è³ªçã«ãTWorksetã¯æ¬¡ã®åœ¢åŒã®æ§é ã®ãªã¹ããä¿åããŸãã
TShareInfo = record Shared: Boolean; SharedCount: Byte; end;
ãããã®æ§é ã¯èŸæžã«ä¿åããããããããç¹å®ã®ããŒãžã¢ãã¬ã¹ã«é¢é£ä»ããããŠããŸãã
ãã©ã¡ãŒã¿ãŒã¯ç°¡åã§ãïŒ
- å ±æ-ããŒãžãå ¬éãããŠãããã©ãã
- SharedCount-ããŒãžäžã«ãããªã³ã¯ã®æ°
ãã®ããŒã¿ã¯æ¬¡ã®æ¹æ³ã§ååŸãããŸãããã®æ¹æ³ã§ã¯ããã¹ãŠãQueryWorkingSeté¢æ°ãåŒã³åºãããšã«ãªããŸãã
procedure TWorkset.InitWorksetData(hProcess: THandle); const {$IFDEF WIN64} AddrMask = $FFFFFFFFFFFFF000; {$ELSE} AddrMask = $FFFFF000; {$ENDIF} SharedBitMask = $100; SharedCountMask = $E0; function GetSharedCount(Value: ULONG_PTR): Byte; inline; begin Result := (Value and SharedCountMask) shr 5; end; var WorksetBuff: array of ULONG_PTR; I: Integer; ShareInfo: TShareInfo; begin SetLength(WorksetBuff, $400000); while not QueryWorkingSet(hProcess, @WorksetBuff[0], Length(WorksetBuff) * SizeOf(ULONG_PTR)) do SetLength(WorksetBuff, WorksetBuff[0] * 2); for I := 0 to WorksetBuff[0] - 1 do begin ShareInfo.Shared := WorksetBuff[I] and SharedBitMask <> 0; ShareInfo.SharedCount := GetSharedCount(WorksetBuff[I]); try FData.Add(Pointer(WorksetBuff[I] and AddrMask), ShareInfo); except on E: EListError do ; else raise; end; end; end;
ãã®é¢æ°ã¯ULONG_PTRé åãè¿ããŸããé åã®åèŠçŽ ã¯æ¬¡ã®ããã«ããŒã¿ãä¿åããŸããæåã®5ãããã¯ããŒãžã»ãã¥ãªãã£å±æ§ãä¿åããŸãã次ã®3ãããã¯ããã®ããŒãžãå©çšå¯èœãªããã»ã¹ã®æ°ã§ãããã1ãããã¯ãããŒãžã®ã¢ã¯ã»ã·ããªãã£ã瀺ããŸãã次ã«ãããŒãžèªäœã®ã¢ãã¬ã¹ãæ¥ãŸãã
詳现ã«ã€ããŠã¯ãPSAPI_WORKING_SET_BLOCKãåç §ããŠãã ããã
å®éãããã¯åãªãæ å ±ã¯ã©ã¹ã§ããããã以äžã§ããã以äžã§ããããŸããã
ãã ããã³ãŒãã«æ»ããŸãã
次ã®æé ã¯æ¬¡ã®ãšããã§ãã
- GetAllRegionsã¯ãæåã®ç« ã®ã³ãŒãã«é¡äŒŒããŠããŸãã
- AddThreadsDataã¯ã第2ç« ã®ã³ãŒãã«é¡äŒŒããŠããŸãã
- AddHeapsDataã¯ã第3ç« ã®ã³ãŒãã«é¡äŒŒããŠããŸãã
- AddPEBData-第5ç« ã®æ§é ããŒã¿ã®åºåã
- AddImagesDataã¯ã第4ç« ã®ã³ãŒãã«é¡äŒŒããŠããŸãã
ã芧ã®ãšãããé¢çœãïŒã»ãŒïŒãã¹ãŠãæ¢ã«èª¬æããŸãã:)
æ®ãã®æé ã¯ãUpdateRegionFiltersã®åŒã³åºããé€ããŠãèå³æ·±ããã®ã§ã¯ãããŸããã
ã€ãŸããå®çšçãªæ©èœãå®è¡ããŸããã€ãŸããçŸåšäžèŠãªé åããªã¹ãããé€å€ããŸãïŒããšãã°ãæªå²ãåœãŠã®ã¡ã¢ãªãããé åãåé€ãããªã©ïŒã
ãã®ããããã£ã¯ãFilterããããã£ã§ãã£ã«ã¿ãŒãå€æŽããããšãã«åžžã«åŒã³åºãããŸãã
ãã ããå¿ èŠã«å¿ããŠãã¯ã©ã¹èªäœã®ã³ãŒãããããããã¹ãŠã確èªã§ããŸãã
äœæ¥ã¯éåžžã«ç°¡åã§ãã
var AMemoryMap: TMemoryMap; M: TMemoryStream; I: Integer; begin try M := TMemoryStream.Create; try // AMemoryMap := TMemoryMap.Create; try // AMemoryMap.InitFromProcess(GetCurrentProcessId, ''); // , AMemoryMap.SaveToStream(M); // finally AMemoryMap.Free; end; // -, M.Position := 0; // AMemoryMap := TMemoryMap.Create; try // AMemoryMap.LoadFromStream(M); // AMemoryMap.Filter := fiNone; // // AMemoryMap.ShowEmpty := True; // for I := 0 to AMemoryMap.Count - 1 do Writeln(NativeUInt(AMemoryMap[I].MBI.BaseAddress)); finally AMemoryMap.Free; end; finally M.Free; end; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; Readln; end.
圌ããèšãããã«ãç§ã¯èªåèªèº«ã®ããã«æžããã®ã§ããã®ã¯ã©ã¹ã§ã®äœæ¥ã¯æ¢šãç ²æããã®ãšåããããç°¡åã§ã:)
8. TSymbols-ã·ã³ãã«ã®æäœ
ãã®ã¯ã©ã¹ã®æ¬è³ªã¯ãããã»ã¹ã®äœæã«é¢ãããã詳现ãªæ å ±ãååŸããããšã§ããããšãã°ã第2ç« ã§ã¯ãCallStackã¹ããªãŒã ïŒãŸãã¯SEHãã¬ãŒã ãã³ãã©ãŒïŒãåãåããŸãããããããã¯åãªãã¢ãã¬ã¹ã§ãããããã也ç¥ããæ°åã®ä»£ããã«ãã®åçã®ãããªãã®ãèŠãæ¹ãã¯ããã«èå³æ·±ãã§ãïŒ
ããã¯éåžžã«ç°¡åã«è¡ãããŸã-SymGetSymFromAddré¢æ°ãåŒã³åºãã ãã§ååã§ãããããã€ãã®åŸ®åŠãªéãããããŸãã
æåã«ã³ãŒããèŠãŠã¿ãŸãããã
function TSymbols.GetDescriptionAtAddr(Address, BaseAddress: ULONG_PTR; const ModuleName: string): string; const BuffSize = $7FF; {$IFDEF WIN64} SizeOfStruct = SizeOf(TImagehlpSymbol64); MaxNameLength = BuffSize - SizeOfStruct; var Symbol: PImagehlpSymbol64; Displacement: DWORD64; {$ELSE} SizeOfStruct = SizeOf(TImagehlpSymbol); MaxNameLength = BuffSize - SizeOfStruct; var Symbol: PImagehlpSymbol; Displacement: DWORD; {$ENDIF} begin Result := ''; if not FInited then Exit; GetMem(Symbol, BuffSize); try Symbol^.SizeOfStruct := SizeOfStruct; Symbol^.MaxNameLength := MaxNameLength; Symbol^.Size := 0; SymLoadModule(FProcess, 0, PAnsiChar(AnsiString(ModuleName)), nil, BaseAddress, 0); try if SymGetSymFromAddr(FProcess, Address, @Displacement, Symbol) then Result := string(PAnsiChar(@(Symbol^).Name[0])) + ' + 0x' + IntToHex(Displacement, 4) else begin // SymLoadModule(FProcess, 0, PAnsiChar(AnsiString(ModuleName)), nil, BaseAddress, 0); if SymGetSymFromAddr(FProcess, Address, @Displacement, Symbol) then Result := string(PAnsiChar(@(Symbol^).Name[0])) + ' + 0x' + IntToHex(Displacement, 4); end; finally SymUnloadModule(FProcess, BaseAddress); end; finally FreeMem(Symbol); end; if Result = '' then Result := ExtractFileName(ModuleName) + ' + 0x' + IntToHex(Address - BaseAddress, 1); end;
ã¢ãã¬ã¹ãå±ããé¢æ°ã®ååã®èª¬æãæ£ããååŸããã«ã¯ãé¢æ°ãå±ããã©ã€ãã©ãªãŒãžã®ãã¹ããŸãã¯ãã®ã©ã€ãã©ãªãŒãããŒããããã¢ãã¬ã¹ãç¥ãå¿ èŠããããŸãïŒäž¡æ¹ã®ãã©ã¡ãŒã¿ãŒãã³ãŒãã§äœ¿çšãããŸãïŒããããã®ãã©ã¡ãŒã¿ãŒã¯ãSymLoadModuleé¢æ°ã«å¿ èŠã§ãã
2çªç®ã®æ³šæç¹ã¯ãSymGetSymFromAddré¢æ°ã®åŒã³åºãã倱æããå Žåãããããšã§ãããã®çç±ã¯ç§ã«ã¯æããã§ã¯ãããŸããããã€ã³ã¿ãŒãããã¯ãã®ç¶æ³ãå®æçã«èª¬æãããã®è§£æ±ºæ¹æ³ã¯SymUnloadModuleãåŒã³åºããã«SymLoadModuleé¢æ°ãå床åŒã³åºãããšã§ããç§ã¯ãã®ãããªå¥åŠãªåäœãç解ããŠããŸããã§ãã-ããããããã¯æ¬åœã«åœ¹ç«ã¡ãŸãã
æåŸã®åŸ®åŠãªç¹ã¯ããã®é¢æ°ããã®æ å ±ãååšããå Žåã«ã®ã¿ã¢ãã¬ã¹ã®æå¹ãªèª¬æãè¿ãããšã§ãïŒå€éšãã¡ã€ã«ããã®æåãããŒããããããããããç®çã®ã¢ãžã¥ãŒã«ã®äžéšã§ãïŒã
ãã®æ å ±ã¯ãããã°ã«ã¯ããŸãéèŠã§ã¯ãããŸããããå°ãç°¡åã«ãªããŸãã
ããšãã°ãããã§ã¯ãæšæºã®Chromeãã©ãŠã¶ã¹ããªãŒã ã¹ã¿ãã¯ã®ããã«èŠããŸãïŒCallStack + SEHãã¬ãŒã ïŒïŒ
ã·ã³ãã«ãæäŸã§ããããæçšãªæ å ±ã¯ããšã¯ã¹ããŒããããã©ã€ãã©ãªé¢æ°ãšãã®çŸåšã®ã¢ãã¬ã¹ã®ãªã¹ãã§ãã
TSymbolsã¯ã©ã¹ã§ã¯ããã®æ å ±ã¯GetExportFuncListããã·ãŒãžã£ãåŒã³åºãããšã§ååŸããã次ã®ããã«ãªããŸãã
function SymEnumsymbolsCallback(SymbolName: LPSTR; SymbolAddress: ULONG_PTR; SymbolSize: ULONG; UserContext: Pointer): Bool; stdcall; var List: TStringList; begin List := UserContext; List.AddObject(string(SymbolName), Pointer(SymbolAddress)); Result := True; end; procedure TSymbols.GetExportFuncList(const ModuleName: string; BaseAddress: ULONG_PTR; Value: TStringList); begin SymLoadModule(FProcess, 0, PAnsiChar(AnsiString(ModuleName)), nil, BaseAddress, 0); try if not SymEnumerateSymbols(FProcess, BaseAddress, @SymEnumsymbolsCallback, Value) then begin SymLoadModule(FProcess, 0, PAnsiChar(AnsiString(ModuleName)), nil, BaseAddress, 0); SymEnumerateSymbols(FProcess, BaseAddress, @SymEnumsymbolsCallback, Value) end; finally SymUnloadModule(FProcess, BaseAddress); end; end;
ãã¹ãŠã¯ãã³ãŒã«ããã¯é¢æ°ã®ã¢ãã¬ã¹ãæž¡ãSymEnumerateSymbolsãåŒã³åºãããšã«ãªããŸãã
åŒã³åºããããšãSymbolNameãã©ã¡ãŒã¿ãŒã«ã¯ãšã¯ã¹ããŒããããé¢æ°ã®ååãšSymbolAddressã®ã¢ãã¬ã¹ãå«ãŸããŸãã
ããã¯ããŠãŒã¶ãŒã«æ¬¡ã®ãµã€ã³ã衚瀺ããã®ã«ååã§ãã
ã¢ãžã¥ãŒã«ãMemoryMap.Symbols.pasãã®SymSetOptionsããã³SymInitializeã®çç¥ãããåŒã³åºããå«ãããã®ã¯ã©ã¹ã®å®è£ ããã詳现ã«ç¢ºèªã§ããŸãã
9. ProcessMemoryMap
ããŠãããã§èšäºã®æåŸã®éšåã«è¡ããŸãã
åã«èšã£ãããã«ã2ã€ã®æ¹æ³ã§MemoryMapã¯ã©ã¹ã»ããã䜿çšã
ãŸãã1. OnAttachedFilesRequestãã³ãã©ãŒããªãŒããŒã©ããããŠEurekaLogåºåã«çµ±åããäŸå€ãçºçããæç¹ã§çŸåšã®ããã»ã¹ããããè¿œå ããŠã MEM_PRIVATEãã©ã°ãæã€ç¹å®ã®ããŒã¿ïŒãšã¹ããªãŒã ã¹ã¿ãã¯ãããã«PEBããã®æ å ±ã®äžéšãéåžžãããã¯ãšã©ãŒã®åå ãåæããã®ã«ååã§ãã
2.ãããã°ãããã¢ããªã±ãŒã·ã§ã³ãåæããããã®ä»£æ¿ããŒã«ãšããŠäœ¿çšããŸãã
2çªç®ã®ãªãã·ã§ã³ã§ã¯ãMemoryMapã¯ã©ã¹ãšçŽæ¥é£æºããå¥ã®ãŠãŒãã£ãªãã£ãå®è£ ãããããã«ããã€ãã®è¿œå æ©èœãè¿œå ãããŸããã
ãã®ãœãŒã¹ã³ãŒãã«ã€ããŠã¯èª¬æããŸãããæ©èœã«ã€ããŠã¯å°ãã ã説æããŸãã
ããã³ããšã³ãããèŠããšãã»ãŒ1察1ã®VMMapã«äŒŒãŠããŸãããã ãããã®ãããªã€ã³ã¿ãŒãã§ã€ã¹ã¯åæã«æã䟿å©ã§ãããããããã¯åœåèšç»ãããŠããŸããã
äžéšã«ã¯ãã¿ã€ãããšã«ã°ã«ãŒãåãããå°åã«é¢ããäžè¬æ å ±ãå«ããªã¹ãããããããããã£ã«ã¿ãŒã§ãã
çŸæç¹ã§ã¯ã次ã®æ©èœãè¡šããŠããŸã
ã1.æå®ãããã¢ãã¬ã¹ã®ã¡ã¢ãªã®å 容ã衚瀺ããŸãïŒCtrl + QïŒã
ååãšããŠããã®æ©èœã¯Delphiãããã¬ãŒã®[CPUãã¥ãŒ]ãŠã£ã³ããŠã«ãããŸããããã®ã¢ãŒãã«ã¯ããã«å€ãã®å¯èœæ§ããããŸããããšãã°ãPEBãã£ãŒã«ããèŠããšãããŒã¿ã¯ç°ãªã圢åŒã§è¡šç€ºãããŸãã
ããã»ã¹ãã©ã¡ãŒã¿ãããã¯ã¯æ¬¡ã®ããã«ãªããŸãã
ãŸããªã©ã çŸæç¹ã§ã¯ããŠãŒãã£ãªãã£ã¯æ¬¡ã®æ§é ã®ãããããããããŒã¿ã衚瀺ã§ããŸãã
- PEB-ããã»ã¹ç°å¢ãããã¯ïŒ32/64ïŒ
- TEB-ã¹ã¬ããç°å¢ãããã¯ïŒ32/64ïŒ
- KUSER_SHARED_DATA
- PEããããŒïŒIMAGE_DOS_HEADER / IMAGE_NT_HEADER / IMAGE_FILE_HEADER / IMAGE_OPTIONAL_HEADERïŒ32/64ïŒ/ IMAGE_DATA_DIRECTORY / IMAGE_SECTION_HEADERSïŒ
- ããã»ã¹ãã©ã¡ãŒã¿ïŒ32/64ïŒ
ãã®ãªã¹ãã¯æçµçãªãã®ã§ã¯ãªããå®æçã«æ°ããæ§é ãè¿œå ãããŸãã
2.ããã»ã¹ã¡ã¢ãªå ã®ããŒã¿ãæ€çŽ¢ããŸãïŒCtrl + FïŒïŒ
æ®å¿µãªãããDelphiãããã¬ã«ã¯ãã®æ©èœããããŸããã
AnsiãUnicodeæååããŸãã¯åã«æœè±¡HEXãããã¡ã§æ€çŽ¢ã§ããŸããæ€çŽ¢æã«ã¯ãæ€çŽ¢ã®éå§ã¢ãã¬ã¹ãšãããŒãžãæ€çŽ¢ããå¿ èŠãããããšã瀺ããã©ã°ãæå®ã§ããŸãããã®ãã©ã°ãžã®ã¢ã¯ã»ã¹ã¯èªã¿åãå°çšã§ãã
çµæã¯ãäžèšã®ã¡ã¢ãªãã³ããå«ããŠã£ã³ããŠãšããŠè¡šç€ºãããŸãã
3. 2æã®ã¡ã¢ãªã«ãŒãã®ã³ã³ãã¬ãŒã¿ãèšå®ã«å«ãŸããŠããŸãã
2ã€ã®ã¡ã¢ãªã«ãŒãã®éããèŠã€ããŠãããã¹ããšããŠè¡šç€ºã§ããŸãã
ããŒã¿ã§ã¯ãªããã«ãŒãèªäœã®ã¿ãæ¯èŒãããŸãã ã€ãŸãããã¢ãã¬ã¹ã§4ãã€ããå€æŽãããå Žåããã®å€æŽã¯è¡šç€ºãããŸããããã ãããªãŒãžã§ã³ã®ãµã€ãºãå€æŽãããå Žåãæããªããªã£ãå Žåããã¡ã€ã«ãã¢ããããŒã/ããŠã³ããŒããããå Žåãªã©ã§ãã -ãããã¯ãã¹ãŠæ¯èŒçµæã«è¡šç€ºãããŸãã
ã«ãŒãã®çŸåšã®åçãšä»¥åã«ä¿åããåçãæ¯èŒããããšããF5ãããããŒã䜿çšããŠåçãæŽæ°ããããšãã§ããŸãã
4.ã¡ã¢ãªãã³ãã
ãŸããDelphiãããã¬ãŒã®æ©èœãæ¬ èœããŠããŸããæå®ãããé åã®ã¡ã¢ãªã®å 容ãŸãã¯æå®ãããã¢ãã¬ã¹ã®ããŒã¿ããã£ã¹ã¯ã«ä¿åã§ããŸãã
5.åæãããããã»ã¹ã«èªã¿èŸŒãŸãããã¹ãŠã®ã©ã€ãã©ãªããå©çšå¯èœãªãã¹ãŠã®ãšã¯ã¹ããŒããããé¢æ°ã®åºåïŒCtrl + EïŒã
ååãŸãã¯ã¢ãã¬ã¹ã«ããæ©èœã®ã¯ã€ãã¯æ€çŽ¢ãšåæ§ã«ã
ãããŸã§ã®ãšãããç§ã¯å人çã«çŸåšã®æ©èœãååã«åããŠãããæ°ããæ©èœã¯è¿œå ããŸããã§ããããå°æ¥ãã®ãŠãŒãã£ãªãã£ã¯éçºãããŸãã
ProcessMemoryMapã¯ããªãŒãã³ãœãŒã¹ãããžã§ã¯ãã§ãã
ææ°ã®å®å®çãªãªãŒã¹ã¯ãåžžã«æ¬¡ã®ãªã³ã¯ããå ¥æã§ããŸããhttp ïŒ//rouse.drkb.ru/winapi.php#pmm2
ææ°ã®ã³ãŒãå€æŽãå«ãGitHubãªããžããªã¯ãhttps ïŒ//github.com/AlexanderBagel/ProcessMemoryMapã«ãããŸãã
ãœãŒã¹ã³ãŒããžã®çŽæ¥ãªã³ã¯ïŒhttps : //github.com/AlexanderBagel/ProcessMemoryMap/archive/master.zip
ææ°ãã«ããžã®çŽæ¥ãªã³ã¯ïŒhttp : //rouse.drkb.ru/files/processmm_bin.zip
èªå·±ã¢ã»ã³ããªã«ã¯ãVirtual TreeViewããŒãžã§ã³5以éã®ã³ã³ããŒãã³ãã®ã€ã³ã¹ããŒã«ããã±ãŒãžãå¿ èŠã§ãïŒhttp : //www.soft-gems.net/ã
ã¢ã»ã³ããªã¯ãDelphi XE4以éã䜿çšããŠãWin32 /ãªãªãŒã¹ãã¢ãŒãã§å®è¡ããããã®ãŠãŒãã£ãªãã£ã®64ãããããŒãžã§ã³ãèªåçã«ã¢ã»ã³ãã«ãããæ¥ç¶ãããŸãïŒãªãœãŒã¹ãšããŠïŒã
Delphiã®å€ãããŒãžã§ã³ã§ã¯ãProcessMemoryMapã¯ãã¹ããããŠããŸããã
10.çµè«ãšããŠ
ããŠããã®è³æãããªãã®åœ¹ã«ç«ã€ããšãé¡ã£ãŠããŸãããã¡ããããã¹ãŠã®è³æããã詳现ã«é瀺ãããšãèšäºã®éãéåžžã«å¢å ãããããæäžéšã®ã¿ã«è¡ããŸããã
ãã®ãããããã«ããå°ãæ å ±ãèŠã€ããããã«äœ¿çšã§ãããªã³ã¯ããããŸãã
TEB / PEBã·ã¹ãã æ§é ãªã©ã«é¢ããæ å ±ããã§èŠã€ããããšãã§ããŸãïŒ
http://processhacker.sourceforge.net/
http://redplait.blogspot.ru/
http://www.reactos.org/ru
PEãã¡ã€ã«ã«é¢ããæ å ±ïŒ
http://msdn.microsoft.com/ en-us / magazine / ms809762.aspx
SEHæ å ±ïŒ
http : //msdn.microsoft.com/en-us/library/ms680657(v=VS.85).aspx
http://www.microsoft.com/msj /0197/exception/exception.aspx
http://qxov.narod.ru/articles/seh/seh.html
ãã¹ãŠã®ãã¢äŸã®ãœãŒã¹ã³ãŒãã¯ããã®ãªã³ã¯ããååŸã§ããŸããDelphi Masters
ãã©ãŒã©ã ã«ãèšäºã®äœæã«ç¹°ãè¿ãååããŠãããããšã«æè¬ããŸããDmitryå¥åãPtiburdukovã®å åŒããAndrei Vasilievå¥åãInovetããããã³Sergeyå¥åãCartmanãã«æ ¡æ£è³æãæäŸããŠãããããšã«å人çã«æè¬ããŸãã
ããã°ã£ãŠã