DR.com客户端解密过程逆向分析

DR.com客户端解密过程逆向分析

说明:

Dr.com Client是城市热点提供的校园网认证平台,很多学校都用这个,例如,CQUCQNU等等(不过我们家是用H3Com认证的,有点意思)。

离校前一天晚上三个人在宿舍密谋弄个关于Dr.com的猥琐东东出来,此破文是那个小东东的前期分析,主要解决如何从Dr.com加密文本中获得加密字符串后,自己实现解密函数进行解密分析,得到真正的密码。

此破文仅仅对客户端进行了跟踪,因为家里不可能连到网络中心,所以不涉及任何通信数据包截获解密的部分.此部分可参考Xfocus上某帖

参考文献:

Dr.com客户端认证研究    www.xfocus.net/bbs/index.php?act=ST&f=2&t=42694&page=1

探究Dr.COM Client内存显示明文密码漏洞    http://hack.77169.com/HTML/20080723140033.html

Dr.com3.46客户端密码文件解密过程        http://bbs.pediy.com/showthread.php?p=440464

此破文大部分参考自《Dr.com3.46客户端密码文件解密过程》,此文作者经过我社工后发现:

1、   貌似是我老乡..郑州人好像..

2、   貌似是我师兄、CQU计院研二..

以上均属社工猜测,可能与实际不符..

正文:

工具、平台: WINXP SP1 + OllyICE + IDA + VS2008 + UltraEdit + EditPlus

Dr.com版本号:v3.482,其它版本大致通用

 

主要逆向了三部分,一是找到加密字符串所在文本并打开过程、二是密钥的生成过程、三是利用密钥对加密字符串的解密过程..

详细过程:

因为关于DR.com的解密逆向已经不少了,看了几篇paper后,大致有了思路,先小跟了下程序,一直跟到了那个要输入帐号密码的对话框,因为没有选择保存密码,所以没有发现文件操作部分..


 大致熟悉初始化过程后,根据DRcom的内存明文显示密码问题下手,首先,用OD加载Drcom,搜索引用字符串:


 从这点跟进,终于找到放密码的内存地址,这个地址是硬编码,不会变的..


经过分析发现

0x0041DB00是存放帐号的地址;0x41DB1B是存放密码的地址,在这两个字符串之间还有一段数据,因为目前用不到就没解,有兴趣的自己尝试..


 0040CFA5  |.  8D7424 2C     lea     esi, dword ptr [esp+2C]

0040CFA9  |.  BF 00DB4100   mov     edi, 0041DB00                    ;  20075440

0040CFAE  |.  8A4424 47     mov     al, byte ptr [esp+47]

在这里断下来,0x0041DB00果真是帐号吧.呵呵

下面提供一种相当猥琐的方法:

在内存上下断点,我在0x0041DB00内存位置下内存写入断点,当把20075440写入的时候就会触发,我大致跟了下,这个帐号是从同目录下的login2.dat里读出的..

0x0041DB00下断的目的是为了分析读密码的文件流操作,如果只想逆向解密那部分,可以直接断在0x0041DB1B

 

下面单步几下来到对密码所在文件操作的部分:


 UINT WINAPI GetSystemDirectory(

  __out  LPTSTR lpBuffer,

  __in   UINT uSize

);

lpBuffer装的是系统路径,usize为其长度,即eax,后面判断如果长度为0,就直接退出

0040F917   |>   83C9 FF       or      ecx, FFFFFFFF
0040F91A  
| .  BF  00704100    mov     edi,  00417000                     ;  \micsy
0040F91F  
| .  33C0          xor     eax, eax                         ;  eax清0
0040F921  
| .   53             push    ebx
0040F922  
| .  F2:AE         repne   scas  byte  ptr es:[edi]           ;  计算0x0041700处字符串长度
0040F924  
| .  F7D1          not     ecx                              ;  ecx  =  strlen( " \micsy " );
0040F926  
| .  2BF9          sub     edi, ecx
0040F928  
| .  8D5424  48      lea     edx, dword ptr [esp + 48 ]          ;  应该是上面函数getSystemDirectoryA出来的
0040F92C  
| .  8BD9          mov     ebx, ecx
0040F92E  
| .  8BF7          mov     esi, edi
0040F930  
| .  83C9 FF       or      ecx, FFFFFFFF
0040F933  
| .  8BFA          mov     edi, edx
0040F935  
| .  F2:AE         repne   scas  byte  ptr es:[edi]           ;  移到系统目录字符串末尾
0040F937  
| .  8BCB          mov     ecx, ebx
0040F939  
| .  4F            dec     edi                              ;  把 ' \0 ' 去掉
0040F93A  
| .  C1E9  02        shr     ecx,  2
0040F93D  
| .  F3:A5         rep     movs dword ptr es:[edi], dword p >
0040F93F  
| .  8BCB          mov     ecx, ebx
0040F941  
| .  8D5424  48      lea     edx, dword ptr [esp + 48 ]
0040F945  
| .  83E1  03        and     ecx,  3
0040F948  
| .   50             push    eax                              ;  / hTemplateFile  =>  NULL
0040F949  
| .  F3:A4         rep     movs  byte  ptr es:[edi],  byte  ptr > |
0040F94B  
| .  BF F86F4100   mov     edi, 00416FF8                    ;  | stem.存放密码文件的另一半够变态吧,micsy + sytem就出来了那个放密码的文件名了
0040F950  
| .  83C9 FF       or      ecx, FFFFFFFF                    ;  |
0040F953  
| .  F2:AE         repne   scas  byte  ptr es:[edi]           ;  |
0040F955  
| .  F7D1          not     ecx                              ;  |
0040F957  
| .  2BF9          sub     edi, ecx                         ;  |
0040F959  
| .   50             push    eax                              ;  | Attributes  =>   0
0040F95A  
| .  8BF7          mov     esi, edi                         ;  |
0040F95C  
| .  8BD9          mov     ebx, ecx                         ;  |
0040F95E  
| .  8BFA          mov     edi, edx                         ;  |
0040F960  
| .  83C9 FF       or      ecx, FFFFFFFF                    ;  |
0040F963  
| .  F2:AE         repne   scas  byte  ptr es:[edi]           ;  |
0040F965  
| .  8BCB          mov     ecx, ebx                         ;  |
0040F967  
| .  4F            dec     edi                              ;  |
0040F968  
| .  C1E9  02        shr     ecx,  2                            ;  |
0040F96B  
| .  F3:A5         rep     movs dword ptr es:[edi], dword p > |
0040F96D  
| .  8BCB          mov     ecx, ebx                         ;  |
0040F96F  
| .  8D5424  50      lea     edx, dword ptr [esp + 50 ]          ;  |
0040F973  
| .  83E1  03        and     ecx,  3                            ;  |
0040F976  
| .  6A  04          push     4                                 ;  | Mode  =  OPEN_ALWAYS
0040F978  
| .  F3:A4         rep     movs  byte  ptr es:[edi],  byte  ptr > |
0040F97A  
| .  BF F46F4100   mov     edi, 00416FF4                    ;  | binstem.
0040F97F  
| .  83C9 FF       or      ecx, FFFFFFFF                    ;  |
0040F982  
| .  F2:AE         repne   scas  byte  ptr es:[edi]           ;  |
0040F984  
| .  F7D1          not     ecx                              ;  |
0040F986  
| .  2BF9          sub     edi, ecx                         ;  |
0040F988  
| .   50             push    eax                              ;  | pSecurity  =>  NULL
0040F989  
| .  8BF7          mov     esi, edi                         ;  |
0040F98B  
| .  8BD9          mov     ebx, ecx                         ;  |
0040F98D  
| .  8BFA          mov     edi, edx                         ;  |
0040F98F  
| .  83C9 FF       or      ecx, FFFFFFFF                    ;  |
0040F992  
| .  F2:AE         repne   scas  byte  ptr es:[edi]           ;  |
0040F994  
| .  8BCB          mov     ecx, ebx                         ;  |
0040F996  
| .  4F            dec     edi                              ;  |
0040F997  
| .  C1E9  02        shr     ecx,  2                            ;  |
0040F99A  
| .  F3:A5         rep     movs dword ptr es:[edi], dword p > |
0040F99C  
| .  8BCB          mov     ecx, ebx                         ;  |
0040F99E  
| .   50             push    eax                              ;  | ShareMode  =>   0
0040F99F  
| .  83E1  03        and     ecx,  3                            ;  |
0040F9A2  
| .  8D4424 5C     lea     eax, dword ptr [esp + 5C]          ;  |
0040F9A6  
| .   68   00000080    push     80000000                          ;  | Access  =  GENERIC_READ
0040F9AB  
| .   50             push    eax                              ;  | FileName
0040F9AC  
| .  F3:A4         rep     movs  byte  ptr es:[edi],  byte  ptr > |
0040F9AE  
| .  FF15 A0204100 call    dword ptr [ <& KERNEL32.CreateFile > ; \CreateFileA
0040F9B4  
| .  8BF0          mov     esi, eax                         ;  组合出路径,然后createfile
0040F9B6  
| .  5B            pop     ebx
0040F9B7  
| .  83FE FF       cmp     esi,  - 1
0040F9BA  
| .   75  0B         jnz      short  0040F9C7

 

---------------------------------------------------------------------------------------------------------------------------

以上代码组合出密码文件所在路径!


 以上为三次strlen+strcat得到的字符串.把一些硬编码连接在一起就组合出了这个路径,里面存的就是加密后的密码.

0040F948   | .   50             push    eax                              ;  / hTemplateFile  =>  NULL

0040F959  
| .   50             push    eax                              ;  | Attributes  =>   0

0040F976  
| .  6A  04          push     4                                 ;  | Mode  =  OPEN_ALWAYS

0040F988  
| .   50             push    eax                              ;  | pSecurity  =>  NULL

0040F99E  
| .   50             push    eax                              ;  | ShareMode  =>   0

0040F9A6  
| .   68   00000080    push     80000000                          ;  | Access  =  GENERIC_READ

0040F9AB  
| .   50             push    eax                              ;  | FileName

0040F9AE  
| .  FF15 A0204100 call    dword ptr [ <& KERNEL32.CreateFileA > ]             ; \CreateFileA

我把所有的push整合后,出来了CreateFile的调用

HANDLE CreateFile(

  LPCTSTR lpFileName, 

  DWORD dwDesiredAccess, 

  DWORD dwShareMode, 

  LPSECURITY_ATTRIBUTES lpSecurityAttributes, 

  DWORD dwCreationDisposition, 

  DWORD dwFlagsAndAttributes, 

  HANDLE hTemplateFile

);

完全符合,参数从右到左压栈了!

调用最终返回一个文件句柄。

继续:


 和我们平常写文件流操作完全一样,CreatFile后自然开始ReadFile()

判断返回值eax,如果为0就是调用失败,函数退出


读完后CloseHandle(),不说了..

看看ReadFile出来了什么:


 EDX指向esp+8,就是堆栈中的字符串的显示


 堆栈中的字符串


 

 看一下文件中真是这个字符串么:

打开 C:\WINDOWS\system32\micsystem.bin

 


果真如此,哈哈!

读出的内容已经压栈了,应该是下面那个call的一个参数,call  00401D00

这个很明显,解密函数到了!

F7单步进去: 

 

这里是计算密钥的函数,可惜Dr.com公司接口留的不错,只是没有利用,这个函数永远返回定值:0x75B9,以为它的参数字符串是硬编码,汗..

但还是跟进去看一下吧:


00401FA0  
/ $  83EC  08        sub     esp,  8
00401FA3  
| .   53             push    ebx
00401FA4  
| .   56             push    esi
00401FA5  
| .   57             push    edi
00401FA6  
| .  8B7C24  18      mov     edi, dword ptr [esp + 18 ]                         ;  esp + num;为传递的参数的形式.num足够大就是传参,小就是局部变量
00401FAA  
| .  83C9 FF       or      ecx, FFFFFFFF
00401FAD  
| .  33C0          xor     eax, eax
00401FAF  
| .  33DB          xor     ebx, ebx
00401FB1  
| .  33F6          xor     esi, esi
00401FB3  
| .  F2:AE         repne   scas  byte  ptr es:[edi]                          ;  貌似是把字符串读进去,然后edi就是字符串末尾,ecx记录长度
00401FB5  
| .  F7D1          not     ecx                                             ;  去反
00401FB7  
| .   49             dec     ecx                                             ;  去掉\ 0
00401FB8  
| .  33FF          xor     edi, edi
00401FBA  
| .  3BCB          cmp     ecx, ebx
00401FBC  
| .  895C24 0C     mov     dword ptr [esp + C], ebx
00401FC0  
| .  894C24  10      mov     dword ptr [esp + 10 ], ecx
00401FC4  
| .  7E  56          jle      short  0040201C
00401FC6  
| .   55             push    ebp
00401FC7  
|>   8B4424 1C      / mov     eax, dword ptr [esp + 1C]                        ;  取常量字符串
00401FCB  
| .   56              | push    esi                                            ;  上次除的余数压栈
00401FCC  
| .  0FBE2C07       | movsx   ebp,  byte  ptr [edi + eax]                        ;  取字符串的第i个字符
00401FD0  
| .  E8 6B000000    | call     00402040                                        ;  eax  =   2 ^ esi
00401FD5  
| .  0FAFC5         | imul    eax, ebp                                       ;  eax * ebp;ebp为str[i]
00401FD8  
| .  8B4C24  14       | mov     ecx, dword ptr [esp + 14 ]                        ;  esp + 14 | 18  固定存异或的结果
00401FDC  
| .   53              | push    ebx                                            ;  ebx压栈
00401FDD  
| .  33C8           | xor     ecx, eax                                       ;  ecx与eax亦或
00401FDF  
| .  894C24  18       | mov     dword ptr [esp + 18 ], ecx                        ;  果真,每次存异或的结果
00401FE3  
| .  E8  58000000     | call     00402040                                        ;  eax  =   2 ^ ebx
00401FE8  
| .  0FAFC5         | imul    eax, ebp                                       ;  eax * ebp;ebp为str[i]
00401FEB  
| .  8B5424  18       | mov     edx, dword ptr [esp + 18 ]                        ;  取出异或的结果
00401FEF  
| .  B9  13000000     | mov     ecx,  13
00401FF4  
| .  33D0           | xor     edx, eax
00401FF6  
| .  8D46  07         | lea     eax, dword ptr [esi + 7 ]                         ;  余数加7  10
00401FF9  
| .   895424   18       | mov     dword ptr [esp + 18 ], edx
00401FFD  
| .  83C4  08         | add     esp,  8
00402000    | .   99              | cdq
00402001    | .  F7F9           | idiv    ecx                                            ;  eax存值,edx存余数
00402003    | .  8D43 0D        | lea     eax, dword ptr [ebx + D]                         ;  余数 + 13    13
00402006    | .  B9  17000000     | mov     ecx,  17
0040200B  
| .  8BF2           | mov     esi, edx                                       ;  esi  =  eax % 13h
0040200D  
| .   99              | cdq
0040200E  
| .  F7F9           | idiv    ecx
00402010    | .  8B4424  14       | mov     eax, dword ptr [esp + 14 ]                        ;  esp + 14为strlen
00402014    | .   47              | inc     edi                                            ;  edi控制循环
00402015    | .  3BF8           | cmp     edi, eax
00402017    | .  8BDA           | mov     ebx, edx                                       ;  ebx  =  eax % 17h
00402019    | . ^  7C AC         \jl       short  00401FC7
0040201B  
| .  5D            pop     ebp
0040201C  
|>   8B4424 0C     mov     eax, dword ptr [esp + C]
00402020    | .  B9 B9880100   mov     ecx, 188B9
00402025    | .   35   01890100    xor     eax,  18901
0040202A  
| .  5F            pop     edi
0040202B  
| .   99             cdq
0040202C  
| .  F7F9          idiv    ecx
0040202E  
| .  5E            pop     esi
0040202F  
| .  5B            pop     ebx
00402030    | .  8BC2          mov     eax, edx
00402032    | .  83C4  08        add     esp,  8
00402035   \.  C3            retn

上面是我结合其它文章和自己的分析给出的,个别地方注释是早期留得,有点错误.

上面这个函数都比较简单,里面有个call 0x00402040,这个函数调用更简单,代码如下:

00402040    / $  8B4C24  04      mov     ecx, dword ptr [esp + 4 ]
00402044    | .  B8  01000000    mov     eax,  1
00402049    | .  3BC8          cmp     ecx, eax
0040204B  
| .  7C  05          jl       short   00402052
0040204D  
|>   03C0           / add     eax, eax
0040204F  
| .   49              | dec     ecx
00402050    | . ^   75  FB         \jnz      short  0040204D
00402052   \ >   C3            retn

还原出来大致是int Fun(int n),返回2n次幂

给出C实现:

int  Fun( int  num)
{
    
if  (num == 0 )
    {
        
return   1 ;
    }
    
int  sum  =   1 ;
    
for  ( int  i = 0 ;i < num;i ++ )
    {
        sum 
<<=   1
    }
    
return  sum;
}

对照下即可明白!

加上此函数,就可得到那个得到密钥的函数

原型

int Decode(char* pch)

C实现:

int  decode( char *  pch)
{
    
int  len  =  strlen(pch);
    
char  ch;
    
int  num  =   0 ;
    
int  si  =   0 ;
    
int  bx  =   0 ;
    
for  ( int  i = 0 ;i < len;i ++ )
    {
        ch 
=   * (pch + i);
        
int  temp  =  Fun(si) * ch;
        num 
^=  temp;
        temp 
=  Fun(bx) * ch;
        num 
^=  temp;
        si 
=  (si + 0x07 ) % 0x13 ;
        bx 
=  (bx + 0x0d ) % 0x17 ;
    }
    
    
return  num;
}

然后综合分析自己写个得到密钥DEMO

 1  #include  < iostream >
 2  #include  < string .h >
 3  using   namespace  std;
 4 
 5  int  Fun( int  num)
 6  {
 7       if  (num == 0 )
 8      {
 9           return   1 ;
10      }
11       int  sum  =   1 ;
12       for  ( int  i = 0 ;i < num;i ++ )
13      {
14          sum  <<=   1
15      }
16       return  sum;
17  }
18 
19  int  decode( char *  pch)
20  {
21       int  len  =  strlen(pch);
22       char  ch;
23       int  num  =   0 ;
24       int  si  =   0 ;
25       int  bx  =   0 ;
26       for  ( int  i = 0 ;i < len;i ++ )
27      {
28          ch  =   * (pch + i);
29           int  temp  =  Fun(si) * ch;
30          num  ^=  temp;
31          temp  =  Fun(bx) * ch;
32          num  ^=  temp;
33          si  =  (si + 0x07 ) % 0x13 ;
34          bx  =  (bx + 0x0d ) % 0x17 ;
35      }
36      
37       return  num;
38  }
39 
40  int  main()
41  {
42       char *  constr  =   " TblRefreshCurMonthServiceUse " ;
43       int  num  =  decode(constr);
44      num  ^=   0x18901 ;
45      num  %=   0x188B9 ;
46 
47      cout << num << endl;
48 
49  }

由于参数是个常量字符串,结果自然也是常量:30317

这段代码明显在浪费时间..

接着分析:

00401DD0   / $  83EC  74        sub     esp,  74
00401DD3  
| .   55             push    ebp
00401DD4  
| .   56             push    esi
00401DD5  
| .   57             push    edi
00401DD6  
| .  B9  00020000    mov     ecx,  200
00401DDB  
| .  33C0          xor     eax, eax
00401DDD  
| .  BF 8CC64100   mov     edi, 0041C68C
00401DE2  
| .  F3:AB         rep     stos dword ptr es:[edi]                         ;  开放缓冲区
00401DE4  
| .   68   34444100    push     00414434                                         ;  tblrefreshcurmonthserviceuse
00401DE9  
| .  E8 B2010000   call    00401FA0                                        ;  上面那个字符串参数诡异,返回常量75B9
00401DEE  
| .  8BBC24  880000 > mov     edi, dword ptr [esp + 88 ]                         ;  取加密字符串
00401DF5  
| .  8BE8          mov     ebp, eax                                        ;  常量存入ebp;75B9
00401DF7  
| .  83C9 FF       or      ecx, FFFFFFFF
00401DFA  
| .  33C0          xor     eax, eax
00401DFC  
| .  83C4  04        add     esp,  4                                           ;  弹出字符串指针
00401DFF  
| .  8BF0          mov     esi, eax                                        ;  准备做循环控制变量
00401E01  
| .  F2:AE         repne   scas  byte  ptr es:[edi]
00401E03  
| .  F7D1          not     ecx
00401E05  
| .   49             dec     ecx                                             ;  以上几句为取strlen的固定格式..
00401E06  
| .   49             dec     ecx
00401E07  
| .  894C24  18      mov     dword ptr [esp + 18 ], ecx                         ;  ecx  =  strlen  -   1 ;
00401E0B  
| .  0F88  98000000  js      00401EA9
00401E11  
| .  8BC5          mov     eax, ebp
00401E13  
| .  33FF          xor     edi, edi
00401E15  
| .  F7D8          neg     eax                                             ;  eax取反,并且会影响CF位
00401E17  
| .   53             push    ebx
00401E18  
| .  C74424  10  8CC > mov     dword ptr [esp + 10 ], 0041C68C
00401E20  
| .   894424   18      mov     dword ptr [esp + 18 ], eax                         ;  下面应该是解密的循环
00401E24  
|>   8B8424  880000 >/ mov     eax, dword ptr [esp + 88 ]
00401E2B  
| .  8A0406         | mov     al,  byte  ptr [esi + eax]                         ;  取一个加密字符 esi代表数组下标
00401E2E  
| .  0FBED8         | movsx   ebx, al                                        ;  ebx放当前字符
00401E31  
| .  83FB  20         | cmp     ebx,  20                                         ;  是否为空格,以下程序判断字符是否为可打印字符
00401E34  
| .   884434   20       | mov      byte  ptr [esp + esi + 20 ], al                      ;  一直加堆栈位貌似
00401E38  
| .  7C 5B          | jl       short  00401E95
00401E3A  
| .  83FB 7E        | cmp     ebx, 7E
00401E3D    | .  7F  56           | jg       short  00401E95
00401E3F    | .  03FD           | add     edi, ebp                                       ;   // edi  edi = key×i
00401E41   | .  B9 B9880100    | mov     ecx, 188B9
00401E46  
| .  8BC7           | mov     eax, edi
00401E48  
| .   46              | inc     esi                                            ;  循环加一
00401E49  
| .   99              | cdq
00401E4A  
| .  F7F9           | idiv    ecx
00401E4C  
| .   895424   14       | mov     dword ptr [esp + 14 ], edx                        ;  保存余数
00401E50  
| .  DB4424  14       | fild    dword ptr [esp + 14 ]
00401E54  
| .  DC0D A8234100  | fmul    qword ptr [4123A8]
00401E5A  
| .  DC0D A0234100  | fmul    qword ptr [4123A0]
00401E60  
| .  E8 3BF20000    | call     < jmp. & MSVCRT._ftol >                             ;  进入浮点数计算
00401E65  
| .  8BD0           | mov     edx, eax                                       ;  把结果放入edx,结果固定是1c么?不是
00401E67  
| .  8BC3           | mov     eax, ebx                                       ;  取出加密字符
00401E69  
| .  2BC2           | sub     eax, edx                                       ;  加密字符与计算结果相减放入eax
00401E6B  
| .  B9 5F000000    | mov     ecx, 5F
00401E70  
| .  83E8  20         | sub     eax,  20
00401E73  
| .   99              | cdq
00401E74  
| .  F7F9           | idiv    ecx                                            ;  edx  =  (ch[i] - ftoih - 20h) % 5fh
00401E76  
| .  85D2           | test    edx, edx                                       ;  是否除尽
00401E78  
| .  7D  02           | jge      short  00401E7C
00401E7A  
| .  03D1           | add     edx, ecx
00401E7C  
|>   8B4424  18       | mov     eax, dword ptr [esp + 18 ]
00401E80  
| .  8B4C24 1C      | mov     ecx, dword ptr [esp + 1C]
00401E84  
| .  03F8           | add     edi, eax                                       ;  edi - key
00401E86  
| .  8B4424  10       | mov     eax, dword ptr [esp + 10 ]                        ;  eax存放加密字符
00401E8A  
| .  80C2  20         | add     dl,  20
00401E8D    | .  4E             | dec     esi
00401E8E  
| .   8810            | mov      byte  ptr [eax], dl                             ;  dl为对应密码,取出后放在0x41C68C + i
00401E90  
| .   40              | inc     eax
00401E91  
| .   894424   10       | mov     dword ptr [esp + 10 ], eax
00401E95  
|>    46              | inc     esi
00401E96  
| .  03FD           | add     edi, ebp
00401E98  
| .  3BF1           | cmp     esi, ecx
00401E9A  
| . ^  7E  88          \jle      short  00401E24                                 ;  判断解密是否结束
00401E9C  
| .  5B            pop     ebx
00401E9D    | .  5F            pop     edi
00401E9E  
| .  5E            pop     esi
00401E9F    | .  B8 8CC64100   mov     eax, 0041C68C
00401EA4  
| .  5D            pop     ebp
00401EA5  
| .  83C4  74        add     esp,  74
00401EA8  
| .  C3            retn
00401EA9  
|>   5F            pop     edi
00401EAA  
| .  5E            pop     esi
00401EAB  
| .  B8 8CC64100   mov     eax, 0041C68C
00401EB0  
| .  5D            pop     ebp
00401EB1  
| .  83C4  74        add     esp,  74
00401EB4  \.  C3            retn

上面的分析已经比较清楚了,看下这个函数:

00401E50   | .  DB4424  14       | fild    dword ptr [esp + 14 ]
00401E54  
| .  DC0D A8234100  | fmul    qword ptr [4123A8]
00401E5A  
| .  DC0D A0234100  | fmul    qword ptr [4123A0]
00401E60  
| .  E8 3BF20000    | call     < jmp. & MSVCRT._ftol >                             ;  进入浮点数计算
00401E65  
| .  8BD0           | mov     edx, eax                                       ;  把结果放入edx,结果固定是1c么?不是

_atoi(),是一个系统CRT函数,还是Dr.COM的人懒,传的参数又是两个常数,这个_atoi()代码不超过10行,本来是很容易逆向的,但是里面的waitleave指令不懂,自己实现的_atoi()结果不对,所以放弃,还是用直接调用系统本身的方法..

 

整个解密过程到此算是逆向的差不多了,自己根据反汇编代码可以写出解密函数,还有一种更猥琐的方法,我正在试验中,写个dll远程注入到ishare_user.exe中,直接调用drcom本身就可以完成一切功能..这个方法配合一些歪门邪道有点用处的..

解密过程代码:

 1  #include  < iostream >
 2  #include  < string .h >
 3  #include < Windows.h >
 4  using   namespace  std;
 5 
 6  void  Decode( char *  pch)
 7  {
 8       int  key  =   0x75B9 ,sum  = 0 ;
 9       char *  code  =   new   char [ 1024 ];
10       int  len  =  strlen(pch);
11       for  ( int  i = 0 ;i < len;i ++ )
12      {
13           char  ch  =  pch[i];
14           if  (ch >= 0x20 && ch <= 0x7e )
15          {
16              sum  +=  key;
17              
18               int  st0  =   0 ,dst  =   0 ;
19               double  d310  =   96.00000000000000 ;              
20               double  d318  =   9.946586828729721e-06 ;
21 
22              HINSTANCE LibHandle;
23              LibHandle = LoadLibrary(L " msvcrt.dll " );
24               void *  _ftol;
25              _ftol  = ( void * )GetProcAddress(LibHandle, " _ftol " );
26              st0  =  sum % 0x188B9 ;
27              __asm
28              {
29                  fild st0;
30                  fmul d318;
31                  fmul d310;
32                  call _ftol;
33                  mov  dst,eax
34              }
35              dst = (ch - dst - 0x20 ) % 0x5f ;
36               if (dst < 0 )  dst = dst + 0x5F ;
37              code[i] = dst + 32 ;
38          }
39      }
40      code[len]  =   ' \0 ' ;
41      cout << code << endl;
42  }
43 
44  int  main()
45  {
46       char *  pch  =   " Pk-Jf!:_u " ;
47      Decode(pch);
48 
49       return   0 ;
50  }

 

相关文档下载:RV-Drcom.rar

 

进一步改进:

目前Dr.com的这个问题就比较尴尬,内存明文显示密码,解密过程路人皆知。但是他们公司却认为这个是本机的问题,问题是相信杀毒软件可以监控Dr.COM的镜象还不如相信没人去反汇编Dr.com呢。

杀毒软件有N种方法可以阻止进入Dr.com的内存,我们自然就有N+1种方法可以进入Dr.com内存,大不了ring0下把杀软给干掉,然后读取那个内存位置,获得帐号密码,然后…自己想去吧..

还有个问题,如何解决通用性,各个版本的Dr的那个地址是不一样的,我的思路是stack callback,就是利用栈回溯到那个具有0x0041C68C特征的调用函数位置,然后再结合静态代码分析得到那个指向密码的指针,Dr.com的那段二进制码应该差别不大,很好定位特征应该..

 

既然有解密过程,剩下的就是一些猥琐技巧了..争取回校前搞定..

 

                                                                                                  -----------by     0x0o

                                                                                                          Time   09.01.20

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/ns517/archive/2009/01/21/1379677.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
object Form1: TForm1 Left = 216 Top = 131 AutoSize = True BorderIcons = [biSystemMenu, biMinimize] BorderStyle = bsNone Caption = 'Calculator' ClientHeight = 304 ClientWidth = 226 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False Position = poDesktopCenter OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 13 object BgImg: TImage Tag = 1100 Left = 0 Top = 0 Width = 226 Height = 304 AutoSize = True Picture.Data = { 0A544A504547496D616765AE1E0000FFD8FFE000104A46494600010101006000 600000FFDB004300020101010101020101010202020202040302020202050404 0304060506060605060606070908060709070606080B08090A0A0A0A0A06080B 0C0B0A0C090A0A0AFFDB004301020202020202050303050A0706070A0A0A0A0A 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A 0A0A0A0A0A0A0A0A0A0A0A0A0AFFC2001108013000E203012200021101031101 FFC4001D000101010002030101000000000000000000060704080203050109FF C4001C0101010101000301010000000000000000000704050102030608FFDA00 0C03010002100310000001DEF07467F42422B524ECF2EB5242B5242B5242B524 2B5242B5242B5242B5242B5242B5242B5242B781F065F16DFE88BF9328A577B5 58DEC98857E578BA650AB3D32645326453264536CBD74F66FC3DCDFCF77A7FA1 2181A3E40000000256AA579DBB2B128A676AF10DBF10A07E17AE23F9F6E80000 01C8F670DF4F9F31C379F1CC70C731C31CC70C731C31CC70C765F9FC0E7DBE3B 958FC6FEB7B57037D255599C32E5CCE8432E4432E4432E4432E4432E4432E443 2E4432E4432E4432E4432E4713E0554AEDCD95898517B57255B255B9706DCC00 00000000000000256AA579DBB2B128A676AE4AB64AB72E0DB980000000000000 0004AD54AF3B76562514CED5C956C956E5C1B730000000000000000095AA95E7 6ECAC4A299DAB92AD92ADCB836E6000000000000000012B552BCEDD95894533B 57255B255B9706DCC0000000000000000256AA579DBB2B128A676AE4AB64AB72 E0DB9800000000000000004AD54AF3B76562514CED5C95
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值