由捕获到的数据包重组html网页技术
原创:杜香和
根据解析协议得到端口号,由端口号判断对应进程,再根据进程对数据的封装格式,可以由捕获的数据包恢复数据(数据重组技术)。下面介绍如何根据捕获到的http协议TCP数据包恢复html网页技术。
任何一应用程序要利用网络进行通信,必须有自己的通信格式,即,发送端发送的数据,接收端要能够正确解释;接收端返回数据,发送端也要能解释返回的数据并作相应处理。浏览器也不例外。
HTTP有两类报文,从客户到服务器的请求报文和从服务器到客户的响应报文。
典型的HTTP请求报文如下:
GET /dirABC/docu1.html http/1.1 // 请求行
Connection: close // 此行和以下都是首部行
User-agent: Mozilla/4.0
Accept: text/html, image/gif,image/jpeg
Accept-language: en
// 此处有一空行
在请求行中的第一个字段是"方法(method)"。这是面向对象技术中使用的专门名词,也就是对所请求的对象进行的操作,因此这些方法实际上就是一些命令。此处填入的方法是GET,表示请求读取一个万维网页面,这是最常用的一个方法。其它常用的方法还有HEAD(请求读取的不是整个页面而只是其首部)和POST(请求接受所附加的实体,如将一个记录附加到一个数据库中)。请求行的第二个字段是所要链接到的对象的URL。由于在建立TCP连接时已经有了主机名,因此这里只写上主机中的文件名(包括路径)。第三个字段说明是HTTP的1.1版本。
以下就是首部行。" Connection: close "表示浏览器希望服务器在传送完所请示的对象后即关闭TCP连接(还有一种可选择的情况是暂不关闭TCP连接,继续读取其它对象)。下一行是余明浏览器的类型。" Mozilla/4.0"是Netscape浏览器4.0版本。再下面两行是浏览器告诉服务器它准备接收什么和使用的语言是英文(en)。使用GET时,首部行后面没有最后的实体主体。
当用户在网上填写表单(form)时,要用到POST方法。这时,用户键入的信息要填写到最后的主体中,和前面的请求行、首部行一起发送给HTTP服务器。
典型的HTTP响应报文如下:
HTTP/1.1 200 OK // 状态行
Connection: close // 此行开始的6行都是首部行
Date: Thu,06 Aug,2003 12:00:15 GMT
Server: Apache/1.30(Unix)
Last-Modified: Mon,22 Jun 2003 09:23:24 GMT
Content-Length: 8765 // 文件长度字节数
Content-Type: text/html
// 此处一个空行
…… // 数据开始
状态行中的200是状态码,OK是短语,表示一切正常。
状态码共有41种,常用的有下述几种:
301(Moved Premanently,网站已转移,新的URL指明在响应报文首部Location:
的后面);
400(Bad Request,服务器无法理解请求报文);
401(Not Found,服务器上没有所请求的对象);
505(HTTP Version Not Supported,服务器不支持请求的HTTP的协议版本)。
超文本标记语言HTML(HyperText Markup Language)是一种制作万维网页面的标准语言。HTML使用HTML标签,如:网页文档应该写在<html>和</html>标签之间,<head></head>定义文档的首部,<br>为强制换行。HTTP(当Content-Type为text/html时)响应报文内容的数据部分就是HTML文档。如图8:
图8
在浏览网页时,浏览器首先向服务器发出HTTP请求报文,服务器作出响应并返回HTTP响应报文。一般一个页面大小都在数10K以上,而IP包最大为1500B,再加上IP首部,TCP首部,真正用于传输页面内容的部分最大只有1460B。很明显,要用很多报文段才能传输完一个页面。数据传送时被TCP分割成认为最适合发送的数据块,也就是说数据在发送方被分成一块一块的发送,接受端收到这些数据后再将它们组合在一起。TCP在三次握手建立连接时确定了开始传输第一块数据的序列号和确认号,又因为TCP连接完全是双向的,即双方的数据流可同时传输,在传输过程中双方数据是独立的,因此在传输某一页面时,确认号不会改变,序列号为上一TCP数据包的序列号加和数据长度。
综上所述,要恢复某一页面,可根据确认号判定哪些TCP包是用来传输该页面的。先选中任一传输页面的TCP包,得到服务端传输该页面的ACK,查找最近接收的包中有哪些TCP包的ACK与此ACK相同,如果相同,表示这些TCP包都是用来传输同一页面的。按包的SEQ(序号)顺序,解析这些包,把包中传输数据部分保存下来,这样就得恢复了页面内容。但在此过程中,要注意:是否捕获到了所有的数据包,数据包在传输过程中本身有没有错误等。
具体实现:
1. 如何得到要恢复文件的文件名和文件类型。
当你访问一网页时,很少出现全文本格式的HTML,大部分网站页面包含很多的图像文件:jpeg、gif等,flash动画:swf,还有的网站有背景音乐或其它类型文件,保存时不可能以一种文件格式来保存,命名时也是不能以同样一个名称来命名,这就需要我们在保存文件之前先得到文件名和文件类型。
在服务端向客户端发送数据之前,客户端先要向服务端请求传送什么文件,这在HTTP请求报文中的请求行中指明,如:GET /dirABC/docu1.html http/1.1,这里的docu1.html就是请求要传送的文件,docu1是文件名,而.html就是文件类型扩展名,所以要找到传送文件的文件名和文件类型,只要找到请求传送该文件的客户端请求报文。客户端请求报文的ACK是服务端传送文件时的第一个包的SEQ。当要恢复(重组)一个文件时,根据选择的数据包很容易得到传送该文件时所用的ACK,搜索最近接收到的所有包,并找到所有ACK相同的包,这些包中,第一个(也是发送该文件的第一个包)的SEQ就是请求报文所有包的ACK,由此可以得到请求报文,分析提取文件名和文件类型。
2. 如何将得到的包重组。
把所有属于传输要恢复的文件的包都找到后,重组该文件是一件简单的事情。在第一个包中除了含有文件内容外,还有更重要的是状态行和首部行信息(见上文HTTP响应报文)。由首部行的信息可以得到继续恢复后面的包是否有意义,比如:在首部行中有一句401 Not Found,意味着后面即使有相同ACK的包,也是一些没有意思的包;从首部行也可以分析出文件的类型,可以提示用户用什么程序打开恢复后的文件。
将第一个包的状态行和首部行信息去除后,剩下的就是要恢复文件的内容了(注:有些传输文件的首部行很长而包又很短,首部行信息有部分出现在第二个包中),将文件内容保存,再把下一个包的内容加在已保存内容的尾部(对于HTML或其它文本文件来说,多一个空格或少一个空格都无所谓,但对于图像动画文件,常常因为多一个空格或少一个空格显示出乱码),直到所有包都保存完,这时保存文件,便算是恢复结束。
3. 重组整个html页面。
当打开一个html页面时,页面中的图片、动画都以HTML标签:src="http://www.swau.edu.cn/image/picture.gif" 引用其它地址的图片、动画,有些页面还使用了框架,有src="login.html"等标签。浏览器向服务器发出请求报文其实只是请求当前页面,页面内的其它每一个以src 进入的内容,必须单独发送请求报文,这也是为什么我们在访问某些网页时发现在图片或其它链接打不开或失效但页面其它内容还正常显示的原因(因为:如果页面的所有内容都是由一个请求报文发出,那任一内容出错就表示整个服务器应答报文错误)。
选择要重组的html页面,根据页面内的HTML标签找出所有src 内容的文件名和文件类型扩展名,枚举当前收到的所有请求报文是否为src内容的请求报文,如果是,则把该请求报文的服务器应答报文内容重组,重组后可以将所有src放在同一目录下,再把源html页面的所有src标签指向本地重组的内容文件,整个html页面重组完成。