静态分析EnumProcessModules

分析这个函数最初是因为 代码注入远程进程时 需要确定远程进程的模块基址
RING3下 通过调用EnumProcessModules来实现 仔细分析了下  实际上不需要调用函数
通过PEB结构直接就可以知道IMAGEBASE
.text:687E1981 ; BOOL __stdcall EnumProcessModules(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded)
.text:687E1981                 public _EnumProcessModules@16
.text:687E1981 _EnumProcessModules@16 proc near
.text:687E1981
.text:687E1981 var_9C          = dword ptr -9Ch
.text:687E1981 var_94          = byte ptr -94h
.text:687E1981 var_8C          = dword ptr -8Ch
.text:687E1981 var_7C          = dword ptr -7Ch
.text:687E1981 var_4C          = dword ptr -4Ch
.text:687E1981 Buffer          = dword ptr -48h
.text:687E1981 var_40          = byte ptr -40h
.text:687E1981 var_3C          = dword ptr -3Ch
.text:687E1981 var_24          = dword ptr -24h
.text:687E1981 var_18          = dword ptr -18h
.text:687E1981 var_14          = dword ptr -14h
.text:687E1981 var_10          = dword ptr -10h
.text:687E1981 var_4           = dword ptr -4
.text:687E1981 hProcess        = dword ptr  8
.text:687E1981 lphModule       = dword ptr  0Ch
.text:687E1981 cb              = dword ptr  10h
.text:687E1981 lpcbNeeded      = dword ptr  14h
.text:687E1981
.text:687E1981                 push    ebp
.text:687E1982                 mov     ebp, esp
.text:687E1984                 push    0FFFFFFFFh
.text:687E1986                 push    offset dword_687E1330
.text:687E198B                 push    offset __except_handler3
.text:687E1990                 mov     eax, large fs:0
.text:687E1996                 push    eax
.text:687E1997                 mov     large fs:0, esp ; 异常处理
.text:687E199E                 push    ecx
.text:687E199F                 push    ecx
.text:687E19A0                 sub     esp, 88h
.text:687E19A6                 push    ebx
.text:687E19A7                 push    esi
.text:687E19A8                 push    edi
.text:687E19A9                 mov     [ebp+var_18], esp
.text:687E19AC                 xor     ebx, ebx
.text:687E19AE                 push    ebx             ; &ReturnLength
.text:687E19AF                 push    18h             ; sizeof(PROCESS_BASIC_INFORMATION)
.text:687E19B1                 lea     eax, [ebp+var_40]
.text:687E19B4                 push    eax             ; &PROCESS_BASIC_INFORMATION
.text:687E19B5                 push    ebx             ; ProcessBasicInformation (0)
.text:687E19B6                 push    [ebp+hProcess]  ; hProcess
.text:687E19B9                 call    ds:__imp__NtQueryInformationProcess@20 ; NtQueryInformationProcess(x,x,x,x,x)
.text:687E19BF                 cmp     eax, ebx        ; PROCESS_BASIC_INFORMATION
.text:687E19C1                 jge     short loc_687E19D8 ;  ntStatus == STATUS_SUCCESS
.text:687E19C3                 push    eax
.text:687E19C4                 call    ds:__imp__RtlNtStatusToDosError@4 ; RtlNtStatusToDosError(x)
.text:687E19CA                 push    eax             ; dwErrCode
.text:687E19CB                 call    ds:__imp__SetLastError@4 ; SetLastError(x)
.text:687E19D1
.text:687E19D1 loc_687E19D1:                           ; CODE XREF: EnumProcessModules(x,x,x,x)+72j
.text:687E19D1                                         ; EnumProcessModules(x,x,x,x)+8Cj ...
.text:687E19D1                 xor     eax, eax
.text:687E19D3                 jmp     loc_687E1A9A
.text:687E19D8 ; ---------------------------------------------------------------------------
.text:687E19D8
.text:687E19D8 loc_687E19D8:                           ; CODE XREF: EnumProcessModules(x,x,x,x)+40j
.text:687E19D8                 push    ebx             ; lpNumberOfBytesRead
.text:687E19D9                 push    4               ; nSize
.text:687E19DB                 lea     eax, [ebp+Buffer]
.text:687E19DE                 push    eax             ; lpBuffer
.text:687E19DF                 mov     eax, [ebp+var_3C] ; PROCESS_BASIC_INFORMATION.PPEB
.text:687E19E2                 add     eax, 0Ch        ; &PPEB->Ldr
.text:687E19E5                 push    eax
.text:687E19E6                 push    [ebp+hProcess]  ; hProcess
.text:687E19E9                 mov     edi, ds:__imp__ReadProcessMemory@20 ; ReadProcessMemory(x,x,x,x,x)
.text:687E19EF                 call    edi ; ReadProcessMemory(x,x,x,x,x) ; ReadProcessMemory(x,x,x,x,x)
.text:687E19F1                 test    eax, eax        ; 读取到Ptr32 _PEB_LDR_DATA
.text:687E19F3                 jz      short loc_687E19D1
.text:687E19F5                 mov     eax, [ebp+Buffer] ; ebp+buffer 存放的是_PEB_LDR_DATA结构的地址
.text:687E19F8                 add     eax, 14h        ; &_PEB_LDR_DATA.InMemoryOrderModuleList
.text:687E19FB                 mov     [ebp+var_4C], eax
.text:687E19FE                 push    ebx             ; lpNumberOfBytesRead
.text:687E19FF                 push    4               ; nSize
.text:687E1A01                 lea     ecx, [ebp+var_24]
.text:687E1A04                 push    ecx             ; lpBuffer
.text:687E1A05                 push    eax             ; &_PEB_LDR_DATA.InMemoryOrderModuleList
.text:687E1A06                 push    [ebp+hProcess]  ; hProcess
.text:687E1A09                 call    edi ; ReadProcessMemory(x,x,x,x,x) ; ReadProcessMemory(x,x,x,x,x)
.text:687E1A0B                 test    eax, eax        ; 读取到 _PEB_LDR_DATA.InMemoryOrderModuleList
.text:687E1A0D                 jz      short loc_687E19D1
.text:687E1A0F                 mov     esi, [ebp+cb]   ; size in bytes
.text:687E1A12                 shr     esi, 2          ; size in dwords
.text:687E1A15                 mov     eax, [ebp+var_24] ; InMemoryOrderModuleList.flink(flink指向下一个的_PEB_LDR_DATA的ListEntry段)
.text:687E1A18
.text:687E1A18 loc_687E1A18:                           ; CODE XREF: EnumProcessModules(x,x,x,x)+D3j
.text:687E1A18                 cmp     eax, [ebp+var_4C] ; 链表遍历结束
.text:687E1A1B                 jz      short loc_687E1A86
.text:687E1A1D                 push    0               ; lpNumberOfBytesRead
.text:687E1A1F                 push    48h             ; nSize
.text:687E1A21                 lea     ecx, [ebp+var_94]
.text:687E1A27                 push    ecx             ; lpBuffer
.text:687E1A28                 add     eax, 0FFFFFFF8h
.text:687E1A2B                 push    eax             ; lpBaseAddress
.text:687E1A2C                 push    [ebp+hProcess]  ; hProcess
.text:687E1A2F                 call    edi ; ReadProcessMemory(x,x,x,x,x) ; ReadProcessMemory(x,x,x,x,x)
.text:687E1A31                 test    eax, eax        ; 读取 InLoadOrderModuleList.flink开始的48H个字节
.text:687E1A33                 jz      short loc_687E19D1
.text:687E1A35                 cmp     ebx, esi
.text:687E1A37                 jnb     short loc_687E1A4A
.text:687E1A39                 and     [ebp+var_4], 0
.text:687E1A3D                 mov     eax, [ebp+var_7C]; _PEB_LDR_DATA.EntryInProgress
.text:687E1A40                 mov     ecx, [ebp+lphModule]
.text:687E1A43                 mov     [ecx+ebx*4], eax
.text:687E1A46                 or      [ebp+var_4], 0FFFFFFFFh
.text:687E1A4A
.text:687E1A4A loc_687E1A4A:                           ; CODE XREF: EnumProcessModules(x,x,x,x)+B6j
.text:687E1A4A                 inc     ebx
.text:687E1A4B                 mov     eax, [ebp+var_8C];InMemoryOrderModuleList.flink
.text:687E1A51                 mov     [ebp+var_24], eax
.text:687E1A54                 jmp     short loc_687E1A18 ; 链表遍历结束

上面可以看出函数得到进程中各模块的基址  是通过InMemoryOrderModuleList.Flink来遍历的
我们知道EnumProcessModules函数得到的hModule数组中hModule[0]中存放的就是进程基址,而
从上面的反汇编可以看出 hModule[0]里存放的是_PEB_LDR_DATA[1]中的EntryInProgress
_PEB_LDR_DATA[0]中的是EntryInProgress为0,_PEB_LDR_DATA[0]很明显作为双链表的表头来使用
_PEB_LDR_DATA.InMemoryOrderModuleList故名思义 它指向的双链表 是按照在内存中虚拟地址的大小的排列顺序链接的
_PEB_LDR_DATA.InInitializationOrderModuleList 指向的双链表 链接的是初始化时的_PEB_LDR_DATA结构
_PEB_LDR_DATA.InLoadOrderModuleList 它所指向的双链表 是按照载入内存的先后顺序来排列的 ring3其中一个
隐藏模块技术就是 断掉InMemoryOrderModuleList指向的双链表
远程线程中得到进程模块基址 只需要插几句汇编就行
mov eax,fs:[30h]  ;Ptr32 _PEB
mov ebx,[eax+8h]   ;进程的基址
或者
mov eax,fs:[30h]  ;Ptr32 _PEB
mov eax,[eax+0ch]   ;Ptr32  _PEB_LDR_DATA
mov eax,[eax+14h] ;_PEB_LDR_DATA[1]
mov edx,[eax+10h] ;edx存放的就是进程基址
注:后来查了下网上的资料 _PEB_LDR_DATA的3条链表 实际指向的是_LDR_MODULE结构 但是XP下_PEB_LDR_DATA结构增加了entryinprocess字段 所以只取基址的话 无影响 
只取基址的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值