吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9900|回复: 15
收起左侧

[原创] 160个CrackMe练手之012

[复制链接]
Pnmker 发表于 2015-5-27 23:10
本帖最后由 Pnmker 于 2015-5-27 23:12 编辑

160CrackMe练手之012

Pnmker

    当当当,期待已久的012破文终于面世了。这个CM技术上的难点不多,只因其程序格式不是主流PE之类的格式,看似破之颇有难度,其实非也。尽管如此,这篇破文中不会给出详细的跟踪步骤,而代替的是反汇编的静态分析。

    主要讲述静态分析,并不意味着动态跟踪就不重要。之所以把跟踪忽略掉,一方面是跟踪调试技术大家都很熟练,另一方面这个CM对调试技术的要求也不高(前面已有朋友提及),最重要的我认为对于想要成为大牛的新手来说,要精通掌握破解逆向唯耐心不破。相对动态跟踪来说,静态分析更加考验个人的耐心与耐力,尤其是对于新手,在其学习的道路上考验更加之多。
       所以此文仍然仅献给那些奔走在成为大牛之路上的新手们。大牛们如果认为写得不好可以无视。
       对于这个CM的前期工作这里简单带过一下,只因它是比较古老的16NE格式,我可是废了不少的周折。尽管之前已经有朋友提起过,在我拿到这个程序的时候没有想起。直到把它拖到PEiD上提示“不是有效的PE文件”才模糊记起来,于是拿资源工具ResScope检测一下果然是16 NE。不多想了,直接上W32DAsm找程序中可能使用到的Windows API中有关的弹窗函数调用,确实找到了MessageBox,立即TRW2000bpx MessageBox下断跑起来。咦,竟然没断下来!嗯,好吧,再试一下其它的bpxdialogbox, bpx dialogboxparam,bpx createwindow,这么奇怪一个都没断下来!这时突然想起来这个程序是TPascal的,跟Delphi同出一家,估计这些函数都是不能断下来的。(不要告诉我使用万能断点 bpxhmemcpy,我在学习如果使用了它很多经验就没法获得了。)而且看W32DAsm的反汇编是不太可能的了,很多代码的段偏移地址跟TRW2000都对应不上。于是返回去看我已经发过的关于16位的帖子,记得是有朋友提过使用IDA的。好吧,IDA隆重上场了,果然是神器!整个的反汇编连函数名都给出了,如果不确定的函数/过程,则使用sub_前缀顺序编号,反汇编中的函数调用关系也十分详细。大概浏览了一遍发现有几个重要的函数MessageDlg,MessageDlgPos, CreateMessageDialog可能跟弹窗有关,bpx这几个函数名是断不下来的(当时估计可能不是导出函数的原因吧)。细看CreateMessageDialog里面有调用USER模块的DRAWTEXT,果断bpx DRAWTEXT!啊哈,断下来了,Delphi果然可以不用调用Windows的经典弹窗API,但谁让你运行在Windows系统上呢,某些底层实现始终不能绕开Windows啊,这不DRAWTEXT不就是一个可以断下来的吗。循着这个断点层层追踪,不费吹灰之力就找到了“CheckIt"按钮的点击处理事件的处理过程,在IDA里面的地址是cseg01:01F4。由于TRW2000每次载入程序的时候,代码段寄存器的基址可能都不一样,所以只需每次载入断在程序入口的时候bpx cs:01F4就行了。查了下看雪论坛的TRW2000操作手册,使用u cs:01F4 >aa.txt导出了反汇编代码。下面的工作主要是静态分析反汇编了,不确定的地方在针对性下断确认。
       这段反汇编代码490行左右,不像之前朋友说的只有十几行。我逐部分按代码在做什么讲下就OK了,至于细节有兴趣的朋友个人去分析和跟踪吧。
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
220F:01F4 PUSH BP[/align][align=left]220F:01F5 MOV BP,SP
220F:01F7 MOV AX,050E
220F:01FA CALL 270B       ;__StackCheck(Word)
220F:01FF SUB SP,050E       
 
220F:0203 LEA DI,[BP-40E]
220F:0207 PUSH SS
220F:0208 PUSH DI ;
220F:0209 LES DI,[BP+06]
220F:020C LES DI,[ES:DI+0188]
220F:0211 PUSH ES       ;
220F:0212 PUSH DI       
220F:0213 CALL 1D53 ;TControl::GetText(void)
220F:0218 ADD SP,BYTE +04 ;
220F:021B CMP BYTE [BP-40E],00 ;输入的Password的长度
220F:0220 JNZ 0225 ;长度不为0获取成功
220F:0222 JMP 0781 ;长度为0直接退出,0781是函数结尾

上面这段主要是做了堆栈检查和判断输入文本的长度,非常简单不多说。

[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
220F:0225  MOV      BYTE [BP-30D],01  ;
220F:022A  MOV      BYTE [BP-100],00  ;
220F:022F  XOR      AX,AX
220F:0231  MOV      [BP-104],AX       ;
220F:0235  MOV      BYTE [BP-204],00  ;
220F:023A  XOR      AX,AX
220F:023C  MOV      [BP-306],AX       ;
220F:0240  MOV      WORD [BP-30C],00  ;
220F:0246  MOV      WORD [BP-30A],00  ;
220F:024C  MOV      WORD [BP-308],00  ;以上几行都是对局部变量的初始化
 
220F:0252  LEA      DI,[BP-40E]                  ; 获取输入的Password存入[BP-40E]
220F:0256  PUSH     SS
220F:0257  PUSH     DI
220F:0258  LES      DI,[BP+06]
220F:025B  LES      DI,[ES:DI+0188]
220F:0260  PUSH     ES
220F:0261  PUSH     DI
220F:0262  CALL     1D53               ;TControl:GetText(void)
                                                                                ;
220F:0267  LEA      DI,[BP-100]        ;将[BP-40E]的Password复制到[BP-100]
220F:026B  PUSH     SS
220F:026C  PUSH     DI
220F:026D  PUSH     WORD FF
220F:0270  CALL     34C7               ; In IDA : operator=(String &,String &,Byte),
 
220F:0275  LEA      DI,[BP-100]        ;将[BP-100]再复制到[BP-304一份]
220F:0279  PUSH     SS                                       ;因此程序一开头[BP-40E],[BP-100],[BP-304]存放都是Password
220F:027A  PUSH     DI                                       ;当然后面[BP-40E] ,[BP-100]有发生变化
220F:027B  LEA      DI,[BP-304]
220F:027F  PUSH     SS
220F:0280  PUSH     DI
220F:0281  PUSH     WORD FF
220F:0284  CALL     34C7                           ; operator=(String &,String &,Byte)
 
220F:0289  MOV      AL,[BP-100]                   ; [BP-100]为输入文本的长度,注意Pascal/Delphi存放字符串的方式是
220F:028D  XOR      AH,AH                               ;首地址第一个字节给出文本长度,后面紧接着就是文本(超过0xFF(255d)咋办呢?)
220F:028F  MOV      [BP-306],AX        ;
220F:0293  MOV      WORD [BP-30C],00   ;置为0,其实这三个连续双字是存放浮点数的
220F:0299  MOV      WORD [BP-30A],00   ;
220F:029F  MOV      WORD [BP-308],00   ;
220F:02A5  MOV      AX,[BP-306]        ;
220F:02A9  MOV      [BP-310],AX        ; 文本长度
220F:02AD  MOV      AX,01
220F:02B0  CMP      AX,[BP-310]        ;
220F:02B4  JG       0308               ; 如果文本长度<1,直接跳转;长度大于0不跳转的,从220F:02B6
                                                                                ;到220F:0306是在求所有的字符ASCII码之和
220F:02B6  MOV      [BP-104],AX                   ;[BP-104]为求和的循环变量
220F:02BA  JMP      SHORT 02C0
220F:02BC  INC      WORD [BP-104]      ;
220F:02C0  MOV      AX,[BP-30C]                   ;正如上面所说,这三个连续双字为浮点数,程序中存放的是字符ASCII码之和
220F:02C4  MOV      BX,[BP-30A]        ;
220F:02C8  MOV      DX,[BP-308]        ;
220F:02CC  CALL     2CEE                   ;Extended(Real),将通用寄存器中的浮点数(IEE?)转换为
                                                                                ;浮点数寄存器FPU运算支持的扩展实数
220F:02D1  MOV      DI,[BP-104]        ;
220F:02D5  MOV      AL,[BP+DI-100]     ;
220F:02D9  XOR      AH,AH
220F:02DB  XOR      DX,DX
220F:02DD  MOV      [BP-314],AX        ;
220F:02E1  MOV      [BP-312],DX        ;
220F:02E5  NOP    
220F:02E6  FILD     DWORD [BP-314]     ;以上为将Password的逐个字符作为浮点数载入FPU寄存器栈顶st(0)
220F:02EA  NOP                                                    ;此时st(1)就是上次循环所求的和
220F:02EB  FADDP    ST1                                       ;相加,st(0)同时出战
220F:02ED  CALL     2D18               ;Real(Extended),FPU扩展实数转换为通用寄存器实数(IEE)
220F:02F2  MOV      [BP-30C],AX                   ;
220F:02F6  MOV      [BP-30A],BX                       ;
220F:02FA  MOV      [BP-308],DX        ;此次循环所求得的和数
220F:02FE  MOV      AX,[BP-104]
220F:0302  CMP      AX,[BP-310]        ;循环控制
220F:0306  JNZ      02BC


上面这段主要工作有局部变量初始化、输入的Password拷贝三份和对输入文本进行ASCII码求和。

[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
;接下来,这三个双字存储的浮点数为字符ASCII码的和
;以下因为涉及到比较复杂的数学运算,并且使用到了两个全局浮点数变量,所以在此规定记:
;1.输入Password的文本长度为len,
;2.字符ASCII码之和为sum(浮点数存储)
;3.[CS:01C3]存储的全局浮点数0.296439,记为d1
;4.[CS:01CD]存储的全局浮点数1294.39894,记为d2
;另对于FPU浮点数寄存器栈不熟的,请仔细查阅相关资料
220F:0308  MOV      AX,[BP-30C]    ;
220F:030C  MOV      BX,[BP-30A]           ;
220F:0310  MOV      DX,[BP-308]    ;
220F:0314  CALL     2CEE           ;Extended(Real),sum转FPU扩展实数
220F:0319  NOP    
220F:031A  FSTP     TWORD [BP-322] ;将sum转存到[BP-322]
220F:031E  MOV      AX,[BP-30C]
220F:0322  MOV      BX,[BP-30A]
220F:0326  MOV      DX,[BP-308]
220F:032A  CALL     2CEE           ;Extended(Real),sum转FPU扩展实数
220F:032F  NOP    
220F:0330  FLD      TWORD [CS:01C3] ; d1载入FPU寄存器栈顶st(0)
220F:0335  NOP    
220F:0336  FMULP    ST1                               ;求得乘积sum * d1,并将栈顶元素d1退栈
220F:0338  CALL     2DC4           ;sqrt(double),求平方根 sqrt(sum*d1)
220F:033D  NOP    
220F:033E  FSTP     TWORD [BP-318] ;存储sqrt(sum*d1)
220F:0342  MOV      AX,[BP-30C]
220F:0346  MOV      BX,[BP-30A]
220F:034A  MOV      DX,[BP-308]
220F:034E  CALL     2CEE           ;Extended(Real),sum转FPU扩展实数
220F:0353  NOP    
220F:0354  FLD      TWORD [CS:01CD]       ;d2载入FPU寄存器栈顶st(0)
220F:0359  CALL     2799           ;FSafeDivide(void),浮点数除法sum/d2
220F:035E  CALL     2DD4                       ;Ln(Extended),求自然对数:ln(sum/d2)
220F:0363  NOP    
220F:0364  FLD      TWORD [BP-318] ; 载入220F:033E处存在[BP-318]的计算结果sqrt(sum*d1)到FPU栈顶st(0)
220F:0368  NOP    
220F:0369  FADDP    ST1            ; 求和sqrt(sum*d1)+ln(sum/d2)
220F:036B  NOP    
220F:036C  FLD      TWORD [BP-322] ; 将220F:031出存在[BP-322]的sum载入到FPU栈顶st(0)
220F:0370  NOP    
220F:0371  FMULP    ST1                           ; 求乘积sum * (sqrt(sum*d1)+ln(sum/d2)),栈顶元素退栈
220F:0373  NOP    
220F:0374  FSTP     TWORD [BP-336] ;存储sum * (sqrt(sum*d1)+ln(sum/d2))
220F:0378  NOP    
220F:0379  FILD     WORD [BP-306]  ;将220F:028F处存在[BP-306]的len载入到FPU栈顶st(0)
220F:037D  CALL     2DC8                       ;Sin(Extended),求正弦, sin(len)
220F:0382  NOP    
220F:0383  FSTP     TWORD [BP-32C] ; 存储sin(len)
220F:0387  MOV      AX,[BP-30C]
220F:038B  MOV      BX,[BP-30A]
220F:038F  MOV      DX,[BP-308]
220F:0393  CALL     2CEE           ;Extended(Real),sum转FPU扩展实数
220F:0398  NOP    
220F:0399  FILD     WORD [BP-306]  ; len
220F:039D  NOP    
220F:039E  FMULP    ST1            ;乘积, sum*len
220F:03A0  CALL     2DCC                       ; Cos(Extended),求余弦cos(sum*len)
220F:03A5  NOP    
220F:03A6  FLD      TWORD [BP-32C] ; 将220F:0383存储在[BP-32C]的sin(len)载入到FPU栈顶st(0)
220F:03AA  NOP    
220F:03AB  FMULP    ST1                               ; 求乘积sin(len)*cos(sum*len)
220F:03AD  NOP    
220F:03AE  FLD      TWORD [BP-336] ;将220F:0374存储在[BP-336]的计算结果sum * (sqrt(sum*d1)+ln(sum/d2))载入FPU栈顶st(0)
220F:03B2  NOP    
220F:03B3  FADDP    ST1                               ;求和得sum * (sqrt(sum*d1)+ln(sum/d2))+sin(len)*cos(sum*len
220F:03B5  CALL     2DCC                       ;Cos(Extended)求余弦得 cos(sum * (sqrt(sum*d1)+ln(sum/d2))+sin(len)*cos(sum*len))
220F:03BA  CALL     2D18           ;Real(Extended),FPU扩展实数转换为通用寄存器实数(IEE)
220F:03BF  MOV      [BP-30C],AX
220F:03C3  MOV      [BP-30A],BX
220F:03C7  MOV      [BP-308],DX    ;将计算结果cos(sum * (sqrt(sum*d1)+ln(sum/d2))+sin(len)*cos(sum*len))存储在此三个双字
 
;下面这小段主要是将计算结果cos(sum * (sqrt(sum*d1)+ln(sum/d2))+sin(len)*cos(sum*len))
;转换为了使用科学计数法的字符串,总长度0x17,例如我输入Password为pnmker的时候转换为的字符串(注意正数有一个前导空格)
;为“ 7.87999800586476E-0001”
220F:03CB  MOV      AX,[BP-30C]
220F:03CF  MOV      BX,[BP-30A]
220F:03D3  MOV      DX,[BP-308]
220F:03D7  CALL     2CEE           ;Extended(Real),计算结果转FPU扩展实数
220F:03DC  PUSH     BYTE +17       ;0x17,表示字符串的总长度吗???
220F:03DE  PUSH     BYTE -01       ;难点是一个枚举值,表示转为科学计数法
220F:03E0  LEA      DI,[BP-100]    ;科学计数法的字符串存储在此
220F:03E4  PUSH     SS
220F:03E5  PUSH     DI
220F:03E6  PUSH     WORD FF
220F:03E9  CALL     37A7           ; Str(Extended,Word,Word,String &,Word),转为字符串
220F:03EE  MOV      WORD [BP-30C],00
220F:03F4  MOV      WORD [BP-30A],00
220F:03FA  MOV      WORD [BP-308],00 ;清零

上面这段个人认为比较复杂的一段,不过从IDA的反汇编上来看也不难,主要进行了一系列复杂的数学运算求得了结果cos(sum *(sqrt(sum*d1)+ln(sum/d2))+sin(len)*cos(sum*len)),并将其转换为了科学计数法的字符串

[Asm] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
;从220F:0400到220F:06B8这段挺长,看似吓人,其实做得事情很简单
;叙述方便期间做以下规定:(以输入pnmker为例)
;1.记输入Password在[BP-40E]处字符串首地址为P,则P[0]为字符串长度,P[1]='p',P[2]='n',...,P[6]='r'
;2.记存储在[BP-100]的科学计数法字符串首地址为Q,则Q[0]为字符串长度,Q[1]...Q[字符串长度]同1所述
;3.记[BP-50E]存储的字符串首地址记为R
;4.记[BP-204]存储的字符串首地址记为S
;5.记程序开始存储在[BP-40E] 的输入Password的首地址为K;
;那么最终[BP-204]的字符串即为所求,其计算公式如下:
;S[0]=0x9,字符串长度
;S[1]=Q[0x2]+0xA;         S[2]= Q[0x8]+0x3C; S[3]=Q[0x11]+0x30
;S[4]=Q[0x10]+0x2A; S[5]=Q[0xF]+0x35;  S[6]=Q[0xE]+0x2C
;S[7]=Q[0xD]+0x2F;  S[8]=Q[0xC]-0x15;  S[9]=Q[0x3]-0xD
220F:0400  MOV      AL,[BP-100]                            ;Q[0]字符串长度
220F:0404  XOR      AH,AH
220F:0406  CMP      AX,01
220F:0409  JNL      040E           
220F:040B  JMP      06BB                                   ;如果Q[0]=1直接跳转到06BB
 
220F:040E  MOV      [BP-104],AX                            ;[BP-104]存储Q字符串的逆序逐个字符遍历的循环变量
220F:0412  JMP      SHORT 0418
220F:0414  DEC      WORD [BP-104]                               ;逆序遍历字符
 
220F:0418  CMP      WORD [BP-104],BYTE +12     ;
220F:041D  JNZ      0465
220F:041F  LEA      DI,[BP-50E]                ;将字符串S赋给R
220F:0423  PUSH     SS
220F:0424  PUSH     DI
220F:0425  LEA      DI,[BP-204]
220F:0429  PUSH     SS
220F:042A  PUSH     DI
220F:042B  CALL     34AD                                          ; operator=(String &,String &)
220F:0430  LEA      DI,[BP-40E]                                   ;K,曾经为输入Password,注意经过此次处理K变成了只有一个字符的字符串!
220F:0434  PUSH     SS
220F:0435  PUSH     DI
220F:0436  MOV      AX,[BP-104]                                   ;AX=0x12,循环变量
220F:043A  SUB      AX,0A                                                 ;AX=0x12-0xA=0x8
220F:043D  MOV      DI,AX                                         ;DI=0x8
220F:043F  MOV      AL,[BP+DI-100]                                ;AL=Q[0x8]
220F:0443  XOR      AH,AH
220F:0445  ADD      AX,[BP-104]                                   ;AX=Q[0x8]+0x12
220F:0449  ADD      AX,2A                                         ;AX=Q[0x8]+0x12+0x2A=Q[0x8]+0x3C
220F:044C  PUSH     AX                                            ;
220F:044D  CALL     35C9                                          ; operator=(String &,Char), K[0]=1,K[1]=AX,K只有一个字符了
220F:0452  CALL     352C                                          ; Concat(String &,String &), R=R + K
220F:0457  LEA      DI,[BP-204]                ;将字符串R赋给S
220F:045B  PUSH     SS
220F:045C  PUSH     DI
220F:045D  PUSH     WORD FF
220F:0460  CALL     34C7                                                  ; operator=(String &,String &,Byte) , S=R
 
220F:0465  CMP      WORD [BP-104],BYTE +11
220F:046A  JNZ      04A9
220F:046C  LEA      DI,[BP-50E]                ;将字符串S赋给R
220F:0470  PUSH     SS
220F:0471  PUSH     DI
220F:0472  LEA      DI,[BP-204]
220F:0476  PUSH     SS
220F:0477  PUSH     DI
220F:0478  CALL     34AD                                          ; operator=(String &,String &)
220F:047D  LEA      DI,[BP-40E]                                   ;K,此处K只有一个字符
220F:0481  PUSH     SS
220F:0482  PUSH     DI
220F:0483  MOV      DI,[BP-104]                                   ;DI=0x11
220F:0487  MOV      AL,[BP+DI-100]                                ;AL=Q[0x11]
220F:048B  XOR      AH,AH                       
220F:048D  ADD      AX,30                                               ;AX=Q[0x11]+0x30
220F:0490  PUSH     AX                                                       ;
220F:0491  CALL     35C9                                          ; operator=(String &,Char), K[0]=1,K[1]=AX
220F:0496  CALL     352C                                          ; Concat(String &,String &), R = R + K
220F:049B  LEA      DI,[BP-204]                ;将字符串R赋给S
220F:049F  PUSH     SS
220F:04A0  PUSH     DI
220F:04A1  PUSH     WORD FF
220F:04A4  CALL     34C7                                                  ; operator=(String &,String &,Byte)
 
220F:04A9  CMP      WORD [BP-104],BYTE +10
220F:04AE  JNZ      04F1
220F:04B0  LEA      DI,[BP-50E]                ;将字符串S赋给R
220F:04B4  PUSH     SS
220F:04B5  PUSH     DI
220F:04B6  LEA      DI,[BP-204]
220F:04BA  PUSH     SS
220F:04BB  PUSH     DI
220F:04BC  CALL     34AD                                          ; operator=(String &,String &)
220F:04C1  LEA      DI,[BP-40E]                                       ; K只有一个字符了
220F:04C5  PUSH     SS
220F:04C6  PUSH     DI
220F:04C7  MOV      DI,[BP-104]                                       ; DI=0x10
220F:04CB  MOV      AL,[BP+DI-100]                               ; AL=Q[0x10]
220F:04CF  XOR      AH,AH
220F:04D1  ADD      AX,[BP-104]                                       ; AX = Q[0x10]+0x10
220F:04D5  ADD      AX,1A                                               ; AX = Q[0x10]+0x10+0x1A=Q[0x10]+0x2A
220F:04D8  PUSH     AX
220F:04D9  CALL     35C9                                          ; operator=(String &,Char), K[0]=1, K[1]=AX
220F:04DE  CALL     352C                                          ; Concat(String &,String &),R=R+K
220F:04E3  LEA      DI,[BP-204]                                       ;将字符串R赋给S
220F:04E7  PUSH     SS
220F:04E8  PUSH     DI
220F:04E9  PUSH     WORD FF
220F:04EC  CALL     34C7                                                  ; operator=(String &,String &,Byte)
 
220F:04F1  CMP      WORD [BP-104],BYTE +0F
220F:04F6  JNZ      0541
220F:04F8  LEA      DI,[BP-50E]                                       ;将字符串S赋给R
220F:04FC  PUSH     SS
220F:04FD  PUSH     DI
220F:04FE  LEA      DI,[BP-204]
220F:0502  PUSH     SS
220F:0503  PUSH     DI
220F:0504  CALL     34AD                                      ; operator=(String &,String &)
220F:0509  LEA      DI,[BP-40E]                                       ; K只有一个字符了
220F:050D  PUSH     SS
220F:050E  PUSH     DI
220F:050F  MOV      AX,[BP-104]                                       ; AX=0xF
220F:0513  MUL      WORD [BP-104]                               ; AX=0xF*0xF=0xE1
220F:0517  MOV      DX,AX                                               ; DX=0xE1
220F:0519  MOV      DI,[BP-104]                                       ; DI=0xF
220F:051D  MOV      AL,[BP+DI-100]                               ; AL=Q[0xF]
220F:0521  XOR      AH,AH
220F:0523  ADD      AX,DX                                               ;AX = Q[0xF]+0xE1
220F:0525  SUB      AX,0ACh                                               ;AX = Q[0xF]+0xE1-0xAC=Q[0xF]+0x35
220F:0528  PUSH     AX
220F:0529  CALL     35C9                                          ; operator=(String &,Char), K[0]=1,K[1]=AX
220F:052E  CALL     352C                                          ; Concat(String &,String &) ,R=R+K
220F:0533  LEA      DI,[BP-204]                                       ;将字符串R赋给S
220F:0537  PUSH     SS
220F:0538  PUSH     DI
220F:0539  PUSH     WORD FF
220F:053C  CALL     34C7                                                  ; operator=(String &,String &,Byte)
 
220F:0541  CMP      WORD [BP-104],BYTE +0E
220F:0546  JNZ      0589
220F:0548  LEA      DI,[BP-50E]                                        ;将字符串S赋给R
220F:054C  PUSH     SS
220F:054D  PUSH     DI
220F:054E  LEA      DI,[BP-204]
220F:0552  PUSH     SS
220F:0553  PUSH     DI
220F:0554  CALL     34AD                                     ; operator=(String &,String &)
220F:0559  LEA      DI,[BP-40E]                                  ; K只有一个字符了
220F:055D  PUSH     SS
220F:055E  PUSH     DI
220F:055F  MOV      DI,[BP-104]               ;DI=0xE
220F:0563  MOV      AL,[BP+DI-100]                          ;AL=Q[0xE]
220F:0567  XOR      AH,AH
220F:0569  ADD      AX,[BP-104]                                  ;AX=Q[0xE]+0xE
220F:056D  ADD      AX,1E                                          ;AX=Q[0xE]+0xE+0x1E=Q[0xE]+0x2C
220F:0570  PUSH     AX
220F:0571  CALL     35C9                                     ; operator=(String &,Char), K[0]=1,K[1]=AX
220F:0576  CALL     352C                      ; Concat(String &,String &) ,R=R+K
220F:057B  LEA      DI,[BP-204]               ;将字符串R赋给S
220F:057F  PUSH     SS                        
220F:0580  PUSH     DI                        
220F:0581  PUSH     WORD FF                   
220F:0584  CALL     34C7                                          ; operator=(String &,String &,Byte)
 
220F:0589  CMP      WORD [BP-104],BYTE +0D
220F:058E  JNZ      05DA
220F:0590  LEA      DI,[BP-50E]                                  ;将字符串S赋给R
220F:0594  PUSH     SS
220F:0595  PUSH     DI
220F:0596  LEA      DI,[BP-204]
220F:059A  PUSH     SS
220F:059B  PUSH     DI
220F:059C  CALL     34AD                                     ; operator=(String &,String &)
220F:05A1  LEA      DI,[BP-40E]                                  ; K只有一个字符了
220F:05A5  PUSH     SS
220F:05A6  PUSH     DI
220F:05A7  MOV      AX,[BP-104]               ; AX=0xD
220F:05AB  CWD    
220F:05AC  IDIV     WORD [BP-104]                          ; AX=0xD/0xD=0x1
220F:05B0  MOV      DX,AX                                          ; DX=AX=0x1
220F:05B2  MOV      DI,[BP-104]                                  ;
220F:05B6  MOV      AL,[BP+DI-100]                          ; AL=Q[0xD]
220F:05BA  XOR      AH,AH                                          
220F:05BC  ADD      AX,DX                                          ; AL=Q[0xD]+0x1
220F:05BE  ADD      AX,2E                                          ; AX=Q[0xD]+0x1+0x2E=Q[0xD]+0x2F
220F:05C1  PUSH     AX
220F:05C2  CALL     35C9                                     ; operator=(String &,Char), K[0]=1,K[1]=AX
220F:05C7  CALL     352C                                     ; Concat(String &,String &) ,R=R+K
220F:05CC  LEA      DI,[BP-204]               ;将字符串R赋给S
220F:05D0  PUSH     SS                        
220F:05D1  PUSH     DI                        
220F:05D2  PUSH     WORD FF                   
220F:05D5  CALL     34C7                                  ; operator=(String &,String &,Byte)
 
220F:05DA  CMP      WORD [BP-104],BYTE +0C
220F:05DF  JNZ      0622
220F:05E1  LEA      DI,[BP-50E]                                  ;将字符串S赋给R
220F:05E5  PUSH     SS
220F:05E6  PUSH     DI
220F:05E7  LEA      DI,[BP-204]
220F:05EB  PUSH     SS
220F:05EC  PUSH     DI
220F:05ED  CALL     34AD                                     ; operator=(String &,String &)
220F:05F2  LEA      DI,[BP-40E]                                  ; K只有一个字符了
220F:05F6  PUSH     SS
220F:05F7  PUSH     DI
220F:05F8  MOV      DI,[BP-104]                                  ; DI=0xC
220F:05FC  MOV      AL,[BP+DI-100]                          ; AL=Q[0xC]
220F:0600  XOR      AH,AH
220F:0602  ADD      AX,[BP-104]                                  ; AX=Q[0xC]+0xC
220F:0606  SUB      AX,21                                          ; AX=Q[0xC]+0xC-0x21=Q[0xC]-0x15
220F:0609  PUSH     AX
220F:060A  CALL     35C9                                     ; operator=(String &,Char), K[0]=1,K[1]=AX
220F:060F  CALL     352C                                     ; Concat(String &,String &) ,R=R+K
220F:0614  LEA      DI,[BP-204]               ;将字符串R赋给S
220F:0618  PUSH     SS                        
220F:0619  PUSH     DI                        
220F:061A  PUSH     WORD FF                   
220F:061D  CALL     34C7                                          ; operator=(String &,String &,Byte)
 
220F:0622  CMP      WORD [BP-104],BYTE +02
220F:0627  JNZ      0667
220F:0629  LEA      DI,[BP-40E]                                  ; K只有一个字符了
220F:062D  PUSH     SS
220F:062E  PUSH     DI
220F:062F  MOV      AX,[BP-104]                                  ; AX=0x2               
220F:0633  MUL      WORD [BP-104]                          ; AX=0x2*0x2=0x4
220F:0637  MOV      DX,AX                                          ; DX=0x4
220F:0639  MOV      DI,[BP-104]
220F:063D  MOV      AL,[BP+DI-100]                          ; AL=Q[0x2]
220F:0641  XOR      AH,AH
220F:0643  ADD      AX,DX                                          ; AX=Q[0x2]+0x4
220F:0645  ADD      AX,06                                          ; AX=Q[0x2]+0x4+0x6=Q[0x2]+0xA
220F:0648  PUSH     AX
220F:0649  CALL     35C9                      ; operator=(String &,Char), K[0]=1,K[1]=AX
220F:064E  LEA      DI,[BP-204]                                  
220F:0652  PUSH     SS
220F:0653  PUSH     DI
220F:0654  CALL     352C                                     ; Concat(String &,String &), K = K + S, K最后又发生变化
220F:0659  LEA      DI,[BP-204]
220F:065D  PUSH     SS
220F:065E  PUSH     DI
220F:065F  PUSH     WORD FF
220F:0662  CALL     34C7                                          ; operator=(String &,String &,Byte), S=K
 
220F:0667  CMP      WORD [BP-104],BYTE +0A
220F:066C  JNZ      06B1
220F:066E  LEA      DI,[BP-50E]                                  ;将字符串S赋给R
220F:0672  PUSH     SS
220F:0673  PUSH     DI
220F:0674  LEA      DI,[BP-204]
220F:0678  PUSH     SS
220F:0679  PUSH     DI
220F:067A  CALL     34AD                                     ; operator=(String &,String &)
220F:067F  LEA      DI,[BP-40E]                                  ; K只有一个字符了
220F:0683  PUSH     SS
220F:0684  PUSH     DI
220F:0685  MOV      AX,[BP-104]               ; AX=0xA
220F:0689  SHL      AX,1                                          ; AX=0xA*2=0x14
220F:068B  SUB      AX,07                                          ; AX=0x14-0x7=0xD
220F:068E  MOV      DX,AX                                          ; DX=AX=0xD
220F:0690  MOV      AL,[BP-0FD]                                  ; (BP-0xFD)-(BP-0x100)=0x3, AL=Q[0x3]
220F:0694  XOR      AH,AH
220F:0696  SUB      AX,DX                                          ; AX=Q[0x3]-0xD
220F:0698  PUSH     AX
220F:0699  CALL     35C9                                     ; operator=(String &,Char), K[0]=1,K[1]=AX
220F:069E  CALL     352C                                     ; Concat(String &,String &) ,R=R+K
220F:06A3  LEA      DI,[BP-204]               ;将字符串R赋给S
220F:06A7  PUSH     SS                        
220F:06A8  PUSH     DI                        
220F:06A9  PUSH     WORD FF                   
220F:06AC  CALL     34C7                                             ; operator=(String &,String &,Byte)
220F:06B1  CMP      WORD [BP-104],BYTE +01
220F:06B6  JZ       06BB
220F:06B8  JMP      0414

上面这段完成了由科学计数法的字符串计算出一个新的9个字符的字符串,看似很长,相对来说还是简单的。

[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
;[BP-304]正如我们程序一开始所说保存的是输入的Password,记其首地址为W,其长度W[0]记为len
;[BP-204]字符串的首地址依然记为S,即其字符串长度S[0]位ls
;[BP-100]字符串的首地址依然记为Q
220F:06BB  MOV      AL,[BP-2FE]                  ;(BP-2FE)-(BP-304)=0x6, AL=W[0x6]
220F:06BF  XOR      AH,AH                        ;
220F:06C1  MOV      DX,AX                                 ;DX=W[6]
220F:06C3  MOV      AL,[BP-0FA]                         ;(BP-0FA)-(BP-100)=0x6, AL=Q[0x6]
220F:06C7  XOR      AH,AH                                 ;00
220F:06C9  ADD      AX,16                                 ;AX=Q[0x6]+0x16
220F:06CC  CMP      AX,DX                        ;W[6]  ?? Q[0x6]+0x16
220F:06CE  JZ       06D5                               ;这里必然要跳,因为从下面的分析看要保证BYTE [BP-30D]为1,
220F:06D0  MOV      BYTE [BP-30D],00
220F:06D5  MOV      AL,[BP-2FB]                   ;(BP-2FB)-(BP-304)=0x9, AL=W[0x9]
220F:06D9  XOR      AH,AH                               
220F:06DB  MOV      DX,AX                               ; DX = W[0x9]
220F:06DD  MOV      AL,[BP-0F9]                  ;(BP-0F9)-(BP-100)=0x7, AL=Q[0x7]
220F:06E1  XOR      AH,AH
220F:06E3  SHL      AX,1                               ;AX = Q[0x7]*2
220F:06E5  SUB      AX,09                               ;AX = Q[0x7]*2-0x9
220F:06E8  CMP      AX,DX                               ; W[0x9]   ??  Q[0x7]*2-0x9
220F:06EA  JZ       06F1                         ;这里必然要跳,因为从下面的分析看要保证BYTE [BP-30D]为1,
220F:06EC  MOV      BYTE [BP-30D],00
220F:06F1  MOV      AL,[BP-204]                       ; S[0]
220F:06F5  XOR      AH,AH
220F:06F7  MOV      [BP-310],AX        ;[BP-310]=S[0]=ls
220F:06FB  MOV      AX,01
220F:06FE  CMP      AX,[BP-310]
220F:0702  JG       072A               ;[BP-310]>1=AX,一定不跳转
220F:0704  MOV      [BP-104],AX        ;循环控制变量,初始[BP-306]为输入的Password长度,即len
220F:0708  JMP      SHORT 070E
220F:070A  INC      WORD [BP-104]      ;步进1
220F:070E  MOV      DI,[BP-104]                       
220F:0712  MOV      AL,[BP+DI-204]     ;S[DI]
220F:0716  XOR      AH,AH
220F:0718  ADD      AX,[BP-306]        ;
220F:071C  MOV      [BP-306],AX        
220F:0720  MOV      AX,[BP-104]
220F:0724  CMP      AX,[BP-310]                
220F:0728  JNZ      070A                               ;最终[BP-306]的值为 len + (S中所有字符之和)
 
220F:072A  MOV      AL,[BP-204]                       ;S[0],即S的长度ls
220F:072E  XOR      AH,AH
220F:0730  INC      AX                                       ;ls+1                               
220F:0731  SHL      AX,1                               ;(ls+1)*2
220F:0733  MOV      CX,AX                                ;(ls+1)*2
220F:0735  MOV      AL,[BP-0FB]                ;(BP-0FB)-(BP-100)=5, AL=Q[0x5]
220F:0739  XOR      AH,AH
220F:073B  SHL      AX,02                               ; Q[0x5]*4
220F:073E  MOV      DX,AX                               ;DX=Q[0x5]*4
220F:0740  MOV      AL,[BP-0FC]                ;(BP-0FC)-(BP-100)=4, AL=Q[0x4]
220F:0744  XOR      AH,AH
220F:0746  IMUL     AX,AX,BYTE +09               ;AX=Q[0x4]*9
220F:0749  ADD      AX,DX                               ;AX=Q[0x4]*9+Q[0x5]*4
220F:074B  ADD      AX,CX                               ;AX=Q[0x4]*9+Q[0x5]*4+(ls+1)*2
 
;下面的判断是程序的前面所有跳转的必经之路,到这里已经完全明朗了,必须满足
;1.(Q[0x4]*9+Q[0x5]*4+(ls+1)*2)与len + (S中所有字符之和)相等
;2.BYTE [BP-30D]必须为01,而此值程序初始化时已经设为1
;3.W[6] 等于 Q[0x6]+0x16
;4.W[0x9] 等于 Q[0x7]*2-0x9
;其中W为输入的Password,len为其长度
;Q为cos(sum * (sqrt(sum*d1)+ln(sum/d2))+sin(len)*cos(sum*len))的17位科学计数法字符串
;S为由Q计算得来的字符串,方法为
;S[0]=0x9,字符串长度, ls=9
;S[1]=Q[0x2]+0xA;         S[2]= Q[0x8]+0x3C; S[3]=Q[0x11]+0x30
;S[4]=Q[0x10]+0x2A; S[5]=Q[0xF]+0x35;  S[6]=Q[0xE]+0x2C
;S[7]=Q[0xD]+0x2F;  S[8]=Q[0xC]-0x15;  S[9]=Q[0x3]-0xD
;
220F:074D  CMP      AX,[BP-306]                 ; (Q[0x4]*9+Q[0x5]*4+(ls+1)*2) == len + (S中所有字符之和)
220F:0751  JNZ      076F                               ;
220F:0753  CMP      BYTE [BP-30D],01       ;这个条件
220F:0758  JNZ      076F
220F:075A  LEA      DI,[BP-204]
220F:075E  PUSH     SS
220F:075F  PUSH     DI
220F:0760  PUSH     BYTE +02
220F:0762  PUSH     BYTE +04
220F:0764  PUSH     BYTE +00
220F:0766  PUSH     BYTE +01
220F:0768  CALL     07BF                       ;MessageDlg
220F:076D  JMP      SHORT 0781
220F:076F  MOV      DI,01D7
220F:0772  PUSH     CS
220F:0773  PUSH     DI                          ;[CS:DI]='Invalid password. Try again'
220F:0774  PUSH     BYTE +02
220F:0776  PUSH     BYTE +04
220F:0778  PUSH     BYTE +00
220F:077A  PUSH     BYTE +01
220F:077C  CALL     07BF                  ;MessageDlg
220F:0781  LEAVE  
220F:0782  RETF     08

到这里程序已经明朗了,输入的Password需要满足的条件为:
1.(Q[0x4]*9+Q[0x5]*2+(ls+1)*2)len + (S中所有字符之和)相等
2.W[6] 等于 Q[0x6]+0x16
3.W[0x9] 等于 Q[0x7]*2-0x9
其中W为输入的Passwodlen为其长度
Qcos(sum * (sqrt(sum*d1)+ln(sum/d2))+sin(len)*cos(sum*len))17位科学计数法字符串
S为由Q计算得来的字符串,方法为
S[0]=0x9,字符串长度, ls=9
S[1]=Q[0x2]+0xA;       S[2]= Q[0x8]+0x3C;S[3]=Q[0x11]+0x30
S[4]=Q[0x10]+0x2A; S[5]=Q[0xF]+0x35; S[6]=Q[0xE]+0x2C
S[7]=Q[0xD]+0x2F; S[8]=Q[0xC]-0x15;  S[9]=Q[0x3]-0xD
整理的S中所有字符之和X=S[1]+S[2]+...+S[9]=
Q[0x02]+0x0A+ Q[0x08]+0x3C+Q[0x11]+0x30+ Q[0x10]+0x2A+ Q[0x0F]+0x35+
Q[0x0E]+0x2C+ Q[0x0D]+0x2F+Q[0x0C]-0x15+ Q[0x03]-0x0D
= Q[0x02]+ Q[0x03]+ Q[0x08]+ Q[0x0C]+ Q[0x0D]+ Q[0x0E]+ Q[0x0F]+ Q[0x10]+ Q[0x11]+
  0x0A+0x3C+0x30+0x2A+0x35+0x2C+0x2F-0x15-0x0D
=Q[2]+Q[3]+Q[8]+Q[12]+Q[13]+Q[14]+Q[15]+Q[16]+Q[17]+
10+60+48+42+53+44+47-21-13
= Q[2]+Q[3]+Q[8]+Q[12]+Q[13]+Q[14]+Q[15]+Q[16]+Q[17]+270

整理(Q[0x4]*9+Q[0x5]*4+(ls+1)*2)记为Y=9Q[4]+4Q[5]+20
X=Y,即
Q[2]+Q[3]+Q[8]+Q[12]+Q[13]+Q[14]+Q[15]+Q[16]+Q[17]+270=9Q[4]+4Q[5]+20
分析可知这个方程有解,因而可程序求解。

但是我遇到了一个困难,这CM跟踪调试是输入“pnmker”求得的Q字符串为
7.87999800586476E-0001”, 而我用32位程序去求解得出来结果却是
7.879980058627672e-001 ,先不要看准不准确,他们的精度在小数点后的第5位就已经出现差距了,即便我的程序能求出来拿到他上面也可能会有问题。
难道真的只能用16位去写这程序吗,而且数学运算库还必须得用Win87Em.dll?!!

有哪位大神使用过Win87Em.dll数学运算库的能告诉一下怎么使用吗?
c012_1.png c012_2.png



免费评分

参与人数 1热心值 +1 收起 理由
KaQqi + 1 已答复!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

cxj98 发表于 2015-5-29 14:52
这好像又是一枚大牛。
touyuan001 发表于 2015-5-29 14:29
Hmily 发表于 2015-5-28 15:33
16位的程序太少见了,学习。

每次看你的头像都有种莫名的喜感,请原谅我笑点低~~~~~~
asd9988 发表于 2015-5-27 23:36
touyuan001 发表于 2015-5-28 13:26
打死占广告位的~
Hmily 发表于 2015-5-28 15:33
16位的程序太少见了,学习。
如果我徘徊 发表于 2015-5-28 15:41
感谢分享。。
头像被屏蔽
hybmn 发表于 2015-5-29 00:55
提示: 作者被禁止或删除 内容自动屏蔽
brakefast 发表于 2015-5-29 23:58 来自手机
不错啊,感谢分享了~
越峥嵘越从容 发表于 2015-5-31 08:07
谢谢大家支持一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-5-18 15:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表