如何替换人家DLL文件中的一个函数?? 最简单的方法 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 如果不知道要替换函数的参数类型个数难办,否则可以用类似的替换GINA的方法,搜索GINA会有很多 不好搞啊!就算知道参数类型也难办!可以尝试hook 可以重定向啊,<windows核心编程>里面有介绍这个方法,不是很难. ------------------------------------------------------------------------------------/*以下.H*/------------------------------------------------------------------------------------#ifndef INTERCEPT_H#define INTERCEPT_H// 这里定义了一个产生指针的宏#define makeptr(cast, ptr, addvalue) (cast)((DWORD)(ptr)+(DWORD)(addvalue))// 定义了HOOKFUNCDESC结构,我们用这个结构作为参数传给HookImportFunction函数typedef struct TAG_HOOKFUNCDESC{ LPCSTR szfunc; // the name of the function to hook. PROC pproc; // the procedure to blast in.} HOOKFUNCDESC , * LPHOOKFUNCDESC;// 这个函数监测当前系统是否是windowntBOOL IsNT();// 这个函数得到hModule -- 即我们需要截获的函数所在的dll模块的引入描述符(import descriptor)PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szimportmodule);bool HookImportFunction(HMODULE hModule, LPCSTR szimportmodule, LPHOOKFUNCDESC pahookfunc, PROC* paorigfuncs);#endif------------------------------------------------------------------------------------/*以下CPP*/------------------------------------------------------------------------------------// Intercept.cpp : Defines the entry point for the console application.//#include <windows.h>#include <stdio.h>#include <assert.h>#include <crtdbg.h>#include "intercept.h"void log(char *p){FILE *fp=fopen("intercept.txt","a+");fprintf(fp,"%s\n",p);fclose(fp);}// 我们的主函数bool HookImportFunction(HMODULE hModule, LPCSTR szimportmodule, LPHOOKFUNCDESC pahookfunc, PROC* paorigfuncs){ /////////////////////// 下面的代码检测参数的有效性 //////////////////////////// assert(szimportmodule); assert(!IsBadReadPtr(pahookfunc, sizeof(HOOKFUNCDESC))); #ifdef _debug if (paorigfuncs) assert(!isbadwriteptr(paorigfuncs, sizeof(proc))); assert(pahookfunc.szfunc); assert(*pahookfunc.szfunc != '\0'); assert(!isbadcodeptr(pahookfunc.pproc)); #endif if ((szimportmodule == NULL) || (IsBadReadPtr(pahookfunc, sizeof(HOOKFUNCDESC)))) { assert(false); SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR); return false; } ////////////////////////////////////////////////////////////////////////////// // 监测当前模块是否是在2gb虚拟内存空间之上 // 这部分的地址内存是属于win32进程共享的 if (!IsNT() && ((DWORD)hModule >= 0x80000000)) { assert(false); SetLastErrorEx(ERROR_INVALID_HANDLE, SLE_ERROR); return false; } // 清零 if (paorigfuncs) memset(paorigfuncs, NULL, sizeof(PROC)); // 调用GetNamedImportDescriptor()函数,来得到hModule -- 即我们需要 // 截获的函数所在的dll模块的引入描述符(import descriptor) PIMAGE_IMPORT_DESCRIPTOR pimportdesc = GetNamedImportDescriptor(hModule, szimportmodule); if (pimportdesc == NULL) return false; // 若为空,则模块未被当前进程所引入 // 从dll模块中得到原始的thunk信息,因为pimportdesc->firstthunk数组中的原始信息已经 // 在应用程序引入该dll时覆盖上了所有的引入信息,所以我们需要通过取得pimportdesc->originalfirstthunk // 指针来访问引入函数名等信息 PIMAGE_THUNK_DATA porigthunk = makeptr(PIMAGE_THUNK_DATA, hModule, pimportdesc->OriginalFirstThunk); // 从pimportdesc->firstthunk得到image_thunk_data数组的指针,由于这里在dll被引入时已经填充了 // 所有的引入信息,所以真正的截获实际上正是在这里进行的 PIMAGE_THUNK_DATA prealthunk = makeptr(PIMAGE_THUNK_DATA, hModule, pimportdesc->FirstThunk); // 穷举image_thunk_data数组,寻找我们需要截获的函数,这是最关键的部分! while (porigthunk->u1.Function) { // 只寻找那些按函数名而不是序号引入的函数 if (IMAGE_ORDINAL_FLAG != (porigthunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) { // 得到引入函数的函数名 PIMAGE_IMPORT_BY_NAME pbyname = makeptr(PIMAGE_IMPORT_BY_NAME, hModule, porigthunk->u1.AddressOfData); // 如果函数名以NULL开始,跳过,继续下一个函数 if ('\0' == pbyname->Name[0]) continue; // bdohook用来检查是否截获成功 BOOL bdohook = false; // 检查是否当前函数是我们需要截获的函数 if ((pahookfunc->szfunc[0] == pbyname->Name[0]) && (strcmpi(pahookfunc->szfunc, (char*)pbyname->Name) == 0)) { // 找到了! if (pahookfunc->pproc) bdohook = true; } if (bdohook) { // 我们已经找到了所要截获的函数,那么就开始动手吧 // 首先要做的是改变这一块虚拟内存的内存保护状态,让我们可以自由存取 MEMORY_BASIC_INFORMATION mbi_thunk; VirtualQuery(prealthunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); assert(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect)); // 保存我们所要截获的函数的正确跳转地址 if (paorigfuncs) *paorigfuncs = (PROC)prealthunk->u1.Function; // 将image_thunk_data数组中的函数跳转地址改写为我们自己的函数地址! // 以后所有进程对这个系统函数的所有调用都将成为对我们自己编写的函数的调用 prealthunk->u1.Function = (PDWORD)pahookfunc->pproc; // 操作完毕!将这一块虚拟内存改回原来的保护状态 DWORD dwoldprotect; assert(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwoldprotect)); SetLastError(ERROR_SUCCESS); return true; } } // 访问image_thunk_data数组中的下一个元素 porigthunk++; prealthunk++; } return true;}// GetNamedImportDescriptor函数的实现PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szimportmodule){ // 检测参数 assert(szimportmodule); assert(hModule); if ((szimportmodule == NULL) || (hModule == NULL)) { assert(false); SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR); return NULL; } // 得到dos文件头 PIMAGE_DOS_HEADER pdosheader = (PIMAGE_DOS_HEADER) hModule; // 检测是否mz文件头 if (IsBadReadPtr(pdosheader, sizeof(IMAGE_DOS_HEADER)) || (pdosheader->e_magic != IMAGE_DOS_SIGNATURE)) { assert(false); SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR); return NULL; } // 取得pe文件头 PIMAGE_NT_HEADERS pntheader = makeptr(PIMAGE_NT_HEADERS, pdosheader, pdosheader->e_lfanew); // 检测是否pe映像文件 if (IsBadReadPtr(pntheader, sizeof(IMAGE_NT_HEADERS)) || (pntheader->Signature != IMAGE_NT_SIGNATURE)) { assert(false); SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR); return NULL; } // 检查pe文件的引入段(即 .idata section) if (pntheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0) return NULL; // 得到引入段(即 .idata section)的指针 PIMAGE_IMPORT_DESCRIPTOR pimportdesc = makeptr(PIMAGE_IMPORT_DESCRIPTOR, pdosheader, pntheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); // 穷举pimage_import_descriptor数组寻找我们需要截获的函数所在的模块 while (pimportdesc->Name) { PSTR szcurrmod = makeptr(PSTR, pdosheader, pimportdesc->Name); log(szcurrmod); if (stricmp(szcurrmod, szimportmodule) == 0) break; // 找到!中断循环 // 下一个元素 pimportdesc++; } // 如果没有找到,说明我们寻找的模块没有被当前的进程所引入! if (pimportdesc->Name == NULL) return NULL; // 返回函数所找到的模块描述符(import descriptor) return pimportdesc;}// IsNT()函数的实现BOOL IsNT(){ OSVERSIONINFO stosvi; memset(&stosvi, NULL, sizeof(OSVERSIONINFO)); stosvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); BOOL bret = GetVersionEx(&stosvi); assert(TRUE == bret); if (false == bret) return FALSE; return (VER_PLATFORM_WIN32_NT == stosvi.dwPlatformId);}/////////////////////////////////////////////// end ////////////////////////////////////////////////////////////////////// 兄弟们,发现了一个事情. 软件通过网络激活的原理是什么呢? 给你一个MFC调用数据库的工程代码~发到我信箱 再MFC中又没有哪个类是是线FTP server的? 在TC下如何判断文件是否存在? 关于使用SetWindowLong改变一个控件的STYLE的问题。。。 谁能提供一个SourceSafe6的下载啊? 求点阵字体的压缩算法/解压(最好是C语言的) mfc中按下某个按钮,图片空间中导入某张图片的方法 一个简单的传值? 最发现了一个好东东!!!跟大家分享!!!!! 对齐、设置相同风格按钮的快捷键是什么来着?
/*以下.H*/
------------------------------------------------------------------------------------#ifndef INTERCEPT_H
#define INTERCEPT_H// 这里定义了一个产生指针的宏
#define makeptr(cast, ptr, addvalue) (cast)((DWORD)(ptr)+(DWORD)(addvalue))// 定义了HOOKFUNCDESC结构,我们用这个结构作为参数传给HookImportFunction函数
typedef struct TAG_HOOKFUNCDESC
{
LPCSTR szfunc; // the name of the function to hook.
PROC pproc; // the procedure to blast in.
} HOOKFUNCDESC , * LPHOOKFUNCDESC;// 这个函数监测当前系统是否是windownt
BOOL IsNT();// 这个函数得到hModule -- 即我们需要截获的函数所在的dll模块的引入描述符(import descriptor)
PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szimportmodule);bool HookImportFunction(HMODULE hModule, LPCSTR szimportmodule,
LPHOOKFUNCDESC pahookfunc, PROC* paorigfuncs);#endif------------------------------------------------------------------------------------
/*以下CPP*/
------------------------------------------------------------------------------------
// Intercept.cpp : Defines the entry point for the console application.
//#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <crtdbg.h>
#include "intercept.h"void log(char *p){FILE *fp=fopen("intercept.txt","a+");fprintf(fp,"%s\n",p);fclose(fp);}// 我们的主函数
bool HookImportFunction(HMODULE hModule, LPCSTR szimportmodule,
LPHOOKFUNCDESC pahookfunc, PROC* paorigfuncs)
{
/////////////////////// 下面的代码检测参数的有效性 ////////////////////////////
assert(szimportmodule);
assert(!IsBadReadPtr(pahookfunc, sizeof(HOOKFUNCDESC)));
#ifdef _debug
if (paorigfuncs) assert(!isbadwriteptr(paorigfuncs, sizeof(proc)));
assert(pahookfunc.szfunc);
assert(*pahookfunc.szfunc != '\0');
assert(!isbadcodeptr(pahookfunc.pproc));
#endif
if ((szimportmodule == NULL) || (IsBadReadPtr(pahookfunc, sizeof(HOOKFUNCDESC))))
{
assert(false);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return false;
}
////////////////////////////////////////////////////////////////////////////// // 监测当前模块是否是在2gb虚拟内存空间之上
// 这部分的地址内存是属于win32进程共享的
if (!IsNT() && ((DWORD)hModule >= 0x80000000))
{
assert(false);
SetLastErrorEx(ERROR_INVALID_HANDLE, SLE_ERROR);
return false;
}
// 清零
if (paorigfuncs) memset(paorigfuncs, NULL, sizeof(PROC)); // 调用GetNamedImportDescriptor()函数,来得到hModule -- 即我们需要
// 截获的函数所在的dll模块的引入描述符(import descriptor)
PIMAGE_IMPORT_DESCRIPTOR pimportdesc = GetNamedImportDescriptor(hModule, szimportmodule);
if (pimportdesc == NULL)
return false; // 若为空,则模块未被当前进程所引入 // 从dll模块中得到原始的thunk信息,因为pimportdesc->firstthunk数组中的原始信息已经
// 在应用程序引入该dll时覆盖上了所有的引入信息,所以我们需要通过取得pimportdesc->originalfirstthunk
// 指针来访问引入函数名等信息
PIMAGE_THUNK_DATA porigthunk = makeptr(PIMAGE_THUNK_DATA, hModule,
pimportdesc->OriginalFirstThunk); // 从pimportdesc->firstthunk得到image_thunk_data数组的指针,由于这里在dll被引入时已经填充了
// 所有的引入信息,所以真正的截获实际上正是在这里进行的
PIMAGE_THUNK_DATA prealthunk = makeptr(PIMAGE_THUNK_DATA, hModule, pimportdesc->FirstThunk); // 穷举image_thunk_data数组,寻找我们需要截获的函数,这是最关键的部分!
while (porigthunk->u1.Function)
{
// 只寻找那些按函数名而不是序号引入的函数
if (IMAGE_ORDINAL_FLAG != (porigthunk->u1.Ordinal & IMAGE_ORDINAL_FLAG))
{
// 得到引入函数的函数名
PIMAGE_IMPORT_BY_NAME pbyname = makeptr(PIMAGE_IMPORT_BY_NAME, hModule,
porigthunk->u1.AddressOfData); // 如果函数名以NULL开始,跳过,继续下一个函数
if ('\0' == pbyname->Name[0])
continue; // bdohook用来检查是否截获成功
BOOL bdohook = false; // 检查是否当前函数是我们需要截获的函数
if ((pahookfunc->szfunc[0] == pbyname->Name[0]) &&
(strcmpi(pahookfunc->szfunc, (char*)pbyname->Name) == 0))
{
// 找到了!
if (pahookfunc->pproc)
bdohook = true;
}
if (bdohook)
{
// 我们已经找到了所要截获的函数,那么就开始动手吧
// 首先要做的是改变这一块虚拟内存的内存保护状态,让我们可以自由存取
MEMORY_BASIC_INFORMATION mbi_thunk;
VirtualQuery(prealthunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
assert(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
PAGE_READWRITE, &mbi_thunk.Protect)); // 保存我们所要截获的函数的正确跳转地址
if (paorigfuncs)
*paorigfuncs = (PROC)prealthunk->u1.Function; // 将image_thunk_data数组中的函数跳转地址改写为我们自己的函数地址!
// 以后所有进程对这个系统函数的所有调用都将成为对我们自己编写的函数的调用
prealthunk->u1.Function = (PDWORD)pahookfunc->pproc; // 操作完毕!将这一块虚拟内存改回原来的保护状态
DWORD dwoldprotect;
assert(VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
mbi_thunk.Protect, &dwoldprotect));
SetLastError(ERROR_SUCCESS);
return true;
}
}
// 访问image_thunk_data数组中的下一个元素
porigthunk++;
prealthunk++;
}
return true;
}// GetNamedImportDescriptor函数的实现
PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szimportmodule)
{
// 检测参数
assert(szimportmodule);
assert(hModule);
if ((szimportmodule == NULL) || (hModule == NULL))
{
assert(false);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return NULL;
} // 得到dos文件头
PIMAGE_DOS_HEADER pdosheader = (PIMAGE_DOS_HEADER) hModule; // 检测是否mz文件头
if (IsBadReadPtr(pdosheader, sizeof(IMAGE_DOS_HEADER)) ||
(pdosheader->e_magic != IMAGE_DOS_SIGNATURE))
{
assert(false);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return NULL;
} // 取得pe文件头
PIMAGE_NT_HEADERS pntheader = makeptr(PIMAGE_NT_HEADERS, pdosheader, pdosheader->e_lfanew); // 检测是否pe映像文件
if (IsBadReadPtr(pntheader, sizeof(IMAGE_NT_HEADERS)) ||
(pntheader->Signature != IMAGE_NT_SIGNATURE))
{
assert(false);
SetLastErrorEx(ERROR_INVALID_PARAMETER, SLE_ERROR);
return NULL;
} // 检查pe文件的引入段(即 .idata section)
if (pntheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
return NULL; // 得到引入段(即 .idata section)的指针
PIMAGE_IMPORT_DESCRIPTOR pimportdesc = makeptr(PIMAGE_IMPORT_DESCRIPTOR, pdosheader,
pntheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); // 穷举pimage_import_descriptor数组寻找我们需要截获的函数所在的模块
while (pimportdesc->Name)
{
PSTR szcurrmod = makeptr(PSTR, pdosheader, pimportdesc->Name);
log(szcurrmod);
if (stricmp(szcurrmod, szimportmodule) == 0)
break; // 找到!中断循环
// 下一个元素
pimportdesc++;
} // 如果没有找到,说明我们寻找的模块没有被当前的进程所引入!
if (pimportdesc->Name == NULL)
return NULL; // 返回函数所找到的模块描述符(import descriptor)
return pimportdesc;
}// IsNT()函数的实现
BOOL IsNT()
{
OSVERSIONINFO stosvi;
memset(&stosvi, NULL, sizeof(OSVERSIONINFO));
stosvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
BOOL bret = GetVersionEx(&stosvi);
assert(TRUE == bret);
if (false == bret) return FALSE;
return (VER_PLATFORM_WIN32_NT == stosvi.dwPlatformId);
}
/////////////////////////////////////////////// end //////////////////////////////////////////////////////////////////////