现在的位置: 首页 > 综合 > 正文

HOOK SOCKET

2019年10月05日 ⁄ 综合 ⁄ 共 9274字 ⁄ 字号 评论关闭

分析完了数据,我们开始写程序了

 

首先我们创建一个MFC的解决方案,然后在解决方案中添加一个dll新项目

 

名称大家可以自拟

 

 

 

Dll中我们写hook函数,MFC作为交互窗体

 

首先我们开始写dll

 

经过分析游戏所需协议,发现我们需要hook的只是socket中TCP的send和recv两个函数

 

 

 

我们先创建一个IPPackLib.h的头文件,这个文件我们保存的是数据存放类型和自定义信息

 

看一些源码,应该不难懂的

 

#ifndef __IPPACKLIB_H__

 

#define __IPPACKLIB_H__

 

 

 

struct CMessageData//数据类型

 

{

 

    intnDataLength;

 

    TCHAR* data()           

 

    { return(TCHAR*)(this+1); }//真正的数据在这个类型所占内存的后边

 

};

 

enum HOOK_MESSAGE//自定信息,作用是告诉MFC有新的HOOK消息

 

{

 

    HM_RECEIVE = WM_USER + 100,

 

};

 

#endif 

 

然后我们在新建一个ShareMemory.h的头文件,作用是共享内存到MFC,共享内存是一种不同线程间传递信息的方式。效率很高的,  注释很详细,我们看一下源码,具体共享内存是怎样实现的,读者可以百度一下,鉴于字数要求,我就不copy过来了

 

#ifndef __SHAREMEMORY_H__

 

#define __SHAREMEMORY_H__

 

class CShareMemory

 

{

 

public:

 

// 构造函数和析构函数

 

    CShareMemory(constchar * pszMapName, intnFileSize = 0, BOOL bServer = FALSE);

 

    ~CShareMemory();

 

// 属性

 

    LPVOID GetBuffer() const{ return m_pBuffer; }

 

// 实现

 

private

 

    HANDLE  m_hFileMap;

 

    LPVOID  m_pBuffer;

 

};

 

inline CShareMemory::CShareMemory(constchar *pszMapName, 

 

            intnFileSize, BOOL bServer) : m_hFileMap(NULL), m_pBuffer(NULL)

 

{

 

    if(bServer)

 

    {

 

        // 创建一个内存映射文件对象

 

        m_hFileMap =CreateFileMapping(INVALID_HANDLE_VALUE, 

 

            NULL, PAGE_READWRITE, 0, nFileSize,pszMapName);

 

    }

 

    else

 

    {

 

        // 打开一个内存映射文件对象

 

        m_hFileMap =OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, pszMapName);

 

    }

 

    

 

    // 映射它到内存,取得共享内存的首地址

 

    m_pBuffer = (LPBYTE)MapViewOfFile(m_hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);

 

}

 

inline CShareMemory::~CShareMemory()

 

{

 

    // 取消文件的映射,关闭文件映射对象句柄

 

    UnmapViewOfFile(m_pBuffer);

 

    CloseHandle(m_hFileMap);

 

}

 

#endif// __SHAREMEMORY_H__

 

 

 

在新建一个ULHook.h的头文件

 

Hook一个函数其实就是把应用程序调用的函数的前8字节内存修改,从而使那个函数转到自己写的函数上来,所以这里我写了一个类来保存原函数的地址,新函数的地址和实现挂钩等功能的类

 

#ifndef __ULHOOK_H__

 

#define __ULHOOK_H__

 

#include<windows.h>

 

class CULHook

 

{

 

public:

 

    CULHook(LPSTR pszModName, LPSTR pszFuncName,PROC pfnHook,bool ifbegin);

 

    ~CULHook();

 

    // 取消挂钩

 

    voidUnhook();

 

    // 重新挂钩

 

    voidRehook();

 

protected:

 

    PROC m_pfnOrig;                 // 目标API函数的地址

 

    BYTE m_btNewBytes[8];       // 新构建的8个字节

 

    BYTE m_btOldBytes[8];       // 原来8个字节

 

    HMODULE m_hModule;

 

};

 

#endif// __ULHOOK_H__

 

 

 

这样,我们的头文件就完成了,接下来我们开始源文件的编写

 

新建一个IPPackLib.cpp的源文件,实现新函数的储存和挂钩等功能

 

应该可以读懂的,时间要求,直接上源码了

 

///////////////////////////////////////////

 

//IPHookLib.cpp文件

 

#include<Winsock2.h>

 

#include"ShareMemory.h"

 

#include"ULHook.h"

 

#include"IPPackLib.h"

 

 

 

#pragmacomment(lib, "WS2_32")

 

 

 

// 共享数据区

 

HWND g_hWndCaller =NULL;   

 

HHOOK g_hHook =NULL;

 

#pragmadata_seg()

 

 

 

char* StringToJinZhi16(char*Date,int BegPos,intEndPos);

 

void SndMsg(char*Msg);

 

 

 

extern CULHook g_recv;

 

extern CULHook g_send;

 

 

 

 

 

int WINAPI hook_recv(SOCKET s, char  *buf, int len, int flags)

 

{

 

    // 调用原来的函数,接受数据,设置参数

 

    g_recv.Unhook();

 

    //将信息给被hook的应用程序发过去

 

    int nRet =recv(s, buf, len, flags);

 

 

 

    if (len <50 && strcmp(StringToJinZhi16(buf,0,4),"1140 01 00 "))

 

    {

 

        CShareMemory sm("IPPACK_RECEIVE",sizeof(CMessageData) + len, TRUE);

 

        CMessageData *pData =(CMessageData*)sm.GetBuffer();

 

        memcpy(pData->data(),buf,nRet);

 

        pData->nDataLength = nRet;

 

        // 通知主窗口,进行过滤

 

        SendMessage(g_hWndCaller, HM_RECEIVE, 0,0);

 

    }

 

 

 

    g_recv.Rehook();

 

    return nRet;

 

}

 

 

 

int WINAPI hook_send(SOCKET s, constchar* buf, int len, int flags)

 

{

 

    // 申请指定长度的共享内存空间

 

    CShareMemory sm("IPPACK_RECEIVE",sizeof(CMessageData) + len, TRUE);

 

    // 取得指向共享内存的指针

 

    CMessageData *pData =(CMessageData*)sm.GetBuffer();

 

 

 

    pData->nDataLength = len;

 

    memcpy(pData->data(), buf,pData->nDataLength);

 

 

 

    // 通知主窗口,进行过滤

 

    ::SendMessage(g_hWndCaller, HM_RECEIVE, 0,0);

 

 

 

    // 调用原来的函数,发送数据

 

    g_send.Unhook();

 

    int nRet =::send(s, pData->data(), pData->nDataLength, flags);

 

 

 

    if(!strcmp(StringToJinZhi16((char*)buf,0,3),"0140 01 ")){     

 

       SndMsg("ss2");

 

       g_recv.Rehook();

 

    }

 

    else

 

        g_send.Rehook();

 

    return nRet;

 

}

 

 

 

 

 

void SndMsg(char*Msg)

 

{

 

    // 申请指定长度的共享内存空间

 

    CShareMemory sm("IPPACK_RECEIVE",sizeof(CMessageData) + 3, TRUE);

 

    // 取得指向共享内存的指针

 

    CMessageData *pData =(CMessageData*)sm.GetBuffer();

 

 

 

    pData->nDataLength = 3;

 

    memcpy(pData->data(), Msg,pData->nDataLength);

 

 

 

    // 通知主窗口,进行过滤

 

    ::SendMessage(g_hWndCaller, HM_RECEIVE, 0,0);

 

}

 

 

 

char* StringToJinZhi16(char*Date,int BegPos,intEndPos)

 

{

 

    char* pBuf =newchar[(EndPos- BegPos)*3];

 

 

 

    // 转化截获的数据为16进制字符串的形式

 

    char* pTemp= pBuf;

 

    char* psz =Date;

 

    psz+=BegPos;

 

    for(int i=BegPos; i<EndPos; i++, psz++)

 

    {

 

        wsprintf(pTemp, "%02x", (BYTE)(*psz));

 

        pTemp += 3;

 

    }

 

    return pBuf;

 

}

 

 

 

 

 

 

 

CULHook g_send("Ws2_32.dll", "send",(PROC)hook_send,true);

 

CULHook g_recv("Ws2_32.dll", "recv",(PROC)hook_recv,false);

 

 

 

////////////////////////////////////////////

 

 

 

static HMODULE ModuleFromAddress(PVOID pv) 

 

{

 

    MEMORY_BASIC_INFORMATION mbi;

 

    if(::VirtualQuery(pv,&mbi, sizeof(mbi)) != 0)

 

    {

 

        return(HMODULE)mbi.AllocationBase;

 

    }

 

    else

 

    {

 

        returnNULL;

 

    }

 

}

 

 

 

 

 

 

 

static LRESULT WINAPI GetMsgProc(int code, WPARAM wParam, LPARAM lParam) 

 

{

 

    return::CallNextHookEx(g_hHook, code, wParam, lParam);

 

}

 

 

 

BOOL WINAPISetHook(BOOL bInstall, DWORD dwThreadId, HWND hWndCaller)

 

{

 

    BOOL bOk;

 

    g_hWndCaller = hWndCaller;

 

 

 

    if(bInstall)

 

    {

 

        g_hHook =::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, 

 

                        ModuleFromAddress(GetMsgProc),dwThreadId);

 

        bOk = (g_hHook != NULL);

 

 

 

        SndMsg("ss1");

 

    } 

 

    else 

 

    {

 

        bOk = ::UnhookWindowsHookEx(g_hHook);

 

        g_hHook = NULL;

 

    }

 

    return bOk;

 

}

 

 

 

之后我们写一个IPPackLib.def的附加文件

 

EXPORTS

 

   SetHook

 

DEF文件就是将DLL的函数入口导出,使程序可以正确访问

 

然后我们添加ULHook.CPP文件,一看名字就知道是完成ULHook.h功能的源文件,不多说,上源码

 

///////////////////////////////////////////

 

//ULHook.cpp文件

 

 

 

 

 

#include"ULHook.h"

 

 

 

CULHook::CULHook(LPSTRpszModName, LPSTR pszFuncName, PROC pfnHook,boolifbegin)

 

{

 

 

 

    

 

    BYTE btNewBytes[8] = { 0xB8, 0x00, 0x00,0x40, 0x00, 0xFF, 0xE0, 0x00 }; //这个翻译成汇编的功能就是函数跳转

 

    memcpy(m_btNewBytes, btNewBytes, 8);

 

    *(DWORD *)(m_btNewBytes + 1) =(DWORD)pfnHook; 

 

 

 

    // 加载指定模块,取得API函数地址

 

    m_hModule = ::LoadLibrary(pszModName);

 

    if(m_hModule== NULL)

 

    {

 

        m_pfnOrig = NULL;

 

        return;

 

    }

 

    m_pfnOrig = ::GetProcAddress(m_hModule,pszFuncName);

 

 

 

 

 

    // 修改原API函数执行代码的前8个字节,使它跳向我们的函数

 

    if(m_pfnOrig!= NULL)

 

    {

 

        DWORD dwOldProtect;

 

        MEMORY_BASIC_INFORMATION    mbi;

 

        ::VirtualQuery( m_pfnOrig, &mbi, sizeof(mbi) );

 

        ::VirtualProtect(m_pfnOrig, 8, PAGE_READWRITE,&dwOldProtect);

 

        // 保存原来的执行代码

 

        memcpy(m_btOldBytes, m_pfnOrig, 8);

 

        // 写入新的执行代码

 

        ::WriteProcessMemory(::GetCurrentProcess(),(void *)m_pfnOrig, 

 

            m_btNewBytes, sizeof(DWORD)*2, NULL); 

 

 

 

        ::VirtualProtect(m_pfnOrig, 8,mbi.Protect, 0);

 

    }

 

 

 

    if(!ifbegin)

 

    {

 

        Unhook();

 

    }

 

}

 

 

 

 

 

CULHook::~CULHook()

 

{

 

    Unhook();

 

    if(m_hModule!= NULL)

 

        ::FreeLibrary(m_hModule);

 

}

 

 

 

void CULHook::Unhook()

 

{

 

    if(m_pfnOrig!= NULL)

 

    {

 

        DWORD dwOldProtect;

 

        MEMORY_BASIC_INFORMATION    mbi;

 

        ::VirtualQuery(m_pfnOrig, &mbi, sizeof(mbi));

 

        ::VirtualProtect(m_pfnOrig, 8,PAGE_READWRITE, &dwOldProtect);

 

 

 

        // 写入原来的执行代码

 

        ::WriteProcessMemory(::GetCurrentProcess(),(void *)m_pfnOrig, 

 

                        m_btOldBytes, sizeof(DWORD)*2, NULL); 

 

    

 

        ::VirtualProtect(m_pfnOrig, 8,mbi.Protect, 0);

 

    }

 

}

 

 

 

void CULHook::Rehook()

 

{

 

    // 修改原API函数执行代码的前8个字节,使它跳向我们的函数

 

    if(m_pfnOrig!= NULL)

 

    {

 

        DWORD dwOldProtect;

 

        MEMORY_BASIC_INFORMATION    mbi;

 

        ::VirtualQuery( m_pfnOrig, &mbi, sizeof(mbi) );

 

        ::VirtualProtect(m_pfnOrig, 8,PAGE_READWRITE, &dwOldProtect);

 

 

 

        // 写入新的执行代码

 

        ::WriteProcessMemory(::GetCurrentProcess(),(void *)m_pfnOrig, 

 

                        m_btNewBytes, sizeof(DWORD)*2, NULL); 

 

    

 

        ::VirtualProtect(m_pfnOrig, 8,mbi.Protect, 0);

 

    }

 

}

 

好了,编译DLL就可以了

 

 

 

因为时间要求,教程比较粗略,如果有错误请指出,如果有问题,可以留言。



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



http://wuqinzhong.blog.163.com/blog/static/4522231200932542020736/


hook socket 简易防火墙的实现  

2009-04-25 16:20:20|  分类: C++|字号 订阅

#include "stdafx.h"

#include "winsock2.h"

#include "DetourDll.h"

//转载注明出处 by webxeyes http://blog.csdn.net/webxeyes

#include "detours.h"    //the main API header of detours

#pragma comment(lib,"detours.lib")

#pragma comment(lib,"Ws2_32.lib")

int WSAAPI sendto(SOCKET s,const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen );

int WSAAPI send(SOCKET s,const char* buf,int len,int flags);

DETOUR_TRAMPOLINE(int WSAAPI sendto1(SOCKET s,const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen ), sendto);

DETOUR_TRAMPOLINE(int WSAAPI send1(SOCKET s,const char* buf,int len,int flags), send);

int WSAAPI send2(SOCKET s,const char* buf,int len,int flags)

{

    /*
http://blog.csdn.net/webxeyes

    sockaddr_in sa;

    int leng = 0;

    getsockname(s,(sockaddr*)&sa,&leng);

    char* addr = inet_ntoa(sa.sin_addr);

    //这样就获取地址了http://blog.csdn.net/webxeyes

    MessageBox(0,addr,"出现 TCP socket",0);

    return send1(s,buf,len,flags);

    */

    return 0;

}

int

WSAAPI

sendto2(SOCKET s,const char FAR * buf,int len,int flags,const struct sockaddr FAR * to,int tolen)

{

    //MessageBox(0,buf,"出现 UDP socket",0);

    return sendto1(s,buf,len,flags,to,tolen );

}

//转载注明出处 by webxeyes http://blog.csdn.net/webxeyes

BOOL APIENTRY DllMain( HANDLE hModule, 

                      DWORD  ul_reason_for_call, 

                      LPVOID lpReserved

                      )

{

    switch (ul_reason_for_call)

    {

    case DLL_PROCESS_ATTACH:

        DetourFunctionWithTrampoline((PBYTE)sendto1, (PBYTE)sendto2);

        DetourFunctionWithTrampoline((PBYTE)send1, (PBYTE)send2);

        break;

    case DLL_THREAD_ATTACH:

        break;

    case DLL_THREAD_DETACH:

        break;

    case DLL_PROCESS_DETACH:

        DetourRemove((PBYTE)sendto1, (PBYTE)sendto2);

        DetourRemove((PBYTE)send1, (PBYTE)send2);

        break;

    }

    return TRUE;

}

LRESULT DETOURDLL_API WINAPI  MsgProc(int code, WPARAM wParam, LPARAM lParam)

{

    return(CallNextHookEx(NULL,code,wParam,lParam));

}

抱歉!评论已关闭.