研究了好久hook,主要是inline hook和iat hook。具体的目标是要勾住通过USB连接到电脑上的rfid读卡器的读卡函数。读卡函数是从读卡器公司封装好的dll中导入的。
(即:读卡函数AAA是通过loadlibrary BBB.dll,然后实现读卡的,我的目的是勾住读卡的AAA函数)
现在我对于系统自带的API函数,例如messagebox,是能够成功勾到的。但是尝试这个外部导入的函数时,就总是不成功。
希望有朋友可以提供一些思路。千谢万谢。我把读卡器程序放在附件,hook的dll代码贴在下面。
//inline hook
#include "StdAfx.h" //预处理文件放第一行 ,否则 有些函数 会报错
#include <windows.h>
#include <stdio.h>
DWORD dwAddrpiccreadex; //保存真的piccreadex函数地址
unsigned char __stdcall Mypiccreadex(unsigned char ctrlword,
unsigned char *serial,
unsigned char area,
unsigned char keyA1B0,
unsigned char *picckey,
unsigned char *piccdata0_2)
{
MessageBox(NULL,"执行My函数", "提示", MB_OK);//跳出这个代表hook成功
return 10;
}
//JMP跳转-自定义函数
void WriteJMP(DWORD ProcAddr,LPVOID lpData)
{
BYTE _data[5];//声明了一个字节数组_data,字节长度为5
_data[0]=0xE9;// 0xE9代表汇编指令JMP
DWORD OldPro;//声明了一个整数OldPro,保存原来的内存属性
VirtualProtect((LPVOID)(ProcAddr),5,PAGE_EXECUTE_READWRITE,&OldPro);
//VirtualProtect函数功能是修改内存属性
memcpy((LPVOID)(_data+1),lpData,4);//_data是变量的内存地址
//以上是填充 机器码字节数组data[1]...到 data[4]
memcpy((LPVOID)(ProcAddr),_data,5);
VirtualProtect((LPVOID)(ProcAddr),5,OldPro,&OldPro);//内存属性恢复为只读
}
//卸载HOOK -恢复piccreadex函数头的5个字节
//卸载部分有点问题,但是安装钩子都没有成功,所以卸载先不考虑
void UnHOOK(DWORD ProcAddr)
{
BYTE _data[5];//声明了一个字节数组_data,字节长度为5
DWORD OldPro;//声明了一个整数OldPro,保存原来的内存属性
VirtualProtect((LPVOID)(ProcAddr),5,PAGE_EXECUTE_READWRITE,&OldPro);
//修改内存属性为可读可写,修改长度为5,PAGE_EXECUTE_READWRITE表示可读可写
_data[0]= 0x8B;
_data[1]= 0xFF;
_data[2]= 0x55;
_data[3]= 0x8B;
_data[4]= 0xEC;
memcpy((LPVOID)(ProcAddr),_data,5);
//通过字节数组的形式把8B,FF,55,8B,EC原来的5个字节写入 真Api函数地址
VirtualProtect((LPVOID)(ProcAddr),5,OldPro,&OldPro);//内存属性恢复为只读
}
BOOL WINAPI DllMain(HINSTANCE hmodule,DWORD reason, LPVOID lpreserved)
{
if(reason==DLL_PROCESS_ATTACH)// 如果DLL被注入到其他进程,DLL_PROCESS_ATTACH表示注入DLL的时候
{
MessageBox(NULL,"你好!我被注入了", "注入提示", MB_OK);
HMODULE hWsock32=GetModuleHandle("OUR_MIFAR.dll");//获取OUR_MIFAR.dll模块句柄
dwAddrpiccreadex=(DWORD)GetProcAddress(hWsock32,"piccreadex");//获取api函数piccreadex真正的地址
DWORD tmp=(DWORD)Mypiccreadex-(dwAddrpiccreadex+5);// 假冒的API函数地址的字节(一个4个字节)
//通过字节的形式来代表假冒api函数Mypiccreadex的地址 ,保存到变量tem里面
//公式:假冒的API函数地址的4个字节=My函数地址-(真的函数地址+5)
WriteJMP(dwAddrpiccreadex,&tmp);//开始HOOK-修改piccreadex函数头的5个字节
}
if(reason==DLL_PROCESS_DETACH)// 如果DLL被卸载, DLL_PROCESS_DETACH表示卸载DLL的时候
{
UnHOOK(dwAddrpiccreadex);//卸载HOOK -恢复piccreadex函数头的5个字节
MessageBox(NULL,"你好!我被卸载了", "卸载提示", MB_OK);
}
return TRUE;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)