首页
社区
课程
招聘
[分享]海狼三人组CrackMe分析过程
发表于: 2008-12-29 16:50 17075

[分享]海狼三人组CrackMe分析过程

2008-12-29 16:50
17075

【文章标题】: 海狼三人组CrackMe分析过程
【文章作者】: 书呆彭
【下载地址】: http://bbs.pediy.com/showthread.php?t=78925
【编写语言】: VB
【使用工具】: OD
【操作平台】: Windows XP x64 SP2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

----------------------8<-----------------------------------------------------------------------

【详细过程】
  通常,对于VB编译器生成的东西,我称之为“又臭又长”,不喜欢动它。
  
  幸好,有个VB Decompiler,能省去不少麻烦事。
  
  不过这个工具对于有些VB的程序不认识,比如这个CrackMe。所以,不得已,只能硬着头皮去看这“又臭又长”的代码了。
  
  
  这句是写完后补上的:写完后才发现实在是太长了,不知道有没有人愿意把它看完。
  

  书归正文,直入主题。
  
  
  整个分析过程有这么几个步骤

------------------------8<------------------------------------------------------------------------
  
  1.由于程序通过创建子进程来脱离调试的管辖,要先过了这一关。
  
  
  VB是UNICODE的,所以下W版本的API断点:
  
  bp CreateProcessW
  
  断下来,看堆栈:
  
  

  0013F584   660CCEBF  /CALL 到 CreateProcessW 来自 MSVBVM60.660CCEB9
  0013F588   00000000  |ModuleFileName = NULL
  0013F58C   0023BE74  |CommandLine = "F:\Debugee\Crack Me\021.exe"
  0013F590   00000000  |pProcessSecurity = NULL
  0013F594   00000000  |pThreadSecurity = NULL
  0013F598   00000000  |InheritHandles = FALSE
  0013F59C   00000000  |CreationFlags = 0
  0013F5A0   00000000  |pEnvironment = NULL
  0013F5A4   00000000  |CurrentDir = NULL
  0013F5A8   0013F5BC  |pStartupInfo = 0013F5BC
  0013F5AC   0013F600  \pProcessInfo = 0013F600
  0013F5B0   660FEA4C  MSVBVM60.__vbaFreeVar
  0013F5B4   00000008
  0013F5B8   660DC1FB  MSVBVM60.rtcRandomize
  0013F5BC   00000044
  0013F5C0   00000000
  0013F5C4   00000000
  0013F5C8   00000000
  0013F5CC   00000000
  0013F5D0   00000000
  0013F5D4   00000000
  0013F5D8   00000000
  0013F5DC   00000000
  0013F5E0   00000000
  0013F5E4   00000000
  0013F5E8   00000001
  0013F5EC   00000001
  0013F5F0   00000000
  0013F5F4   00000000
  0013F5F8   00000000
  0013F5FC   00000000
  0013F600   00000007
  0013F604   00FACFA9
  0013F608   00000000
  0013F60C   0013F6FC
  0013F610  /0013F6FC
  0013F614  |0040FC1F  返回到 021.0040FC1F 来自 MSVBVM60.rtcShell    -> 鼠标点一下这里,按回车
  
  0040FBF6       > \>FLD     QWORD PTR SS:[EBP-44]
  0040FBF9       .  >FCOMP   QWORD PTR DS:[401328]
  0040FBFF       .  >FSTSW   AX
  0040FC01       .  >TEST    AH, 41
  0040FC04       . />JNZ     SHORT 021.0040FC29
  0040FC06       . |>LEA     ECX, DWORD PTR SS:[EBP-48]
  0040FC09       . |>MOV     DWORD PTR SS:[EBP-78], ECX
  0040FC0C       . |>MOV     DWORD PTR SS:[EBP-80], 4008
  0040FC13       . |>PUSH    1
  0040FC15       . |>LEA     EDX, DWORD PTR SS:[EBP-80]
  0040FC18       . |>PUSH    EDX
  0040FC19       . |>CALL    DWORD PTR DS:[<&MSVBVM60.#600>]                ;  MSVBVM60.rtcShell
  0040FC1F       . |>FSTP    ST                                             ;  这里就是堆栈中看到的返回地址
  0040FC21       . |>JMP     SHORT 021.0040FC23
  0040FC23       > |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaEnd>]            ;  MSVBVM60.__vbaEnd
  0040FC29       > \>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaExitProc>]       ;  MSVBVM60.__vbaExitProc
  0040FC2F       .  >WAIT
  0040FC30       .  >PUSH    021.0040FC8E
  0040FC35       .  >JMP     SHORT 021.0040FC6C
  ...
  
  7D96A753 ClipCursor      >MOV     EAX, 122C
  7D96A758                 >LEA     EDX, DWORD PTR SS:[ESP+4]
  7D96A75C                 >MOV     ECX, 4
  7D96A761                 >CALL    DWORD PTR FS:[C0]
  7D96A768                 >RETN    4
  
  66106554   ENGINE     输出         __vbaExitEachAry
  66106576   ENGINE     输出         __vbaExitEachColl
  66106534   ENGINE     输出         __vbaExitEachVar
  660E3F0D   .text      输出         __vbaExitProc
  
  0013F19C   00409D55  返回到 021.00409D55 来自 MSVBVM60.__vbaExitProc
  
  004092E2   .  8>LEA     EDX, DWORD PTR SS:[EBP-38]
  004092E5   .  >PUSH    EDX
  004092E6   .  >PUSH    EDI
  004092E7   .  >CALL    DWORD PTR DS:[ECX+A0]
  004092ED   .  >FCLEX
  004092EF   .  >CMP     EAX, EBX
  004092F1   . />JGE     SHORT 021.00409305
  004092F3   . |>PUSH    0A0
  004092F8   . |>PUSH    021.00407DCC
  004092FD   . |>PUSH    EDI
  004092FE   . |>PUSH    EAX
  004092FF   . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaHr>;  MSVBVM60.__vbaHresultCheckObj
  00409305   > \>MOV     EAX, DWORD PTR SS:[EBP-38]
  00409308   .  >PUSH    EAX                              ;  eax=UNICODE "code"。哈,正是我们的注册码。我们也知道了上面004092E7的call是取得输入,放入[EBP-0x38]
  00409309   .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaLe>;  MSVBVM60.__vbaLenBstr
  0040930F   .  >XOR     ECX, ECX
  00409311   .  >CMP     EAX, 10
  00409314   .  >SETL    CL                               ;  注册码长度小于0x10(==16)吗?
  00409317   .  >NEG     ECX
  00409319   .  >MOV     EDI, ECX
  0040931B   .  >LEA     ECX, DWORD PTR SS:[EBP-38]
  0040931E   .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFr>;  MSVBVM60.__vbaFreeStr
  00409324   .  >LEA     ECX, DWORD PTR SS:[EBP-40]
  00409327   .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFr>;  MSVBVM60.__vbaFreeObj
  0040932D   .  >CMP     DI, BX
  00409330   .  >JE      SHORT 021.00409375               ;  小于16,这里不跳,出错。
  ...
  
  00409330   . />JE      SHORT 021.00409375               ;  这回跳了
  00409332   . |>MOV     EDX, DWORD PTR DS:[ESI]
  ...          |                                                 ;  这里省略几行
  0040936A   . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFr>;  MSVBVM60.__vbaFreeObj
  00409370   . |>JMP     021.00409D4F
  00409375   > \>MOV     EAX, DWORD PTR DS:[ESI]                ;  跳到这里
  00409377   .  >PUSH    ESI                                    ;  继续往下走,略去
  
  004093D0       .  >MOV     ECX, DWORD PTR SS:[EBP-20]
  004093D3       .  >PUSH    ECX                              ;  ECX = UNICODE "104E0295",是机器码,看到[EBP-20]是机器码
  004093D4       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaLe>;  MSVBVM60.__vbaLenBstr
  004093DA       .  >MOV     ECX, EAX
  004093DC       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaI2>;  MSVBVM60.__vbaI2I4
  004093E2       .  >MOV     DWORD PTR SS:[EBP-2A0], EAX      ;  [epb-0x2a0] = 8,机器码的长度
  004093E8       .  >MOV     EDI, 1                           ;  for i = 0 to len(machine) step 1 --> 本人对BASIC语法不通,不知道是不是这么写。
  004093ED       > />CMP     DI, WORD PTR SS:[EBP-2A0]        ;  di为循环变量
  004093F4       . |>JG      021.004094A9                     ;  循环出口
  004093FA       . |>MOV     DWORD PTR SS:[EBP-48], 1         ;  VB“又臭又长”的原因在于,它不是编译期强类型,所以必须在运行时做各种类型相关的处理
  00409401       . |>MOV     DWORD PTR SS:[EBP-50], 2         ;  [ebp-0x50]处的Variable对象的类型是整数型,值即为1
  00409408       . |>LEA     EDX, DWORD PTR SS:[EBP-20]
  0040940B       . |>MOV     DWORD PTR SS:[EBP-1F8], EDX      ;  这是[ebp-200]处的Variable对象的值域,是[EBP-20],即机器码
  00409411       . |>MOV     DWORD PTR SS:[EBP-200], 4008     ;  4008是Variable中的类型识别域(表示值域部分是指针)
  0040941B       . |>LEA     EAX, DWORD PTR SS:[EBP-50]       ;  以后关于Variable对象构造的代码不再解释了
  0040941E       . |>PUSH    EAX                              ;  Arg4 = ebp-50,即立即数1
  0040941F       . |>MOVSX   ECX, DI
  00409422       . |>PUSH    ECX                              ;  Arg3 = i,循环变量
  00409423       . |>LEA     EDX, DWORD PTR SS:[EBP-200]
  00409429       . |>PUSH    EDX                              ;  Arg2 = ebp-200,机器码
  0040942A       . |>LEA     EAX, DWORD PTR SS:[EBP-60]
  0040942D       . |>PUSH    EAX                              ;  Arg1 = ebp-60,注意这个参数是out参数
  0040942E       . |>CALL    DWORD PTR DS:[<&MSVBVM60.#632>]  ;  MSVBVM60.rtcMidCharVar
  00409434       . |>MOV     ECX, DWORD PTR SS:[EBP-34]       ;  以上“又臭又长”的代码完成的只是个machinecode[i]的功能,C++编译器生成的代码用三五条指令就完成
  00409437       . |>PUSH    ECX                              ;  这个变量需要注意一下,记住它的偏移是0x34
  00409438       . |>LEA     EDX, DWORD PTR SS:[EBP-60]       ;  machinecode[i]
  0040943B       . |>PUSH    EDX
  0040943C       . |>LEA     EAX, DWORD PTR SS:[EBP-38]       ;  注意ebp-38实际是个临时变量,这里用来接收结果,已经不再指向输入的注册码,释放对象的代码省略了。
  0040943F       . |>PUSH    EAX
  00409440       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaSt>;  MSVBVM60.__vbaStrVarVal
  00409446       . |>PUSH    EAX
  00409447       . |>CALL    DWORD PTR DS:[<&MSVBVM60.#516>]  ;  MSVBVM60.rtcAnsiValueBstr
  0040944D       . |>PUSH    EAX
  0040944E       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaSt>;  MSVBVM60.__vbaStrI2
  00409454       . |>MOV     EDX, EAX                         ;  这里eax指向UNICODE“49”,这是??? 其实就是code[0]的ASCII值的10进制。
  00409456       . |>LEA     ECX, DWORD PTR SS:[EBP-3C]
  00409459       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaSt>;  MSVBVM60.__vbaStrMove
  0040945F       . |>PUSH    EAX                              ;  和谁strcat??? 注意上面我说的ebp-0x34。
  00409460       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaSt>;  MSVBVM60.__vbaStrCat
  00409466       . |>MOV     EDX, EAX
  00409468       . |>LEA     ECX, DWORD PTR SS:[EBP-34]       ;  cat后再存回ebp-0x34
  0040946B       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaSt>;  MSVBVM60.__vbaStrMove
  00409471       . |>LEA     ECX, DWORD PTR SS:[EBP-3C]       ;  下面几条指令不用看了。这也是VB“又臭又长”的表现。
  00409474       . |>PUSH    ECX                              ;  我们已经弄清了这个循环的过程是把机器码的每一个字符转换成它的ASCII码十进制形式
  00409475       . |>LEA     EDX, DWORD PTR SS:[EBP-38]       ;  结果存放在ebp-0x34这个变量。
  00409478       . |>PUSH    EDX
  00409479       . |>PUSH    2
  0040947B       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFr>;  MSVBVM60.__vbaFreeStrList
  00409481       . |>LEA     EAX, DWORD PTR SS:[EBP-60]
  00409484       . |>PUSH    EAX
  00409485       . |>LEA     ECX, DWORD PTR SS:[EBP-50]
  00409488       . |>PUSH    ECX
  00409489       . |>PUSH    2
  0040948B       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFr>;  MSVBVM60.__vbaFreeVarList
  00409491       . |>ADD     ESP, 18
  00409494       . |>MOV     EAX, 1
  00409499       . |>ADD     AX, DI
  0040949C       . |>JO      021.00409E73
  004094A2       . |>MOV     EDI, EAX
  004094A4       .^\>JMP     021.004093ED                     ;  循环
  004094A9       >  >LEA     EDX, DWORD PTR SS:[EBP-34]       ;  循环结束后来到这里。
  
  
  0013F44C  002501BC  UNICODE "4948526948505753"
  0013F450  00000018
  0013F454  00000018
  0013F458  00000000
  0013F45C  00010000  UNICODE "=::=::\"
  0013F460  00292684  UNICODE "104E0295"
  0013F464  0013F9BC  指向下一个 SEH 记录的指针
  0013F468  00401496  SE处理程序
  0013F46C  0013F1A0
  0013F470  00401210  021.00401210
  
  004094A9       > \>LEA     EDX, DWORD PTR SS:[EBP-34]                 ;  循环结束
  004094AC       .  >MOV     DWORD PTR SS:[EBP-1F8], EDX
  004094B2       .  >MOV     DWORD PTR SS:[EBP-200], 4008
  004094BC       .  >PUSH    8                                          ;  arg3 = 8
  004094BE       .  >LEA     EAX, DWORD PTR SS:[EBP-200]                ;      +8偏移处的指针指向 UNICODE "4948526948505753"
  004094C4       .  >PUSH    EAX                                        ;  arg2 = ASCII_machinecode
  004094C5       .  >LEA     ECX, DWORD PTR SS:[EBP-50]
  004094C8       .  >PUSH    ECX                                        ;  arg1 = ebp-50,out参数
  004094C9       .  >CALL    DWORD PTR DS:[<&MSVBVM60.#617>]            ;  MSVBVM60.rtcLeftCharVar
  004094CF       .  >LEA     EDX, DWORD PTR SS:[EBP-50]                 ;  [ebp-50] = ASCII_machine的前8位
  004094D2       .  >PUSH    EDX
  004094D3       .  >LEA     EAX, DWORD PTR SS:[EBP-38]
  004094D6       .  >PUSH    EAX
  004094D7       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaStrVarVal>]  ;  MSVBVM60.__vbaStrVarVal
  004094DD       .  >PUSH    EAX
  004094DE       .  >CALL    DWORD PTR DS:[<&MSVBVM60.#581>]            ;  MSVBVM60.rtcR8ValFromBstr
  004094E4       .  >FSTP    QWORD PTR SS:[EBP-30]                      ;  看一下浮点寄存器窗口,返回值是49485269.00000
  004094E7       .  >LEA     ECX, DWORD PTR SS:[EBP-38]                 ;  返回的浮点数存放于ebp-30处,注意是qword
  004094EA       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFreeStr>]    ;  MSVBVM60.__vbaFreeStr
  ...
  
  004094A9       > \>LEA     EDX, DWORD PTR SS:[EBP-34]                 ;  循环结束
  004094AC       .  >MOV     DWORD PTR SS:[EBP-1F8], EDX
  004094B2       .  >MOV     DWORD PTR SS:[EBP-200], 4008
  004094BC       .  >PUSH    8                                          ;  arg3 = 8
  004094BE       .  >LEA     EAX, DWORD PTR SS:[EBP-200]                ;      +8偏移处的指针指向 UNICODE "4948526948505753"
  004094C4       .  >PUSH    EAX                                        ;  arg2 = ASCII_machinecode
  004094C5       .  >LEA     ECX, DWORD PTR SS:[EBP-50]
  004094C8       .  >PUSH    ECX                                        ;  arg1 = ebp-50,out参数
  004094C9       .  >CALL    DWORD PTR DS:[<&MSVBVM60.#617>]            ;  MSVBVM60.rtcLeftCharVar
  004094CF       .  >LEA     EDX, DWORD PTR SS:[EBP-50]                 ;  [ebp-50] = ASCII_machine的前8位
  004094D2       .  >PUSH    EDX
  004094D3       .  >LEA     EAX, DWORD PTR SS:[EBP-38]
  004094D6       .  >PUSH    EAX
  004094D7       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaStrVarVal>]  ;  MSVBVM60.__vbaStrVarVal
  004094DD       .  >PUSH    EAX
  004094DE       .  >CALL    DWORD PTR DS:[<&MSVBVM60.#581>]            ;  MSVBVM60.rtcR8ValFromBstr
  004094E4       .  >FSTP    QWORD PTR SS:[EBP-30]                      ;  看一下浮点寄存器窗口,返回值是49485269.00000
  004094E7       .  >LEA     ECX, DWORD PTR SS:[EBP-38]                 ;  返回的浮点数存放于ebp-30处,注意是qword
  004094EA       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFreeStr>]    ;  MSVBVM60.__vbaFreeStr
  004094F0       .  >LEA     ECX, DWORD PTR SS:[EBP-50]
  004094F3       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFreeVar>]    ;  MSVBVM60.__vbaFreeVar
  004094F9       .  >MOV     ECX, DWORD PTR DS:[ESI]
  004094FB       .  >PUSH    ESI
  004094FC       .  >CALL    DWORD PTR DS:[ECX+304]
  00409502       .  >PUSH    EAX
  00409503       .  >LEA     EDX, DWORD PTR SS:[EBP-40]
  00409506       .  >PUSH    EDX
  00409507       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaObjSet>]     ;  MSVBVM60.__vbaObjSet
  0040950D       .  >MOV     EDI, EAX
  0040950F       .  >MOV     EAX, DWORD PTR DS:[EDI]
  00409511       .  >LEA     ECX, DWORD PTR SS:[EBP-38]                 ;  前面说了,ebp-38充当临时变量
  00409514       .  >PUSH    ECX
  00409515       .  >PUSH    EDI
  00409516       .  >CALL    DWORD PTR DS:[EAX+A0]                      ;  这次用来接收输入的注册码的值
  0040951C       .  >FCLEX
  0040951E       .  >CMP     EAX, EBX
  00409520       . />JGE     SHORT 021.00409534
  00409522       . |>PUSH    0A0
  00409527       . |>PUSH    021.00407DCC
  0040952C       . |>PUSH    EDI
  0040952D       . |>PUSH    EAX
  0040952E       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaHresultCheck>;  MSVBVM60.__vbaHresultCheckObj
  00409534       > \>MOV     EAX, DWORD PTR SS:[EBP-38]
  00409537       .  >MOV     DWORD PTR SS:[EBP-38], EBX
  0040953A       .  >MOV     DWORD PTR SS:[EBP-48], EAX
  0040953D       .  >MOV     DWORD PTR SS:[EBP-50], 8
  00409544       .  >PUSH    8
  00409546       .  >LEA     EDX, DWORD PTR SS:[EBP-50]
  00409549       .  >PUSH    EDX
  0040954A       .  >LEA     EAX, DWORD PTR SS:[EBP-60]
  0040954D       .  >PUSH    EAX                                        ;  也取输入注册码的前8位
  0040954E       .  >CALL    DWORD PTR DS:[<&MSVBVM60.#617>]            ;  MSVBVM60.rtcLeftCharVar
  00409554       .  >LEA     ECX, DWORD PTR SS:[EBP-60]
  00409557       .  >PUSH    ECX
  00409558       .  >LEA     EDX, DWORD PTR SS:[EBP-3C]
  0040955B       .  >PUSH    EDX
  0040955C       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaStrVarVal>]  ;  MSVBVM60.__vbaStrVarVal
  00409562       .  >PUSH    EAX                                        ;  前8位由字符串直接转化为浮点数
  00409563       .  >CALL    DWORD PTR DS:[<&MSVBVM60.#581>]            ;  MSVBVM60.rtcR8ValFromBstr
  00409569       .  >MOV     EDI, DWORD PTR DS:[<&MSVBVM60.__vbaFpI4>]  ;  返回值在浮点寄存器中
  0040956F       .  >CALL    EDI                                        ;  <&MSVBVM60.__vbaFpI4>
  00409571       .  >MOV     EDX, EAX                                   ;  __vbaFpI4是把浮点数转化成4字节(即32位)整数,返回值在EAX
  00409573       .  >FLD     QWORD PTR SS:[EBP-30]                      ;  由机器码前8位转化而来的浮点数
  00409576       .  >MOV     DWORD PTR SS:[EBP-2C8], EDX
  0040957C       .  >CALL    EDI                                        ;  也转化成32位整数
  0040957E       .  >MOV     ECX, DWORD PTR SS:[EBP-2C8]
  00409584       .  >XOR     ECX, EAX                                   ;  这两个整数(由机器码前8位和由注册码前8位分别转化过来的)进行异或
  00409586       .  >MOV     DWORD PTR SS:[EBP-2CC], ECX                ;  结果暂存于ebp-0x2cc
  0040958C       .  >FILD    DWORD PTR SS:[EBP-2CC]
  00409592       .  >FSTP    QWORD PTR SS:[EBP-30]                      ;  这两条指令是再将整型转换为双精度浮点型,还存于ebp-0x30
  00409595       .  >LEA     ECX, DWORD PTR SS:[EBP-3C]
  00409598       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFreeStr>]    ;  MSVBVM60.__vbaFreeStr
  0040959E       .  >LEA     ECX, DWORD PTR SS:[EBP-40]
  004095A1       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFreeObj>]    ;  MSVBVM60.__vbaFreeObj
  004095A7       .  >LEA     EDX, DWORD PTR SS:[EBP-60]
  004095AA       .  >PUSH    EDX
  004095AB       .  >LEA     EAX, DWORD PTR SS:[EBP-50]
  004095AE       .  >PUSH    EAX
  004095AF       .  >PUSH    2
  004095B1       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFreeVarList>>;  MSVBVM60.__vbaFreeVarList
  004095B7       .  >ADD     ESP, 0C
  004095BA       .  >MOV     EDI, DWORD PTR SS:[EBP-2C]
  004095BD       .  >PUSH    EDI
  004095BE       .  >MOV     ECX, DWORD PTR SS:[EBP-30]
  004095C1       .  >PUSH    ECX                                        ;  这两条push实际是压入一个双精度浮点数。
  004095C2       .  >CALL    DWORD PTR DS:[<&MSVBVM60.#587>]            ;  MSVBVM60.rtcLog
  004095C8       .  >FSTP    QWORD PTR SS:[EBP-28C]                     ;  取对数,结果存放于[ebp-0x28c],注意也是qword
  004095CE       .  >PUSH    EDI
  004095CF       .  >MOV     EDX, DWORD PTR SS:[EBP-30]
  004095D2       .  >PUSH    EDX
  004095D3       .  >CALL    DWORD PTR DS:[<&MSVBVM60.#587>]            ;  MSVBVM60.rtcLog
  004095D9       .  >FSTP    QWORD PTR SS:[EBP-2D4]                     ;  还是同一个值,存入[ebp-0x2d4]
  004095DF       .  >FLD     QWORD PTR SS:[EBP-28C]                     ;  这是第一次存入的对数值
  004095E5       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFPFix>]      ;  舍入到整数
  004095EB       .  >FSUBR   QWORD PTR SS:[EBP-2D4]                     ;  再减第二次存入的对数值,注意是fsubr,所以是减数,而不是被减数
  004095F1       .  >FSTP    QWORD PTR SS:[EBP-30]                      ;  剩下的差是小数部分,存入ebp-30
  004095F4       .  >FSTSW   AX
  004095F6       .  >TEST    AL, 0D
  004095F8       .  >JNZ     021.00409E6E                               ;  异常检查。注意VB没有使用80x87的硬件异常,而是是软件判断状态位来实现的“软异常”
  004095FE       .  >FLD     QWORD PTR SS:[EBP-30]                      ;  取刚才计算出的小数部分
  00409601       .  >FMUL    QWORD PTR DS:[401238]                      ;  乘以程序内置的常数,值为1000000000.0000,即10的9次方
  00409607       .  >FSTP    QWORD PTR SS:[EBP-48]                      ;  结果存放[ebp-0x48]
  0040960A       .  >FSTSW   AX
  0040960C       .  >TEST    AL, 0D
  0040960E       .  >JNZ     021.00409E6E                               ;  同上,“软异常”
  
  0040960E       . />JNZ     021.00409E6E                               ;  同上,软异常
  00409614       . |>MOV     DWORD PTR SS:[EBP-50], 5                   ;  [ebp-0x50]这个变量的类型域,5表示双精度浮点。
  0040961B       . |>PUSH    8                                          ;  取左边8位
  0040961D       . |>LEA     EAX, DWORD PTR SS:[EBP-50]                 ;  请注意,[ebp-0x50]的值域恰是ebp-0x48
  00409620       . |>PUSH    EAX                                        ;  现在它的值是 7.1718556708082199100e+16
  00409621       . |>LEA     ECX, DWORD PTR SS:[EBP-60]                 ;  [ebp-0x60]用来接收结果
  00409624       . |>PUSH    ECX
  00409625       . |>CALL    DWORD PTR DS:[<&MSVBVM60.#617>]            ;  MSVBVM60.rtcLeftCharVar
  0040962B       . |>LEA     EDX, DWORD PTR SS:[EBP-60]
  0040962E       . |>PUSH    EDX
  0040962F       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaStrVarMove>] ;  MSVBVM60.__vbaStrVarMove
  00409635       . |>MOV     EDX, EAX
  00409637       . |>LEA     ECX, DWORD PTR SS:[EBP-20]                 ;  最后把高8位转化成的字符串"71718556"存放于[ebp-20]处的变量
  0040963A       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaStrMove>]    ;  MSVBVM60.__vbaStrMove
  00409640       . |>LEA     EAX, DWORD PTR SS:[EBP-60]
  00409643       . |>PUSH    EAX
  00409644       . |>LEA     ECX, DWORD PTR SS:[EBP-50]
  00409647       . |>PUSH    ECX
  00409648       . |>PUSH    2
  0040964A       . |>CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFreeVarList>>;  MSVBVM60.__vbaFreeVarList
  
  
  00409669       .  >MOV     ECX, DWORD PTR DS:[EDI]
  0040966B       .  >LEA     EDX, DWORD PTR SS:[EBP-38]                 ;  临时变量ebp-0x38再次上场,这次还是用来接收输入的注册码
  0040966E       .  >PUSH    EDX
  0040966F       .  >PUSH    EDI
  00409670       .  >CALL    DWORD PTR DS:[ECX+A0]                      ;  取输入的注册码
  00409676       .  >FCLEX
  00409678       .  >CMP     EAX, EBX
  0040967A       .  >JGE     SHORT 021.0040968E
  0040967C       .  >PUSH    0A0
  00409681       .  >PUSH    021.00407DCC
  00409686       .  >PUSH    EDI
  00409687       .  >PUSH    EAX
  00409688       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaHresultCheck>;  MSVBVM60.__vbaHresultCheckObj
  0040968E       >  >MOV     EAX, DWORD PTR SS:[EBP-38]
  00409691       .  >MOV     DWORD PTR SS:[EBP-38], EBX
  00409694       .  >MOV     DWORD PTR SS:[EBP-48], EAX                 ;  如上所说,这里反汇编显示的是[ebp-0x48],而实际变量使用时是ebp-0x50
  00409697       .  >MOV     DWORD PTR SS:[EBP-50], 8
  0040969E       .  >PUSH    8
  004096A0       .  >LEA     EAX, DWORD PTR SS:[EBP-50]
  004096A3       .  >PUSH    EAX
  004096A4       .  >LEA     ECX, DWORD PTR SS:[EBP-60]                 ;  这次[ebp-0x60]这个变量用来存放输入注册码的最右8位
  004096A7       .  >PUSH    ECX
  004096A8       .  >CALL    DWORD PTR DS:[<&MSVBVM60.#619>]            ;  MSVBVM60.rtcRightCharVar
  004096AE       .  >MOV     EDX, DWORD PTR SS:[EBP-20]                 ;  [ebp-0x20]是什么变量,还记得吧
  004096B1       .  >MOV     DWORD PTR SS:[EBP-1F8], EDX                ;  把它放入[ebp-0x200]这个变量的值域
  004096B7       .  >MOV     DWORD PTR SS:[EBP-200], 8008               ;  类型域是8008,不用管它具体是什么意思,只要记住到偏移08处找它真正的值就行了
  004096C1       .  >LEA     EAX, DWORD PTR SS:[EBP-60]
  004096C4       .  >PUSH    EAX
  004096C5       .  >LEA     ECX, DWORD PTR SS:[EBP-200]
  004096CB       .  >PUSH    ECX
  004096CC       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaVarTstEq>]   ;  比较[ebp-0x200]和[ebp-0x60]是不是相等
  004096D2       .  >MOV     EDI, EAX                                   ;  不相等,返回值为false,即0。结果暂存于edi
  004096D4       .  >LEA     ECX, DWORD PTR SS:[EBP-40]
  004096D7       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFreeObj>]    ;  MSVBVM60.__vbaFreeObj
  004096DD       .  >LEA     EDX, DWORD PTR SS:[EBP-60]
  004096E0       .  >PUSH    EDX
  004096E1       .  >LEA     EAX, DWORD PTR SS:[EBP-50]
  004096E4       .  >PUSH    EAX
  004096E5       .  >PUSH    2
  004096E7       .  >CALL    DWORD PTR DS:[<&MSVBVM60.__vbaFreeVarList>>;  MSVBVM60.__vbaFreeVarList
  004096ED       .  >ADD     ESP, 0C
  004096F0       .  >CMP     DI, BX                                     ;  记得di中是什么值吧
  004096F3       .  >JE      SHORT 021.00409724                         ;  di为0,跳走。
  004096F5       .  >MOV     ECX, DWORD PTR DS:[ESI]
  
  

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (38)
雪    币: 1355
活跃值: (339)
能力值: ( LV13,RANK:920 )
在线值:
发帖
回帖
粉丝
2
不管了,先抢位置。

呵呵,抢了位置再聊聊天。

顶书呆的文章,尤其是这篇,呵呵;分析的入木三分,我要搬个凳子坐下来好好看。
2008-12-29 17:20
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
3
学习+膜拜 Orz
2008-12-29 17:50
0
雪    币: 1137
活跃值: (10)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
直接挂掉我电脑系统

且记我蓝屏5次的crackMe啊

膜拜!  

一直不敢去试VB的程序
2008-12-29 18:20
0
雪    币: 328
活跃值: (10)
能力值: ( LV9,RANK:370 )
在线值:
发帖
回帖
粉丝
5
深水鱼雷
我没看程序,也把你文章看完了……
NOTE:
VB万能断点 __vbaExitProc
由于VB的框架性质,用户代码只是由被框架代码所调用的函数组成的。所以,必须有一种机制,用来通知框架,我已经干完活了。
  
  这就是__vbaExitProc
2008-12-29 18:57
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
老大这文写地,真是太厉害,一口气看完,我晃然大悟了,感动+感激+热泪盈框,谢谢!老大指点,受用+管用+好用+真好用...
2008-12-29 19:05
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
7
书呆不出一系列教程太可惜了
听说做教程也能赚钱.
2008-12-29 19:08
0
雪    币: 11138
活跃值: (158)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
好文章,顶一下。居然很多都看不懂。
2008-12-29 19:33
0
雪    币: 1074
活跃值: (160)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
9
谢谢高手发出这么好的文章,我有一点疑问,请问破解第一关的时候,我把
0040FC04       . />JNZ     SHORT 021.0040FC29
改成了JMP复制到可执行文件后再运行,为什么注册按钮消失不见了,而且看不见机器码???????
2008-12-29 21:05
0
雪    币: 1355
活跃值: (339)
能力值: ( LV13,RANK:920 )
在线值:
发帖
回帖
粉丝
10
书呆彭已经专心复习功课备考去了,该问题还是由我来回答吧

:因为有防修改自校验,且不直接退出,检测到修改间接计算到控件上面去,防止进一步被解密。

解决办法:

0040D886     /0F84 B8000000 JE 海狼三人.0040D944

修改为:

0040D886     /E9 B9000000   JMP 海狼三人.0040D944
0040D88B     |90            NOP

强行跳过即可。
2008-12-29 21:11
0
雪    币: 2368
活跃值: (81)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
11
好好的看了看书呆子的文章,先顶,再膜拜....
我一值没有静下心来,好好分析....又开始浮躁了......因为开始几次否没有鼠标用...就不想crack了...后来看上去挺火....就花了些时间看了看...但是也是走马观花,只是把码跟跟出来了...

对了,之前看到帖子有人说是明码...呵呵。实际上算是作弊的..不过我发现自己越来越不会crack了。都不如之前了.....
2008-12-29 22:19
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
我跟过一会,由于第一次接触VB的代码,开始看代码觉得很糟糕,很多不明白意思的CALL,后来跳过一个鼠标限制和一个创建窗口的限制,开始调到关键CALL那里,跟了2-3遍,跟出4849...等字样,再接着试注册码,一直出现异常,不知道是在哪对比的,就没信心跟了。今天哪知道看了一遍楼主的破文,恍然大悟,原来我当初离成功仅是一步之遥。当初如果在XXXEqu的时候下个断,结果就出来了。哎……
佩服楼主的精神,顶起来。
2008-12-29 22:45
0
雪    币: 213
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
13
太好了,终于看到答案了,先顶再看
2008-12-29 22:53
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
程序非常奇怪,

当这样操作时会出现奇怪的问题:

1、OD载入
2、下bp CreateProcessW,然后按shift+F9
3、程序断在这:
   
7C802336 >  8BFF            mov edi,edi
7C802338    55              push ebp
7C802339    8BEC            mov ebp,esp
7C80233B    6A 00           push 0

4、看堆栈:
0013F584              660D6DF0    /CALL 到 CreateProcessW 来自 MSVBVM60.660D6DEA
0013F588              00000000    |ModuleFileName = NULL
0013F58C              0015DCCC    |CommandLine = "E:\CrackMe\海狼三人队.exe"
0013F590              00000000    |pProcessSecurity = NULL
0013F594              00000000    |pThreadSecurity = NULL
0013F598              00000000    |InheritHandles = FALSE
0013F59C              00000000    |CreationFlags = 0
0013F5A0              00000000    |pEnvironment = NULL
0013F5A4              00000000    |CurrentDir = NULL
0013F5A8              0013F5BC    |pStartupInfo = 0013F5BC
0013F5AC              0013F600    \pProcessInfo = 0013F600
0013F5B0              6610009E    MSVBVM60.__vbaFreeVar
0013F5B4              00000008
0013F5B8              660E1BFA    MSVBVM60.rtcRandomize
0013F5BC              00000044
0013F5C0              00000000
0013F5C4              00000000
0013F5C8              00000000
0013F5CC              00000000
0013F5D0              00000000
0013F5D4              00000000
0013F5D8              00000000
0013F5DC              00000000
0013F5E0              00000000
0013F5E4              00000000
0013F5E8              00000001
0013F5EC              00000001
0013F5F0              00000000
0013F5F4              00000000
0013F5F8              00000000
0013F5FC              00000000
0013F600              00000007
0013F604              009F9DA9
0013F608              00000000
0013F60C              0013F6FC
0013F610             /0013F6FC
0013F614             |0040FC1F    返回到 海狼三人.0040FC1F 来自 MSVBVM60.rtcShell
                                  选中此处按回车

5、程序来到这:
0040FC04   /75 23           jnz short 海狼三人.0040FC29   ;把jnz改为jmp,然后保存程序。
0040FC06   |8D4D B8         lea ecx,dword ptr ss:[ebp-48]
0040FC09   |894D 88         mov dword ptr ss:[ebp-78],ecx
0040FC0C   |C745 80 0840000>mov dword ptr ss:[ebp-80],4008
0040FC13   |6A 01           push 1
0040FC15   |8D55 80         lea edx,dword ptr ss:[ebp-80]
0040FC18   |52              push edx
0040FC19   |FF15 F8104000   call dword ptr ds:[<&MSVBVM60.#600>]         ; MSVBVM60.rtcShell
0040FC1F   |DDD8            fstp st
0040FC21   |EB 00           jmp short 海狼三人.0040FC23
0040FC23   |FF15 38104000   call dword ptr ds:[<&MSVBVM60.__vbaEnd>]     ; MSVBVM60.__vbaEnd
0040FC29   \FF15 7C104000   call dword ptr ds:[<&MSVBVM60.__vbaExitProc>>; MSVBVM60.__vbaExitProc

当把jnz改为jmp,保存程序后,在运行程序,奇怪的事发生了:


当把 jnz 改为 jmp 之后,不保存程序,然后F8 执行jmp 跳过之后,些时
Ctrl+G 输入 ClipCursor 程序来到这里:

77D3FDC5 >  B8 4A110000     mov eax,114A   ;改成retn 4
77D3FDCA    BA 0003FE7F     mov edx,7FFE0300
77D3FDCF    FF12            call dword ptr ds:[edx]
77D3FDD1    C2 0400         retn 4

改成retn 4 之后此时按 shift+F9 程序正常了。。。。
上传的附件:
  • 2.jpg (20.92kb,960次下载)
2008-12-30 00:17
0
雪    币: 2316
活跃值: (129)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
15
学到很多。好文。
2008-12-30 09:10
0
雪    币: 213
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
好多看不懂 弱弱的补充一下:好像有自检验。。。
2008-12-30 09:38
0
雪    币: 107
活跃值: (1693)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
17
楼主放出来的绝招
2008-12-30 09:40
0
雪    币: 1355
活跃值: (339)
能力值: ( LV13,RANK:920 )
在线值:
发帖
回帖
粉丝
18
请看10楼我的回答

自校验请参考10楼解答
2008-12-30 09:42
0
雪    币: 1074
活跃值: (160)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
19
呵呵,我找到这处自校验了,下断ReadFile,然后Ctrl+F9几次以后返回到程序领空,能看到一个比较大的JE跳转,将它改为JMP,自校验就去掉了,晕,作者太强了,佩服!
    更佩服的是软件分析者,我从头看了一遍,思路太好了,我受益匪浅,再一次感叹,自己实在是太弱了,还有好多要学习的啊!
2008-12-30 09:43
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
膜拜,虽然把你的分析全部看完了,但是发觉我现在还离得好远好远
2008-12-30 13:00
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
谢谢.收藏先.慢慢学习下.
2008-12-30 13:04
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
学习学习,不错不许哦
2008-12-31 09:35
0
雪    币: 218
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
好长的文章啊  分析的不错  学习再学习 顺便问下楼主那所学校攻读啊
2009-1-1 01:32
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
好文要支持~
2009-1-2 14:46
0
雪    币: 227
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
学习一下,~~~~~~~~~~~~~~~
2009-1-6 16:48
0
游客
登录 | 注册 方可回帖
返回
//