里的ecx值
cld
rep cmpsb
jne FindNext//如果当前函数不是指定的函数则查找下一个
add esp,4//如果查找成功,则清除用于控制外层循环而压入的Ecx,准备返回
mov eax,[IED]
mov eax,[eax+0x1c]
add eax,ImageBase//获得函数地址表
shl Count,2//根据函数索引计算函数地址指针=函数地址表基址+(函数索引*4)
add eax,Count
mov eax,[eax]//获得函数地址相对偏移量
add eax,ImageBase//计算函数真实地址,并通过Eax返回给调用者
jmp Found
FindNext:
inc Count//记录函数索引
add [FunNameArray],4//下一个函数名指针
mov eax,FunNameArray
pop ecx//恢复压入的ecx(NumberOfFunctions),进行计数循环
loop FindLoop//如果ecx不为0则递减并回到FindLoop,往后查找
NotFound:xor eax,eax//如果没有找到,则返回0
Found:
}
}
/*
让我们来测试一下,先用GetFunctionByName获得kernel32.dll中LoadLibraryA
的地址,再用它装载user32.dll,再用GetFunctionByName获得MessageBoxA的地址,call
它一下
*/
int main(void)
{
char title[]="test",user32[]="user32",msgf[]="MessageBoxA";
unsigned int loadlibfun;
loadlibfun=GetFunctionByName(0x77e60000,"LoadLibraryA",12);
//0x77e60000是我机器上的kernel32.dll的基址,不同机器上的值可能不同
__asm
{
lea eax,user32
push eax
call dword ptr loadlibfun //相当于执行LoadLibrary("user32");
lea ebx,msgf
push 0x0b//"MessageBoxA"的长度
push ebx
push eax
call GetFunctionByName
mov ebx,eax
add esp,0x0c//GetFunctionByName使用C调用约定,由调用者调整堆栈
push 0
lea eax,title
push eax
push eax
push 0
call ebx//相当于执行MessageBox(NULL,"test","test",MB_OK)
}
return 1;
}
函数的内联汇编代码有很多这样的语句:
mov eax,[somewhere]
mov eax,[eax+0x??]
add eax,ImageBase
我试过使用mov eax,[ImageBase+eax+0x??]之类的语法,因为用到很多多级指针,而它们指向的又是相对偏移量所以要不断的"获取和计算",否则很容易导致"访问违例".编译运行,弹出了一个MessageBox标题和内容都是"test"看到了吗?你可能会问这个程序拿到其它机器上也可能运行吗?在整个程序里我们唯一依赖的就是0x77e60000这个kernel32.dll基址,其它机器上的可能不是这个值,如果这个地址值可以在程序运行时动态的计算出来,那么这个程序将非常通用,它可以动态计算出来吗?答案是肯定的!下一节我们将来分析一种并不很流行但很通用的动态计算获得kernel32.dll基址的方法.
二,在动态获得Kernel32.DLL地址方法的分析
1,简析结构化异常处理(SEH,Structred Exception Handling)
SEH已经不是很什么新技术了,但是对于我将要讲了非常重要,所以在这里对它做一个简单的分析.Ok,打开VC,让我们来分析一个简单的"除"
;运算程序,看看它哪里有问题:
#include <stdio.h>
#include <conio.h>
int main(void)
{
int x,y,z=y=x=0;
printf("Input two integer numbe