Chapter4——数据包中的功能控制
通过一次次各种截获数据包、发数据包、看是否弹出窗口的时候后,得出了如下结论:每次截获的数据包只对本次拨号在线的状态下起作用。那,问题也就随之而来了,我们得弄清楚数据包中的判定条件在哪。也就是,哪些是校验码?
那?我们为什么要去弄清楚这个呢?因为,按照我们现在的分析,如果我们知道了数据包的整个生成原理,包括每一位相应的功能,那么是不是就可以构造出能够实现我们想要实现的功能的数据包呢?比如:弹出我们想要弹出的消息,打开我们指定的网站,等等……那么,这个就是我接下来的目的:做一个这样的数据包生成器!
那么,首先,我们得对数据包进行分析。OD载入,对recvform下断点。直接Shift+F9运行起来,拨号。然后呢?因为我们是自己搭建的系统,所以,服务器不可能有数据包发过去,于是我们要自己发数据包过去。还记得上章节中的那些数据包么?直接拿过来用吧,反正我们也是想知道为什么上次截获的数据包这次不用了。
复制一个截获到的数据包内容,UDP方式发送到客户端所在的ip的4999端口。然后,我们的od成功中断程序。
Alt+F9返回程序代码段。我看看堆栈情况。EAX中存放的就是接收到的数据包的总长度。现在单步运行,往后看看,你会发现,这是一个switch case 语句。我们看看反汇编的代码吧。(UDD文件丢失,以前所有的注释都没了,所以~~再敲上一点点吧)
00408C8C |> \83FB 12 |cmp ebx,0x12
00408C8F |. 0F8E C9000000 |jle 1_2_9破?00408D5E //当总长度小于0x12时,丢弃该数据包
00408C95 |. 8D8424 380100>|lea eax,dword ptr ss:[esp+0x138] //数据包存放地址放到eax中
00408C9C |. 53 |push ebx
00408C9D |. 50 |push eax
00408C9E |. E8 FD99FFFF |call 1_2_9破?004026A0 //这是一个解密call,我们在前面的章节破解的
00408CA3 |. 8B8C24 400100>|mov ecx,dword ptr ss:[esp+0x140] ; 将解密后数据包中前四个字符给ecx,其实也就用到第一个字符
00408CAA |. 83C4 08 |add esp,0x8
00408CAD |. 81E1 FF000000 |and ecx,0xFF //得到数据包解密后的首个字符
00408CB3 |. 8D41 FC |lea eax,dword ptr ds:[ecx-0x4] ; Switch (cases 4..CA)
……
00408CD0 |> 8D8424 380100>|lea eax,dword ptr ss:[esp+0x138] ; Case 4 of switch 00408CB3
……
00408CD9 |. E8 82030000 |call 1_2_9破?00409060 //这个call中将会出现数据包中各位对应的功能
……
00408CEB |> 8D8C24 380100>|lea ecx,dword ptr ss:[esp+0x138] ; Case 6 of switch 00408CB3
……
00408D02 |> 8B4424 14 |mov eax,dword ptr ss:[esp+0x14] ; Case C8 of switch 00408CB3
……
00408D2D |> 8B4C24 14 |mov ecx,dword ptr ss:[esp+0x14] ; CaseCAof switch 00408CB3
……
00408D5E |> 8B35 98CE4300 |mov esi,dword ptr ds:[0x43CE98] ; Default case of switch 00408CB3
……
00408D6A |.^0F84 36FEFFFF \je 1_2_9破?00408BA6
从这里可以看出,首字符有“04,06,C8,CA”四个不同选项,大概是四种不同功能的数据包,由于我只收过04开头的数据包,所以,我们也只能够通过这个数据包来分析清楚数据包中数据的结构。当然,你如果有兴趣的话,也可以试着逆向来分析一下06,C8,CA得功能,我估计吧,应该有一个是调出在线升级程序,一个是进行消息提醒(相当于突然弹出一个对话框警告你啥啥啥的)。废话就不多说了,暂时先来分析下04中的功能吧,我们主要分析00408CD9处的那个call。代码如下(先去掉除call和case分支以外的代码):
……
004090F4 |. 897424 18 mov dword ptr ss:[esp+0x18],esi ; 清空内存数据
004090F8 |. E8 D3190000 call 1_2_9破?0040AAD0
004090FD |. 83C4 08 add esp,0x8
00409100 |. 84C0 test al,al
00409102 |. 0F84 ED010000 je 1_2_9破?004092F5
0040913B |. |83C0 FC |add eax,-0x4 ; Switch (cases 4..10)
……
0040914E |> |8D4C24 18 |lea ecx,dword ptr ss:[esp+0x18] ; Case 9 of switch 0040913B
……
0040915F |> |684C1A4400 |push 1_2_9破?00441A4C ; Case 4 of switch 0040913B
……
00409170 |> |68 90064400 |push 1_2_9破?00440690 ; Case A of switch 0040913B
……
00409177 |> |688C064400 |push 1_2_9破?0044068C ; Case B of switch 0040913B
……
0040917E |> |684C1E4400 |push 1_2_9破?00441E4C ; Case C of switch 0040913B
……
00409185 |> |684C124400 |push 1_2_9破?0044124C ; Case D of switch 0040913B
……
0040918C |> |68 88064400 |push 1_2_9破?00440688 ; Case E of switch 0040913B
……
00409193 |> |68 84064400 |push 1_2_9破?00440684 ; Case F of switch 0040913B
……
0040919A |> |684C164400 |push 1_2_9破?0044164C ; Case 10 of switch 0040913B
……
004091A9 |> |E8 A2030000 |call 1_2_9破?00409550 //对接收到数据的数据结构进行判定,若异常,则丢弃数据包,若正确,则保存数据到相应的位置
……
004091BB |> |8D5424 30 |lea edx,dword ptr ss:[esp+0x30] ; Case 8 of switch 0040913B
是不是发现看起来很舒服啊,从上面我们可以大概看出数据包中的控制字符有“09,04,0A,0B,0C,0D,0E,0F,10,08”,我们暂时先跟进大的分支选择:
0040912E |. /0F8E C1010000 jle 1_2_9破?004092F5 ; 循环开始
00409134 |> |8B4424 10 /mov eax,dword ptr ss:[esp+0x10] ; 剩余数据的第一个字符位置,即功能字符
00409138 |. |0FBE00 |movsx eax,byte ptr ds:[eax] ; 放入eax
0040913B |. |83C0 FC |add eax,-0x4 ; Switch (cases 4..10)
0040913E |. |83F80C |cmp eax,0xC ; 减4后再与0xC比较,也就是0x10以内的条件分支
00409141 |. |0F87 D0000000 |ja 1_2_9破?00409217
经过一轮后,我们会发现,在如下图红色框框的位置上,对应的是我们的功能代码。
而粉红色的框框中的数值则是我们相应功能代码内容的长度-2。为什么-2?我也不知道。其中第一个字符是数据包类型代码(我们暂且这么称呼它吧),第二个字符则是我们的数据包总长度,地3-17中16个字符我们暂时不说(下章要进行分析~)。后面都是统一的格式了,一个功能代码+一个长度标识+内容。
光凭眼睛看,我们大概也能确定这么几个性质:
0C后面接的肯定是要输出的消息内容,而0D、10与弹出的网址有关,08是时间,那么这个时间在神马地方用到了呢?同时,我们还有很多诸如0A、、09、0B、0E等功能的字符没弄明白。为了弄清楚数据包中这些控制字符的相应功能,就得先把对数据包进行判定的判定条件去除掉。
那么,哪些地方做了判定和限制呢?继续跟下去~跟到功能代码为08的case时我们发现,这地方有好多跳转,稍微分析后就知道了,程序通过拨号成功的时间保留起来,与接收到的数据包中的时间进行逐位对比,若有偏差则丢弃数据包(跳转),这也是为什么数据包中会包含时间的原因了。如下图:
所以,改动的地方应该时间判定处:
将所有的跳转nop掉后,时间已经不构成限制了。
F9运行后弹出消息提示框和网站。
于是,我们就解决了先前的那个问题,为什么上次的数据包对这次拨号后发送没有效果,因为数据包中包含有拨号成功时间,会与保存在程序内存中的时间进行比对,若两个时间不相同,则丢弃数据包,于是自然也就没有效果了。
好的,那照这么说我们就已经成功解开了限制问题了。我们就可以去分析其他的功能标识符的含义?我们再次把数据包发送到客户端,同样断下程序,解密后把0D(对应网址)的标识改为0C看看会发生什么?
这次我们不单步了,直接F9跑起来,看是否会弹出两个对话框,来证实我们的猜想。
可结果却:
这又是为什么呢?我又随意改了一些其他的功能表示符号,或则内容,都弹出上图提示。
看来,做到这步还是不能完全去试验数据包的每一位是控制什么功能的,还是有些限制在其他地方。那么,在哪呢?且看下回分解~