原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题
第一种方法
通过线程初始化时, 获得esp堆栈指针中的ExitThread函数的地址,然后通过搜索获得kernel32.dll的基地址。
线程在被初始化的时,其堆栈指针指向ExitThread函数的地址,windows这样做是为了通过ret返回时来调用ExitThread地址。所以一般我们可以在我们主线程的起始位置(也就是
程序入口点处)通过获得堆栈指针中ExitThread函数(当然你要想创建一个线程时候获得也可以)
我们直接通过
mov edx, [esp] ;获得堆栈指针中ExitThread地址到edx寄存器。因为ExitThread地址在kernel32.dll空间中,所以我们可以通过它往上搜索来获得基地址。
分析过kernel32.dll的朋友应该都知道kernel32.dll的块对齐值是00001000h, 并且一般DLL以1M为边界,所以我们可以通过10000h (64k) 作为跨度,这样可以增加搜索速度。我们如何确定这个地址是基地址,我们都知道我们判断这个地址的前两个字节是否是"MZ",然后定位到PE头结构,然后判断是否是"PE",如果这两个都符合的话则表示我们的地址则是基地址了.
注意,程序要用汇编编写,至少我不会用VC来内联编写,应为这个方法需要在程序的一开始就获取,而用VC编写的会有启动函数,也就是mainCRTStartup这些
代码如下:
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib user32.lib
includelib kernel32.lib
.const
szFormat db 'kernel32.dll address is: %x', 0dh, 0ah, 0
szFormat1 db 'LoadLibrary kernel32.dll address is: %x', 0dh, 0ah, 0
szKrnl32 db 'kernel32.dll', 0
.data?
hStdOut dd ?
dwWriteBytes dd ?
szBuffer db 1024 (?)
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 获取字符串长度
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
GetStrLen proc _lpString
mov edi, _lpString
or ecx, 0ffffffffh ; ecx初值等于-1
xor eax, eax
repnz scasb ; 循环扫描,每循环执行一次,ecx-1,直到出现0为止,0也会减1
; 一个公式(摘自《C++反汇编与逆向分析技术揭秘》P