作者:yulongying
声明:献给想我一样的新手们
日期:18:03 2011-4-1
前天在qq群里灌水的时候,一个网友求助,说是使用一个文件夹加密的东东忘了密码了,
于是就分析了一下那个程序,一方面是练习,一方面是助人为乐 呵呵。
程序比较小所以比较容易。希望对像我一样的新手们有所帮助。
这个程序文件夹加密信息在放在一个.XX2文件里面的,安装这个程序之后这个文件会变图标默认一文件夹加密这个程序打开。
这个文件我用UE打开看了下:
绝大多数都是用A9来填充的有些地方有其他数据填充。
0000032eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000033eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000034eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000035eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000036eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000037eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000038eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000039eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
000003aeh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
000003beh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
000003ceh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
000003deh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
000003eeh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
000003feh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000040eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000041eh: BA 9A CA A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; 施┅┅┅┅┅┅
0000042eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000043eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000044eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000045eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000046eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000047eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000048eh: A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 A9 ; ┅┅┅┅┅┅┅┅
0000049eh: 99 A9                                           ; 


首先打开程序,点击添加将.XX2文件添加进来,然后点击解密,随便输入一个密码,居然出现了提示信息“密码不匹配!请重新输入。” 呵呵。

于是用OD打开这个程序,找到这个字符串的位置

00407F08  |> /8A8C04 880100>|/mov     cl, byte ptr ss:[esp+eax+188]  ;  将加密后的输入字符与内存中的密码进行比较过程
00407F0F  |. |8A9404 000C00>||mov     dl, byte ptr ss:[esp+eax+C00]
00407F16  |. |3ACA          ||cmp     cl, dl
00407F18     |75 0E         ||jnz     short HideFold.00407F28
00407F1A  |. |40            ||inc     eax
00407F1B  |. |3D 80000000   ||cmp     eax, 80
00407F20  |. |0F8D 15010000 ||jge     HideFold.0040803B
00407F26  |.^\EB E0         |\jmp     short HideFold.00407F08
00407F28  |>  6A 10         |push    10
00407F2A      68 B8954100   push    HideFold.004195B8                ;  密码错误
00407F2F  |.  68 9C954100   |push    HideFold.0041959C               ;  密码不匹配!请重新输入。

很紧接着上面有一个循环比较的过程而且这个一句就是关键跳了
cmp     eax, 80
00407F20  |. |0F8D 15010000 ||jge     HideFold.0040803B
循环了80此就跳走了。

继续还往上翻
有一个明显的特征出来了
00407E78  |. /0F84 55050000 |je      HideFold.004083D3
00407E7E  |. |8D9424 E40700>|lea     edx, dword ptr ss:[esp+7E4]
00407E85  |. |68 A0040000   |push    4A0
00407E8A  |. |52            |push    edx
00407E8B  |. |8D4C24 74     |lea     ecx, dword ptr ss:[esp+74]
00407E8F  |. |FF15 A8344100 |call    near dword ptr ds:[<&MSVCP60.st>;  MSVCP60.std::basic_istream<char,std::char_traits<char> >::read
这就是读取.xx2文件了 放在ss:[esp+7E4],就断在这里开始分析了 呵呵

00407E8A  |.  52            |push    edx                                           ;  读取.xx2文件
00407E8B  |.  8D4C24 74     |lea     ecx, dword ptr ss:[esp+74]
00407E8F  |.  FF15 A8344100 |call    near dword ptr ds:[<&MSVCP60.std::basic_istre>;  MSVCP60.std::basic_istream<char,std::char_traits<char> >::read
00407E95  |.  8B4424 6C     |mov     eax, dword ptr ss:[esp+6C]
00407E99  |.  8B48 04       |mov     ecx, dword ptr ds:[eax+4]
00407E9C  |.  F6440C 70 01  |test    byte ptr ss:[esp+ecx+70], 1
00407EA1  |.  0F85 20020000 |jnz     HideFold.004080C7
00407EA7  |.  B9 1F000000   |mov     ecx, 1F
00407EAC  |.  33C0          |xor     eax, eax
00407EAE  |.  8DBC24 890100>|lea     edi, dword ptr ss:[esp+189]
00407EB5  |.  C68424 880100>|mov     byte ptr ss:[esp+188], 0
00407EBD  |.  F3:AB         |rep     stos dword ptr es:[edi]
00407EBF  |.  66:AB         |stos    word ptr es:[edi]
00407EC1  |.  AA            |stos    byte ptr es:[edi]
00407EC2  |.  B9 20000000   |mov     ecx, 20
00407EC7  |.  33C0          |xor     eax, eax
00407EC9  |.  8DBC24 880100>|lea     edi, dword ptr ss:[esp+188]
00407ED0  |.  8D9424 000100>|lea     edx, dword ptr ss:[esp+100]                   ;  输入的信息放到edx中
00407ED7  |.  F3:AB         |rep     stos dword ptr es:[edi]
00407ED9  |.  68 80000000   |push    80
00407EDE  |.  8D8424 8C0100>|lea     eax, dword ptr ss:[esp+18C]
00407EE5  |.  52            |push    edx
00407EE6  |.  50            |push    eax
00407EE7  |.  FFD5          |call    near ebp                                      ;  msvcrt.memmove
00407EE9  |.  8D8C24 0C0100>|lea     ecx, dword ptr ss:[esp+10C]
00407EF0  |.  8D9424 940100>|lea     edx, dword ptr ss:[esp+194]
00407EF7  |.  51            |push    ecx                                           ;  输入的信息
00407EF8  |.  68 80000000   |push    80
00407EFD  |.  52            |push    edx                                           ;  也是输入的信息
00407EFE  |.  E8 4DA3FFFF   |call    HideFold.00402250                             ;  加密关键函数 跟了进去
00407F03  |.  83C4 18       |add     esp, 18
00407F06  |.  33C0          |xor     eax, eax
00407F08  |>  8A8C04 880100>|/mov     cl, byte ptr ss:[esp+eax+188]                ;  将加密后的输入字符与内存中的密码进行比较过程
00407F0F  |.  8A9404 000C00>||mov     dl, byte ptr ss:[esp+eax+C00]
00407F16  |.  3ACA          ||cmp     cl, dl
00407F18      75 0E         ||jnz     short HideFold.00407F28
00407F1A  |.  40            ||inc     eax
00407F1B  |.  3D 80000000   ||cmp     eax, 80
00407F20  |.  0F8D 15010000 ||jge     HideFold.0040803B
00407F26  |.^ EB E0         |\jmp     short HideFold.00407F08
00407F28  |>  6A 10         |push    10
00407F2A      68 B8954100   push    HideFold.004195B8                              ;  密码错误
00407F2F  |.  68 9C954100   |push    HideFold.0041959C                             ;  密码不匹配!请重新输入。
00407F34  |.  8BCB          |mov     ecx, ebx
00407F36  |.  E8 F38F0000   |call    <jmp.&MFC42.#4224_CWnd::MessageBoxA>          ;  (初始 cpu 选择)


跟进去
00407EFE  |.  E8 4DA3FFFF   |call    HideFold.00402250                             ;  加密关键函数 跟了进去

设输入的字符串变量名为Input

关键代码段1:
00402275  |> /0FBE3C32      /movsx   edi, byte ptr ds:[edx+esi]
00402279  |. |03C7          |add     eax, edi
0040227B  |. |42            |inc     edx
0040227C  |. |3BD1          |cmp     edx, ecx
0040227E  |.^\7C F5         \jl      short HideFold.00402275                       ;  循环》输入的字符串所有ascii码相加
00402280  |>  33D2          xor     edx, edx
00402282  |.  B9 FF000000   mov     ecx, 0FF
00402287  |.  F7F1          div     ecx                                            ;  ascii码之和除以FF 余数放到bl中 就是取模运算
00402289  |.  8ADA          mov     bl, dl                                         ;  bl=sum(Input[0,1,..]) mod 0xFF(等于sum(Input[0,1,..])本身,为啥要这么做?求解释)
0040228B  |.  84DB          test    bl, bl
0040228D  |.  75 2B         jnz     short HideFold.004022BA


运算后跳转到关键代码2:
004022C2  |.  8B7424 10     mov     esi, dword ptr ss:[esp+10]
004022C6  |>  8A0E          /mov     cl, byte ptr ds:[esi]
004022C8  |.  56            |push    esi
004022C9  |.  32CB          |xor     cl, bl                                        ;  bl(bl=sum(Input[0,1,..])) xor Input[i]
004022CB  |.  880E          |mov     byte ptr ds:[esi], cl
004022CD  |.  E8 5EFFFFFF   |call    HideFold.00402230                             ;  将运算结果的高四位与低四位 互换
004022D2  |.  83C4 04       |add     esp, 4
004022D5  |.  46            |inc     esi
004022D6  |.  4F            |dec     edi
004022D7  |.^ 75 ED         \jnz     short HideFold.004022C6                       ;  循环80h次

高地位互换的方法是
00402236  |.  8AC8          mov     cl, al
00402238  |.  C0E9 04       shr     cl, 4
0040223B  |.  C0E0 04       shl     al, 4
0040223E  |.  0AC1          or      al, cl
00402240  |.  8802          mov     byte ptr ds:[edx], al

当input[i]=0的时候就等于将sum(Input[0,1,..])的值高地位互换放到剩余字节填充 补齐80h

00407F08  |> /8A8C04 880100>|/mov     cl, byte ptr ss:[esp+eax+188]                ;  将加密后的输入字符与内存中的密码进行比较过程
00407F0F  |. |8A9404 000C00>||mov     dl, byte ptr ss:[esp+eax+C00]                ;  .xx2文件中数据BA 9A CA A9 A9 A9 A9 A9 A9  施┅┅┅
00407F16  |. |3ACA          ||cmp     cl, dl
00407F18     |75 0E         ||jnz     short HideFold.00407F28                      ;  不等就跳转 弹出密码验证错误提示
00407F1A  |. |40            ||inc     eax
00407F1B  |. |3D 80000000   ||cmp     eax, 80
00407F20  |. |0F8D 15010000 ||jge     HideFold.0040803B                            ;  比较完所有80h 密码验证正确
00407F26  |.^\EB E0         |\jmp     short HideFold.00407F08

总结出验证算法
s[i] = sum(Input[0,1,...]) xor Input[i] , i=0,1,2,....,0x80-1

然后将s[i]高四位与低四位 互换
最后与文件中数据
BA 9A CA A9 A9 A9 A9 A9 A9  施┅┅┅
高地位互换
AB A9 AC 9A 9A 9A.....
后面一大串都是A9 A9 A9 
所以推出9A=sum(Input[0,1,...])
AB A9 AC 分别再与9A异或密码就还原了
分别是1 3 6的ascii码值
.xx2文件 和那个文件夹加密工具在附件里面
有兴趣的自己可以分析下 呵呵。

上传的附件 wjjjmb.rar