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]ftoih20h)%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                                       ;  edikey
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(Lmsvcrt.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=(chdst0x20)%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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

版权声明:本文为ns517原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/ns517/archive/2009/01/21/1379677.html