2.windbg-PE完整分析

1.PE结构常用的结构体

0:001> dt ntdll!*IMAGE*
          ntdll!_IMAGE_NT_HEADERS
          ntdll!_IMAGE_FILE_HEADER
          ntdll!_IMAGE_OPTIONAL_HEADER
          ntdll!_IMAGE_DOS_HEADER
          ntdll!_IMAGE_DATA_DIRECTORY
仅在exe使用了winnt.h(驱动ntimage.h)才会显示其他结构体,如IID:
0:001> dt ole32!_IMAGE_IMPORT_DESCRIPTOR
   +0x000 Characteristics  : Uint4B
   +0x000 OriginalFirstThunk : Uint4B
   +0x004 TimeDateStamp    : Uint4B
   +0x008 ForwarderChain   : Uint4B
   +0x00c Name             : Uint4B
   +0x010 FirstThunk       : Uint4B

2.DOS头

0:001> lmvm kernel32
start    end        module name
76d00000 76e10000   kernel32   (pdb symbols)          c:\mysymbol\wkernel32.pdb\69083C6D23244DC3BF8B73A9EE01C7742\wkernel32.pdb
    Loaded symbol image file: C:\Windows\syswow64\kernel32.dll
    Image path: C:\Windows\syswow64\kernel32.dll
0:001> dt ntdll!_IMAGE_DOS_HEADER 76d00000 
   +0x000 e_magic          : 0x5a4d
   +0x002 e_cblp           : 0x90
   +0x004 e_cp             : 3
   +0x006 e_crlc           : 0
   +0x008 e_cparhdr        : 4
   +0x00a e_minalloc       : 0
   +0x00c e_maxalloc       : 0xffff
   +0x00e e_ss             : 0
   +0x010 e_sp             : 0xb8
   +0x012 e_csum           : 0
   +0x014 e_ip             : 0
   +0x016 e_cs             : 0
   +0x018 e_lfarlc         : 0x40
   +0x01a e_ovno           : 0
   +0x01c e_res            : [4] 0
   +0x024 e_oemid          : 0
   +0x026 e_oeminfo        : 0
   +0x028 e_res2           : [10] 0
   +0x03c e_lfanew         : 232   // 指向PE头

3.PE头

0:001> dt ntdll!_IMAGE_NT_HEADERS 76d00000+0n232
   +0x000 Signature        : 0x4550
   +0x004 FileHeader       : _IMAGE_FILE_HEADER
   +0x018 OptionalHeader   : _IMAGE_OPTIONAL_HEADER
0:001> ? 76d00000+0n232
Evaluate expression: 1993343208 = 76d000e8    // PE头地址

4.可选头中找到EXPORT表基地址

0:001> dt ntdll!_IMAGE_OPTIONAL_HEADER -v -ny DataDirectory 76d000e8+0x018 
struct _IMAGE_OPTIONAL_HEADER, 31 elements, 0xe0 bytes
   +0x060 DataDirectory : [16] struct _IMAGE_DATA_DIRECTORY, 2 elements, 0x8 bytes
DataDirectory[0]即为导出表,地址为76d00160
0:001> ? 76d000e8+0x018+0x060 
Evaluate expression: 1993343328 = 76d00160

5.找到EXPORT实际地址

0:001> dt ole32!_IMAGE_DATA_DIRECTORY 76d00160
   +0x000 VirtualAddress   : 0xc0070
   +0x004 Size             : 0xa9b1
0:001> ? 76d00000+0xc0070   //kernel32基地址+VA
Evaluate expression: 1994129520 = 76dc0070 
0:001> dt ole32!IMAGE_EXPORT_DIRECTORY  76dc0070
   +0x000 Characteristics  : 0
   +0x004 TimeDateStamp    : 0x5609edc5
   +0x008 MajorVersion     : 0
   +0x00a MinorVersion     : 0
   +0x00c Name             : 0xc35e0  // 模块的真实名称
   +0x010 Base             : 1        // 基数,加上序数就是函数地址数组的索引
   +0x014 NumberOfFunctions : 0x554   // 指向的数组元素个数
   +0x018 NumberOfNames    : 0x554    // 指向的数组元素个数
   +0x01c AddressOfFunctions : 0xc0098// 指向函数地址数组
   +0x020 AddressOfNames   : 0xc15e8  // 指向函数名字数组
   +0x024 AddressOfNameOrdinals : 0xc2b38// 指向输出序号数组

6.遍历EXPORT

模块名:
0:001> da 76d00000+0xc35e0
76dc35e0  "KERNEL32.dll"

原理:AddressOfNames和AddressOfNameOrdinals一样多,一个名字肯定只有一个地址(function),但一个地址可能有多个名字(name)

先用loadpe看下kernel32:


函数遍历
0:001> .foreach(place {dd 76dc0098 L10}){ln ${place}+76d00000} 
(76d13368)   kernel32!BaseThreadInitThunk   |  (76d13386)   kernel32!ConDllInitialize
Exact matches:
    kernel32!BaseThreadInitThunk = <no type information>
(76dc0070)   kernel32!$$VProc_ImageExportDirectory+0xa434   |  (76de0000)   kernel32!BasepAllowResourceConversion
(76dc0070)   kernel32!$$VProc_ImageExportDirectory+0x9eb5   |  (76de0000)   kernel32!BasepAllowResourceConversion
(76dc0070)   kernel32!$$VProc_ImageExportDirectory+0x9ed6   |  (76de0000)   kernel32!BasepAllowResourceConversion
(76d15448)   kernel32!ActivateActCtx   |  (76d15479)   kernel32!ReleaseActCtx
Exact matches:
    kernel32!ActivateActCtx = <no type information>
(76d2ed3e)   kernel32!AddAtomA   |  (76d2edb4)   kernel32!FindAtomA
Exact matches:
    kernel32!AddAtomA = <no type information>
(76d2cdd4)   kernel32!AddAtomW   |  (76d2cdee)   kernel32!DeleteAtom
Exact matches:
    kernel32!AddAtomW = <no type information>
(76db6b86)   kernel32!AddConsoleAliasA   |  (76db6be3)   kernel32!GetConsoleAliasW
Exact matches:
    kernel32!AddConsoleAliasA = <no type information>
(76db6b1c)   kernel32!AddConsoleAliasW   |  (76db6b86)   kernel32!AddConsoleAliasA
Exact matches:
    kernel32!AddConsoleAliasW = <no type information>
(76dc0070)   kernel32!$$VProc_ImageExportDirectory+0x9ef4   |  (76de0000)   kernel32!BasepAllowResourceConversion
(76d94f72)   kernel32!AddIntegrityLabelToBoundaryDescriptor   |  (76d94f9d)   kernel32!CreatePrivateNamespaceA
Exact matches:
    kernel32!AddIntegrityLabelToBoundaryDescriptor = <no type information>
(76d87538)   kernel32!AddLocalAlternateComputerNameA   |  (76d87581)   kernel32!RemoveLocalAlternateComputerNameW
Exact matches:
    kernel32!AddLocalAlternateComputerNameA = <no type information>
(76d8744d)   kernel32!AddLocalAlternateComputerNameW   |  (76d87538)   kernel32!AddLocalAlternateComputerNameA
Exact matches:
    kernel32!AddLocalAlternateComputerNameW = <no type information>
(76d2d510)   kernel32!AddRefActCtx   |  (76d2d521)   kernel32!GetCurrentActCtx
Exact matches:
    kernel32!AddRefActCtx = <no type information>
(76d3915f)   kernel32!AddSIDToBoundaryDescriptor   |  (76d39257)   kernel32!LocalOpenPerformanceData
Exact matches:
    kernel32!AddSIDToBoundaryDescriptor = <no type information>
(76d8f4c2)   kernel32!AddSecureMemoryCacheCallback   |  (76d8f4ea)   kernel32!RemoveSecureMemoryCacheCallback
Exact matches:
    kernel32!AddSecureMemoryCacheCallback = <no type information>

函数名遍历
0:001> .foreach(place {dd 76dc15e8}){r @$t0=${place}+76d00000; .if(@$t0<86d00000){da @$t0}} 
76dc35ed  "AcquireSRWLockExclusive"
76dc3605  "AcquireSRWLockShared"
76dc361a  "ActivateActCtx"
76dc3629  "AddAtomA"
76dc3632  "AddAtomW"
76dc363b  "AddConsoleAliasA"
76dc364c  "AddConsoleAliasW"
76dc365d  "AddDllDirectory"
76dc366d  "AddIntegrityLabelToBoundaryDescr"
76dc368d  "iptor"
76dc3693  "AddLocalAlternateComputerNameA"
76dc36b2  "AddLocalAlternateComputerNameW"
76dc36d1  "AddRefActCtx"
76dc36de  "AddSIDToBoundaryDescriptor"
76dc36f9  "AddSecureMemoryCacheCallback"
76dc3716  "AddVectoredContinueHandler"
76dc3731  "AddVectoredExceptionHandler"
76dc374d  "AdjustCalendarDate"
76dc3760  "AllocConsole"
76dc376d  "AllocateUserPhysicalPages"
76dc3787  "AllocateUserPhysicalPagesNuma"
76dc37a5  "ApplicationRecoveryFinished"
76dc37c1  "ApplicationRecoveryInProgress"
76dc37df  "AreFileApisANSI"
76dc37ef  "AssignProcessToJobObject"
76dc3808  "AttachConsole"
76dc3816  "BackupRead"
76dc3821  "BackupSeek"
76dc382c  "BackupWrite"
76dc3838  "BaseCheckAppcompatCache"
76dc3850  "BaseCheckAppcompatCacheEx"
76dc386a  "BaseCheckRunApp"
76dc387a  "BaseCleanupAppcompatCacheSupport"
76dc389a  ""
因为传参会把地址也传进去,所以加了个限制范围,过滤地址,只要内容

7.遍历IMPORT

0:001> dt ole32!_IMAGE_DATA_DIRECTORY 76d00160+8
   +0x000 VirtualAddress   : 0xcaa24
   +0x004 Size             : 0x1f4
0:001> ? 76d00000+0xcaa24
Evaluate expression: 1994172964 = 76dcaa24
DataDirectory[1]即为导入表,地址为76dcaa24
0:001> dt ole32!_IMAGE_IMPORT_DESCRIPTOR 76dcaa24
   +0x000 Characteristics  : 0xcaf6c
   +0x000 OriginalFirstThunk : 0xcaf6c // 输入表名(INT)
   +0x004 TimeDateStamp    : 0
   +0x008 ForwarderChain   : 0
   +0x00c Name             : 0xcaf44
   +0x010 FirstThunk       : 0x10000  // 输入地址表(IAT)

_IMAGE_IMPORT_DESCRIPTOR的大小为
0:001> ?? sizeof(_IMAGE_IMPORT_DESCRIPTOR)
unsigned int 0x14

遍历IID得到所有输入表试试
0:001> da 76d00000 + 0xcaf44
76dcaf44  "API-MS-Win-Core-RtlSupport-L1-1-"
76dcaf64  "0.dll"
0:001> dt ole32!_IMAGE_IMPORT_DESCRIPTOR 76dcaa24+0x14
   +0x000 Characteristics  : 0xcaf7c
   +0x000 OriginalFirstThunk : 0xcaf7c
   +0x004 TimeDateStamp    : 0
   +0x008 ForwarderChain   : 0
   +0x00c Name             : 0xcaf38
   +0x010 FirstThunk       : 0x10010
0:001> da 76d00000 + 0xcaf38
76dcaf38  "ntdll.dll"
分析第一个IID的IAT和INT吧:
先看INT:
IMAGE_THUNK_DATA其实就是一个DWORD,如IID一样,也是一个接一个,最后一个为NULL
第一个:
0:001> dd 0xcaf7c+76d00000 L1
76dcaf7c  000cbd98
最高位不为1(为1表示为序号输入)
指向_IMAGE_IMPORT_BY_NAME结构
0:001> .foreach(place {dd 76dcaf7c}) {r @$t0 = ${place}+76d00000+2; .if (@$t0<86d00000){da @$t0;}}
76dcbd9a  "NtCreateEvent"
76dcbdaa  "NtDuplicateObject"
76dcbdbe  "RtlConvertSidToUnicodeString"
76dcbdde  "NtNotifyChangeKey"
76dcbdf2  "RtlRunOnceInitialize"
76dcbe0a  "NtResetEvent"
76dcbe1a  "RtlValidSecurityDescriptor"
76dcbe38  "RtlOpenCurrentUser"
76dcbe4e  "strncat"
76dcbe58  "_strlwr"
76dcbe62  "NtQueryInstallUILanguage"
76dcbe7e  "RtlpConvertCultureNamesToLCIDs"
76dcbea0  "RtlpConvertLCIDsToCultureNames"
76dcbec2  "EtwEventEnabled"
76dcbed4  "RtlSetProcessPreferredUILanguage"
76dcbef4  "s"
76dcbef8  "RtlExpandEnvironmentStrings_U"
76dcbf18  "RtlUnicodeStringToInteger"
76dcbf34  "RtlLCIDToCultureName"
76dcbf4c  "RtlIdnToUnicode"
76dcbf5e  "RtlIdnToNameprepUnicode"
76dcbf78  "RtlIdnToAscii"
76dcbf88  "RtlIsNormalizedString"
76dcbfa0  "RtlNormalizeString"
76dcbfb6  "RtlIntegerToUnicodeString"
76dcbfd2  "_ui64tow"
76dcbfde  "_wtol"
76dcbfe6  "_wcslwr"
76dcbff0  "RtlUnhandledExceptionFilter"
76dcc00e  "NtTerminateProcess"
76dcc024  "wcsncpy"
76dcc02e  "wcsncmp"
76dcc038  "RtlReadThreadProfilingData"
对比loadpe










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值