核心代碼從網上找的,但原始函數調用一直有問,經過分析 整理并測試成功。
#include <stdio.h>
#include<windows.h>
#pragma comment( lib, "Ws2_32.lib" )
DWORD OldProtect2;
byte pData[10]; //保留原始函數的調用
FARPROC FunAddr; //生成新的函數調用
typedef int ( WINAPI RecvFromFN)( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen);
RecvFromFN* pfnOrigRecvFrom ;
void inhook(char* path,char* FunctionName,DWORD NewAddr)
{
if(FunAddr!=0)
return ;
HMODULE ModuleHandle= LoadLibraryA(path);
FunAddr = GetProcAddress(ModuleHandle,FunctionName);
VirtualProtect(FunAddr,5,PAGE_EXECUTE_READWRITE,&OldProtect);
ZeroMemory(pData,10);
RtlMoveMemory(pData,FunAddr,5);
long b;
b=NewAddr-((long)FunAddr+5);
byte a[5];
a[0]=0xE9;
RtlMoveMemory(&a[1],&b,4);
WriteProcessMemory(GetCurrentProcess(),FunAddr,a,5,NULL);
pData[5]=0xE9;
pData[6]=0;
pData[7]=0;
pData[8]=0;
pData[9]=0;
b=(long)FunAddr+5-(long)(pData+10);
WriteProcessMemory(GetCurrentProcess(),pData+6,&b,4,NULL);
FreeLibrary(ModuleHandle);
//下面這兩行用于調用原始函數
pfnOrigRecvFrom = (RecvFromFN*) (DWORD) (pData);
VirtualProtect(pfnOrigRecvFrom,10,PAGE_EXECUTE_READWRITE,&OldProtect2);
}
void unhook(void)
{
if(FunAddr==0)
return ;
WriteProcessMemory(GetCurrentProcess(),FunAddr,pData,5,NULL);
VirtualProtect(FunAddr,5,OldProtect,NULL);
FunAddr=0;
ZeroMemory(pData,10);
VirtualProtect(pfnOrigRecvFrom,10,OldProtect2,NULL); //恢複原始函數指針
}
int WINAPI Mine_RecvFrom(SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen)
{
int tmpRet = pfnOrigRecvFrom(s,buf,len,flags,from,fromlen);
sockaddr_in * pSin = (sockaddr_in *) from;
//顯示接收資料長度,來源IP和端口
fprintf(stdout,"Recv Data Size:%d From:%s:%d.\n",tmpRet, inet_ntoa(pSin->sin_addr),ntohs(pSin->sin_port));
return tmpRet;
}
以上代碼在程序内調用有效,也支援程序内DLL方式,實際調用時使用代碼
inhook("Ws2_32.dll","recvfrom",(DWORD) Mine_RecvFrom);
就可以了,DLL的話在DllMain中直接加載。