您的位置:首页 > 其它

如何破解安腾校园网客户端(2)

2010-12-06 13:27 211 查看
好了吃饱了,继续我们的破解之路。

前面已经追到了关键函数,函数中有下面一段代码

004166B7 |. 51 PUSH ECX

004166B8 |. 68 0C914500 PUSH upplican.0045910C ; 这里应该指向一个结构体

004166BD |. 6A 06 PUSH 6

004166BF |. 6A 07 PUSH 7

004166C1 |. 52 PUSH EDX

004166C2 |. C705 C43A5200>MOV DWORD PTR DS:[523AC4],1000000

004166CC |. 894424 1C MOV DWORD PTR SS:[ESP+1C],EAX

004166D0 |. C74424 20 120>MOV DWORD PTR SS:[ESP+20],12

004166D8 |. E8 C3400000 CALL upplican.0041A7A0 ; 获取mac地址

其中第二个push有点意思,直接是一个地址,转到数据窗口

0045910C 00 0B 2F 20 64 91 35 39 2E 36 38 2E 31 2E 32 30 . / d?9.68.1.20

什么?居然是自己的mac地址,IP地址,网关地址,DNS服务器地址!(后面的数据我没有列出来)

那就看这个函数在做什么吧?

这个函数比较简单,只是几个movs而已,那就需要注意究竟是把什么数据复制到了什么地方。而且

后面对用户名,密码,IP地址等数据的处理也都是这个函数,那么很可能这个函数是用来对某个相同的数据进行赋值

(当然这是我跟踪多遍才发现的),那么是向什么地方赋值呢?直接看edi就可以了,对!直接EDI!

因为在复制的时候编译器编译之后绝大部分都是esi和edi的使用。经过跟踪发现,很大部分的验证信息都被放到了

11df22e地址左右的内存中。

0041680D |. 51 PUSH ECX

0041680E |. 6A 01 PUSH 1

00416810 |. 52 PUSH EDX

00416811 |. E8 0A0F0000 CALL 00417720 ; 这一部分填充的是什么呢?

00416816 |. 8B4424 40 MOV EAX,DWORD PTR SS:[ESP+40]

0041681A |. 8D8C24 C40000>LEA ECX,DWORD PTR SS:[ESP+C4]

00416821 |. 50 PUSH EAX ; 数据长度

00416822 |. 51 PUSH ECX ; 数据指针

00416823 |. E8 180E0000 CALL upplican.00417640 ; 对数据进行加密传送

00416828 |. 8B5424 48 MOV EDX,DWORD PTR SS:[ESP+48]

0041682C |. 8B0D C43C5200 MOV ECX,DWORD PTR DS:[523CC4]

00416832 |. 68 080F0000 PUSH 0F08

00416837 |. 68 7C924500 PUSH upplican.0045927C ; ASCII "192.168.4.2"

0041683C |. 8D8424 D40000>LEA EAX,DWORD PTR SS:[ESP+D4]

00416843 |. 52 PUSH EDX

00416844 |. 50 PUSH EAX

00416845 |. 51 PUSH ECX

00416846 |. E8 C5260000 CALL upplican.00418F10 ; 调用sendto发送数据

跟到后面发现了这两个函数,其中CALL 00417720这个函数也对12df214这个内存进行了填充,但目前还不知道究竟填充了什么。

而CALL 00417640 这个函数对12df214内存中的数据进行了变形,紧跟其后的函数就调用sendto进行发送数据,那么这个函数肯定是

对数据进行加密!!!那就跟进去看看吧

00417663 |> /8A043E /MOV AL,BYTE PTR DS:[ESI+EDI]

00417666 |. |8AC8 |MOV CL,AL

00417668 |. |8AD0 |MOV DL,AL

0041766A |. |C0E9 02 |SHR CL,2

0041766D |. |80E1 20 |AND CL,20

00417670 |. |80E2 40 |AND DL,40

00417673 |. |0ACA |OR CL,DL

00417675 |. |8AD0 |MOV DL,AL

00417677 |. |C0E9 02 |SHR CL,2

0041767A |. |80E2 20 |AND DL,20

0041767D |. |0ACA |OR CL,DL

0041767F |. |8AD0 |MOV DL,AL

00417681 |. |D0E9 |SHR CL,1

00417683 |. |80E2 02 |AND DL,2

00417686 |. |0ACA |OR CL,DL

00417688 |. |8AD0 |MOV DL,AL

0041768A |. |80E2 1C |AND DL,1C

0041768D |. |C0E0 05 |SHL AL,5

00417690 |. |0AD0 |OR DL,AL

00417692 |. |D0E9 |SHR CL,1

00417694 |. |C0E2 02 |SHL DL,2

00417697 |. |0ACA |OR CL,DL

00417699 |. |880C3E |MOV BYTE PTR DS:[ESI+EDI],CL

0041769C |. |46 |INC ESI

0041769D |. |3BF5 |CMP ESI,EBP

0041769F |.^/7C C2 /JL SHORT upplican.00417663

跟进去之后有上面的一段关键代码,它就是对数据进行加密的,先不管他是怎么变换的,不管他是用了某种算法,还是自己写的算法,都不重要了关键是这段代码是对数据进行加密的。那么我们模拟客户端发送数据的话,也一定要实现这个函数,还好这个函数不是太长,很容易就可以写出与之对应的C代码。

//发送之前对数据进行加密

void CCodeHelper::Encrpy(byte code[],int len)

{

for (int i=0;i<len;i++)

{

byte al=code[i];

byte cl=al,dl=al;

cl=cl>>2;

cl=cl&0x20;

dl=dl&0x40;

cl=cl|dl;

dl=al;

cl=cl>>2;

dl=dl&0x20;

cl=cl|dl;

dl=al;

cl=cl>>1;

dl=dl&2;

cl=cl|dl;

dl=al;

dl=dl&0x1c;

al=al<<5;

dl=dl|al;

cl=cl>>1;

dl=dl<<2;

cl=cl|dl;

code[i]=cl;

}

return;

}

那就验证一下我们的想法吧,构造一个和12df214内存数据相同的一个字节数组然后用我们的函数对其进行加密,比对结果,一致!OK

这个函数就搞定了。但是还有一个问题没有解决,就是前面有一个函数填充了另外一些数据,究竟是什么还没有弄明白。

那就跟进CALL 00417720函数一探究竟吧

0040DEFC |. 51 PUSH ECX ; /Arg1

0040DEFD |. 8BCB MOV ECX,EBX ; |

0040DEFF |. E8 7CF4FFFF CALL upplican.0040D380 ; /两次计算生成最终数据

经过层层跟进来到了这个函数处,这是个关键点,为什么说他是关键点呢,因为这是一个MD5函数的实现,为什么这样那个说呢?

0040D3DC |. 8D8C01 78A46A>LEA ECX,DWORD PTR DS:[ECX+EAX+D76AA478]

0040D3E3 |. 8BC1 MOV EAX,ECX

............................

0040D3FD |. 03CD ADD ECX,EBP

0040D3FF |. 8D940A 56B7C7>LEA EDX,DWORD PTR DS:[EDX+ECX+E8C7B756]

0040D406 |. 8BCA MOV ECX,EDX

上面是函数体的一部分代码,怎么样看出端倪了没有?这是md5经常用到的一些常数啊!

好了,CALL 00417720函数的功能就搞明白了。它是用了对某些数据求MD5值,随数据一起发送。其实这也很容易理解,在网络通信中,

为了防止数据被随意改动过都需要对数据进行求MD5。那么他是对谁进行求MD5的呢?

跟踪发现求MD5的函数有一个指针,是12df214!也就是前面的内存块儿。很可能是对所有需要发送的数据进行MD5然后填充。其实这是我跟踪多遍才发现的,在这个函数上我花了比较长的时间。

那就来验证一下吧。在网上找一份MD5的代码,对12df214内存的数据进行求MD5。12df214是起始地址,数据长度是多少呢?75!

为什么这样说呢?因为在前面抓包的过程中已经知道UDP的数据长度是75了。

再次比对成功。那就验证了我们的猜测。

好了,梳理一下思路,客户端发送验证数据的过程如下:

1、构造数据块清零。

2、用相关数据填充数据块,如下:

ABCDEF0000GHIJK

3、对上面的数据(包含其中的0)求MD5值,假设为XXXX填入上面的数据块,填充后如下
ABCDEFXXXXGHIJK

4、用某种算法进行加密。加密后如下:

EFJLEDXFYENXLWP

5、调用sendto发送。

下一步就是如何构造要发送的数据块了,这是一个难点。经过网上查询,知道安腾验证使用的是radius sever方式。

radius协议分为三部分:标志、长度、数据。

这样就很容易看出12df214内存中数据的结构了。但是我们用什么对应的C数据结构实现呢?本想用一个字节数组来实现的

,但是这样太“野蛮”,不利于扩展,根据经验构造数据结构如下:

typedef struct _NODE

{

byte flag;//标志

byte len;//长度

byte data[1];//数据

}NODE,*PNODE;

m_pUserPwd = (PNODE)malloc(sizeof(NODE)+strlen(m_szUserPwd)-1);

怎么样这种数据结构是不是很不错呢?呵呵当然啦,这可是跟着大牛们学的!以后还是多看点书哇。

好了万事具备就欠东风了,开始写我们的C++代码了。这部分并不太难,在此略过。

好了可以发送了,那怎么对接收的数据进行处理呢?我们知道发送的时候对数据进行了加密,那么接收的时候肯定也是要

解密的。那就继续用OD解决吧,有了前面的破解经验,破解解密算法并不困难。

好了到此为止我们就完全解决了发送数据,接收数据的全部问题。下一个问题就是对接收数据意义的解释,也就是什么样的数据表示

验证成功呢?这个比较简单,只要对比成功和不成功时候的数据就可以了。比对后发现有一个字段表示验证结果,是1则表示成功。

恩,所有的问题都解决了,那我们就写一个“暴力破解器”吧。

我们从第一学号(例如00000)开始循环一直到最后一个学号(9999),连续的向服务器发送数据,直到验证成功,找到学号abcde。

好了那就让我们用abcde登录吧。呵呵,是不是已经登录成了呢。

其实我们还可以对程序进行优化,那就是使用多线程,当然的注意,向服务器发送数据的频率不要太高,这样会引起服务器的不响应。

因为学校是严格限制上网的流量的。

好了,到此为止,对安腾校园网客户端的破解就到此为止了,怎么样是不是很有成就感呢。

这次破解用到了很多知识,比如MD5加密算法,比如UDP通信,还有很多其他无法用知识点表现的经验。

在此要非常感谢安腾客户端的漏洞,要不是这样一个漏洞,我哪里还能学到这么多的知识呢^_^

PS:有些地方说的比较含糊,这是故意的,考虑到我们处在天国的时代,说不定哪一天被和谐了,就麻烦了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: