#include
#include
__inline __declspec(naked) unsigned int findkerneldll(){
__asm{
push esi
push edi
push ecx
xor ecx, ecx
mov esi, fs:0x30
mov esi, [esi + 0x0c]
mov esi, [esi + 0x1c]
next_module:
mov eax, [esi + 0x8]
mov edi,[esi+0x20]
mov esi ,[esi]
cmp [edi+12*2],cx
jne next_module
pop ecx
pop edi
pop esi
Ret
}
}
unsigned int GetFunctionByName(unsigned int ImageBase,const char*FuncName,int flen)
{
unsigned int FunNameArray,PE,Count=0,*IED;
__asm
{
mov eax,ImageBase
add eax,0x3c//指向PE头部偏移值e_lfanew
mov eax,[eax]//取得e_lfanew值
add eax,ImageBase//指向PE header
//cmp [eax],0x00004550
//jne NotFound//如果ImageBase句柄有错
mov PE,eax
mov eax,[eax+0x78]
add eax,ImageBase
mov [IED],eax//指向IMAGE_EXPORT_DIRECTORY
mov eax,[eax+0x20]
add eax,ImageBase
mov FunNameArray,eax//保存函数名称指针数组的指针值
mov ecx,[IED]
mov ecx,[ecx+0x14]//根据引出函数个数NumberOfFunctions设置最大查找次数
FindLoop:
push ecx//使用一个小技巧,使用程序循环更简单
mov eax,[eax]
add eax,ImageBase
mov esi,FuncName
mov edi,eax
mov ecx,flen//逐个字符比较,如果相同则为找到函数,注意这里的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: nop
}
}
typedef HMODULE (WINAPI *fun_ptr)(LPCSTR);
int main()
{
unsigned int keradd;
unsigned int loadlibfun,getprofun;
HANDLE lh,mytest;
fun_ptr pmytestfun;
unsigned int test;
char title[]="test",user32[]="user32.dll",msgf[]="MessageBoxA";
lh = LoadLibraryA("kernel32.dll");
printf("real--kernel32.dll--:%x\n",lh);
printf("real\"LoadLibraryA\" :%x\n",(unsigned int)LoadLibraryA);
printf("real\"GetProcAddress\" :%x\n",(unsigned int)GetProcAddress);
lh = LoadLibraryA("user32.dll");
printf("real--user32.dll--:%x\n",lh);
test = (unsigned int)GetProcAddress(lh,"MessageBoxA");
printf("real\"MessageBoxA\":%x\n\n",(unsigned int)MessageBoxA);
keradd = findkerneldll();
printf("my kernel32.dll:%x\n",keradd);
getprofun=GetFunctionByName(keradd,"GetProcAddress",14);
loadlibfun=GetFunctionByName(keradd,"LoadLibraryA",12);
printf("my \"LoadLibraryA\":%x\n",loadlibfun);
printf("my \"GetProcAddress\":%x\n",getprofun);
pmytestfun=(fun_ptr)loadlibfun;
mytest=pmytestfun("user32.dll");
printf("my user32.dll:%x\n",(unsigned int)mytest );
printf("my \"MessageBoxA\":%x\n",GetFunctionByName((unsigned int)mytest,"MessageBoxA",11));
// __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 0;
}