// KernelTest.cpp : 定义控制台应用程序的入口点。
//
/*
调用函数一般过程
1:一般来说调用一个函数习惯是导入所需要的头文件
2:调用具体的函数
不导入头文件如何调用函数
1:通过动态调用的方法LoadLibaryW()
2: 调用GetProcAddress()
3:根据获取的函数指针调用具体的函数
今天所说的是通过Kernel32.dll基地址调用函数
1:根据fs:[30]通过一系列步骤查找到kernel32.dll的基地址
ps这里需要有关于PE导出表的知识需要自行观看相关书籍推荐PE权威指南
2:根据基地址查找这两个函数的地址LoadLibary GetProcAddress
3:步骤跟上面的一样了,只需要调用函数即可
*/
#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
//添加windows.h是为了定义的方便
//MessageBoxW()函数类型
typedef int (WINAPI *MsgBox)(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
//LoadLibaryW()函数类型
typedef HMODULE (WINAPI *LQLoadLibrary)( _In_ LPCTSTR lpFileName);
//GetProcAddress()函数类型
typedef FARPROC (WINAPI *LQGetProcAddress)(HMODULE hModule,LPCSTR lpProcName );
int _tmain(int argc, _TCHAR* argv[])
{
char*GetProcAddress="GetProcAddress";
char*MyLoadLibrary="LoadLibraryW";
HMODULE lib=NULL;
//申明三个函数指针
LQLoadLibrary ld;
LQGetProcAddress addr;
MsgBox mb;
DWORD hModule=0;
//获取kernel32.dll基地址,网上有详细解释
__asm
{
push eax
mov eax, fs:[30h] //PEB 址, mov eax, fs:[18h] 这个获得TEB地址
mov eax, [eax + 0Ch]
mov eax, [eax + 1Ch]
mov eax, [eax]
mov eax, [eax]
mov eax, [eax + 8]
mov hModule, eax
pop eax
}
printf("%x\n",hModule);
//根据导出表获取具体函数地址,具体的可以参考市面上众多的PE文件解析书籍
IMAGE_DOS_HEADER *pIDH=(IMAGE_DOS_HEADER*)(hModule);
IMAGE_NT_HEADERS *pINH=(IMAGE_NT_HEADERS*)(hModule+pIDH->e_lfanew);
//偏移78是导出表地址rva
IMAGE_DATA_DIRECTORY *pIDD=(IMAGE_DATA_DIRECTORY*)((DWORD)pINH+0x78);
//导出表
IMAGE_EXPORT_DIRECTORY *pIED=(IMAGE_EXPORT_DIRECTORY*)(hModule+pIDD->VirtualAddress);
//AddressOfNameOrdinals的起始地址
USHORT * AddressOfNameOrdinals=(USHORT*)(hModule+pIED->AddressOfNameOrdinals);
//函数地址
DWORD *arrayAdress=(DWORD*)(pIED->AddressOfFunctions+hModule);
PVOID getProcAddress=NULL;
//函数名称地址
DWORD Name=pIED->AddressOfNames+hModule;
//AddressOfNameOrdinals的起始地址
SHORT *ordinals=(SHORT*)(pIED->AddressOfNameOrdinals+hModule);
//计数器
int count=-1;
//是否找到函数
bool isfound=false;
//便利所有的有名称的函数
for(int i=0;i<pIED->NumberOfNames;i++){
//这个比下面的后执行经过我的测试
if(!isfound&&strcmp((char*)(*(DWORD*)Name+hModule),MyLoadLibrary)==0){
printf("%s",(char*)(*(DWORD*)Name+hModule));
//复制函数指针
ld=(LQLoadLibrary)(hModule+arrayAdress[ordinals[i]]);
//调用函数
lib=ld(_T("user32.dll"));
//跳出循环
break;
isfound=true;
}
if(strcmp((char*)(*(DWORD*)Name+hModule),GetProcAddress)==0){
printf("%s\n",(char*)(*(DWORD*)Name+hModule));
//赋值函数指针
addr=(LQGetProcAddress)(arrayAdress[ordinals[i]]+hModule);
printf("finished Get %x\n",addr);
}
//名字指针往后走
Name+=4;
}
if(lib!=INVALID_HANDLE_VALUE&&lib!=NULL){
//调用函数
mb=(MsgBox)addr(lib,"MessageBoxW");
mb(NULL,_T("ff"),_T("ff"),0);
printf("finished Load %x\n",lib);
}else{
printf(" Load error ");
}
//这里还有一个FreeLibary函数就不写了,可以根据上面的写下来了
system("pause");
return 0;
}
来看一下效果图