首页
社区
课程
招聘
ResScope1.92算法分析
2004-7-21 21:06 13379

ResScope1.92算法分析

2004-7-21 21:06
13379
ResScope,一个将比exeScope更强的软件资源分析工具,很不错的软件。

delphi程序,无壳无反调试无校验,我喜欢,:)。
通过字符串容易找到这里,很容易看到,读取注册表中的用户名和注册码,分别计算后进行再比较。
 
CODE:0051B6EB                 mov     cl, 1
CODE:0051B6ED                 mov     edx, offset aSoftwareRest_3 ; "SOFTWARE\\RESTOOLS\\ResScope"
CODE:0051B6F2                 mov     eax, [ebp+var_8]
CODE:0051B6F5                 call    @Registry@TRegistry@OpenKey$qqrx17System@AnsiStringo ; Registry::TRegistry::OpenKey(System::AnsiString,bool)
CODE:0051B6FA                 test    al, al
CODE:0051B6FC                 jz      loc_51B888
CODE:0051B702                 lea     eax, [ebp+var_C]
CODE:0051B705                 call    @System@@LStrClr$qqrr17System@AnsiString ; System::__linkproc__ LStrClr(System::AnsiString &)
CODE:0051B70A                 lea     eax, [ebp+var_10]
CODE:0051B70D                 call    @System@@LStrClr$qqrr17System@AnsiString ; System::__linkproc__ LStrClr(System::AnsiString &)
CODE:0051B712                 mov     edx, offset aReguser_2 ; "reguser"
CODE:0051B717                 mov     eax, [ebp+var_8]
CODE:0051B71A                 call    @Registry@TRegistry@ValueExists$qqrx17System@AnsiString ; Registry::TRegistry::ValueExists(System::AnsiString)
CODE:0051B71F                 test    al, al
CODE:0051B721                 jz      short loc_51B733
CODE:0051B723                 lea     ecx, [ebp+var_C]
CODE:0051B726                 mov     edx, offset aReguser_2 ; "reguser"
CODE:0051B72B                 mov     eax, [ebp+var_8]
CODE:0051B72E                 call    @TRegistry@ReadString$qqrx10AnsiString ; TRegistry::ReadString(AnsiString)
CODE:0051B733 
CODE:0051B733 loc_51B733:                             ; CODE XREF: sub_51B6A0+81j
CODE:0051B733                 mov     edx, offset aRegcode_1 ; "regcode"
CODE:0051B738                 mov     eax, [ebp+var_8]
CODE:0051B73B                 call    @Registry@TRegistry@ValueExists$qqrx17System@AnsiString ; Registry::TRegistry::ValueExists(System::AnsiString)
CODE:0051B740                 test    al, al
CODE:0051B742                 jz      short loc_51B754
CODE:0051B744                 lea     ecx, [ebp+var_10]
CODE:0051B747                 mov     edx, offset aRegcode_1 ; "regcode"
CODE:0051B74C                 mov     eax, [ebp+var_8]
CODE:0051B74F                 call    @TRegistry@ReadString$qqrx10AnsiString ; TRegistry::ReadString(AnsiString)
CODE:0051B754 
CODE:0051B754 loc_51B754:                             ; CODE XREF: sub_51B6A0+A2j
CODE:0051B754                 mov     eax, [ebp+var_10]
CODE:0051B757                 call    @System@@LStrLen ; System::__linkproc__ LStrLen
CODE:0051B75C                 cmp     eax, 30h
CODE:0051B75F                 jnz     loc_51B888
CODE:0051B765                 mov     eax, [ebp+var_C]
CODE:0051B768                 call    @System@@LStrLen ; System::__linkproc__ LStrLen
CODE:0051B76D                 test    eax, eax
CODE:0051B76F                 jle     loc_51B888
CODE:0051B775                 lea     eax, [ebp+var_14] ; 保存返回值
CODE:0051B775                                         ; 指向18字节长PCHAR
CODE:0051B778                 push    eax
CODE:0051B779                 mov     cl, 1
CODE:0051B77B                 mov     dl, 1
CODE:0051B77D                 mov     eax, [ebp+var_C] ; "reguser"
CODE:0051B780                 call    sub_51A06C      ; 处理用户名
CODE:0051B785                 mov     eax, [ebp+var_14] ; 处理用户名得到的18字节长的串,先入栈,待会好比较
CODE:0051B788                 push    eax
CODE:0051B789                 lea     ecx, [ebp+var_18] ; 保存返回值。。
CODE:0051B78C                 mov     dl, 1
CODE:0051B78E                 mov     eax, [ebp+var_10] ; "regcode"
CODE:0051B791                 call    sub_519298      ; 注册码变换函数
CODE:0051B796                 mov     edx, [ebp+var_18]
CODE:0051B799                 pop     eax
CODE:0051B79A                 call    @System@@LStrCmp$qqrv ; System::__linkproc__ LStrCmp(void)
CODE:0051B79F                 jnz     short loc_51B7A5 ; 

这个软件的爆破起来不是很容易
 
CODE:00525CBB                 mov     eax, ds:off_525214  ; * Reference to class THexDumpPass
CODE:00525CC0                 call    sub_425EEC      ; * Reference to: Classes.TComponent.Create(TComponent;boolean;TComponent);
CODE:00525CC5                 mov     ebx, eax
CODE:00525CC7                 lea     eax, [ebp+var_130]
CODE:00525CCD                 call    sub_518E18      ; 用户名进行变换转为一串字符
CODE:00525CD2                 mov     edx, [ebp+var_130]
CODE:00525CD8                 mov     eax, ebx
CODE:00525CDA                 mov     ecx, [eax]
CODE:00525CDC                 call    dword ptr [ecx+18h] ; Classes::TComponent::SetName()

在此处设置用户名变换而来得串设置组件名字,然后使用注册码变换而来得串来FindComponent(),如果注册码正确,两个串应该相等,则能得到正确的句柄,
保存起来,然后在校验注册时候使用该句柄,若没找到则例外出错。

下面来看看注册算法:
使用peid来探测一下用了什么算法,一下出来8种算法,够吓人,不过还有不少没探测出来,:)。
DEDE反汇编看看,注意到类名中有大量的类似TCipher_MD5、TCipher_Blowfish、TCipher_IDEA类似这样的类名,
熟悉的人一眼就看出来使用DEC控件,这是Hagen Reddmann写的Delphi Encryption Compendium 控件,控件支持20余种Hash,40多种分组密码算法,
而且附带源码,是很好的学习算法的教程。

在分析过程中可以用delphi编译一个小例子,然后跟踪看看,并参考源码效果很好。
先来看看处理用户名的函数
CODE:0051B780                 call    sub_51A06C      ; 处理用户名
用户ID的生成是调用CPUID指令获取cpu信息,然后编码至16字节。与用户名连接起来,通过简单算法变换为18h字节,
 
CODE:0051A0C3                 mov     edx, ds:dword_578440 ; 用户ID,类似"92F1L8EACT2FFNFF"一串字符。。。
CODE:0051A0C9                 call    @System@@LStrCat$qqrv ; System::__linkproc__ LStrCat(void)

CODE:0051A4A6                 push    offset unk_575B10 ; IVector,初始化向量
CODE:0051A4AB                 mov     edx, offset byte_575B08 ; keyCAST..64位密钥
CODE:0051A4B0                 lea     eax, [ebp+var_F4_TCast128Data] ; 0012FAF8
CODE:0051A4B0                                         ;   TCast128Data= record
CODE:0051A4B0                                         ;     InitBlock: array[0..7] of byte;    { initial IV }
CODE:0051A4B0                                         ;     LastBlock: array[0..7] of byte;    { current IV }
CODE:0051A4B0                                         ;     xKey: array[0..31] of DWord;
CODE:0051A4B0                                         ;     Rounds: integer;
CODE:0051A4B0                                         ;   end;
CODE:0051A4B6                 mov     ecx, 8          ; sizeof(Key)
CODE:0051A4BB                 call    Cast128Init     ; 注意此处Cast128非调用DEC的函数,乃是独立的类。
                                                      ; 注意其sbox乃是作者随机生成


采用CBC模式调用Cast128算法,即密码分组链接模式即每次分组加密结果,与下组明文xor后,作为输入。
 
CODE:0051A50E                 lea     edx, [ebp+eax+var_48] ; 输入串,输出也保存再该地址
CODE:0051A512                 lea     eax, [ebp+var_F4_TCast128Data] ; 密钥初始化结果
CODE:0051A518                 call    Cast128EncryptCBC ; procedure Cast128EncryptCBC(var Data: TCast128Data; InData, OutData: pointer);
CODE:0051A518                                         ;   { encrypts the data in a 64bit block using the CBC chaining mode }

下面就是调用DEC中的密码算法来进行加密
 
CODE:0051A6FB                 mov     edx, ds:off_4F31E0 ; Reference to class TCipher_3Way,这个可由DEDE反汇编代码中看到
CODE:0051A701                 mov     eax, [ebp+var_14]
CODE:0051A704                 call    @TCipherManager@@SetClass ; TCipherManager::__linkproc__ SetClass
CODE:0051A709                 xor     ecx, ecx
CODE:0051A70B                 mov     edx, [ebp+var_18]
CODE:0051A70E                 mov     eax, [ebp+var_14]
CODE:0051A711                 call    @TCipherManager@@InitKey ; procedure TCipherManager.InitKey(const Key: String; IVector: Pointer);
CODE:0051A716                 push    18h             ; 待Encode串长度
CODE:0051A718                 lea     ecx, [ebp+var_60] ; 返回串
CODE:0051A71B                 lea     edx, [ebp+var_48] ; Source串,由Cast128而来
CODE:0051A71E                 mov     eax, [ebp+var_14]
CODE:0051A721                 call    @TCipherManager@@EncodeBuffer ; procedure TCipherManager.EncodeBuffer
CODE:0051A721                                         ; (const Source; var Dest; DataSize: Integer);

下面级连的还有
 
CODE:0051A7F6                 mov     edx, ds:off_4F29DC ; * Reference to class TCipher_Blowfish  (注: pbox,sbox非标)
CODE:0051A8F1                 mov     edx, ds:off_4F2940 ; * Reference to class TCipher_Gost      (注: Gost_Data非标)
CODE:0051AA15                 mov     edx, ds:off_4F2A7C ; * Reference to class TCipher_IDEA
CODE:0051AB39                 mov     edx, ds:off_4F3144 ; * Reference to class TCipher_Q128      (注: Q128_Data非标)
CODE:0051AC5D                 mov     edx, ds:off_4F2B18 ; * Reference to class TCipher_SAFER     (注: DEC库中默认没有添加入列表,需修改代码注册该Cipher类到控件) 
CODE:0051AD58                 mov     edx, ds:off_4F2E34 ; * Reference to class TCipher_SAFER_K128
CODE:0051AE7C                 mov     edx, ds:off_4F2BB4 ; * Reference to class TCipher_SAFER_K40
CODE:0051AF77                 mov     edx, ds:off_4F2CF4 ; * Reference to class TCipher_SAFER_K64

对用户名的变换用了10种算法,不过调用DEC库格式比较标准,跟踪起来也什么困难.

下面看注册码变换算法
 
CODE:0051B791                 call    sub_519298      ; 注册码变换函数

注册码为30h字符,先解码后为18h字节数据,每2字符变换为一个字节
然后
CODE:005193C2                 push    offset unk_575AE0 ; GOST初始化向量
CODE:005193C7                 mov     edx, offset unk_575AE8 ; GOST密钥 20h字节
CODE:005193CC                 lea     eax, [ebp+var_98] ;   TGOSTData= record
CODE:005193CC                                         ;     InitBlock: array[0..7] of byte;    { initial IV }
CODE:005193CC                                         ;     LastBlock: array[0..7] of byte;    { current IV }
CODE:005193CC                                         ;     XKey: array[0..7] of DWord;
CODE:005193CC                                         ;   end;
CODE:005193D2                 mov     ecx, 20h
CODE:005193D7                 call    GOSTInit        ; procedure GOSTInit(var Data: TGOSTData; Key: pointer; Len: integer; IV: pointer
                                                      ; 注意此处Cast128非调用DEC的函数,乃是独立的类。其Gost_Data非标
      

同样采用CBC模式解码数据,每次处理8字节,共处理3次。
 
CODE:00519429                 lea     edx, [ebp+eax+var_50] ; 输出
CODE:0051942D                 lea     eax, [ebp+var_98] ; var Data: TGOSTData
CODE:00519433                 call    GOSTDecryptCBC  ; //procedure GOSTDecryptCBC(var Data: TGOSTData; InData, OutData: pointer);
CODE:00519433                                         ;   { decrypts the data in a 64bit block using the CBC chaining mode }
                  
同样下面级连了一串变换,不过此处调用的都是@TCipherManager@@DecodeBuffer,解码函数

 
CODE:005195FB                 mov     edx, ds:off_4F327C ; * Reference to class TCipher_Twofish    (注: Twofish_Data,Twofish_8x8值非标)
CODE:00519714                 mov     edx, ds:off_4F300C ; * Reference to class TCipher_TEAN
CODE:00519810                 mov     edx, ds:off_4F2F74 ; * Reference to class TCipher_TEA
CODE:0051990C                 mov     edx, ds:off_4F33B4 ; * Reference to class TCipher_Square
CODE:00519A2D                 mov     edx, ds:off_4F3318 ; * Reference to class TCipher_Shark
CODE:00519B29                 mov     edx, ds:off_4F30A8 ; * Reference to class TCipher_SCOP
CODE:00519C4A                 mov     edx, ds:off_4F2D94 ; * Reference to class TCipher_SAFER_SK64
CODE:00519D6B                 mov     edx, ds:off_4F2C54 ; * Reference to class TCipher_SAFER_SK40
CODE:00519E67                 mov     edx, ds:off_4F2ED4 ; * Reference to class TCipher_SAFER_SK128


最后将用户名变换输出结果和注册码变换输出进行比较。
对于1.75版只使用了Cast128和Gost两种算法,而1.92版堆叠了大概有18种密码学算法,
但由于该库格式又比较固定,总体说来所以不难做出注册机。基本上就照着作者的流程,用户名变换部分全部照抄,
注册码变换部分从后往前逆向使用。类似这样,只是把DecodeBuffer改为EncodeBuffer就可以了,类似
 
    CipherManager1.Algorithm := 'Twofish';
    CipherManager1.InitKey(keystr, nil);
    CipherManager1.EncodeBuffer(Source,Out,$18);

另外注意其中有些DEC库函数的s盒被更改,所以还需要修改DEC控件中的cipher.inc里面的值,重新编译该控件。

感谢DiKeN/IPB提供ResScope1.75注册机源码,省下了我不少时间,:)。

yesky1/IPB
7.21

[培训]《安卓高级研修班(网课)》月薪三万计划,掌 握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞7
打赏
分享
最新回复 (23)
雪    币: 239
活跃值: (220)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
mejy 3 2004-7-21 21:19
2
0
zan
雪    币: 896
活跃值: (4039)
能力值: ( LV9,RANK:3410 )
在线值:
发帖
回帖
粉丝
fly 85 2004-7-21 21:29
3
0
GOOD  :D
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wzdbzd 1 2004-7-21 22:02
4
0
最初由 yesky1 发布
这个软件的爆破起来不是很容易

55555555……我爆了一天啊,没爆掉!
雪    币: 2264
活跃值: (1885)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
benladen 2004-7-22 08:33
5
0
楼主说的对,我虽然爆破不用注册了,但是在使用时出现了资源保存错误的对话框(和1.90一样)。
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
平等 2004-7-22 10:58
6
0
1楼的,能不能发个注册机给我,谢谢。
wx_fengcw@163.com
雪    币: 223
活跃值: (106)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
temerata 1 2004-7-22 11:19
7
0
好不容易等到如此强帖啊!:D
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
nbw 24 2004-7-22 11:21
8
0
不愧是IPB的。俺不懂算法,看你这个很吓人
雪    币: 674
活跃值: (1684)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
daxia200N 6 2004-7-22 13:36
9
0
学习
雪    币: 367
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
DarkNess0ut 2004-7-22 14:06
10
0
:D 终于被你搞定了?
雪    币: 2264
活跃值: (1885)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
benladen 2004-7-22 15:55
11
0
这次的注册码破天荒的升为48位了,厉害。
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
forrest 2004-7-22 16:50
12
0
强人啊!
雪    币: 1126
活跃值: (156)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
DiKeN 5 2004-7-22 20:51
13
0
:)
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
www505ok 2004-7-22 21:16
14
0
请给兄弟们做个注册机,交流交流吧。
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
eCool 2004-7-22 22:34
15
0
强!:)
雪    币: 319
活跃值: (866)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
aqtata 2 2004-7-22 23:15
16
0
good
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
t1111 2004-7-23 00:47
17
0
good,好好学习
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Nnewell 2004-7-23 10:11
18
0
很久没来看雪了,一来就看到yesky1兄的佳作,gREAt:D
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Nnewell 2004-7-23 10:12
19
0
最初由 eCool 发布
强!:)

eCool成潜水大鄂了,N久未露面的说,想死偶了,哈哈哈...:D
雪    币: 214
活跃值: (70)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Arucuied 2004-7-23 10:12
20
0
最初由 Nnewell 发布
很久没来看雪了,一来就看到yesky1兄的佳作,gREAt:D


你的呢?;)
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Nnewell 2004-7-23 10:14
21
0
最初由 Arucuied 发布



你的呢?;)

发科右,马甲的说:D
雪    币: 291
活跃值: (400)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
草原猎豹 4 2004-7-26 00:20
22
0
天啊,看完还写不出注册机啊
偶好菜~~~~~~~~~
雪    币: 236
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sixfor 2004-8-10 13:59
23
0
学习中……
雪    币: 2264
活跃值: (1885)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
benladen 2004-8-10 14:39
24
0
破解版已出,没有任何问题。
游客
登录 | 注册 方可回帖
返回