下面的2个函数我是照抄windows程序设计上的...可是居然每用。
一个是打印全部导入的函数,另外一个是修改PE文件的导入表的MessageBoxA这个函数....
可是问题是 打印全部导入函数的回报错.还有修改PE文件的也回找不到MessageBoxA这个函数...为什么...!
#include <windows.h>
#include <iostream>///这个HOOK API是借助修改PE文件的导入表来替换MESSAGEBOX的函数地址来实现的using namespace std;//挂钩指定模块hmod对MESSAGEBOXA的调用
BOOL SetHook(HMODULE hMod);
//定义messageboxa的函数原形
typedef int (WINAPI *PFUNC)(HWND, LPCSTR,LPCSTR,UINT);PROC g_orgProc = (PROC)MessageBoxA;//保存函数的地址
//这个函数打印了导入的所有函数
void PrintAllImportFunc(HMODULE hMod)
{
IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)hMod;//PE文件是从64字节的DOS头开始的
//DOS头里的E_lfanew是NT头的offset量,加上hmod就得到了NT头的地址
//然后NT头里先是4字节的“PE00”字符,然后是20字节的饿不止到什么,再然后是OPTINAL头
IMAGE_OPTIONAL_HEADER *pOptHeader=(IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + pDosHeader->e_lfanew+24);
//在OPTINAL头里保存了很多的信息,这里是得到导入表的地址
IMAGE_IMPORT_DESCRIPTOR *pImportDes = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hMod+pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while(pImportDes->FirstThunk)
{
char* pszDllName = (char*)(BYTE*)hMod + pImportDes->Name;
cout<<"模块名称:"<<pszDllName<<endl;
//一个IMAGE_THUNK_DATA是一个双字,它指定了一个导入函数
IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hMod+pImportDes->OriginalFirstThunk);
int n=0;
while(pThunk->u1.Function)
{
//取得函数名称.hint/name表前2个字节是函数序号,后面的是名称
char *pszFuncName = (char*)((BYTE*)pThunk->u1.AddressOfData+2);
//取得函数地址,IAT就是一个DWORD叔祖
PDWORD lpAddr = (DWORD*)((BYTE*)hMod+pImportDes->FirstThunk)+n;
//打印
printf("从此模块导入的函数: %-25s",pszFuncName);
printf("函数地址: %X\n", lpAddr);
n++;
pThunk++;
}
cout<<endl;
pImportDes++;
}}int WINAPI MyMessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCation, UINT type)
{
return ((PFUNC)g_orgProc)(hWnd, "new function","Demo",type);
}BOOL SetHook(HMODULE hMod)
{
IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)hMod;//PE文件是从64字节的DOS头开始的
//DOS头里的E_lfanew是NT头的offset量,加上hmod就得到了NT头的地址
//然后NT头里先是4字节的“PE00”字符,然后是20字节的饿不止到什么,再然后是OPTINAL头
IMAGE_OPTIONAL_HEADER *pOptHeader=(IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + pDosHeader->e_lfanew+24);
//得到导入表的地址
IMAGE_IMPORT_DESCRIPTOR *pImportDes = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hMod+pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); //在导入表中寻找USER32.DLL模块,因为MESSAGEBOXA是从USER32.DLL里导出的
while(pImportDes->FirstThunk)//导入表的FirstThunk指向一个导入表的数组,以\0为结尾
{
char* pszDllName = (char*)((BYTE*)hMod+pImportDes->Name);
if(strcmp(pszDllName,"USER32.dll")==0)
{
break;
}
pImportDes++;
} if(pImportDes->FirstThunk)
{
//一个IMAGE——THUNK-DATA结构是一个DWORD,它指定了一个导入函数
//导入地址表其实是一个IMAGE_THUNK_DATA的数组,也就是DWORD数组
IMAGE_THUNK_DATA *pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hMod+pImportDes->FirstThunk); while(pThunk->u1.Function)//这个应该是导入模块的函数地址
{
//lpAddr指向的内存保存了函数地址
DWORD *lpAddr = (DWORD*)&(pThunk->u1.Function); if(*lpAddr == (DWORD)g_orgProc)//如果这个函数是MESSAGEBOXA的话
{
//修改IAT表项,让原本的饿函数地址变成自定义的函数
//相当于语句*lpAddr = (DWORD)MyMessageBox;
//不过在RELEASE版本里面因为lpAddr志向的是 只度的所以在写入内存之前要先修改它所在页的属性
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(lpAddr,&mbi,sizeof(mbi));//得到lpAddr制向的页的属性
VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);//修改保护模式
DWORD* lpNewProc = (DWORD*)MyMessageBox;
::WriteProcessMemory(GetCurrentProcess(),lpAddr,lpNewProc,sizeof(DWORD),NULL);
VirtualProtect(lpAddr,sizeof(DWORD),dwOldProtect,0);
return true;
} pThunk++;
}
cout<<"没有找到对应的函数"<<endl;
}
else
cout<<"没有找到USER32.DLL";
return false;
}int main()
{ ::MessageBox(NULL, "old function","Demo",0);
SetHook(GetModuleHandle(NULL));
::MessageBox(NULL,"old function","Demo",0);
PrintAllImportFunc(GetModuleHandle(NULL));
return 0;
}
一个是打印全部导入的函数,另外一个是修改PE文件的导入表的MessageBoxA这个函数....
可是问题是 打印全部导入函数的回报错.还有修改PE文件的也回找不到MessageBoxA这个函数...为什么...!
#include <windows.h>
#include <iostream>///这个HOOK API是借助修改PE文件的导入表来替换MESSAGEBOX的函数地址来实现的using namespace std;//挂钩指定模块hmod对MESSAGEBOXA的调用
BOOL SetHook(HMODULE hMod);
//定义messageboxa的函数原形
typedef int (WINAPI *PFUNC)(HWND, LPCSTR,LPCSTR,UINT);PROC g_orgProc = (PROC)MessageBoxA;//保存函数的地址
//这个函数打印了导入的所有函数
void PrintAllImportFunc(HMODULE hMod)
{
IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)hMod;//PE文件是从64字节的DOS头开始的
//DOS头里的E_lfanew是NT头的offset量,加上hmod就得到了NT头的地址
//然后NT头里先是4字节的“PE00”字符,然后是20字节的饿不止到什么,再然后是OPTINAL头
IMAGE_OPTIONAL_HEADER *pOptHeader=(IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + pDosHeader->e_lfanew+24);
//在OPTINAL头里保存了很多的信息,这里是得到导入表的地址
IMAGE_IMPORT_DESCRIPTOR *pImportDes = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hMod+pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while(pImportDes->FirstThunk)
{
char* pszDllName = (char*)(BYTE*)hMod + pImportDes->Name;
cout<<"模块名称:"<<pszDllName<<endl;
//一个IMAGE_THUNK_DATA是一个双字,它指定了一个导入函数
IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hMod+pImportDes->OriginalFirstThunk);
int n=0;
while(pThunk->u1.Function)
{
//取得函数名称.hint/name表前2个字节是函数序号,后面的是名称
char *pszFuncName = (char*)((BYTE*)pThunk->u1.AddressOfData+2);
//取得函数地址,IAT就是一个DWORD叔祖
PDWORD lpAddr = (DWORD*)((BYTE*)hMod+pImportDes->FirstThunk)+n;
//打印
printf("从此模块导入的函数: %-25s",pszFuncName);
printf("函数地址: %X\n", lpAddr);
n++;
pThunk++;
}
cout<<endl;
pImportDes++;
}}int WINAPI MyMessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCation, UINT type)
{
return ((PFUNC)g_orgProc)(hWnd, "new function","Demo",type);
}BOOL SetHook(HMODULE hMod)
{
IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)hMod;//PE文件是从64字节的DOS头开始的
//DOS头里的E_lfanew是NT头的offset量,加上hmod就得到了NT头的地址
//然后NT头里先是4字节的“PE00”字符,然后是20字节的饿不止到什么,再然后是OPTINAL头
IMAGE_OPTIONAL_HEADER *pOptHeader=(IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + pDosHeader->e_lfanew+24);
//得到导入表的地址
IMAGE_IMPORT_DESCRIPTOR *pImportDes = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hMod+pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); //在导入表中寻找USER32.DLL模块,因为MESSAGEBOXA是从USER32.DLL里导出的
while(pImportDes->FirstThunk)//导入表的FirstThunk指向一个导入表的数组,以\0为结尾
{
char* pszDllName = (char*)((BYTE*)hMod+pImportDes->Name);
if(strcmp(pszDllName,"USER32.dll")==0)
{
break;
}
pImportDes++;
} if(pImportDes->FirstThunk)
{
//一个IMAGE——THUNK-DATA结构是一个DWORD,它指定了一个导入函数
//导入地址表其实是一个IMAGE_THUNK_DATA的数组,也就是DWORD数组
IMAGE_THUNK_DATA *pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hMod+pImportDes->FirstThunk); while(pThunk->u1.Function)//这个应该是导入模块的函数地址
{
//lpAddr指向的内存保存了函数地址
DWORD *lpAddr = (DWORD*)&(pThunk->u1.Function); if(*lpAddr == (DWORD)g_orgProc)//如果这个函数是MESSAGEBOXA的话
{
//修改IAT表项,让原本的饿函数地址变成自定义的函数
//相当于语句*lpAddr = (DWORD)MyMessageBox;
//不过在RELEASE版本里面因为lpAddr志向的是 只度的所以在写入内存之前要先修改它所在页的属性
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(lpAddr,&mbi,sizeof(mbi));//得到lpAddr制向的页的属性
VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);//修改保护模式
DWORD* lpNewProc = (DWORD*)MyMessageBox;
::WriteProcessMemory(GetCurrentProcess(),lpAddr,lpNewProc,sizeof(DWORD),NULL);
VirtualProtect(lpAddr,sizeof(DWORD),dwOldProtect,0);
return true;
} pThunk++;
}
cout<<"没有找到对应的函数"<<endl;
}
else
cout<<"没有找到USER32.DLL";
return false;
}int main()
{ ::MessageBox(NULL, "old function","Demo",0);
SetHook(GetModuleHandle(NULL));
::MessageBox(NULL,"old function","Demo",0);
PrintAllImportFunc(GetModuleHandle(NULL));
return 0;
}
解决方案 »
- 关于SOAP TOOLKIT3 中名字空间的SOAPSDK前缀问题
- [求助]请熟悉VC,WINSOCK网络多媒体方向的强人来帮个忙...
- 求助!!!(如何用VC判断当前系统用户的权限??????)
- 请问怎么给一个按钮上色,并且按钮上的字会实时改变
- 修改问题
- 把CDC的内容,Bitblt到LPDIRECTDRAWSURFACE7上,速度为什么特别慢?
- VC6.0中怎么实现可以显示html的对话框?
- 救命:DirectX的小问题!(在线等待, 急)
- 我用的SDI我想利用CTree,实现类似资源管理器的功能,如何实现。我是小白,贴代码看不懂。希望有详细的实现过程。希望大家帮忙。
- 一个奇怪的问题
- 如下所描述的,怎么解决呢?
- get_anchosr()与get_links()方法有什么不同?
http://research.microsoft.com/en-us/projects/detours/
而另外一个是找不到MessageBoxA这个函数...