源代码:
DWORD GetSelfImageSize(HMODULE hModule)
{
DWORD dwImageSize;
_asm
{
mov ecx,0x30
mov eax, fs:[ecx]
mov eax, [eax + 0x0c]
mov esi, [eax + 0x0c]
add esi,0x20
lodsd
mov dwImageSize,eax
}
return dwImageSize;
}
fs段指向TEB(Thread environment block )结构,fs+30h指向了PEB(Process environment block)结构,PEB[0x0c]指向PEB_LDR_DATA结构,该结构有三个成员均可用于枚举当前进程空间中的模块列表,区别在于加载顺序、内存顺序、初始化顺序。在PEB_LDR_DATA+0x1c地方就是一些动态连接库的地址了,如第一个指向ntdll.dll 第二个就 是我们需要的kernel32.dll的地址(mov ebp, [eax + 0x08] //ebp 就是kernel32.dll的地址了)
LODS 装入串.
把源串中的元素(字或字节)逐一装入AL、AX或者EAX中。(LODSB 传送字符. LODSW 传送字. LODSD 传送双字)
写在后面的
TEB[0x30]是一个指向当前进程PEB(Process Environment Block)的指针。大家都这
么说,可他们如何知道这个偏移的,你该上哪去找TEB的数据结构定义,不同系统上
该结构定义一致吗。windbg的dt命令:
> dt ntdll!*teb* (列出匹配通配符的结构名)
ntdll!_TEB
... ...
> dt -v -r ntdll!_TEB
struct _TEB, 64 elements, 0xfb4 bytes
+0x000 NtTib : struct _NT_TIB, 8 elements, 0x1c bytes
+0x01c EnvironmentPointer : Ptr32 to Void
+0x020 ClientId : struct _CLIENT_ID, 2 elements, 0x8 bytes
+0x028 ActiveRpcHandle : Ptr32 to Void
+0x02c ThreadLocalStoragePointer : Ptr32 to Void
+0x030 ProcessEnvironmentBlock : Ptr32 to struct _PEB, 66 elements, 0x210 bytes
... ...
偏移、名称、类型、大小等等一应俱全地列举在此。
肯定有人见过这样的代码,之后eax将指向PEB:
mov eax,fs:[18h]
mov eax,[eax+30h]
这样的代码居然也能成功获取PEB地址,惟一的解释就是fs:[18h]与fs:0h指向同一处(注意方括号的使用)。TEB结构第一成员是NT_TIB结构,后者的Self成员指向自身这个NT_TIB结构,"碰巧"这个NT_TIB结构是TEB结构第一成员,于是可以认为Self指向TEB。Self的偏移是0x18,就这么简单。