还原精灵密码算法分析
还原精灵是一款很优秀的软件,它能够记录下一切对硬盘的写操作,不论您对硬盘进行拷贝还是移动删除甚至是格式化分区等操作,只要一重新启动,
一切都会恢复到这个操作之前的状态,所以被广泛应用在学校机房和网吧等公共场合的
电脑上.但是装还原精灵的用户如果忘记了密码就成麻烦事了,想卸掉要密码,想删也删不掉.
记得网上有一种能删除还原精灵的软件,是风般的男人(我也不知道他的真名,呵呵)编写的.
我个人是极不赞成用这种方法,因为这软件太 "野蛮" 了,它在取得 RING0 后,直接用硬盘 IO 把
原来的 BOOT 扇区强制写入物理 0 磁道 1 扇区.对 5.5 以上的版本会造成系统崩溃,
因为还原精灵为了与 NT/2000/XP 兼容,会替换一些驱动程序.
希望本文能对那些想卸载还原精灵而又忘记密码的用户带来帮助.
还原精灵早期版本密码加密算法很简单,甚至不加密直接明码比较.
5.0 版本加密算法是: 密文 = 密码 XOR A5A5A5A5A5A5A5A5H
6.0 版本的加密算法比较复杂,下面来分析一下
该程序加了壳,是弱壳,用OD 手动脱了
入口点是 004318A4.
下面列出程序一些关键代码片段(用 OD 分析的),至于怎么跟踪得来,由于篇幅关系暂不讨论
本文只讨论密码算法和解密器的编写.
0040160E .E8 B9F70200 call <jmp.&MFC42.#6334_CWnd::UpdateData>
00401613 .8D86 18020000 lea eax,
00401619 .8BCE mov ecx, esi
0040161B .50 push eax
0040161C .E8 EF010000 call 00401810 ;--------> 验证密码子程序
00401621 .85C0 test eax, eax
00401623 .0F85 D6000000 jnz 004016FF ; ----------> 关键跳转
00401629 .8D4C24 0C lea ecx,
0040162D .E8 4CF70200 call <jmp.&MFC42.#540_CString::CString>
00401632 .8D4C24 08 lea ecx,
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
跟进 CALL 00401810
代码如下:
00401839|.E8 A0F50200 call <jmp.&MFC42.#2915_CString::GetBu>
0040183E|.8BCB mov ecx, ebx
00401840|.8BF0 mov esi, eax
00401842|.8BC1 mov eax, ecx
00401844|.8D7C24 10 lea edi,
00401848|.C1E9 02 shr ecx, 2
0040184B|.F3:A5 rep movs dword ptr es:, dword p>
0040184D|.8BC8 mov ecx, eax
0040184F|.83E1 03 and ecx, 3
00401852|.F3:A4 rep movs byte ptr es:, byte ptr>
00401854|.8D4C24 10 lea ecx,
00401858|.51 push ecx
00401859|.E8 02490100 call 00416160
注意这个CALL,入栈的是密码原文地址.
把它步过,看看各个寄存器和密码原文有何变化.
我们可以看到密码原文变成密文.
把这个CALL 置断点,重新来过
跟进这个CALL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00416160/$8B4424 04 mov eax,
00416164|.6A 20 push 20 ;Arg3 = 00000020
00416166|.50 push eax ;Arg2 = 密码原文
00416167|.68 80254400 push 00442580 ;Arg1 = 00442580 ASCII "NJYZ-RG-60-TT-60"
0041616C|.E8 1FFFFFFF call 00416090 ;-----------------------> 转换密文子程序
00416171|.83C4 0C add esp, 0C
00416174\.C3 retn
注意这个CALL 的3个参数
第一个参数是指向一个字符串 "NJYZ-RG-60-TT-60"
第二个参数是指向密码原文
第三个参数是一个常数 00000020H
不难猜出这个CALL 是一个明文转换密文的子程序
跟进去看看,下面这段代码就是密码转换算法
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00416090/$55 push ebp
00416091|.8BEC mov ebp, esp
00416093|.8B45 10 mov eax,
00416096|.53 push ebx
00416097|.56 push esi
00416098|.57 push edi
00416099|.85C0 test eax, eax
0041609B|.7E 5D jle short 004160FA
0041609D|.60 pushad
0041609E|.8B75 08 mov esi,
004160A1|.8B7D 0C mov edi,
004160A4|.57 push edi
004160A5|.8B1F mov ebx,
004160A7|.8B4F 04 mov ecx,
004160AA|.33C0 xor eax, eax
004160AC|.BA B979379E mov edx, 9E3779B9
004160B1|.66:BF 2000 mov di, 20
这时候各个寄存器:
ESI 指向字符串 "NJYZ-RG-60-TT-60"
EDX 常数 9E3779B9
EBX 密码明文前4个字节
ECX 密码明文后4个字节
DI常数 0020H
大家应该可以下面的代码看出:
密码密文是把明文和字符串"NJYZ-RG-60-TT-60"和常数 9E3779B9 进行加密
其中密码的前4字节和字符串"NJYZ-RG-"加密
密码的后4字节和字符串"60-TT-60"加密
而且密码的前后4字节在每次加密循环都相互加密
004160B5|>03C2 /add eax, edx ;--------------->加密循环
004160B7|.8BE9 |mov ebp, ecx
004160B9|.C1E5 04 |shl ebp, 4
004160BC|.03DD |add ebx, ebp
004160BE|.8B2E |mov ebp,
004160C0|.33E9 |xor ebp, ecx
004160C2|.03DD |add ebx, ebp
004160C4|.8BE9 |mov ebp, ecx
004160C6|.C1ED 05 |shr ebp, 5
004160C9|.33E8 |xor ebp, eax
004160CB|.03DD |add ebx, ebp
004160CD|.035E 04 |add ebx,
004160D0|.8BEB |mov ebp, ebx
004160D2|.C1E5 04 |shl ebp, 4
004160D5|.03CD |add ecx, ebp
004160D7|.8B6E 08 |mov ebp,
004160DA|.33EB |xor ebp, ebx
004160DC|.03CD |add ecx, ebp
004160DE|.8BEB |mov ebp, ebx
004160E0|.C1ED 05 |shr ebp, 5
004160E3|.33E8 |xor ebp, eax
004160E5|.03CD |add ecx, ebp
004160E7|.034E 0C |add ecx,
004160EA|.66:4F |dec di
004160EC|.^ 75 C7 \jnz short 004160B5 ;------------>加密循环
004160EE|.5F pop edi
004160EF|.891F mov , ebx
004160F1|.894F 04 mov , ecx
想解出密码,我们得把密文解密 20H 次,如果直接用汇编代码逆运算是算不出来的,引用 《C 语言程序设计》中的
一句话 "超出人的大脑能直接思考的范围 ",而且碰到 shr 之类的语句就郁闷了,因为你无法知道前一个值是什么.
记得《C 语言程序设计》 有提到过用伪代码描述算法,我们不妨把汇编算法用 C 伪代码描述.
密码算法 C 伪代码:
a = 密码的前4个字节
b = 密码的后4个字节
n = 20H
k = 9E3779B9H
-------------------
c = b << 4
a = a + c
c = b ^ "NJYZ"
a = a + c
c = b >> 5 =============================> 密码的前4个字节加密
c = c ^ (k * n)
a = a + c
a = a + "-RG-"
--------------------
-----------------------------------------------------------------------------
--------------------
c = a << 4
b = b + c
c = a ^ "60-T"
b = b +c
c = a >> 5 =================================> 密码的后4个字节加密
c = c ^ (k * n)
b = b + c
b = b + "T-60"
---------------------
循环加密 20H 次
经过上面的分析,大家应该对还原精灵的加密算法比较熟悉了吧!
接下来讨论一下解密器的制作:
可以看出前后4个字节的加密算法一样的,我们可以遍一个解密子程序
先解出密码的后4个字节,再解出密码的前4个字节,如此循环20H次.
下面是我自己写的还原密码破解程序的源代码,在 VC++ 6.0 下编译通过(控制台程序)
#include "windows.h"
#include "stdio.h"
unsigned long esi0 = 0x5a594a4e;// "NJYZ"
unsigned long esi4 = 0x2d47522d;// "-RG-"
unsigned long esi8 = 0x542d3036;// "60-T"
unsigned long esic = 0x30362d54;// "T-60"
unsigned long edx0 = 0x9e3779b9;
//加密常量要仔细填,不然不但算不出密码,而且也很难找出错误.
void sub(unsigned long *a, unsigned long *b, unsigned long *a1, unsigned long
*b1, unsigned long c1);
void main()
{
printf("\n\t\t\t 还原精灵 6.0 密码读取程序 \n\n\n");
printf("\t\t\t\t\t by FIGO \n\n\n");
printf("\t\t\t 仅供学习交流使用,请勿用于非法目的\n\n\n\n");
long hmov = 0;
unsigned long *pwd;
char str1;
char *p1;
unsigned long *p2;
pwd = (unsigned long*)str1;
unsigned long tmp1, tmp2, tmp3, i;
HANDLE hFile;
hFile = CreateFile("\\\\.\\PhysicalDrive0", GENERIC_ALL, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
PBYTE pBuffer = (PBYTE)malloc(512);
DWORD dwLen;
hmov = SetFilePointer(hFile, 0x00000e00, (long*)(&hmov), FILE_BEGIN);
ReadFile(hFile, pBuffer, 512, &dwLen, NULL);
p1 = (char*)pBuffer + 0x4f;
p2 = (unsigned long*)p1;
tmp1 =*p2;
p2++;
tmp2 =*p2;
for (i = 0x20; i >= 1; i--)
{
tmp3 = i * edx0;
sub(&tmp2, &tmp1, &esi8, &esic, tmp3);
sub(&tmp1, &tmp2, &esi0, &esi4, tmp3);
}
*pwd = tmp1;
pwd = pwd++;
*pwd = tmp2;
pwd++;
*pwd = 0;
printf("\t\t\t password is : %s \n\n\n\n\n\n\n\n\n\n\n\n\n\n ", str1);
CloseHandle(hFile);
free(pBuffer);
}
void sub(unsigned long *a, unsigned long *b, unsigned long *a1,
unsigned long *b1, unsigned long c1)
{
unsigned long higt, low, esi1, esi2, ebp0, edx1;
edx1 = c1;
higt =*a;
low =*b;
esi1 =*a1;
esi2 =*b1;
ebp0 = low << 4;
higt = higt - ebp0;
ebp0 = low ^ esi1;
higt = higt - ebp0;
ebp0 = low >> 5;
ebp0 = ebp0 ^ edx1;
higt = higt - ebp0;
higt = higt - esi2;
*a = higt;
}
至于还原精灵6.0 以上版本及还原精灵网络版6.x的算法也是一样(至少目前为止),
只是加密的字符串不一样.
例如:
解还原精灵网络版 6.02(目前应该算是最新版吧)的密码,只要将上面的代码中的
字符串 "NJYZ-RG-60-TT-60" 替换为 "NJZY-NetCard-V60" 即可.
实际上解还原精灵6.0密码可以直接用内存注册机来解,在 0041616C 出中断,
EAX 指向密码地址(一定要先结束掉还原精灵的进程),网络版的无此BUG.
还原精灵各个版本一般都是把密码的明文或密文写在 0 磁道 8 扇区
偏移量为 04FH,该扇区并没有什么特殊保护,可以直接用 CreateFile 进行读写.
转载JUJU猫宽带宝藏论坛
我也不知道他是原还是转不过加密算法可以借鉴的
页:
[1]