-
-
[原创]一个简单有趣的CM
-
发表于: 2009-11-28 19:54 3780
-
这个CM很简单,没有任何保护,适合新手练习,老手飘过。
我喜欢将软件先拖到IDA中分析一下(这是一个好习惯),很快它的执行流程图就呈现在面前。
看到这里:
loc_4015AE: ; "name?"
push offset s_Name?
call puts
push offset byte_43F1C0 ; char *
call gets
xor ecx, ecx
很明显是输入验证码。
复制地址4015AE,用OD打开程序,Ctrl+G到这里。下段,重新运行,断在这里。F8单步运行,输入用户名:pediy
到这里:
004015C2 . 31C9 XOR ECX,ECX ; msvcrt.773B76C7
004015C4 > 8A1401 MOV DL,BYTE PTR DS:[ECX+EAX]
004015C7 . 41 INC ECX
004015C8 . 80FA 00 CMP DL,0
004015CB .^ 75 F7 JNZ SHORT FJLJ_cra.004015C4 ;循环得到用户名的长度,如果大于8则失败
004015CD . 83F9 09 CMP ECX,9
004015D0 . 7E 18 JLE SHORT FJLJ_cra.004015EA ;跳到用户名验证过程
004015D2 > 68 03164000 PUSH FJLJ_cra.00401603 ; /s = "NO!"
004015D7 . E8 E4F20000 CALL <JMP.&msvcrt.puts> ; \puts
004015DC . /EB 10 JMP SHORT FJLJ_cra.004015EE
004015DE . |68 FE154000 PUSH FJLJ_cra.004015FE ; /s = "YAY!"
004015E3 . |E8 D8F20000 CALL <JMP.&msvcrt.puts> ; \puts
004015E8 . |EB 04 JMP SHORT FJLJ_cra.004015EE
004015EA >^|EB 84 JMP SHORT FJLJ_cra.00401570
下面就是用户名验证(动态):
00401570 > /31D2 XOR EDX,EDX ; ntdll.77519A00
00401572 . |31C9 XOR ECX,ECX
00401574 . |31DB XOR EBX,EBX
00401576 > |8A1C01 MOV BL,BYTE PTR DS:[ECX+EAX] ;依次取注册码相加取低位,DL=1B
00401579 . |00DA ADD DL,BL
0040157B . |41 INC ECX
0040157C . |80FB 00 CMP BL,0
0040157F .^|75 F5 JNZ SHORT FJLJ_cra.00401576
00401581 . |B8 00F24300 MOV EAX,FJLJ_cra.43F200
00401586 . |01D0 ADD EAX,EDX ;eax=43F21B
00401588 . |89C1 MOV ECX,EAX
0040158A . |B8 D9154000 MOV EAX,FJLJ_cra.004015D9
0040158F . |29C8 SUB EAX,ECX ;43F21B-4015D9
00401591 . |66:89C3 MOV BX,AX ;低位放bx
00401594 . |C1C8 10 ROR EAX,10
00401597 . |66:89C2 MOV DX,AX ;高位放dx
0040159A . |31C0 XOR EAX,EAX
0040159C . |C601 E9 MOV BYTE PTR DS:[ECX],0E9 ;依次将0E9,bx,dx,90放入地址43F21B
0040159F . |8859 01 MOV BYTE PTR DS:[ECX+1],BL
004015A2 . |8879 02 MOV BYTE PTR DS:[ECX+2],BH
004015A5 . |8851 03 MOV BYTE PTR DS:[ECX+3],DL
004015A8 .^|E9 3EFFFFFF JMP FJLJ_cra.004014EB
继续跟入:
004014EB > /8871 04 MOV BYTE PTR DS:[ECX+4],DH
004014EE . |C641 05 90 MOV BYTE PTR DS:[ECX+5],90
004014F2 . |51 PUSH ECX
004014F3 . |68 F6154000 PUSH FJLJ_cra.004015F6 ; /s = "serial?"
004014F8 . |E8 C3F30000 CALL <JMP.&msvcrt.puts> ; \puts
004014FD . |8B44E4 04 MOV EAX,DWORD PTR SS:[ESP+4]
00401501 . |89C3 MOV EBX,EAX
00401503 . |81F3 00F24300 XOR EBX,43F200 ;ebx=1B
00401509 . |01D8 ADD EAX,EBX ;eax=43F21B+1B
0040150B . |90 NOP
0040150C . |90 NOP
0040150D . |90 NOP
0040150E . |90 NOP
0040150F . |90 NOP
00401510 . |31DB XOR EBX,EBX
00401512 . |90 NOP
00401513 . |90 NOP
00401514 . |90 NOP
00401515 . |90 NOP
00401516 . |83C0 10 ADD EAX,10 ;eax=43F246,下面将验证码放入43F246
00401519 . |50 PUSH EAX ; /s ;输入1234567
0040151A . |E8 91F30000 CALL <JMP.&msvcrt.gets> ; \gets
0040151F . |33C9 XOR ECX,ECX
00401521 . |33D2 XOR EDX,EDX
00401523 . |33DB XOR EBX,EBX
00401525 . |8BD8 MOV EBX,EAX ebx=43F246
00401527 > |8A1408 MOV DL,BYTE PTR DS:[EAX+ECX] ;取验证码之和+ebx
0040152A . |03DA ADD EBX,EDX
0040152C . |41 INC ECX
0040152D . |8A1408 MOV DL,BYTE PTR DS:[EAX+ECX]
00401530 . |03DA ADD EBX,EDX ;ebx=0043F3B2
00401532 . |41 INC ECX
00401533 . |80FA 00 CMP DL,0
00401536 .^|75 EF JNZ SHORT FJLJ_cra.00401527
00401538 > |83E9 02 SUB ECX,2
0040153B . |8A1408 MOV DL,BYTE PTR DS:[EAX+ECX] ;ebx-偶数位
0040153E . |2BDA SUB EBX,EDX
00401540 . |83F9 00 CMP ECX,0
00401543 .^|7F F3 JG SHORT FJLJ_cra.00401538
00401545 .^|EB 84 JMP SHORT FJLJ_cra.004014CB
00401547 |90 NOP
到004014CB:
004014CB > /8A1408 MOV DL,BYTE PTR DS:[EAX+ECX] ;将上面的结果-(注册码+(i+4))*10h,i=0,i++
004014CE . |C1E2 04 SHL EDX,4
004014D1 . |2BDA SUB EBX,EDX
004014D3 . |83C1 04 ADD ECX,4
004014D6 . |80FE 00 CMP DH,0
004014D9 . |74 04 JE SHORT FJLJ_cra.004014DF
004014DB . |31D2 XOR EDX,EDX
004014DD .^ EB EC JMP SHORT FJLJ_cra.004014CB
004014DF > |EB 6F JMP SHORT FJLJ_cra.00401550
跳到00401550:
00401550 > \8B44E4 08 MOV EAX,DWORD PTR SS:[ESP+8] ; FJLJ_cra.0043F21B
00401554 . 90 NOP
00401555 . 90 NOP
00401556 . 90 NOP
00401557 . 90 NOP
00401558 . 90 NOP
00401559 . 81C3 D6040000 ADD EBX,4D6 ;上面的结果+4D6与eax比较
0040155F . 3BD8 CMP EBX,EAX ;比较
00401561 . 74 02 JE SHORT FJLJ_cra.00401565 ;关键跳,不等失败
00401563 . EB 6D JMP SHORT FJLJ_cra.004015D2
00401565 > FFE3 JMP EBX
在这我就有点迷糊了,显然ebx中就是正确的地址,根据分析正确地址是4015DE,再看看ebx中的地址怎么来的,就是上面43F200 +1B,这是不可能的,43F200>4015DE,所以ebx不能为这个值。看来ebx只是个跳转地址。但要怎么才能找到这个地址了。再回头看代码:
00401581 . |B8 00F24300 MOV EAX,FJLJ_cra.43F200
00401586 . |01D0 ADD EAX,EDX ;eax=43F21B
00401588 . |89C1 MOV ECX,EAX
0040158A . |B8 D9154000 MOV EAX,FJLJ_cra.004015D9
0040158F . |29C8 SUB EAX,ECX ;43F21B-4015D9
00401591 . |66:89C3 MOV BX,AX ;低位放bx
00401594 . |C1C8 10 ROR EAX,10
00401597 . |66:89C2 MOV DX,AX ;高位放dx
0040159A . |31C0 XOR EAX,EAX
0040159C . |C601 E9 MOV BYTE PTR DS:[ECX],0E9 ;依次将0E9,bx,dx,90放入地址43F21B
0040159F . |8859 01 MOV BYTE PTR DS:[ECX+1],BL
004015A2 . |8879 02 MOV BYTE PTR DS:[ECX+2],BH
004015A5 . |8851 03 MOV BYTE PTR DS:[ECX+3],DL
004015A8 .^|E9 3EFFFFFF JMP FJLJ_cra.004014EB
在汇编窗口看看43F21B:
0043F21B - E9 BE23FCFF JMP FJLJ_cra.004015DE
0043F220 90 NOP
0043F221 0000 ADD BYTE PTR DS:[EAX],AL
呵呵,现在一切都明白了。所以对于新手,遇到问题并不可怕,我们只要多看代码,不懂不要紧,只要多看,心里慢慢就明白了。
算法总结:
将用户名相加得t,每次取低位,s=t+43F200 ,再用s-4015D9 就得到一个差值,前面加上E9,就是一个跳转地址了,所以只要注册码算法的地址等于s,注册就成功了。
注册码的计算是:s+t+10h+注册码偶数之和-(注册码+(i+4))*10h【i=0,i++,i<注册码长度】+4D6h,只要结果等于s,就成功了。
一组注册码:name:pediy
serial:1b3g2f
唉,写文章比破解它更累,在这里感谢那些高手们,是他们不辞辛苦的写破文,才有了我们学习的机会。
我喜欢将软件先拖到IDA中分析一下(这是一个好习惯),很快它的执行流程图就呈现在面前。
看到这里:
loc_4015AE: ; "name?"
push offset s_Name?
call puts
push offset byte_43F1C0 ; char *
call gets
xor ecx, ecx
很明显是输入验证码。
复制地址4015AE,用OD打开程序,Ctrl+G到这里。下段,重新运行,断在这里。F8单步运行,输入用户名:pediy
到这里:
004015C2 . 31C9 XOR ECX,ECX ; msvcrt.773B76C7
004015C4 > 8A1401 MOV DL,BYTE PTR DS:[ECX+EAX]
004015C7 . 41 INC ECX
004015C8 . 80FA 00 CMP DL,0
004015CB .^ 75 F7 JNZ SHORT FJLJ_cra.004015C4 ;循环得到用户名的长度,如果大于8则失败
004015CD . 83F9 09 CMP ECX,9
004015D0 . 7E 18 JLE SHORT FJLJ_cra.004015EA ;跳到用户名验证过程
004015D2 > 68 03164000 PUSH FJLJ_cra.00401603 ; /s = "NO!"
004015D7 . E8 E4F20000 CALL <JMP.&msvcrt.puts> ; \puts
004015DC . /EB 10 JMP SHORT FJLJ_cra.004015EE
004015DE . |68 FE154000 PUSH FJLJ_cra.004015FE ; /s = "YAY!"
004015E3 . |E8 D8F20000 CALL <JMP.&msvcrt.puts> ; \puts
004015E8 . |EB 04 JMP SHORT FJLJ_cra.004015EE
004015EA >^|EB 84 JMP SHORT FJLJ_cra.00401570
下面就是用户名验证(动态):
00401570 > /31D2 XOR EDX,EDX ; ntdll.77519A00
00401572 . |31C9 XOR ECX,ECX
00401574 . |31DB XOR EBX,EBX
00401576 > |8A1C01 MOV BL,BYTE PTR DS:[ECX+EAX] ;依次取注册码相加取低位,DL=1B
00401579 . |00DA ADD DL,BL
0040157B . |41 INC ECX
0040157C . |80FB 00 CMP BL,0
0040157F .^|75 F5 JNZ SHORT FJLJ_cra.00401576
00401581 . |B8 00F24300 MOV EAX,FJLJ_cra.43F200
00401586 . |01D0 ADD EAX,EDX ;eax=43F21B
00401588 . |89C1 MOV ECX,EAX
0040158A . |B8 D9154000 MOV EAX,FJLJ_cra.004015D9
0040158F . |29C8 SUB EAX,ECX ;43F21B-4015D9
00401591 . |66:89C3 MOV BX,AX ;低位放bx
00401594 . |C1C8 10 ROR EAX,10
00401597 . |66:89C2 MOV DX,AX ;高位放dx
0040159A . |31C0 XOR EAX,EAX
0040159C . |C601 E9 MOV BYTE PTR DS:[ECX],0E9 ;依次将0E9,bx,dx,90放入地址43F21B
0040159F . |8859 01 MOV BYTE PTR DS:[ECX+1],BL
004015A2 . |8879 02 MOV BYTE PTR DS:[ECX+2],BH
004015A5 . |8851 03 MOV BYTE PTR DS:[ECX+3],DL
004015A8 .^|E9 3EFFFFFF JMP FJLJ_cra.004014EB
继续跟入:
004014EB > /8871 04 MOV BYTE PTR DS:[ECX+4],DH
004014EE . |C641 05 90 MOV BYTE PTR DS:[ECX+5],90
004014F2 . |51 PUSH ECX
004014F3 . |68 F6154000 PUSH FJLJ_cra.004015F6 ; /s = "serial?"
004014F8 . |E8 C3F30000 CALL <JMP.&msvcrt.puts> ; \puts
004014FD . |8B44E4 04 MOV EAX,DWORD PTR SS:[ESP+4]
00401501 . |89C3 MOV EBX,EAX
00401503 . |81F3 00F24300 XOR EBX,43F200 ;ebx=1B
00401509 . |01D8 ADD EAX,EBX ;eax=43F21B+1B
0040150B . |90 NOP
0040150C . |90 NOP
0040150D . |90 NOP
0040150E . |90 NOP
0040150F . |90 NOP
00401510 . |31DB XOR EBX,EBX
00401512 . |90 NOP
00401513 . |90 NOP
00401514 . |90 NOP
00401515 . |90 NOP
00401516 . |83C0 10 ADD EAX,10 ;eax=43F246,下面将验证码放入43F246
00401519 . |50 PUSH EAX ; /s ;输入1234567
0040151A . |E8 91F30000 CALL <JMP.&msvcrt.gets> ; \gets
0040151F . |33C9 XOR ECX,ECX
00401521 . |33D2 XOR EDX,EDX
00401523 . |33DB XOR EBX,EBX
00401525 . |8BD8 MOV EBX,EAX ebx=43F246
00401527 > |8A1408 MOV DL,BYTE PTR DS:[EAX+ECX] ;取验证码之和+ebx
0040152A . |03DA ADD EBX,EDX
0040152C . |41 INC ECX
0040152D . |8A1408 MOV DL,BYTE PTR DS:[EAX+ECX]
00401530 . |03DA ADD EBX,EDX ;ebx=0043F3B2
00401532 . |41 INC ECX
00401533 . |80FA 00 CMP DL,0
00401536 .^|75 EF JNZ SHORT FJLJ_cra.00401527
00401538 > |83E9 02 SUB ECX,2
0040153B . |8A1408 MOV DL,BYTE PTR DS:[EAX+ECX] ;ebx-偶数位
0040153E . |2BDA SUB EBX,EDX
00401540 . |83F9 00 CMP ECX,0
00401543 .^|7F F3 JG SHORT FJLJ_cra.00401538
00401545 .^|EB 84 JMP SHORT FJLJ_cra.004014CB
00401547 |90 NOP
到004014CB:
004014CB > /8A1408 MOV DL,BYTE PTR DS:[EAX+ECX] ;将上面的结果-(注册码+(i+4))*10h,i=0,i++
004014CE . |C1E2 04 SHL EDX,4
004014D1 . |2BDA SUB EBX,EDX
004014D3 . |83C1 04 ADD ECX,4
004014D6 . |80FE 00 CMP DH,0
004014D9 . |74 04 JE SHORT FJLJ_cra.004014DF
004014DB . |31D2 XOR EDX,EDX
004014DD .^ EB EC JMP SHORT FJLJ_cra.004014CB
004014DF > |EB 6F JMP SHORT FJLJ_cra.00401550
跳到00401550:
00401550 > \8B44E4 08 MOV EAX,DWORD PTR SS:[ESP+8] ; FJLJ_cra.0043F21B
00401554 . 90 NOP
00401555 . 90 NOP
00401556 . 90 NOP
00401557 . 90 NOP
00401558 . 90 NOP
00401559 . 81C3 D6040000 ADD EBX,4D6 ;上面的结果+4D6与eax比较
0040155F . 3BD8 CMP EBX,EAX ;比较
00401561 . 74 02 JE SHORT FJLJ_cra.00401565 ;关键跳,不等失败
00401563 . EB 6D JMP SHORT FJLJ_cra.004015D2
00401565 > FFE3 JMP EBX
在这我就有点迷糊了,显然ebx中就是正确的地址,根据分析正确地址是4015DE,再看看ebx中的地址怎么来的,就是上面43F200 +1B,这是不可能的,43F200>4015DE,所以ebx不能为这个值。看来ebx只是个跳转地址。但要怎么才能找到这个地址了。再回头看代码:
00401581 . |B8 00F24300 MOV EAX,FJLJ_cra.43F200
00401586 . |01D0 ADD EAX,EDX ;eax=43F21B
00401588 . |89C1 MOV ECX,EAX
0040158A . |B8 D9154000 MOV EAX,FJLJ_cra.004015D9
0040158F . |29C8 SUB EAX,ECX ;43F21B-4015D9
00401591 . |66:89C3 MOV BX,AX ;低位放bx
00401594 . |C1C8 10 ROR EAX,10
00401597 . |66:89C2 MOV DX,AX ;高位放dx
0040159A . |31C0 XOR EAX,EAX
0040159C . |C601 E9 MOV BYTE PTR DS:[ECX],0E9 ;依次将0E9,bx,dx,90放入地址43F21B
0040159F . |8859 01 MOV BYTE PTR DS:[ECX+1],BL
004015A2 . |8879 02 MOV BYTE PTR DS:[ECX+2],BH
004015A5 . |8851 03 MOV BYTE PTR DS:[ECX+3],DL
004015A8 .^|E9 3EFFFFFF JMP FJLJ_cra.004014EB
在汇编窗口看看43F21B:
0043F21B - E9 BE23FCFF JMP FJLJ_cra.004015DE
0043F220 90 NOP
0043F221 0000 ADD BYTE PTR DS:[EAX],AL
呵呵,现在一切都明白了。所以对于新手,遇到问题并不可怕,我们只要多看代码,不懂不要紧,只要多看,心里慢慢就明白了。
算法总结:
将用户名相加得t,每次取低位,s=t+43F200 ,再用s-4015D9 就得到一个差值,前面加上E9,就是一个跳转地址了,所以只要注册码算法的地址等于s,注册就成功了。
注册码的计算是:s+t+10h+注册码偶数之和-(注册码+(i+4))*10h【i=0,i++,i<注册码长度】+4D6h,只要结果等于s,就成功了。
一组注册码:name:pediy
serial:1b3g2f
唉,写文章比破解它更累,在这里感谢那些高手们,是他们不辞辛苦的写破文,才有了我们学习的机会。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
- [原创]Enigma 1.66正式版试练品脱壳笔记 8856
- [??]想加入一个群~~~ 2616
- [原创]写了一个壳,大家看看 8020
- [原创]一个简单有趣的CM 3781
看原图
赞赏
雪币:
留言: