精华内容
下载资源
问答
  • Wireshark修改数据包

    万次阅读 2019-11-08 11:05:41
    新版本不行。 旧版本可以:https://www.wireshark.org/download/win64/all-versions/Wireshark-win64-1.12.8.exe

    新版本不行。
    旧版本可以:https://www.wireshark.org/download/win64/all-versions/Wireshark-win64-1.12.8.exe

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    修改了包之后进行重发:
    使用tcpreplay
    https://tcpreplay.appneta.com/wiki/installation.html

    展开全文
  • 在Windows网络数据通讯层,通过封包技术在客户端挡截游戏服务器发送来的游戏控制数 据包,分析数据包修改数据包;同时还可以按照游戏数据包结构创建数据包,再模拟客户端发送给游戏服务器,这个过程其实就是一个...

    在Windows网络数据通讯层,通过封包技术在客户端挡截游戏服务器发送来的游戏控制数 据包,分析数据包并修改数据包;同时还可以按照游戏数据包结构创建数据包,再模拟客户端发送给游戏服务器,这个过程其实就是一个封包的过程。

    封包的技术是实现第二类游戏外挂的最核心的技术。封包技术涉及的知识很广泛,实现方法也很多,如挡截 WinSock 、挡截 API 函数、挡截消息、 VxD 驱动程序等。在此我们也不可能在此文中将所有的封包技术都进行详细介绍,故选择两种在游戏外挂程序中最常用的两种方法:挡截 WinSock 和挡截 API 函数。

    1 . 挡截WinSock

    众所周知, Winsock 是 Windows 网络编程接口,它工作于 Windows 应用层,它提供与底层传输协议无关的高层数据传输编程接口。在 Windows 系统中,使用 WinSock 接口为应用程序提供基于 TCP/IP 协议的网络访问服务,这些服务是由 Wsock32.DLL 动态链接库提供的函数库来完成的。

    由上说明可知,任何 Windows 基于 TCP/IP 的应用程序都必须通过 WinSock 接口访问网络,当然网络游戏程序也不例外。由此我们可以想象一下,如果我们可以控制 WinSock 接口的话,那么控制游戏客户端程序与服务器之间的数据包也将易如反掌。按着这个思路,下面的工作就是如何完成控制 WinSock 接口了。由上面的介绍可知, WinSock 接口其实是由一个动态链接库提供的一系列函数,由这些函数实现对网络的访问。有了这层的认识,问题就好办多了,我们可以制作一个类似的动态链接库来代替原 WinSock 接口库,在其中实现 WinSock32.dll 中实现的所有函数,并保证所有函数的参数个数和顺序、返回值类型都应与原库相同。在这个自制作的动态库中,可以对我们感兴趣的函数(如发送、接收等函数)进行挡截,放入外挂控制代码,最后还继续调用原 WinSock 库中提供的相应功能函数,这样就可以实现对网络数据包的挡截、修改和发送等封包功能。

    下面重点介绍创建挡截 WinSock 外挂程序的基本步骤:

    (1) 创建 DLL 项目,选择 Win32 Dynamic-Link Library ,再选择 An empty DLL project 。

    (2) 新建文件 wsock32.h ,按如下步骤输入代码:

    ① 加入相关变量声明:

    HMODULE hModule=NULL; // 模块句柄

    char buffer[1000]; // 缓冲区

    FARPROC proc; // 函数入口指针

    ② 定义指向原WinSock库中的所有函数地址的指针变量,因WinSock库共提供70多个函数,限于篇幅,在此就只选择几个常用的函数列出,有关这些库函数的说明可参考MSDN相关内容。

    // 定义指向原 WinSock 库函数地址的指针变量。

    SOCKET (__stdcall *socket1)(int ,int,int);// 创建 Sock 函数。

    int   (__stdcall *WSAStartup1)(WORD,LPWSADATA);// 初始化 WinSock 库函数。

    int   (__stdcall *WSACleanup1)();// 清除 WinSock 库函数。

    int (__stdcall *recv1)(SOCKET ,char FAR * ,int ,int );// 接收数据函数。

    int (__stdcall *send1)(SOCKET ,const char * ,int ,int);// 发送数据函数。

    int (__stdcall *connect1)(SOCKET,const struct sockaddr *,int);// 创建连接函数。

    int (__stdcall *bind1)(SOCKET ,const struct sockaddr *,int );// 绑定函数。

    ...... 其它函数地址指针的定义略。

    (3) 新建 wsock32.cpp 文件,按如下步骤输入代码:

    ① 加入相关头文件声明:

    #include

    #include

    #include "wsock32.h"

    ② 添加DllMain函数,在此函数中首先需要加载原WinSock库,并获取此库中所有函数的地址。代码如下:

    BOOL WINAPI DllMain (HANDLE hInst,ULONG ul_reason_for_call,LPVOID lpReserved)

    {

    if(hModule==NULL){

    // 加载原 WinSock 库,原 WinSock 库已复制为 wsock32.001 。

    hModule=LoadLibrary("wsock32.001");

    }

    else return 1;

    // 获取原 WinSock 库中的所有函数的地址并保存,下面仅列出部分代码。

    if(hModule!=NULL){

    // 获取原 WinSock 库初始化函数的地址,并保存到 WSAStartup1 中。

    proc=GetProcAddress(hModule,"WSAStartup");

    WSAStartup1=(int (_stdcall *)(WORD,LPWSADATA))proc;

    // 获取原 WinSock 库消除函数的地址,并保存到 WSACleanup1 中。

    proc=GetProcAddress(hModule i,"WSACleanup");

    WSACleanup1=(int (_stdcall *)())proc;

    // 获取原创建 Sock 函数的地址,并保存到 socket1 中。

    proc=GetProcAddress(hModule,"socket");

    socket1=(SOCKET (_stdcall *)(int ,int,int))proc;

    // 获取原创建连接函数的地址,并保存到 connect1 中。

    proc=GetProcAddress(hModule,"connect");

    connect1=(int (_stdcall *)(SOCKET ,const struct sockaddr *,int ))proc;

    // 获取原发送函数的地址,并保存到 send1 中。

    proc=GetProcAddress(hModule,"send");

    send1=(int (_stdcall *)(SOCKET ,const char * ,int ,int ))proc;

    // 获取原接收函数的地址,并保存到 recv1 中。

    proc=GetProcAddress(hModule,"recv");

    recv1=(int (_stdcall *)(SOCKET ,char FAR * ,int ,int ))proc;

    ...... 其它获取函数地址代码略。

    }

    else return 0;

    return 1;

    }

    ③ 定义库输出函数,在此可以对我们感兴趣的函数中添加外挂控制代码,在所有的输出函数的最后一步都调用原WinSock库的同名函数。部分输出函数定义代码如下:

    // 库输出函数定义。

    //WinSock 初始化函数。

    int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)

    {

    // 调用原 WinSock 库初始化函数

    return WSAStartup1(wVersionRequired,lpWSAData);

    }

    //WinSock 结束清除函数。

    int PASCAL FAR WSACleanup(void)

    {

    return WSACleanup1(); // 调用原 WinSock 库结束清除函数。

    }

    // 创建 Socket 函数。

    SOCKET PASCAL FAR socket (int af, int type, int protocol)

    {

    // 调用原 WinSock 库创建 Socket 函数。

    return socket1(af,type,protocol);

    }

    // 发送数据包函数

    int PASCAL FAR send(SOCKET s,const char * buf,int len,int flags)

    {

    // 在此可以对发送的缓冲 buf 的内容进行修改,以实现欺骗服务器。

    外挂代码 ......

    // 调用原 WinSock 库发送数据包函数。

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

    }

    // 接收数据包函数。

    int PASCAL FAR recv(SOCKET s, char FAR * buf, int len, int flags)

    {

    // 在此可以挡截到服务器端发送到客户端的数据包,先将其保存到 buffer 中。

    strcpy(buffer,buf);

    // 对 buffer 数据包数据进行分析后,对其按照玩家的指令进行相关修改。

    外挂代码 ......

    // 最后调用原 WinSock 中的接收数据包函数。

    return recv1(s, buffer, len, flags);

    }

    ....... 其它函数定义代码略。

    (4) 、新建 wsock32.def 配置文件,在其中加入所有库输出函数的声明,部分声明代码如下:

    LIBRARY "wsock32"

    EXPORTS

    WSAStartup @1

    WSACleanup @2

    recv @3

    send @4

    socket @5

    bind @6

    closesocket @7

    connect @8

    ...... 其它输出函数声明代码略。

    (5) 、从 “ 工程 ” 菜单中选择 “ 设置 ” ,弹出 Project Setting 对话框,选择 Link 标签,在 “ 对象 / 库模块 ” 中输入 Ws2_32.lib 。

    (6) 、编译项目,产生 wsock32.dll 库文件。

    (7) 、将系统目录下原 wsock32.dll 库文件拷贝到被外挂程序的目录下,并将其改名为 wsock.001 ;再将上面产生的 wsock32.dll 文件同样拷贝到被外挂程序的目录下。重新启动游戏程序,此时游戏程序将先加载我们自己制作的 wsock32.dll 文件,再通过该库文件间接调用原 WinSock 接口函数来实现访问网络。上面我们仅仅介绍了挡载 WinSock 的实现过程,至于如何加入外挂控制代码,还需要外挂开发人员对游戏数据包结构、内容、加密算法等方面的仔细分析(这个过程将是一个艰辛的过程),再生成外 挂控制代码。关于数据包分析方法和技巧,不是本文讲解的范围,如您感兴趣可以到网上查查相关资料。

    2. 挡截 API

    挡截 API 技术与挡截 WinSock 技术在原理上很相似,但是前者比后者提供了更强大的功能。挡截 WinSock 仅只能挡截 WinSock 接口函数,而挡截 API 可以实现对应用程序调用的包括 WinSock API 函数在内的所有 API 函数的挡截。如果您的外挂程序仅打算对 WinSock 的函数进行挡截的话,您可以只选择使用上小节介绍的挡截 WinSock 技术。随着大量外挂程序在功能上的扩展,它们不仅仅只提供对数据包的挡截,而且还对游戏程序中使用的 Windows API 或其它 DLL 库函数的挡截,以使外挂的功能更加强大。例如,可以通过挡截相关 API 函数以实现对非中文游戏的汉化功能,有了这个利器,可以使您的外挂程序无所不能了。

    挡截 API 技术的原理核心也是使用我们自己的函数来替换掉 Windows 或其它 DLL 库提供的函数,有点同挡截 WinSock 原理相似吧。但是,其实现过程却比挡截 WinSock 要复杂的多,如像实现挡截 Winsock 过程一样,将应用程序调用的所有的库文件都写一个模拟库有点不大可能,就只说 Windows API 就有上千个,还有很多库提供的函数结构并未公开,所以写一个模拟库代替的方式不大现实,故我们必须另谋良方。

    挡截 API 的最终目标是使用自定义的函数代替原函数。那么,我们首先应该知道应用程序何时、何地、用何种方式调用原函数。接下来,需要将应用程序中调用该原函数的指 令代码进行修改,使它将调用函数的指针指向我们自己定义的函数地址。这样,外挂程序才能完全控制应用程序调用的 API 函数,至于在其中如何加入外挂代码,就应需求而异了。最后还有一个重要的问题要解决,如何将我们自定义的用来代替原 API 函数的函数代码注入被外挂游戏程序进行地址空间中,因在 Windows 系统中应用程序仅只能访问到本进程地址空间内的代码和数据。

    综上所述,要实现挡截 API 函数,至少需要解决如下三个问题:

    ● 如何定位游戏程序中调用 API 函数指令代码?

    ● 如何修改游戏程序中调用 API 函数指令代码?

    ● 如何将外挂代码(自定义的替换函数代码)注入到游戏程序进程地址空间?

    下面我们逐一介绍这几个问题的解决方法:

    (1) 、定位调用 API 函数指令代码

    我们知道,在汇编语言中使用 CALL 指令来调用函数或过程的,它是通过指令参数中的函数地址而定位到相应的函数代码的。那么,我们如果能寻找到程序代码中所有调用被挡截的 API 函数的 CALL 指令的话,就可以将该指令中的函数地址参数修改为替代函数的地址。虽然这是一个可行的方案,但是实现起来会很繁琐,也不稳健。庆幸的是, Windows 系统中所使用的可执行文件( PE 格式)采用了输入地址表机制,将所有在程序调用的 API 函数的地址信息存放在输入地址表中,而在程序代码 CALL 指令中使用的地址不是 API 函数的地址,而是输入地址表中该 API 函数的地址项,如想使程序代码中调用的 API 函数被代替掉,只用将输入地址表中该 API 函数的地址项内容修改即可。具体理解输入地址表运行机制,还需要了解一下 PE 格式文件结构,其中图三列出了 PE 格式文件的大致结构。

    图三: PE 格式大致结构图 (003.jpg)

    PE 格式文件一开始是一段 DOS 程序,当你的程序在不支持 Windows 的环境中运行时,它就会显示 “This Program cannot be run in DOS mode” 这样的警告语句,接着这个 DOS 文件头,就开始真正的 PE 文件内容了。首先是一段称为 “IMAGE_NT_HEADER” 的数据,其中是许多关于整个 PE 文件的消息,在这段数据的尾端是一个称为 Data Directory 的数据表,通过它能快速定位一些 PE 文件中段( section )的地址。在这段数据之后,则是一个 “IMAGE_SECTION_HEADER” 的列表,其中的每一项都详细描述了后面一个段的相关信息。接着它就是 PE 文件中最主要的段数据了,执行代码、数据和资源等等信息就分别存放在这些段中。

    在所有的这些段里,有一个被称为 “.idata” 的段(输入数据段)值得我们去注意,该段中包含着一些被称为输入地址表( IAT , Import Address Table )的数据列表。每个用隐式方式加载的 API 所在的 DLL 都有一个 IAT 与之对应,同时一个 API 的地址也与 IAT 中一项相对应。当一个应用程序加载到内存中后,针对每一个 API 函数调用,相应的产生如下的汇编指令:

    JMP DWORD PTR [XXXXXXXX]

    CALL DWORD PTR [XXXXXXXX]

    其中, [XXXXXXXX] 表示指向了输入地址表中一个项,其内容是一个 DWORD ,而正是这个 DWORD 才是 API 函数在内存中的真正地址。因此我们要想拦截一个 API 的调用,只要简单的把那个 DWORD 改为我们自己的函数的地址。

    (2) 、修改调用 API 函数代码

    从上面对 PE 文件格式的分析可知,修改调用 API 函数代码其实是修改被调用 API 函数在输入地址表中 IAT 项内容。由于 Windows 系统对应用程序指令代码地址空间的严密保护机制,使得修改程序指令代码非常困难,以至于许多高手为之编写 VxD 进入 Ring0 。在这里,我为大家介绍一种较为方便的方法修改进程内存,它仅需要调用几个 Windows 核心 API 函数,下面我首先来学会一下这几个 API 函数:

    DWORD VirtualQuery(

    LPCVOID lpAddress, // address of region

    PMEMORY_BASIC_INFORMATION lpBuffer, // information buffer

    DWORD dwLength // size of buffer

    );

    该函数用于查询关于本进程内虚拟地址页的信息。其中, lpAddress 表示被查询页的区域地址; lpBuffer 表示用于保存查询页信息的缓冲; dwLength 表示缓冲区大小。返回值为实际缓冲大小。

    BOOL VirtualProtect(

    LPVOID lpAddress, // region of committed pages

    SIZE_T dwSize, // size of the region

    DWORD flNewProtect, // desired access protection

    PDWORD lpflOldProtect // old protection

    );

    该函数用于改变本进程内虚拟地址页的保护属性。其中, lpAddress 表示被改变保护属性页区域地址; dwSize 表示页区域大小; flNewProtect 表示新的保护属性,可取值为 PAGE_READONLY 、 PAGE_READWRITE 、 PAGE_EXECUTE 等; lpflOldProtect 表示用于保存改变前的保护属性。如果函数调用成功返回 “T” ,否则返回 “F” 。

    有了这两个 API 函数,我们就可以随心所欲的修改进程内存了。首先,调用 VirtualQuery() 函数查询被修改内存的页信息,再根据此信息调用 VirtualProtect() 函数改变这些页的保护属性为 PAGE_READWRITE ,有了这个权限您就可以任意修改进程内存数据了。下面一段代码演示了如何将进程虚拟地址为 0x0040106c 处的字节清零。

    BYTE* pData = 0x0040106c;

    MEMORY_BASIC_INFORMATION mbi_thunk;

    // 查询页信息。

    VirtualQuery(pData, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));

    // 改变页保护属性为读写。

    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,

    PAGE_READWRITE, &mbi_thunk.Protect);

    // 清零。

    *pData = 0x00;

    // 恢复页的原保护属性。

    DWORD dwOldProtect;

    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,

    mbi_thunk.Protect, &dwOldProtect);

    (3) 、注入外挂代码进入被挂游戏进程中

    完成了定位和修改程序中调用 API 函数代码后,我们就可以随意设计自定义的 API 函数的替代函数了。做完这一切后,还需要将这些代码注入到被外挂游戏程序进程内存空间中,不然游戏进程根本不会访问到替代函数代码。注入方法有很多,如利用全局钩子注入、利用注册表注入挡截 User32 库中的 API 函数、利用 CreateRemoteThread 注入(仅限于 NT/2000 )、利用 BHO 注入等。因为我们在动作模拟技术一节已经接触过全局钩子,我相信聪明的读者已经完全掌握了全局钩子的制作过程,所以我们在后面的实例中,将继续利用这个全局钩子。至于其它几种注入方法,如果感兴趣可参阅 MSDN 有关内容。

    有了以上理论基础,我们下面就开始制作一个挡截 MessageBoxA 和 recv 函数的实例,在开发游戏外挂程序 时,可以此实例为框架,加入相应的替代函数和处理代码即可。此实例的开发过程如下:

    (1) 打开前面创建的 ActiveKey 项目。

    (2) 在 ActiveKey.h 文件中加入 HOOKAPI 结构,此结构用来存储被挡截 API 函数名称、原 API 函数地址和替代函数地址。

    typedef struct tag_HOOKAPI

    {

    LPCSTR szFunc;// 被 HOOK 的 API 函数名称。

    PROC pNewProc;// 替代函数地址。

    PROC pOldProc;// 原 API 函数地址。

    }HOOKAPI, *LPHOOKAPI;

    (3) 打开 ActiveKey.cpp 文件,首先加入一个函数,用于定位输入库在输入数据段中的 IAT 地址。代码如下:

    extern "C" __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR

    LocationIAT(HMODULE hModule, LPCSTR szImportMod)

    // 其中, hModule 为进程模块句柄; szImportMod 为输入库名称。

    {

    // 检查是否为 DOS 程序,如是返回 NULL ,因 DOS 程序没有 IAT 。

    PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule;

    if(pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL;

    // 检查是否为 NT 标志,否则返回 NULL 。

    PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader+ (DWORD)(pDOSHeader->e_lfanew));

    if(pNTHeader->Signature != IMAGE_NT_SIGNATURE) return NULL;

    // 没有 IAT 表则返回 NULL 。

    if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0) return NULL;

    // 定位第一个 IAT 位置。

    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader + (DWORD)(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));

    // 根据输入库名称循环检查所有的 IAT ,如匹配则返回该 IAT 地址,否则检测下一个 IAT 。

    while (pImportDesc->Name)

    {

    // 获取该 IAT 描述的输入库名称。

    PSTR szCurrMod = (PSTR)((DWORD)pDOSHeader + (DWORD)(pImportDesc->Name));

    if (stricmp(szCurrMod, szImportMod) == 0) break;

    pImportDesc++;

    }

    if(pImportDesc->Name == NULL) return NULL;

    return pImportDesc;

    }

    再加入一个函数,用来定位被挡截 API 函数的 IAT 项并修改其内容为替代函数地址。代码如下:

    extern "C" __declspec(dllexport)

    HookAPIByName( HMODULE hModule, LPCSTR szImportMod, LPHOOKAPI pHookApi)

    // 其中, hModule 为进程模块句柄; szImportMod 为输入库名称; pHookAPI 为 HOOKAPI 结构指针。

    {

    // 定位 szImportMod 输入库在输入数据段中的 IAT 地址。

    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = LocationIAT(hModule, szImportMod);

    if (pImportDesc == NULL) return FALSE;

    // 第一个 Thunk 地址。

    PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->OriginalFirstThunk));

    // 第一个 IAT 项的 Thunk 地址。

    PIMAGE_THUNK_DATA pRealThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc->FirstThunk));

    // 循环查找被截 API 函数的 IAT 项,并使用替代函数地址修改其值。

    while(pOrigThunk->u1.Function)

    {

    // 检测此 Thunk 是否为 IAT 项。

    if((pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)

    {

    // 获取此 IAT 项所描述的函数名称。

    PIMAGE_IMPORT_BY_NAME pByName =(PIMAGE_IMPORT_BY_NAME)((DWORD)hModule+(DWORD)(pOrigThunk->u1.AddressOfData));

    if(pByName->Name[0] == ‘//0‘) return FALSE;

    // 检测是否为挡截函数。

    if(strcmpi(pHookApi->szFunc, (char*)pByName->Name) == 0)

    {

    MEMORY_BASIC_INFORMATION mbi_thunk;

    // 查询修改页的信息。

    VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));

    // 改变修改页保护属性为 PAGE_READWRITE 。

    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect);

    // 保存原来的 API 函数地址。

    if(pHookApi->pOldProc == NULL)

    pHookApi->pOldProc = (PROC)pRealThunk->u1.Function;

    //修改API函数IAT项内容为替代函数地址。

    pRealThunk->u1.Function = (PDWORD)pHookApi->pNewProc;

    //恢复修改页保护属性。

    DWORD dwOldProtect;

    VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect);

    }

    }

    pOrigThunk++;

    pRealThunk++;

    }

    SetLastError(ERROR_SUCCESS); //设置错误为ERROR_SUCCESS,表示成功。

    return TRUE;

    }

    (4) 定义替代函数,此实例中只给 MessageBoxA 和 recv 两个 API 进行挡截。代码如下:

    static int WINAPI MessageBoxA1 (HWND hWnd , LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)

    {

    // 过滤掉原 MessageBoxA 的正文和标题内容,只显示如下内容。

    return MessageBox(hWnd, "Hook API OK!", "Hook API", uType);

    }

    static int WINAPI recv1(SOCKET s, char FAR *buf, int len, int flags )

    {

    // 此处可以挡截游戏服务器发送来的网络数据包,可以加入分析和处理数据代码。

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

    }

    (5) 在 KeyboardProc 函数中加入激活挡截 API 代码,在 if( wParam == 0X79 ) 语句中后面加入如下 else if 语句:

    ......

    // 当激活 F11 键时,启动挡截 API 函数功能。

    else if( wParam == 0x7A )

    {

    HOOKAPI api[2];

    api[0].szFunc ="MessageBoxA";// 设置被挡截函数的名称。

    api[0].pNewProc = (PROC)MessageBoxA1;// 设置替代函数的地址。

    api[1].szFunc ="recv";// 设置被挡截函数的名称。

    api[1].pNewProc = (PROC)recv1; // 设置替代函数的地址。

    // 设置挡截 User32.dll 库中的 MessageBoxA 函数。

    HookAPIByName(GetModuleHandle(NULL),"User32.dll",&api[0]);

    // 设置挡截 Wsock32.dll 库中的 recv 函数。

    HookAPIByName(GetModuleHandle(NULL),"Wsock32.dll",&api[1]);

    }

    ......

    (6) 在 ActiveKey.cpp 中加入头文件声明 "#include "wsock32.h" 。 从“工程”菜单中选择“设置”,弹出Project Setting对话框,选择Link标签,在“对象/库模块”中输入Ws2_32..lib。

    (7) 重新编译 ActiveKey 项目,产生 ActiveKey.dll 文件,将其拷贝到 Simulate.exe 目录下。运行 Simulate.exe 并启动全局钩子。激活任意应用程序,按 F11 键后,运行此程序中可能调用 MessageBoxA 函数的操作,看看信息框是不是有所变化。同样,如此程序正在接收网络数据包,就可以实现封包功能了。

    来源:http://blog.csdn.net/zfrong/article/details/3616006

    展开全文
  • 为了满足客户对网络测试的需求,MiniSMB网络性能测试仪自主研发自动化脚本测试MiniSMB Wrench,本文介绍MiniSMB Wrench自动化脚本测试入门 – 更改数据包长度。 实验目的 通过修改流配置模版中数据报文长度(length)...

    随着网络科技的高速发展与网络速率的不断提升,用户对网络设备的可靠性需求也随之提高。为了满足客户对网络测试的需求,MiniSMB网络性能测试仪自主研发自动化脚本测试MiniSMB Wrench,本文介绍MiniSMB Wrench自动化脚本测试入门 – 更改数据包长度。

    实验目的

    通过修改流配置模版中数据报文长度(length)字段来实现MiniSMB测试仪表发送用户指定的数据报文长度。

    测试拓扑图

    在这里插入图片描述

    拓扑图描述

    测试IP地址192.168.2.5的工控机上的两张网卡,将网卡192.168.2.5/0的第一个端口与192.168.2.5/1相连,通过在IP地址为192.168.2.10的PC机上编辑并执行自动化测试脚本实现实验目的。

    操作步骤

    1、确认flows类型

    查看样板测试文件“examples/tests/olt.yml”
    查看flows类型
    在这里插入图片描述
    通过以上返回结果确认为“udpVlanFlow”
    查看样板测试文件 “examples/flows/udp-vlan-singleflow.yml”
    在这里插入图片描述
    确认olt.yml文件 使用流类型与udp-vlan-singleflow.yml文件内容描述一致

    2、修改length长度

    编辑样板测试文件“examples/flows/udp-vlan-singleflow.yml”
    修改长度为1514
    在这里插入图片描述
    ( 注:
    参数说明
    length代表字节长度(修改范围60-1514)

    修改后保存退出

    3、验证结果

    运行以下命令行验证返回结果
    minismb-wrench.win.exe test
    –test-resultfile test-results/result.json
    –test-cfgfile examples/tests/olt.yml
    –log-level info
    ( 注:
    在这里插入图片描述


    获取端口统计信息。
    等待返回结果,观察FrameSize字段是否为修改值
    在这里插入图片描述
    我们也可以进行多次修改去验证。

    展开全文
  • 据包,分析数据包修改数据包;同时还需按照游戏数据包结构创建数据包,再模拟客户端发送给游戏服务器,这个过程其实就是一个封包的过程。   封包的技术是实现第二类游戏外挂的最核心的技术。封包技术涉及的知识...

    转自:https://www.xuebuyuan.com/905158.html

    通过对动作模拟技术的介绍,我们对游戏外挂有了一定程度上的认识,也学会了使用动作模拟技术来实现简单的动作模拟型游戏外挂的制作。这种动作模拟型游戏外
    挂有一定的局限性,它仅仅只能解决使用计算机代替人力完成那么有规律、繁琐而无聊的游戏动作。但是,随着网络游戏的盛行和复杂度的增加,很多游戏要求将客
    户端动作信息及时反馈回服务器,通过服务器对这些动作信息进行有效认证后,再向客户端发送下一步游戏动作信息,这样动作模拟技术将失去原有的效应。为了更
    好地 “ 外挂 ”
    这些游戏,游戏外挂程序也进行了升级换代,它们将以前针对游戏用户界面层的模拟推进到数据通讯层,通过封包技术在客户端挡截游戏服务器发送来的游戏控制数
    据包,分析数据包并修改数据包;同时还需按照游戏数据包结构创建数据包,再模拟客户端发送给游戏服务器,这个过程其实就是一个封包的过程。 
      封包的技术是实现第二类游戏外挂的最核心的技术。封包技术涉及的知识很广泛,实现方法也很多,如挡截
    WinSock 、挡截 API 函数、挡截消息、
    VxD
    驱动程序等。在此我们也不可能在此文中将所有的封包技术都进行详细介绍,故选择两种在游戏外挂程序中最常用的两种方法:挡截
    WinSock 和挡截 API 函数。 
       1 . 挡截WinSock
      众所周知, Winsock 是
    Windows 网络编程接口,它工作于
    Windows
    应用层,它提供与底层传输协议无关的高层数据传输编程接口。在
    Windows 系统中,使用 WinSock
    接口为应用程序提供基于 TCP/IP
    协议的网络访问服务,这些服务是由
    Wsock32.DLL
    动态链接库提供的函数库来完成的。 
      由上说明可知,任何 Windows 基于
    TCP/IP 的应用程序都必须通过
    WinSock
    接口访问网络,当然网络游戏程序也不例外。由此我们可以想象一下,如果我们可以控制
    WinSock
    接口的话,那么控制游戏客户端程序与服务器之间的数据包也将易如反掌。按着这个思路,下面的工作就是如何完成控制
    WinSock 接口了。由上面的介绍可知,
    WinSock
    接口其实是由一个动态链接库提供的一系列函数,由这些函数实现对网络的访问。有了这层的认识,问题就好办多了,我们可以制作一个类似的动态链接库来代替原
    WinSock 接口库,在其中实现
    WinSock32.dll
    中实现的所有函数,并保证所有函数的参数个数和顺序、返回值类型都应与原库相同。在这个自制作的动态库中,可以对我们感兴趣的函数(如发送、接收等函数)进行挡截,放入外挂控制代码,最后还继续调用原
    WinSock
    库中提供的相应功能函数,这样就可以实现对网络数据包的挡截、修改和发送等封包功能。

      下面重点介绍创建挡截 WinSock
    外挂程序的基本步骤: 
       (1) 创建 DLL 项目,选择
    Win32 Dynamic-Link
    Library ,再选择 An empty
    DLL project 。 
       (2) 新建文件 wsock32.h
    ,按如下步骤输入代码: 
       ① 加入相关变量声明:
        HMODULE hModule=NULL;
    // 模块句柄 
        char buffer[1000];
    // 缓冲区 
        FARPROC proc; //
    函数入口指针 
       ②
    定义指向原WinSock库中的所有函数地址的指针变量,因WinSock库共提供70多个函数,限于篇幅,在此就只选择几个常用的函数列出,有关这些库函数的说明可参考MSDN相关内容。
        // 定义指向原 WinSock
    库函数地址的指针变量。 
        SOCKET (__stdcall
    *socket1)(int ,int,int);//
    创建 Sock 函数。 
        int   (__stdcall
    *WSAStartup1)(WORD,LPWSADATA);//
    初始化 WinSock 库函数。 
        int   (__stdcall
    *WSACleanup1)();// 清除
    WinSock 库函数。 
        int (__stdcall
    *recv1)(SOCKET ,char FAR
    * ,int ,int );// 接收数据函数。

        int (__stdcall
    *send1)(SOCKET ,const
    char * ,int ,int);//
    发送数据函数。 
        int (__stdcall
    *connect1)(SOCKET,const
    struct sockaddr *,int);//
    创建连接函数。 
        int (__stdcall
    *bind1)(SOCKET ,const
    struct sockaddr *,int
    );// 绑定函数。 
        ...... 其它函数地址指针的定义略。

       (3) 新建 wsock32.cpp
    文件,按如下步骤输入代码: 
       ① 加入相关头文件声明:
        #include <windows.h>
        #include <stdio.h>
        #include "wsock32.h"

       ② 添加DllMain函数,在此函数中首先需要加载原WinSock库,并获取此库中所有函数的地址。代码如下:
        BOOL WINAPI DllMain
    (HANDLE hInst,ULONG
    ul_reason_for_call,LPVOID
    lpReserved)
        {
         if(hModule==NULL){
          // 加载原 WinSock 库,原
    WinSock 库已复制为
    wsock32.001 。 
        hModule=LoadLibrary("wsock32.001");

       }
         else return 1;
    // 获取原 WinSock
    库中的所有函数的地址并保存,下面仅列出部分代码。

    if(hModule!=NULL){
          // 获取原 WinSock
    库初始化函数的地址,并保存到
    WSAStartup1 中。 
    proc=GetProcAddress(hModule,"WSAStartup");
        WSAStartup1=(int (_stdcall
    *)(WORD,LPWSADATA))proc;
          // 获取原 WinSock
    库消除函数的地址,并保存到
    WSACleanup1 中。 
         proc=GetProcAddress(hModule
    i,"WSACleanup");
         WSACleanup1=(int (_stdcall
    *)())proc;
          // 获取原创建 Sock
    函数的地址,并保存到 socket1 中。

         proc=GetProcAddress(hModule,"socket");
          socket1=(SOCKET (_stdcall
    *)(int ,int,int))proc;
          //
    获取原创建连接函数的地址,并保存到
    connect1 中。 
          proc=GetProcAddress(hModule,"connect");
          connect1=(int (_stdcall
    *)(SOCKET ,const struct
    sockaddr *,int ))proc;
          // 获取原发送函数的地址,并保存到
    send1 中。 
          proc=GetProcAddress(hModule,"send");
          send1=(int (_stdcall
    *)(SOCKET ,const char *
    ,int ,int ))proc;
          // 获取原接收函数的地址,并保存到
    recv1 中。 
          proc=GetProcAddress(hModule,"recv");
          recv1=(int (_stdcall
    *)(SOCKET ,char FAR * ,int
    ,int ))proc;
          ......
    其它获取函数地址代码略。 
        }
        else return 0;
        return 1;

       ③
    定义库输出函数,在此可以对我们感兴趣的函数中添加外挂控制代码,在所有的输出函数的最后一步都调用原WinSock库的同名函数。部分输出函数定义代码如下:
    // 库输出函数定义。 
    //WinSock 初始化函数。 
         int PASCAL FAR
    WSAStartup(WORD
    wVersionRequired,
    LPWSADATA lpWSAData)
         {
          // 调用原 WinSock
    库初始化函数 
          return
    WSAStartup1(wVersionRequired,lpWSAData);
         }
         //WinSock 结束清除函数。

         int PASCAL FAR
    WSACleanup(void)
         {
          return
    WSACleanup1(); // 调用原
    WinSock 库结束清除函数。 
         }
         // 创建 Socket 函数。

         SOCKET PASCAL FAR
    socket (int af, int
    type, int protocol)
         {
          // 调用原 WinSock 库创建
    Socket 函数。 
          return
    socket1(af,type,protocol);
         }
         // 发送数据包函数 
         int PASCAL FAR
    send(SOCKET s,const char
    * buf,int len,int flags)
         {
        // 在此可以对发送的缓冲 buf
    的内容进行修改,以实现欺骗服务器。 
       外挂代码 ......
        // 调用原 WinSock
    库发送数据包函数。 
          return
    send1(s,buf,len,flags);
         }
    // 接收数据包函数。 
         int PASCAL FAR
    recv(SOCKET s, char FAR
    * buf, int len, int
    flags)
         {
        //
    在此可以挡截到服务器端发送到客户端的数据包,先将其保存到
    buffer 中。 
        strcpy(buffer,buf);
        // 对 buffer
    数据包数据进行分析后,对其按照玩家的指令进行相关修改。

       外挂代码 ......
        // 最后调用原 WinSock
    中的接收数据包函数。 
          return recv1(s,
    buffer, len, flags);
          }
         ....... 其它函数定义代码略。

       (4) 、新建 wsock32.def
    配置文件,在其中加入所有库输出函数的声明,部分声明代码如下:

        LIBRARY "wsock32"
        EXPORTS 
         WSAStartup @1
        WSACleanup @2
         recv @3
         send @4
         socket @5
        bind @6
        closesocket @7
        connect @8 
        ...... 其它输出函数声明代码略。

       (5) 、从 “ 工程 ” 菜单中选择 “
    设置 ” ,弹出 Project Setting
    对话框,选择 Link 标签,在 “ 对象 /
    库模块 ” 中输入 Ws2_32.lib 。

       (6) 、编译项目,产生
    wsock32.dll 库文件。 
       (7) 、将系统目录下原 wsock32.dll 库文件拷贝到被外挂程序的目录下,并将其改名为 wsock.001 ;再将上面产生的
    wsock32.dll 文件同样拷贝到被外挂程序的目录下。重新启动游戏程序,此时游戏程序将先加载我们自己制作的 wsock32.dll
    文件,再通过该库文件间接调用原 WinSock 接口函数来实现访问网络。上面我们仅仅介绍了挡载 WinSock
    的实现过程,至于如何加入外挂控制代码,还需要外挂开发人员对游戏数据包结构、内容、加密算法等方面的仔细分析(这个过程将是一个艰辛的过程),再生成外
    挂控制代码。关于数据包分析方法和技巧,不是本文讲解的范围,如您感兴趣可以到网上查查相关资料。 
       2. 挡截 API 
      挡截 API 技术与挡截 WinSock
    技术在原理上很相似,但是前者比后者提供了更强大的功能。挡截
    WinSock 仅只能挡截 WinSock
    接口函数,而挡截 API
    可以实现对应用程序调用的包括 WinSock
    API 函数在内的所有 API
    函数的挡截。如果您的外挂程序仅打算对
    WinSock
    的函数进行挡截的话,您可以只选择使用上小节介绍的挡截
    WinSock
    技术。随着大量外挂程序在功能上的扩展,它们不仅仅只提供对数据包的挡截,而且还对游戏程序中使用的
    Windows API 或其它 DLL
    库函数的挡截,以使外挂的功能更加强大。例如,可以通过挡截相关
    API
    函数以实现对非中文游戏的汉化功能,有了这个利器,可以使您的外挂程序无所不能了。

      挡截 API
    技术的原理核心也是使用我们自己的函数来替换掉
    Windows 或其它 DLL
    库提供的函数,有点同挡截 WinSock
    原理相似吧。但是,其实现过程却比挡截
    WinSock 要复杂的多,如像实现挡截
    Winsock
    过程一样,将应用程序调用的所有的库文件都写一个模拟库有点不大可能,就只说
    Windows API
    就有上千个,还有很多库提供的函数结构并未公开,所以写一个模拟库代替的方式不大现实,故我们必须另谋良方。

      挡截 API
    的最终目标是使用自定义的函数代替原函数。那么,我们首先应该知道应用程序何时、何地、用何种方式调用原函数。接下来,需要将应用程序中调用该原函数的指
    令代码进行修改,使它将调用函数的指针指向我们自己定义的函数地址。这样,外挂程序才能完全控制应用程序调用的 API
    函数,至于在其中如何加入外挂代码,就应需求而异了。最后还有一个重要的问题要解决,如何将我们自定义的用来代替原 API
    函数的函数代码注入被外挂游戏程序进行地址空间中,因在 Windows 系统中应用程序仅只能访问到本进程地址空间内的代码和数据。 
      综上所述,要实现挡截 API
    函数,至少需要解决如下三个问题: 
       ● 如何定位游戏程序中调用 API
    函数指令代码? 
       ● 如何修改游戏程序中调用 API
    函数指令代码? 
       ●
    如何将外挂代码(自定义的替换函数代码)注入到游戏程序进程地址空间?

      下面我们逐一介绍这几个问题的解决方法:

       (1) 、定位调用 API 函数指令代码

      我们知道,在汇编语言中使用 CALL
    指令来调用函数或过程的,它是通过指令参数中的函数地址而定位到相应的函数代码的。那么,我们如果能寻找到程序代码中所有调用被挡截的
    API 函数的 CALL
    指令的话,就可以将该指令中的函数地址参数修改为替代函数的地址。虽然这是一个可行的方案,但是实现起来会很繁琐,也不稳健。庆幸的是,
    Windows 系统中所使用的可执行文件( PE
    格式)采用了输入地址表机制,将所有在程序调用的
    API
    函数的地址信息存放在输入地址表中,而在程序代码
    CALL 指令中使用的地址不是 API
    函数的地址,而是输入地址表中该 API
    函数的地址项,如想使程序代码中调用的 API
    函数被代替掉,只用将输入地址表中该 API
    函数的地址项内容修改即可。具体理解输入地址表运行机制,还需要了解一下
    PE 格式文件结构,其中图三列出了 PE
    格式文件的大致结构。

      图三: PE 格式大致结构图
    (003.jpg) 
       PE 格式文件一开始是一段 DOS
    程序,当你的程序在不支持 Windows
    的环境中运行时,它就会显示 “This
    Program cannot be run in
    DOS mode” 这样的警告语句,接着这个
    DOS 文件头,就开始真正的 PE
    文件内容了。首先是一段称为
    “IMAGE_NT_HEADER”
    的数据,其中是许多关于整个 PE
    文件的消息,在这段数据的尾端是一个称为 Data
    Directory
    的数据表,通过它能快速定位一些 PE 文件中段(
    section
    )的地址。在这段数据之后,则是一个
    “IMAGE_SECTION_HEADER”
    的列表,其中的每一项都详细描述了后面一个段的相关信息。接着它就是
    PE
    文件中最主要的段数据了,执行代码、数据和资源等等信息就分别存放在这些段中。

      在所有的这些段里,有一个被称为
    “.idata”
    的段(输入数据段)值得我们去注意,该段中包含着一些被称为输入地址表(
    IAT , Import Address
    Table )的数据列表。每个用隐式方式加载的
    API 所在的 DLL 都有一个 IAT
    与之对应,同时一个 API 的地址也与 IAT
    中一项相对应。当一个应用程序加载到内存中后,针对每一个
    API 函数调用,相应的产生如下的汇编指令:

       JMP DWORD PTR
    [XXXXXXXX] 
      或 
       CALL DWORD PTR
    [XXXXXXXX] 
      其中, [XXXXXXXX]
    表示指向了输入地址表中一个项,其内容是一个
    DWORD ,而正是这个 DWORD 才是
    API
    函数在内存中的真正地址。因此我们要想拦截一个
    API 的调用,只要简单的把那个 DWORD
    改为我们自己的函数的地址。 
       (2) 、修改调用 API 函数代码

      从上面对 PE 文件格式的分析可知,修改调用
    API 函数代码其实是修改被调用 API
    函数在输入地址表中 IAT 项内容。由于
    Windows
    系统对应用程序指令代码地址空间的严密保护机制,使得修改程序指令代码非常困难,以至于许多高手为之编写
    VxD 进入 Ring0
    。在这里,我为大家介绍一种较为方便的方法修改进程内存,它仅需要调用几个
    Windows 核心 API
    函数,下面我首先来学会一下这几个 API 函数:

        DWORD VirtualQuery(
        LPCVOID lpAddress,
    // address of region
       
    PMEMORY_BASIC_INFORMATION
    lpBuffer, // information
    buffer
        DWORD dwLength //
    size of buffer
        ); 
      该函数用于查询关于本进程内虚拟地址页的信息。其中,
    lpAddress 表示被查询页的区域地址;
    lpBuffer 表示用于保存查询页信息的缓冲;
    dwLength
    表示缓冲区大小。返回值为实际缓冲大小。 
        BOOL VirtualProtect(
        LPVOID lpAddress, //
    region of committed
    pages
        SIZE_T dwSize, //
    size of the region
        DWORD flNewProtect,
    // desired access
    protection
        PDWORD
    lpflOldProtect // old
    protection
        ); 
      该函数用于改变本进程内虚拟地址页的保护属性。其中,
    lpAddress
    表示被改变保护属性页区域地址; dwSize
    表示页区域大小; flNewProtect
    表示新的保护属性,可取值为
    PAGE_READONLY 、
    PAGE_READWRITE 、
    PAGE_EXECUTE 等;
    lpflOldProtect
    表示用于保存改变前的保护属性。如果函数调用成功返回
    “T” ,否则返回 “F” 。 
      有了这两个 API
    函数,我们就可以随心所欲的修改进程内存了。首先,调用
    VirtualQuery()
    函数查询被修改内存的页信息,再根据此信息调用
    VirtualProtect()
    函数改变这些页的保护属性为
    PAGE_READWRITE
    ,有了这个权限您就可以任意修改进程内存数据了。下面一段代码演示了如何将进程虚拟地址为
    0x0040106c 处的字节清零。 
        BYTE* pData =
    0x0040106c;
       
    MEMORY_BASIC_INFORMATION
    mbi_thunk; 
        // 查询页信息。 
        VirtualQuery(pData,
    &mbi_thunk,
    sizeof(MEMORY_BASIC_INFORMATION));

        // 改变页保护属性为读写。 
       
    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,

        PAGE_READWRITE,
    &mbi_thunk.Protect); 
        // 清零。 
        *pData = 0x00;
        // 恢复页的原保护属性。 
        DWORD dwOldProtect;

       
    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,

        mbi_thunk.Protect,
    &dwOldProtect); 
       (3) 、注入外挂代码进入被挂游戏进程中

      完成了定位和修改程序中调用 API
    函数代码后,我们就可以随意设计自定义的 API
    函数的替代函数了。做完这一切后,还需要将这些代码注入到被外挂游戏程序进程内存空间中,不然游戏进程根本不会访问到替代函数代码。注入方法有很多,如利用全局钩子注入、利用注册表注入挡截
    User32 库中的 API 函数、利用
    CreateRemoteThread
    注入(仅限于 NT/2000 )、利用 BHO
    注入等。因为我们在动作模拟技术一节已经接触过全局钩子,我相信聪明的读者已经完全掌握了全局钩子的制作过程,所以我们在后面的实例中,将继续利用这个全局钩子。至于其它几种注入方法,如果感兴趣可参阅
    MSDN 有关内容。 
      有了以上理论基础,我们下面就开始制作一个挡截
    MessageBoxA 和 recv
    函数的实例,在开发游戏外挂程序
    时,可以此实例为框架,加入相应的替代函数和处理代码即可。此实例的开发过程如下:
       (1) 打开前面创建的 ActiveKey
    项目。 
       (2) 在 ActiveKey.h
    文件中加入 HOOKAPI
    结构,此结构用来存储被挡截 API 函数名称、原
    API 函数地址和替代函数地址。 
        typedef struct
    tag_HOOKAPI 
        { 
        LPCSTR szFunc;// 被
    HOOK 的 API 函数名称。 
        PROC pNewProc;//
    替代函数地址。 
        PROC pOldProc;// 原
    API 函数地址。 
        }HOOKAPI,
    *LPHOOKAPI; 
       (3) 打开 ActiveKey.cpp
    文件,首先加入一个函数,用于定位输入库在输入数据段中的
    IAT 地址。代码如下: 
        extern "C"
    __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR

        LocationIAT(HMODULE
    hModule, LPCSTR
    szImportMod) 
        // 其中, hModule
    为进程模块句柄; szImportMod
    为输入库名称。 
        { 
        // 检查是否为 DOS 程序,如是返回
    NULL ,因 DOS 程序没有 IAT 。

        PIMAGE_DOS_HEADER
    pDOSHeader =
    (PIMAGE_DOS_HEADER)
    hModule; 
       
    if(pDOSHeader->e_magic
    != IMAGE_DOS_SIGNATURE)
    return NULL; 
         // 检查是否为 NT 标志,否则返回
    NULL 。 
         PIMAGE_NT_HEADERS
    pNTHeader =
    (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader+
    (DWORD)(pDOSHeader->e_lfanew));

        
    if(pNTHeader->Signature
    != IMAGE_NT_SIGNATURE)
    return NULL; 
         // 没有 IAT 表则返回 NULL
    。 
        
    if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
    == 0) return NULL; 
         // 定位第一个 IAT 位置。

        
    PIMAGE_IMPORT_DESCRIPTOR
    pImportDesc =
    (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader
    +
    (DWORD)(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));

         // 根据输入库名称循环检查所有的
    IAT ,如匹配则返回该 IAT
    地址,否则检测下一个 IAT 。 
         while
    (pImportDesc->Name) 
         { 
          // 获取该 IAT
    描述的输入库名称。 
        PSTR szCurrMod =
    (PSTR)((DWORD)pDOSHeader
    +
    (DWORD)(pImportDesc->Name));

        if
    (stricmp(szCurrMod,
    szImportMod) == 0)
    break; 
        pImportDesc++; 
         } 
        
    if(pImportDesc->Name ==
    NULL) return NULL; 
        return pImportDesc;

        } 
      再加入一个函数,用来定位被挡截 API
    函数的 IAT
    项并修改其内容为替代函数地址。代码如下: 
        extern "C"
    __declspec(dllexport)

        HookAPIByName(
    HMODULE hModule, LPCSTR
    szImportMod, LPHOOKAPI
    pHookApi) 
        // 其中, hModule
    为进程模块句柄; szImportMod
    为输入库名称; pHookAPI 为
    HOOKAPI 结构指针。 
        { 
         // 定位 szImportMod
    输入库在输入数据段中的 IAT 地址。 
        
    PIMAGE_IMPORT_DESCRIPTOR
    pImportDesc =
    LocationIAT(hModule,
    szImportMod); 
       if (pImportDesc ==
    NULL) return FALSE; 
         // 第一个 Thunk 地址。

         PIMAGE_THUNK_DATA
    pOrigThunk =
    (PIMAGE_THUNK_DATA)((DWORD)hModule
    +
    (DWORD)(pImportDesc->OriginalFirstThunk));

       // 第一个 IAT 项的 Thunk
    地址。 
         PIMAGE_THUNK_DATA
    pRealThunk =
    (PIMAGE_THUNK_DATA)((DWORD)hModule
    +
    (DWORD)(pImportDesc->FirstThunk));

         // 循环查找被截 API 函数的
    IAT 项,并使用替代函数地址修改其值。 
       
    while(pOrigThunk->u1.Function)


      // 检测此 Thunk 是否为 IAT
    项。 
    if((pOrigThunk->u1.Ordinal
    & IMAGE_ORDINAL_FLAG) !=
    IMAGE_ORDINAL_FLAG) 
    {
      // 获取此 IAT 项所描述的函数名称。

      PIMAGE_IMPORT_BY_NAME
    pByName
    =(PIMAGE_IMPORT_BY_NAME)((DWORD)hModule+(DWORD)(pOrigThunk->u1.AddressOfData));

      if(pByName->Name[0] ==
    ‘//0‘) return FALSE; 
       // 检测是否为挡截函数。 
    if(strcmpi(pHookApi->szFunc,
    (char*)pByName->Name) ==
    0) 
      { 
           
    MEMORY_BASIC_INFORMATION
    mbi_thunk;
            // 查询修改页的信息。 
           
    VirtualQuery(pRealThunk,
    &mbi_thunk,
    sizeof(MEMORY_BASIC_INFORMATION));

    // 改变修改页保护属性为
    PAGE_READWRITE 。 
           
    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,
    PAGE_READWRITE,
    &mbi_thunk.Protect); 
    // 保存原来的 API 函数地址。 
       
      if(pHookApi->pOldProc
    == NULL) 
    pHookApi->pOldProc =
    (PROC)pRealThunk->u1.Function;

     
    //修改API函数IAT项内容为替代函数地址。
    pRealThunk->u1.Function
    =
    (PDWORD)pHookApi->pNewProc;

    //恢复修改页保护属性。
    DWORD dwOldProtect; 
           VirtualProtect(mbi_thunk.BaseAddress,
    mbi_thunk.RegionSize,
    mbi_thunk.Protect,
    &dwOldProtect); 
          } 

      pOrigThunk++; 
      pRealThunk++; 

      SetLastError(ERROR_SUCCESS);
    //设置错误为ERROR_SUCCESS,表示成功。
      return TRUE; 
       } 
       (4) 定义替代函数,此实例中只给
    MessageBoxA 和 recv 两个
    API 进行挡截。代码如下: 
        static int WINAPI
    MessageBoxA1 (HWND hWnd
    , LPCTSTR lpText,
    LPCTSTR lpCaption, UINT
    uType)
        {
         // 过滤掉原 MessageBoxA
    的正文和标题内容,只显示如下内容。 
    return MessageBox(hWnd,
    "Hook API OK!", "Hook
    API", uType); 
        } 
        static int WINAPI
    recv1(SOCKET s, char FAR
    *buf, int len, int flags
    )
        {
        //
    此处可以挡截游戏服务器发送来的网络数据包,可以加入分析和处理数据代码。

        return
    recv(s,buf,len,flags);
        } 
       (5) 在 KeyboardProc
    函数中加入激活挡截 API 代码,在 if(
    wParam == 0X79 )
    语句中后面加入如下 else if 语句:

        ......
        // 当激活 F11 键时,启动挡截
    API 函数功能。 
        else if( wParam ==
    0x7A )
        { 
         HOOKAPI api[2];
    api[0].szFunc
    ="MessageBoxA";//
    设置被挡截函数的名称。 
    api[0].pNewProc =
    (PROC)MessageBoxA1;//
    设置替代函数的地址。 
    api[1].szFunc ="recv";//
    设置被挡截函数的名称。 
    api[1].pNewProc =
    (PROC)recv1; //
    设置替代函数的地址。 
    // 设置挡截 User32.dll 库中的
    MessageBoxA 函数。 
    HookAPIByName(GetModuleHandle(NULL),"User32.dll",&api[0]);
    // 设置挡截 Wsock32.dll 库中的
    recv 函数。 
    HookAPIByName(GetModuleHandle(NULL),"Wsock32.dll",&api[1]);
        }
        ...... 
       (6) 在 ActiveKey.cpp
    中加入头文件声明 "#include
    "wsock32.h" 。
    从“工程”菜单中选择“设置”,弹出Project
    Setting对话框,选择Link标签,在“对象/库模块”中输入Ws2_32..lib。
       (7) 重新编译 ActiveKey
    项目,产生 ActiveKey.dll
    文件,将其拷贝到 Simulate.exe
    目录下。运行 Simulate.exe
    并启动全局钩子。激活任意应用程序,按 F11
    键后,运行此程序中可能调用
    MessageBoxA
    函数的操作,看看信息框是不是有所变化。同样,如此程序正在接收网络数据包,就可以实现封包功能了。

     

     

    展开全文
  • 科莱数据包生成器

    2012-09-05 11:19:22
    科莱数据包生成器,可以用于构造报文,修改报文
  • 基于winpcap发送数据包

    热门讨论 2011-04-09 21:24:32
    03、可以随机修改数据包的:源、目的MAC地址,IP地址,端口、数据内容等属性信息。 04、使用多线程发包,在XP下最多可以同时开2000个线程发包,发包速度快,流量大。在千兆网卡上可以超过15M/s的速度。 05、自动...
  • 该工具用于将XML文件转换为...为了方便大家的使用,已将该文件转换为exe。 下载连接为:https://pan.baidu.com/s/1c2tHWaO   Ps : 新版的PX4固件使用的是mavlink 2.0版本,使用时需要注意。官网目前提供的自定义ma
  • VC++编程实现修改EXE文件图标

    千次阅读 2017-08-22 19:05:36
    VC++编程实现修改EXE文件图标 刚才发现论坛上面有网友问:如何通过编程实现修改EXE文件的图标,类似于 熊猫烧香 的效果!自己也对这个比较感兴趣网上找了找,找到了两种方法,可以满足大家都要求了,这里面收集...
  • http数据包还原

    千次阅读 2010-02-26 09:53:00
    摘要:在因特网日益发展壮大的今天,万维网在其上的通信量已经超过90%...本文介绍应用层HTTP数据包的截获与还原技术的实现,并简要介绍其中所涉及的数据包截获、数据包分析、应用数据重组以及数据包解码等关键技术。该系
  • 一款免费且功能强大的数据包抓取软件。它通过代理的方式获取程序http通讯的数据,可以用其检测网页和服务器的交互情况,能够记录所有客户端和服务器间的http请求,支持监视、设置断点、甚至修改输入输出数据等功能。...
  • 这就需要一种便捷化的工具,能根据我提供的特征去海量数据包中匹配,所以,我用python写了这么一款工具,并打包成exe即可出门干活了。代码不大规范,见谅。 软件特点 你只需要提供存放数据包的文件夹和要检查的...
  • 数据包传输过程

    千次阅读 2019-06-09 23:14:59
    在这一过程中,在网络上发送和接收的数据已经被分成一个或多个数据包(packet),每个数据包包括:要传送的数据;控制信息,即告诉网络怎样处理数据包。TCP/IP决定了每个数据包的格式。如果事先不告诉你,你可能不会...
  • 写这个,主要是工作中正好需要大量的ipv6数据包,但是ipv6数据包不太好找,干脆就直接写个简单的工具,把ipv4转成对应的ipv6,可用于测试。  cpp代码: // Ipv4ToIpv6_pCap.cpp : 定义控制台应用程序的入口...
  • 您可以随意伪造新数据包修改现有数据包并丢弃不需要的数据包。 警告:使用该工具时,请遵守暴雪的 。 该项目仅用于教育目的,强烈建议您不要使用游戏的任何方面。 如何建造 从资源库下载源代码 运行CMake创建您...
  • wireshark抓取本地回环数据包

    万次阅读 2015-10-22 10:05:14
    wireshark抓取本地回环数据包一 The NPF driver isn’t running这个错误是因为没有开启NPF服务造成的。NPF即网络数据包过滤器(Netgroup Packet Filter,NPF)是Winpcap的核心部分,它是Winpcap完成困难工作的组件。...
  • 网络数据包分析 网卡Offload

    万次阅读 2015-11-30 10:02:04
    对于网络安全来说,网络传输数据包的捕获和分析是个基础工作,绿盟科技研究员在日常工作中,经常会捕获到一些大小远大于MTU值的数据包,经过分析这些大包的特性,发现和网卡的offload特性有关,本文对网卡Offload...
  • 一、获取浏览器的数据包 1、设置fiddler代理端口 2、设置浏览器的代理服务器 3、重新启动fiddler,再次打开火狐浏览器,输入待测网址,获取抓包请求数据 4、窗口中状态查看 5、F12来回切换可开始/暂定...
  • 把.cap .pcap文件中的ipv4数据包转换成对应的ipv6数据包,其他的数据包不变, 可以用于批量生产ipv6数据包(用于测试),资源包括源代码和已经编译好的exe,还有一个批量处理的.bat文件
  • 下载安装运行后,查出运行机器的IP,手机连接同一网域内的WIFI,手机WIFI连接设置里的高级里,代理设置填写上Fiddler运行机器的IP,这样从手机访问的链接都会走Fiddler,可以直接在Fiddle里查看数据包 1、PC端...
  • 2019独角兽企业重金招聘Python工程师标准>>>...对于ETH、ARP、IP、ICMP、TCP和UDP类型数据包,渗透测试人员还可以修改其对应的包头。 转载于:https://my.oschina.net/u/1585857/blog/1594407
  • 但在APP测试中,我们需要抓取手机APP上的数据包,应该怎么操作呢? Andriod配置方法 1)确保手机和Fiddler所在主机在同一个局域网中 2)获取Fiddler所在主机的ip地址,通过cmd命令进入命令编辑器,输入ipconfig -all...
  • Windows下底层数据包发送实战

    千次阅读 2016-11-17 11:34:17
     所谓“底层数据包”指的是在“运行”于数据链路层的数据包,简单的说就是“以太网帧”,而我们常用的Socket只能发送“运行”在传输层的TCP、UDP等包,这些传输层数据包已经能满足绝大部分需求,但是有些时候还是...
  • Windows下底层RAW数据包发送实战

    千次阅读 2019-01-20 12:02:05
     所谓“底层数据包”指的是在“运行”于数据链路层的数据包,简单的说就是“以太网帧”,而我们常用的Socket只能发送“运行”在传输层的TCP、UDP等包,这些传输层数据包已经能满足绝大部分需求,但是有些时候还是...
  • 下载安装运行后,查出运行机器的IP,手机连接同一网域内的WIFI,手机WIFI连接设置里的高级里,代理设置填写上Fiddler运行机器的IP,这样从手机访问的链接都会走Fiddler,可以直接在Fiddle里查看数据包 1、PC端...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,408
精华内容 7,363
关键字:

修改exe数据包