吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9657|回复: 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] 纯文本查看 复制代码
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] 纯文本查看 复制代码
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] 纯文本查看 复制代码
;接下来,这三个双字存储的浮点数为字符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] 纯文本查看 复制代码
;从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] 纯文本查看 复制代码
;[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, 2024-12-22 16:31

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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