菜鸟逆袭 Crackme第二弹 附带注册机

本来想每天一破的,发现我天真了。

目标:crackme.rar

先检查有没有壳:
 crackme6.exe:ASPack 2.x (without poly) -> Alexey Solodovnikov [Overlay]
 用AspackDie1.41脱壳后:
 unpacked.ExE:LCC Win32 1.x -> Jacob Navia [Overlay]
 用w32dasm打开,发现了:GetDlgItemTextA
 很好,接下来用OD打开。
 用Ctrl+N 下API断点:GetDlgItemTextA
 F9运行下
00401539  |.  E8 FA010000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
0040153E  |.  89C3          MOV EBX,EAX                              ; EAX是返回的长度,EBX = EAX  
00401540  |.  09DB          OR EBX,EBX                               ; if (len(name) != 0 )
00401542  |.  75 04         JNZ SHORT unpacked.00401548
00401544  |.  31C0          XOR EAX,EAX                           
00401546  |.  EB 50         JMP SHORT unpacked.00401598
00401548  |>  BF BC020000   MOV EDI,2BC                              ; 2BC 是十进制 700
0040154D  |.  BE 30000000   MOV ESI,30                               ; 30 是十进制 48 也就是 '9'
00401552  |.  B8 48000000   MOV EAX,48                               ; 48 是十进制 72 
00401557  |.  99            CDQ                                      ; Convert Double to Quad,EDX拓展为EAX的高位  
00401558  |.  F7FB          IDIV EBX                                 ; 
0040155A  |.  29C6          SUB ESI,EAX                             
0040155C  |.  8D34B6        LEA ESI,DWORD PTR DS:[ESI+ESI*4]
0040155F  |.  29F7          SUB EDI,ESI
00401561  |.  6BFF 6B       IMUL EDI,EDI,6B
00401564  |.  81EF 6CCF0000 SUB EDI,0CF6C
0040156A  |.  81FF 00230000 CMP EDI,2300
00401570  |.  7F 08         JG SHORT unpacked.0040157A
00401572  |.  81FF 90010000 CMP EDI,190
00401578  |.  7D 04         JGE SHORT unpacked.0040157E
0040157A  |>  31C0          XOR EAX,EAX
0040157C  |.  EB 1A         JMP SHORT unpacked.00401598
0040157E  |>  8D85 00FFFFFF LEA EAX,DWORD PTR SS:[EBP-100]



分析过程:
 a = 30 - (48/len(name))
 b = 2BC - ptr[a+4a]
 c = b * b * 6B
 d = c - 0CF6C  可能是个负数。。    
 if d > 2300  跳到 0040157A 然后就完蛋了   
 if d >= 190    跳到 0040157E 有戏
 EDI与0CF6C想减后为e, 400 <= e <=8960
 往上看,发现EDI - ESI,然后一开始的EDI赋值为2BC,关键在ESI
 ESI 赋值为30,30 - (48/len(name)),余数放在EAX中,然后ESI - EAX 减去这个余数
 然后取地址。。这个地址怎么办?DWORD PTR DS:[ESI+ESI*4]?
 
 在这里做不下去了,看了下答案,发现2点很可怕的地方:
 (1)DWORD PTR DS:[ESI+ESI*4] 是取ESI * 5 ,据大神说,lea是专业计算这类公式的 ,这里有中括号,就当成特殊处理吧
 (2)IMUL EDI,EDI,6B 是将 第二个操作数 * 第三个操作数 然后结果放在第一个操作数
 
 纠错后,总结下: EDI = [ 2bc - (30 - 48/namelen)*5 ]*6b- CF6C 然后结果要: 190 <= EDI <= 2300
 那么经过一番运算后:namelen 要在 [3,9] 之间。。
 F9重新运行下,输入长度为6的 xihuan
 序列号输入:woaini
 
接下来进行序列号的猜解:
004013B4  |.  09C0          OR EAX,EAX                            ;if namelen == 0 跳走00401504 挂了
004013B6  |.  0F84 48010000 JE unpacked.00401504
004013BC  |.  B8 CF110000   MOV EAX,11CF              
004013C1  |.  0FB68D E1FCFF>MOVZX ECX,BYTE PTR SS:[EBP-31F]       ;这里是序列号的第一位'w'    
004013C8  |.  99            CDQ
004013C9  |.  F7F9          IDIV ECX
004013CB  |.  83FA 17       CMP EDX,17                            ;if (EDX == 17) 
004013CE  |.  74 07         JE SHORT unpacked.004013D7            ; 跳到004013D7 不挂   
004013D0  |.  31C0          XOR EAX,EAX
004013D2  |.  E9 2D010000   JMP unpacked.00401504                 ; 不跳走就挂掉了,
004013D7  |>  31DB          XOR EBX,EBX
004013D9  |.  EB 0B         JMP SHORT unpacked.004013E6
004013DB  |>  8B45 10       /MOV EAX,DWORD PTR SS:[EBP+10]        ; name = "xihuan"
004013DE  |.  0FBE0418      |MOVSX EAX,BYTE PTR DS:[EAX+EBX]      ; name的第一个字符'x' 
004013E2  |.  0145 FC       |ADD DWORD PTR SS:[EBP-4],EAX         ; ?!
004013E5  |.  43            |INC EBX                              ; 自增     
004013E6  |>  3B5D 0C        CMP EBX,DWORD PTR SS:[EBP+C]         ; name 的 长度 6   
004013E9  |.^ 7C F0         \JL SHORT unpacked.004013DB           ; 递增至长度6则结束
004013EB  |.  31DB          XOR EBX,EBX
004013ED  |.  E9 83000000   JMP unpacked.00401475

分析过程:
EAX = 11CF
ECX = 'w' 
EAX/ECX 商放在EAX,余数放在EDX
if (EDX == 17) 就不会挂 ,那么这个ECX应该是
 23(10) = 17(h):
 36  * 126 + 23
 42  * 108 + 23
 54  * 84 + 23
 56  * 81 + 23
 63  * 72 + 23
 72  * 63 + 23
 81  * 56 + 23
 84  * 54 + 23
 这里我去108,也就是'l',重新开始,F9
 序列号输入为lwoaini,判定成功,避免挂了
 
 004013DB  |>  8B45 10       /MOV EAX,DWORD PTR SS:[EBP+10]        ; name = "xihuan"
004013DE  |.  0FBE0418      |MOVSX EAX,BYTE PTR DS:[EAX+EBX]      ; name的第一个字符'x' 
004013E2  |.  0145 FC       |ADD DWORD PTR SS:[EBP-4],EAX         ; 不懂!
004013E5  |.  43            |INC EBX                              ; 自增     
004013E6  |>  3B5D 0C        CMP EBX,DWORD PTR SS:[EBP+C]         ;   
004013E9  |.^ 7C F0         \JL SHORT unpacked.004013DB

这段就是把用户名 "xihuan"的每一个字符都加到 SS:[EBP-4]中。
那么SS:[EBP-4]到底是什么?
找到0D中的:
0012F8F0   0000021F  <- 这个地方就是EBP-4。
0012F8F4  /0012FA14
0012F8F8  |0040158E  RETURN to unpacked.0040158E from unpacked.00401305
0012F8FC  |00490332
0012F900  |00000006  <- 这里就是 EBP+C 也就是存在着长度
0012F904  |0012F914  ASCII "xihuan"
0012F908  |0012FA3B  ASCII "SHiT ... you entered the correct serial!"
0012F90C  |00402593  ASCII "You have to make an own working keygen!
这里我懂了,把name的每一个字符都加到[EBP-4]中,最后加完 “xihuan”总和为28D.

加完之后又会跳入一个循环,这个循环是计算用:
004013F2  |>  8B55 10       /MOV EDX,DWORD PTR SS:[EBP+10]       ;这是“xihuan”的地址
004013F5  |.  0FBE3C1A      |MOVSX EDI,BYTE PTR DS:[EDX+EBX]     ;这里循环不断去xihuan的单字符,第一个为x  
004013F9  |.  8B75 FC       |MOV ESI,DWORD PTR SS:[EBP-4]        ; 刚刚的 xihuan 字符和 :28D
004013FC  |.  89D9          |MOV ECX,EBX                         ;  
004013FE  |.  C1E1 02       |SHL ECX,2                           ; ECX 左移2为,第一次中为000即为 0     
00401401  |.  89DA          |MOV EDX,EBX                         ;    
00401403  |.  42            |INC EDX                             ; 第一次中,EDX 增1 为 1
00401404  |.  29D1          |SUB ECX,EDX                         ; 0 - 1 = FFFFFFFF 
00401406  |.  0FB68C0D E1FE>|MOVZX ECX,BYTE PTR SS:[EBP+ECX-11F] ; 查看了地址发现是 ECX = 0 
0040140E  |.  89FA          |MOV EDX,EDI                         ; EDX = 'x' 
00401410  |.  31CA          |XOR EDX,ECX                         ; EDX =  name[i] ^SS:[EBP+(3*i-1)-11F]
00401412  |.  89F1          |MOV ECX,ESI                         ; ECX = 28D ..字符和 
00401414  |.  0FAFCB        |IMUL ECX,EBX                        ; 
00401417  |.  29F1          |SUB ECX,ESI
00401419  |.  89CE          |MOV ESI,ECX
0040141B  |.  83F6 FF       |XOR ESI,FFFFFFFF                    ; ESI = (sum*i-sum)^FFFFFFFF 
0040141E  |.  8DB432 4D0100>|LEA ESI,DWORD PTR DS:[EDX+ESI+14D]  ; ESI = DS:[EDX + ESI + 14D]  
00401425  |.  8B4D 0C       |MOV ECX,DWORD PTR SS:[EBP+C]        ;  
00401428  |.  89DA          |MOV EDX,EBX
0040142A  |.  83C2 03       |ADD EDX,3
0040142D  |.  0FAFCA        |IMUL ECX,EDX
00401430  |.  0FAFCF        |IMUL ECX,EDI
00401433  |.  89F0          |MOV EAX,ESI
00401435  |.  01C8          |ADD EAX,ECX
00401437  |.  B9 0A000000   |MOV ECX,0A
0040143C  |.  31D2          |XOR EDX,EDX
0040143E  |.  F7F1          |DIV ECX
00401440  |.  83C2 30       |ADD EDX,30
00401443  |.  88941D FCFEFF>|MOV BYTE PTR SS:[EBP+EBX-104],DL
0040144A  |.  0FB6BC1D FCFE>|MOVZX EDI,BYTE PTR SS:[EBP+EBX-104]
00401452  |.  81F7 ACAD0000 |XOR EDI,0ADAC
00401458  |.  89DE          |MOV ESI,EBX
0040145A  |.  83C6 02       |ADD ESI,2
0040145D  |.  89F8          |MOV EAX,EDI
0040145F  |.  0FAFC6        |IMUL EAX,ESI
00401462  |.  B9 0A000000   |MOV ECX,0A
00401467  |.  99            |CDQ
00401468  |.  F7F9          |IDIV ECX
0040146A  |.  83C2 30       |ADD EDX,30
0040146D  |.  88941D FCFEFF>|MOV BYTE PTR SS:[EBP+EBX-104],DL
00401474  |.  43            |INC EBX
00401475  |>  3B5D 0C        CMP EBX,DWORD PTR SS:[EBP+C]
00401478  |.^ 0F8C 74FFFFFF \JL unpacked.004013F2



分析过程:
这一段好长。
其中涉及到 是一段字母表 CBA0 GFED ...:
0012F7D4   43424100
0012F7D8   47464544
0012F7DC   4B4A4948
0012F7E0   4F4E4D4C
0012F7E4   53525150
0012F7E8   57565554
0012F7EC   005A5958


(((((name[i]^helpStr[i*3-1])+((sum*i-sum)^0xffffffff)+0x14d+(i+3)*name_len*name[i])%10+0x30)^0xadac)*(i+2))%10+0x30;
其中helpStr就是26字母表
把这计算结果存放到 SS:[EBP+EBX-104]
Ps:贫道做完这个计算过程分析后,深感蛋疼。


0040147E  |.  8D85 FCFEFFFF LEA EAX,DWORD PTR SS:[EBP-104]            ;这里存在着计算完的序列号 204069  
00401484  |.  50            PUSH EAX
00401485  |.  6A 54         PUSH 54
00401487  |.  8D85 DCFBFFFF LEA EAX,DWORD PTR SS:[EBP-424]
0040148D  |.  50            PUSH EAX                                 ; |Format
0040148E  |.  8D85 E1FBFFFF LEA EAX,DWORD PTR SS:[EBP-41F]           ; |
00401494  |.  50            PUSH EAX                                 ; |s
00401495  |.  E8 CE020000   CALL <JMP.&USER32.wsprintfA>             ; \wsprintfA <- 这里把结算结果改为T204069
0040149A  |.  8B7D 0C       MOV EDI,DWORD PTR SS:[EBP+C]             ; namelen = 6
0040149D  |.  89F8          MOV EAX,EDI                              ; 6
0040149F  |.  0FAF45 FC     IMUL EAX,DWORD PTR SS:[EBP-4]            ; 6 * 2BD (sum(name)) 
004014A3  |.  B9 64000000   MOV ECX,64                               ; 64 
004014A8  |.  99            CDQ                                  
004014A9  |.  F7F9          IDIV ECX                                 ;  6 * 2BD (sum(name)) /64
004014AB  |.  89D7          MOV EDI,EDX                              ;  6 * 2BD (sum(name)) mod 64
004014AD  |.  83C7 30       ADD EDI,30                               ;  6 * 2BD (sum(name)) mod 64 + 30
004014B0  |.  57            PUSH EDI                                 
004014B1  |.  8DBD E1FBFFFF LEA EDI,DWORD PTR SS:[EBP-41F]       
004014B7  |.  57            PUSH EDI
004014B8  |.  8DBD D6FBFFFF LEA EDI,DWORD PTR SS:[EBP-42A]
004014BE  |.  57            PUSH EDI                                 ; |Format
004014BF  |.  8DBD E1FDFFFF LEA EDI,DWORD PTR SS:[EBP-21F]           ; |         format("%s-%d","T204069",42)
004014C5  |.  57            PUSH EDI                                 ; |s        42的十进制是66  
004014C6  |.  E8 9D020000   CALL <JMP.&USER32.wsprintfA>             ; \wsprintfA <- 到这里计算结果为T204069-66
004014CB  |.  83C4 20       ADD ESP,20
004014CE  |.  8D8D E1FDFFFF LEA ECX,DWORD PTR SS:[EBP-21F]             
004014D4  |.  83C8 FF       OR EAX,FFFFFFFF

 
004014CB  |.  83C4 20       ADD ESP,20
004014CE  |.  8D8D E1FDFFFF LEA ECX,DWORD PTR SS:[EBP-21F]           ; 这里要注意。。应该遍历字符串
004014D4  |.  83C8 FF       OR EAX,FFFFFFFF
004014D7  |>  40            /INC EAX
004014D8  |.  803C01 00     |CMP BYTE PTR DS:[ECX+EAX],0             ; 直到取到了字符‘\0’也就是结尾
004014DC  |.^ 75 F9         \JNZ SHORT unpacked.004014D7
004014DE  |.  50            PUSH EAX                                 ; /Arg3
004014DF  |.  8D85 E1FCFFFF LEA EAX,DWORD PTR SS:[EBP-31F]           ; |             T204069-TT
004014E5  |.  50            PUSH EAX                                 ; |Arg2
004014E6  |.  8D85 E1FDFFFF LEA EAX,DWORD PTR SS:[EBP-21F]           ; |             lwoaini 
004014EC  |.  50            PUSH EAX                                 ; |Arg1
004014ED  |.  E8 D0FDFFFF   CALL unpacked.004012C2                   ; \unpacked.004012C2 这里进去看看
004014F2  |.  83C4 0C       ADD ESP,0C 
004014F5  |.  83F8 00       CMP EAX,0
004014F8  |.  75 07         JNZ SHORT unpacked.00401501
004014FA  |.  B8 00000000   MOV EAX,0
004014FF  |.  EB 03         JMP SHORT unpacked.00401504
00401501  |>  31C0          XOR EAX,EAX
00401503  |.  40            INC EAX
00401504  |>  5F            POP EDI
00401505  |.  5E            POP ESI
00401506  |.  5B            POP EBX
00401507  |.  C9            LEAVE
00401508  \.  C3            RETN


参数是T204069-66 和 lwoaini ,进来call 看看:
004012C2  /$  55            PUSH EBP                                 ; 
004012C3  |.  89E5          MOV EBP,ESP
004012C5  |.  53            PUSH EBX
004012C6  |.  56            PUSH ESI
004012C7  |.  57            PUSH EDI
004012C8  |.  8B5D 10       MOV EBX,DWORD PTR SS:[EBP+10]            ; len=10
004012CB  |.  31F6          XOR ESI,ESI                                
004012CD  |.  46            INC ESI                                  ; <- 这一步导致'T'被忽略从'2'开始   
004012CE  |.  EB 29         JMP SHORT unpacked.004012F9              ; 循环开始      
004012D0  |>  8B55 08       /MOV EDX,DWORD PTR SS:[EBP+8]            ; 204069-66 
004012D3  |.  0FBE3C32      |MOVSX EDI,BYTE PTR DS:[EDX+ESI]         ; 2    
004012D7  |.  89F8          |MOV EAX,EDI                            
004012D9  |.  83F0 20       |XOR EAX,20                              ; 2 XOR 20  
004012DC  |.  B9 0A000000   |MOV ECX,0A                              
004012E1  |.  99            |CDQ        
004012E2  |.  F7F9          |IDIV ECX                                ; (2 XOR 20)/0A
004012E4  |.  89D7          |MOV EDI,EDX                             ; (2 XOR 20) mod 0A
004012E6  |.  83C7 30       |ADD EDI,30                              ; EDI = (2 XOR 20) mod 0A + 30
004012E9  |.  8B55 0C       |MOV EDX,DWORD PTR SS:[EBP+C]            ; lwoaini     
004012EC  |.  0FBE1432      |MOVSX EDX,BYTE PTR DS:[EDX+ESI]         ; EDX = l    
004012F0  |.  39D7          |CMP EDI,EDX                             ; 比较 EDI 和 EDX <- 注意这里是关键!!
004012F2  |.  74 04         |JE SHORT unpacked.004012F8
004012F4  |.  31C0          |XOR EAX,EAX
004012F6  |.  EB 08         |JMP SHORT unpacked.00401300
004012F8  |>  46            |INC ESI
004012F9  |>  39DE           CMP ESI,EBX                           
004012FB  |.^ 7C D3         \JL SHORT unpacked.004012D0

总结: 1. 用户名“xihuan”经过(((((name[i]^helpStr[i*3-1])+((sum*i-sum)^0xffffffff)+0x14d+(i+3)*name_len*name[i])%10+0x30)^0xadac)*(i+2))%10+0x30; 
          变成了“204069”,然后+'T'变成'T204069',加'-',然后加尾巴'66','66'是这么来的 (sum * length) % 0x64 +0x30;(Ps:'66'的分析较简单,于是没写出来)
       2. 每个字符     EDI = (T XOR 20) mod 0A + 30  合起来就是“xihuan”的序列号了
      
if __name__ == "__main__":
    str = "204069-66";
    res = ""
    for i in str :
        lrc = (ord(i) ^ 32) %10 +48
        print "%c %d",i,ord(i),lrc
        res = res + chr(lrc)
    print 'l'+res

结果:l860625322
至此:用户名是xihuan 序列号是:l860625322 


分析很透彻,就随带写了注册机,出了点小问题,用python无法定义出unsigned int,只能转为c语言写了。

// getSerial.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "string.h"
#include "stdlib.h"
#include <stdio.h>

int main(int argc, char* argv[])
{

	unsigned int i,sum,length,length2,esi,ecx,edx,edi;
	char name[] = "xihuan"; 
    char helpstr[]={'\0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
    
	while (true)
	{
		printf("Please enter username(finished with '#' , name's length in [3,9]) :");
		scanf("%s",name) ;
		if(strcmp(name,"#") == 0) break;

		length = strlen(name);
		char *tmpStr = (char*)malloc( sizeof(char)*length);
		char *tmpStr2 = (char*)malloc(sizeof(char)*length+4);
		char *resStr = (char*)malloc(sizeof(char)*length+4);

		sum = 0;
		for(i = 0 ; i < length ; i++) 
			sum  += (unsigned int)name[i];
		for(i = 0 ; i < length ; i++) 
		{
			if (i == 0) 
				edx = 0 ^ (unsigned int)name[i];
			else
				edx = (unsigned int)helpstr[3*i] ^ (unsigned int)name[i];
			esi = (0xFFFFFFFF ^ sum*(i-1)) +edx +0x14d;
			ecx =(length*(i+3)*(unsigned int)name[i]+esi)%0xA+0x30;
			ecx =( (ecx ^ 0xADAC) *(2+i))%0xA+0x30;
			tmpStr[i]=ecx;
		}
		tmpStr[i] = '\0';
		edi = (sum * length) % 0x64 +0x30;
		sprintf(tmpStr2,"%s-%d",tmpStr,edi);

		length2 = strlen(tmpStr2);
		for(i = 0 ; i < length2 ; i++)
		{
			tmpStr2[i] = (tmpStr2[i] ^ 0x20) % 0xA +0x30;
		}
		sprintf(resStr,"%c%s",'l',tmpStr2); 
		printf("Result is:  %s\n",resStr);
	}
	return 0;
}



你可能感兴趣的:(菜鸟逆袭 Crackme第二弹 附带注册机)