【原创】我的毕业设计论文——利用HOOK技术实现应用层网络抓包

 成都东软信息技术职业学院04级毕业论文

 利用HOOK技术实现应用层网络抓包

 班级: 可视化程序设计2班 
导师: 李        丹 
学号: 04311110210 


姓名: 刘   海   平 

 
摘  要


    数据包抓取(拦截)技术,主要应用在信息安全相关领域,特别是防火墙技术。随着网络游戏产业日益兴旺,后来出现很多针对不同游戏的外挂,这些外挂也使用到抓包技术,但是与其他抓包技术很大不同的是,外挂技术中的抓包技术必须达到能顺利截取、完成对数据包的修改、再次发送出去等一系列特殊要求,基于以上要求,所以必须在应用层完成数据包的抓取、修改。
    本毕业设计论文介绍了在WINDOWS环境下,利用HOOK、DLL等技术,实现网络函数的拦截,从而实现在应用层完成数据包的抓取。

关键字:HOOK 、DLL、外挂、数据包抓取

 SUMMARY


    Data packet blocking technique is primarily used in information security field, especially firewall technique. As network game industry grows thriftier, lots of plus for different game appeared. These plus has used data packet blocking technique, too.But the difference to the other packet blocking technique is that in plus technique, packet blocking technique must accomplish requirements such as, blocking data favoringly, modify the data packet and then send them out again, etc. Based on these requirements, we must achieve data blocking, modification at the application layer.
 My dissertation introduces a method to implement the network packet blocking using techniques as HOOK, DLL, etc, under the windows environment. Then accordingly accomplish the data packet scratching at the application layer.

Keyword: HOOK 、DLL 、plus 、Block data packet

                                目      录

 

1. 引言  4
2. 需求分析 5
2.1. 背景 5
2.2. 基本需求  5
2.3. 功能需求  5
2.4. 设计约束 5
3. 系统设计 6
3.1. 技术原理   6
3.1.1. DLL原理简介  6
3.1.2. HOOK原理简介 7
3.1.3. API函数拦截简介 7
3.2. 抓包程序原理 7
3.3. 抓包程序功能模块设计 8
3.4. 结构设计 8
4. 程序实施   9
4.1. HOOK核心代码 9
4.2. 函数拦截核心代码 10
4.3. 内存修改核心代码  11
4.4. DLL函数导出 12
4.5. EXE前台代码功能说明 12
5. 结论 13
6. 参考文献  13
7. 致谢 14

 
引言


    随着网游的发展,出现了越来越多的游戏外挂。从市场的角度来说,游戏外挂打破了游戏运营商的“游戏规则”,所以越来越多的游戏运营商开始设置“反外挂”的部门;从技术的角度上来说,游戏外挂是属于WINDOWS核心编程技术的范畴,对于学习WINDOWS核心编程很有现实性的价值。所以本人选择此课题作为毕业设计,想通过它学习到更多的WINDOWS核心技术。
    本论文主要分为八个章节,从抓包软件的需求、设计、实施三个组成部分。以下为各章内容简介:
    第一章 引言,对论文的框架进行一个大概的描述。
    第二章 需求分析,概述抓包程序的需求、背景知识以及对该技术的发展方向的一个简单概述。
    第三章 系统设计,介绍的本课题的设计方案、设计原理以及各个模块的划分。
    第四章 程序实施,根据系统设计,编写程序的代码,且会讲解本课题部分主要的核心代码。
    第五章 结论,通过本次毕业设计的完成,本人从中的收获,以及对毕业设计的一个总结。
    第六章 参考文献,在本人完成该毕业设计的过程中,所参考过的资料。
    第七章 致谢。

  需求分析
背景
    对于一个商业软件来说,防止不法侵犯是个很重要的问题。这种问题在网络游戏中体现的比较突出。随着网络游戏被越来越多的人所熟知,网游外挂也渐渐走入了人们的视线。网游外挂的泛滥,给游戏运营商带来了不小的损失。后来游戏运营商为了防止游戏玩家使用外挂,还提出过:一旦系统发现某个玩家使用外挂,那么就对其帐号进行查封。因为游戏运行商的这个做法,甚至还有玩家将运营商告上法庭。那么这里又涉及到虚拟财产的问题。由于中国对这方面的立法还比较欠缺,所以对于运营商也好、对于游戏玩家也好,可能这不是最优的解决方案。
    因此,游戏运营商家需要从外挂的开发开始着手,研究其技术特点,从自身完成反外挂的功能,这才是根本的问题解决之道。
    而在游戏外挂中,一般为有数据包拦截、解密、修改、加密封包等步骤。一般反外挂的工作都在数据包拦截和加密这两大模块完成。由于加密技术比较难,研究的成本相对较高,加之任何密文都有被破解的一天。所以从防止数据包拦截入手,可以以最少的投入获得理想的效果。
    所谓知自知彼,百战不殆。本论文就是研究在游戏外挂技术中常用的数据包截取方式,为反外挂技术的研究做一个基础的铺垫。
基本需求
完成网络数据包的抓取。
留出可修改数据包的接口,以便后期完成数据包修改。
功能需求
完成具有数据包的抓取的DLL模块
在前台完成数据包的打印
设计约束
   本课题属于WINDOWS核心编程的范畴,而且涉及道内存的属性修改等问题。所有错误的设计和代码的编写错误可能导致系统的不稳定、甚至崩溃。所有在完成课题的时必须从分考虑系统的稳定性。此外还应考虑是否能方便数据包的修改,是否能承受大量的数据包的抓取等问题。
系统设计
技术原理 
    本课题主要有三个主要的技术要点,以下是各个技术要点的原理简介。
DLL原理简介
    DLL 是一个包含可由多个程序同时使用的代码和数据的库。使用 DLL 有助于促进代码的模块化、代码重用、内存的有效使用和减少所占用的磁盘空间。因此,操作系统和程序能够更快地加载和运行,并且在计算机中占用较少的磁盘空间。
    一旦DLL的文件映像被映射到进程的地址空间种,DLL函数就可以供进程种运行的所有线程使用。(如图4.1)
                           DLL原理(图4.1)
 第一个地址的              DLL的虚拟内存             第二个地址的
  进程空间                                               进程空间
 

 
DLL 的优点:
下表说明了当程序使用 DLL 时提供的一些优点:
• 使用较少的资源
    当多个程序使用同一个函数库时,DLL 可以减少在磁盘和物理内存中加载的代码的重复量。这不仅可以大大影响在前台运行的程序,而且可以大大影响其他在 Windows 操作系统上运行的程序。
• 推广模块式体系结构
    DLL 有助于促进模块式程序的开发。这可以帮助您开发要求提供多个语言版本的大型程序或要求具有模块式体系结构的程序。模块式程序的一个示例是具有多个可以在运行时动态加载的模块的计帐程序。
• 简化部署和安装
    当 DLL 中的函数需要更新或修复时,部署和安装 DLL 不要求重新建立程序与该 DLL 的链接。此外,如果多个程序使用同一个 DLL,那么多个程序都将从该更新或修复中获益。当您使用定期更新或修复的第三方 DLL 时,此问题可能会更频繁地出现。


HOOK原理简介
    钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。HOOK机制如图4.2
        HOOK 机制  (图4.2)

数拦截简介
    Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。本课题采用第二种方法,利用WINDOWS为我们提供的API,较为简单的实现API函数拦截的功能。

 

抓包程序原理
    本课题的程序主要就是将HOOK、DLL和API函数拦截三个技术结合,实现数据包抓取,其基本原理如下:
    首先是利用HOOK技术完成消息的截获,提取出我们感兴趣的消息;再利用API拦截技术,拦截相应的网络程序的SOCKET网络函数;最后利用DLL技术将HOOK和API拦截的代码封装。利用EXE程序将DLL映射到进程中。等到由HOOK挂载的程序的网络函数被调用时,引起API函数拦截,从而拦截相应的网络函数。最后,从网络函数中提取我们想要得到的数据包。
抓包程序功能模块设计
    该抓包程序分为:DLL模块和EXE模块两大模块。
    DLL部分主要完成HOOK钩子的挂载、API函数的拦截和处理拦截到的网络函数。
 EXE程序部分主要完成把DLL映射到进程空间,接受数据包内容的输入和管理钩子的安装、卸载。
 
           DLL 模块部分                  DLL 加载模块

 结构设计
    由EXE将DLL加载到当前进程空间以后,DLL模块会注入到目标进程当中。当监测到有网络套节字的发送、接受时,调用DLL模块中的API拦截函数。经过DLL中的API处理,再把网络函数发出。

 

 

 

 

 

 程序实施 
HOOK核心代码
    HOOK部分主要完成对特定目标程序的消息钩子的挂载,从而实现与目标进程共享DLL的代码和数据。该抓包程序完成以上功能,主要通过FindWindowEx()函数查找CALSS NAME(可以用SPY++确定目标程序的CLASS NAME)来确定目标程序的句柄。从而确定目标线程的标识,再使用SetWindowsHookEx()挂载消息钩子。
    这样,一旦目标程序(线程)启动,那么该程序的所有消息都必须先经过我们的DLL模块,待我们处理完自己感兴趣的消息之后,再将消息发出。
    具体代码如下,以下代码中,还加入了一些异常检测部分:

    g_hArmIns = FindWindowEx(NULL,NULL,/*"目标程序CLASS NAME"*/,NULL);
    //查找目标线程的句柄
 dwThreadID = GetWindowThreadProcessId(g_hArmIns,NULL);
    //保存线程的标识
 if (dwThreadID==NULL)  //异常检测
 {
  MessageBox(hwnd,"要被注入的程序没有被打开","错误",MB_OK);
 }
 else if (g_hInsMouse != NULL && g_hInsKeyboard!=NULL)
 {
  MessageBox(hwnd,"你已经注入了,无需多次注入","错误",MB_OK);
 }
    else
 {
        g_hInsMsg=SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,
                                 GetModuleHandle("dllname"),dwThreadID);
     //安装消息钩子,其具体参数意义,请参看MSDN。
    }


函数拦截核心代码
    函数拦截部分主要完成网络函数的替换。首先动态加载wsock32.dll,所有的网络接受、发送函数都在此DLL中;然后利用GetProcAddress()函数,从DLL中获得我我们想要截获的网络函数的首地址,并保存;其次使用汇编语言再保存一个我们要拦截的函数的副本,以便后期恢复;最后再次使用汇编,使我们的函数的地址覆盖我们要拦截的网络函数。
    这样,当系统调用网络函数发送、接受数据的时候,实际上就是调用的我们自己编写的函数,从而实现函数拦截的功能。
    具体代码如下:
 hModule = LoadLibrary("wsock32.dll");
 //加载wsock32.dll模块
 pfSend = GetProcAddress(hModule,"send");
 //从wsock32.dll模块中获得SEND函数入口地址
 if(pfSend==NULL)
  return false;
 // 保存 pfSend 的一个副本 -- oldSend
    _asm
 {
  lea edi,oldSend
  mov esi,pfSend
  cld
  movsd
  movsb
 }
  newSend[0] = 0xe9;  //jmp MySend的相对指令
 //利用我们的MySend函数替换pfSend函数入口
 _asm
 {
  lea eax,MySend
  mov ebx,pfSend
  sub eax,ebx
  sub eax,5
  mov dword ptr [newSend+1],eax
 }

   以上两段代码只是完成WSOCK32.DLL中的SEND函数拦截。我们知道网络函数都有SEND和RECV两种状态,而且常用的网络连接方式又有TCP和UDP两种。所以我们还应该完成RECV、SENDTO(UDP发送)、RECVTO(UDP接受)的函数拦截,基本方式通SEND。


内存修改核心代码
    内存修改是本程序比较关键的一段待代码。因为WINDOWS的内存是具有保护机制的。每个进程有自己私有的4GB的虚拟地址空间,EXE和DLL程序被映射到底部的2GB的地址上。WINDOWS为了安全,严格的标记此2GB内存空间,所有EXE和DLL的代码都是标记为只读的,因此一个进程想要访问另一个进程的栈、全局内存或者堆内存是不可能的。因此我们必须通过WINDOWS给我们提供的API函数修改内存的属性。
    以下就是将内存修改为可写状态的代码:
void _stdcall sendHookOn() //send
{
    HANDLE hProc;
    dwIdOld=dwIdNew;
    hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
    //得到所属进程的句柄
    VirtualProtectEx(hProc,pfSend,5,PAGE_READWRITE,&dwIdOld);
    //修改所属进程中send的前5个字节的属性为可写
    WriteProcessMemory(hProc,pfSend,newSend,5,0);
    //将所属进程中send的前5个字节改为JMP 到MySend
    VirtualProtectEx(hProc,pfSend,5,dwIdOld,&dwIdOld);
    //修改所属进程中send的前5个字节的属性为原来的属性
    bHook=true;
}

    当我不们不再需要修改内存内容的时候,我们应该将内存还原为以前的只读状态,这样才不会破坏WINDOWS的内存结构,以下代码就是完成所述功能。

void _stdcall sendHookOff()
{
    HANDLE hProc;
    dwIdOld=dwIdNew;
    hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
    VirtualProtectEx(hProc,pfSend,5,PAGE_READWRITE,&dwIdOld);
    WriteProcessMemory(hProc,pfSend,oldSend,5,0);
    VirtualProtectEx(hProc,pfSend,5,dwIdOld,&dwIdOld);
    bHook=false;
}

    以上两段代码只是完成TCP中的SEND函数的修改。我们知道网络函数都有SEND和RECV两种状态,而且常用的网络连接方式又有TCP和UDP两种。所以我们在还应该完成RECV、SENDTO(UDP发送)、RECVTO(UDP接受)。基本方式同SEND。

 

DLL函数导出
    当我们完成DLL功能模块时,我们要讲DLL中的功能函数导出成规则的函数名。因为C++编译器在编译的时候会对函数名进行改编,这样我们想调用自己DLL中的函数就会遇到困难,所以我们要指定要导出的函数的名称,这样才能方便我们的调用。
    有两种方法可以解决以上问题:
    方法一:
   在要导出的全局函数名之前加上这样一句:  extern "C"  _declspec(dllexport) 它表明,将一个DLL中的函数导出,并且遵守标准C的调用约定。
    方法二:
    使用模块定义文件(.def),并将其加入到工程中,添加如下代码:
    LIBRARY  (动态链接库名)
    EXPORTS  (以下列出要导出的函数名)

 

EXE前台代码功能说明
    EXE前台主要完成钩子挂载的安装、卸载和接受DLL的模块的消息,并在其窗口中打印出数据包。
    EXE部分使用MFC的对话框,主要完成的工作有:
    使用_declspec(dllexport)接受导出的函数。因为在EXE前台要调用DLL中的函数,就必须告诉EXE,这个函数是从DLL中获得,不然系统会报告,未定义函数的错误。
    编写消息相应代码,完成钩子的安装和卸载,当EXE得到DLL中的函数时,需要在前台启动钩子。具体步骤为:添加一个按钮、添加其点击事件响应函数、调用DLL中的函数。
    处理用户自定义消息,因为我们在DLL中把数据包的地址和大小以消息的形式发送到EXE端处理,所以我们EXE端必须响应DLL端发出的消息,具体步骤为:1、在头文件中定义消息类型。2、在消息映射宏中添加消息映射。3、在CPP文件中根据消息映射,添加消息处理函数。
    打印数据包到窗口中,根据消息中的数据包地址和长度,打印出数据包的内容。
   

 

 


结论
    通过这次毕业设计,本人不仅熟悉了WINDOWS的核心编程、深入的学习HOOK等技术上的收获,而且明显的感觉自己的自学能力得到的很大的提升。
 在毕业设计的这段时间和过程中,可以深切地体会到,通过实际地进行软件的开发和程序的设计是对所学知识的再认识和更进一步的理解和运用。
    总之,觉得此次毕业设计受益颇深,在学习相关知识的基础上能够充分的运用于实际,并在实际操作中进一步提高了自己的学习能力。因此,本次毕业设计是对大学两年所学知识的检验,同时也是对以后的学习和工作的帮助和启迪。

 

 

 

 

参考文献
图书类:

作者:Jeffrey Richter 书名:《WINDOWS 核心编程》
    出版单位:MICROSOFT PRESS

作者:George Shepherd 、David J.Kruglinski 书名:《VC.NET 技术内幕》  
    出版单位:MICROSOFT PRESS

作者:Charles Petzold 书名:《WINDOWS 程序设计》
    出版单位:MICROSOFT PRESS

作者: Prasad Dabak 、Milind Borate、Sandeep Phadke
书名:《Undocumented Windows NT 中文版》  出版单位:M&T

网上资料类:

作者:姜山   来自:微软中国社区   文章名:HOOK专题   网址:
http://www.microsoft.com/china/community/program/originalarticles/techdoc/hook.mspx

作者:Fang  来自:XFOCUS Team文档中心 文章名:应用层截包方案与实现
 网址:http://www.xfocus.net/articles/200411/751.html

作者:tomh   来自:XFOCUS Team文档中心   文章名:Win2K下的Api函数的拦截 
网址: http://www.xfocus.net/articles/200201/336.html

致谢
    本论文的完成,首先要感谢我的父母对我多年养育以及对我学业的支持。要知道在我初中的时候父母为我学习计算机付出了不小的代价。
    其次,感谢我的指导老师李丹,感谢你花费了很多很多的时间给予我指导,我才有可能完成此论文。
    然后,感谢我的各位朋友,因为你们在我成长的路上,也给了我很多帮助。
    最后,感谢上帝,呵呵,你让我生活在一个如此美好的世界!! ^_^ 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值