病毒运行时可能会用到某些API,但如果导入表中没有的话,病毒的可移植性就不能保证。
已经知道ntdll.dll和kernel32.dll是每个进程都需要加载的,如果知道了kernel32在进程中的地址,就能找到LoadLibrary和GetProcAddress从而加载其他dll文件并调用里面的API。
以前学到过利用PEB结构来获得kernel32在进程中的基址
其实还有两种常用的方法
1.进程初始化时堆栈指针ESP指向ExitThread的地址,位置刚好在kernel32中。通过此地址向上搜索就可找到kernel32的基地址。
因为kernel32的SectionAlignment是64kb所以从ESP开始每次减小00010000h进行搜索。
别人写的搜索代码:
mov edx, [esp] ;此处为第一行代码,否则ESP可能被改变,就找不到地址了
.Next:
dec edx ;
xor dx, dx ; EDX每次减小10000h,相当好玩的方法,值得学习
cmp word [edx], "MZ" ;判断MZ标志
jz .IsPe
jmp .Next
.IsPe:
mov eax, [edx+3ch]
cmp word [eax+edx], 'PE' ;判断PE标志
jnz .Next
xchg eax, edx ;到此就可以确定是kernel32了,EAX中就是基地址
2.遍历SEH链,找到EXCEPTION_REGISTRATION结构prev为-1的异常处理过程地址,这个地址就在kernel32中。既然已经定位到kernel32了,再使用上面的搜索方式找基址就好。
定义:
struct EXCEPTION_REGISTRATION
{
EXCEPTION_REGISTRATION* prev;
DWORD handler;
};
mov edx, [fs:0] ;[fs:0]指向的就是SHE链,记得以前用过的是[fs:30]指向PEB
inc dword [edx] ;prev++,看是否为0
jz .isKernel ;为0说明prev = = -1,找到了
dec dword [edx] ;否则恢复,再找下一个
mov edx, [edx]
.isKernel:
dec dword [edx]
mov edx, [edx+4] ;EDX+4就是句柄值,在kernel32中,再进行搜索…
基本上就是这样