环境:
Windows xp sp3
工具:
Ollydbg
exeinfope
无壳的程序
运行后说需要keyfile,那就创建一个。
OD载入找找看需要的keyfile叫什么名字
00401000 > $ 6A 00 push 0x0 ; |/pModule = NULL
00401002 . E8 64020000 call <jmp.&KERNEL32.GetModuleHandleA> ; |\GetModuleHandleA
00401007 . A3 77214000 mov dword ptr ds:[0x402177],eax ; |
0040100C . C705 97214000>mov dword ptr ds:[0x402197],0x4003 ; |
00401016 . C705 9B214000>mov dword ptr ds:[0x40219B],DueList_.004>; |
00401020 . C705 9F214000>mov dword ptr ds:[0x40219F],0x0 ; |
0040102A . C705 A3214000>mov dword ptr ds:[0x4021A3],0x0 ; |
00401034 . A1 77214000 mov eax,dword ptr ds:[0x402177] ; |
00401039 . A3 A7214000 mov dword ptr ds:[0x4021A7],eax ; |
0040103E . 6A 04 push 0x4 ; |/RsrcName = 4.
00401040 . 50 push eax ; ||hInst => NULL
00401041 . E8 3F030000 call <jmp.&USER32.LoadIconA> ; |\LoadIconA
00401046 . A3 AB214000 mov dword ptr ds:[0x4021AB],eax ; |
0040104B . 68 007F0000 push 0x7F00 ; |/RsrcName = IDC_ARROW
00401050 . 6A 00 push 0x0 ; ||hInst = NULL
00401052 . E8 C8020000 call <jmp.&USER32.LoadCursorA> ; |\LoadCursorA
00401057 . A3 AF214000 mov dword ptr ds:[0x4021AF],eax ; |
0040105C . 6A 00 push 0x0 ; |/hTemplateFile = NULL
0040105E . 68 6F214000 push DueList_.0040216F ; ||Attributes = READONLY|HIDDEN|SYSTEM|ARCHIVE|TEMPORARY|402048
00401063 . 6A 03 push 0x3 ; ||Mode = OPEN_EXISTING
00401065 . 6A 00 push 0x0 ; ||pSecurity = NULL
00401067 . 6A 03 push 0x3 ; ||ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
00401069 . 68 000000C0 push 0xC0000000 ; ||Access = GENERIC_READ|GENERIC_WRITE
0040106E . 68 79204000 push DueList_.00402079 ; ||FileName = "due-cm2.dat"
00401073 . E8 0B020000 call <jmp.&KERNEL32.CreateFileA> ; |\CreateFileA
运气很好,一进去就看到了名字。在40106E的位置:”due-cm2.dat”
那就创建一个叫这样的文件吧。
keyfile无效。因为里面没有东西吧,看看需要什么。。
00401078 . 83F8 FF cmp eax,-0x1 ; |
0040107B . 75 1D jnz XDueList_.0040109A ; |
0040107D . 6A 00 push 0x0 ; |/Style = MB_OK|MB_APPLMODAL
0040107F . 68 01204000 push DueList_.00402001 ; ||Title = "Duelist's Crackme #2"
00401084 . 68 17204000 push DueList_.00402017 ; ||Text = "Your time-trial has ended... Please register and copy the keyfile sent to you to this directory!"
00401089 . 6A 00 push 0x0 ; ||hOwner = NULL
0040108B . E8 D7020000 call <jmp.&USER32.MessageBoxA> ; |\MessageBoxA
00401090 . E8 24020000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
00401095 . E9 28010000 jmp DueList_.004011C2
0040109A > 6A 00 push 0x0 ; /pOverlapped = NULL
0040109C . 68 73214000 push DueList_.00402173 ; |pBytesRead = DueList_.00402173
004010A1 . 6A 46 push 0x46 ; |BytesToRead = 46 (70.)
004010A3 . 68 1A214000 push DueList_.0040211A ; |Buffer = DueList_.0040211A
004010A8 . 50 push eax ; |hFile
004010A9 . E8 2F020000 call <jmp.&KERNEL32.ReadFile> ; \ReadFile
004010AE . 85C0 test eax,eax ; 判断文件是否为空
004010B0 . 75 02 jnz XDueList_.004010B4
004010B2 . EB 43 jmp XDueList_.004010F7
004010B4 > 33DB xor ebx,ebx
004010B6 . 33F6 xor esi,esi
004010B8 . 833D 73214000>cmp dword ptr ds:[0x402173],0x12 ; 长度至少为18
004010BF . 7C 36 jl XDueList_.004010F7
004010C1 > 8A83 1A214000 mov al,byte ptr ds:[ebx+0x40211A]
004010C7 . 3C 00 cmp al,0x0
004010C9 . 74 08 je XDueList_.004010D3
004010CB . 3C 01 cmp al,0x1 ; 要有至少两个0x1
004010CD . 75 01 jnz XDueList_.004010D0
004010CF . 46 inc esi
004010D0 > 43 inc ebx
004010D1 .^ EB EE jmp XDueList_.004010C1
004010D3 > 83FE 02 cmp esi,0x2
004010D6 . 7C 1F jl XDueList_.004010F7
004010D8 . 33F6 xor esi,esi
004010DA . 33DB xor ebx,ebx
004010DC > 8A83 1A214000 mov al,byte ptr ds:[ebx+0x40211A]
004010E2 . 3C 00 cmp al,0x0
004010E4 . 74 09 je XDueList_.004010EF
004010E6 . 3C 01 cmp al,0x1 ; 0x1前面之和要为0x1D5
004010E8 . 74 05 je XDueList_.004010EF
004010EA . 03F0 add esi,eax
004010EC . 43 inc ebx ; 记录第1个0x1的位置
004010ED .^ EB ED jmp XDueList_.004010DC
004010EF > 81FE D5010000 cmp esi,0x1D5
004010F5 . 74 1D je XDueList_.00401114
004010F7 > 6A 00 push 0x0 ; |/Style = MB_OK|MB_APPLMODAL
004010F9 . 68 01204000 push DueList_.00402001 ; ||Title = "Duelist's Crackme #2"
004010FE . 68 86204000 push DueList_.00402086 ; ||Text = "Your current keyfile is invalid... Please obtain a valid one from the software author!"
00401103 . 6A 00 push 0x0 ; ||hOwner = NULL
00401105 . E8 5D020000 call <jmp.&USER32.MessageBoxA> ; |\MessageBoxA
0040110A . E8 AA010000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
0040110F . E9 AE000000 jmp DueList_.004011C2
00401114 > 33F6 xor esi,esi
00401116 > 43 inc ebx ; 第1个0x1后第2个0x1前的内容就是名字
00401117 . 8A83 1A214000 mov al,byte ptr ds:[ebx+0x40211A]
0040111D . 3C 00 cmp al,0x0
0040111F . 74 18 je XDueList_.00401139
00401121 . 3C 01 cmp al,0x1
00401123 . 74 14 je XDueList_.00401139
00401125 . 83FE 0F cmp esi,0xF
00401128 . 73 0F jnb XDueList_.00401139
0040112A . 3286 1A214000 xor al,byte ptr ds:[esi+0x40211A] ; 这里是计算名字,这个没什么所谓
00401130 . 8986 60214000 mov dword ptr ds:[esi+0x402160],eax
00401136 . 46 inc esi
00401137 .^ EB DD jmp XDueList_.00401116
00401139 > 43 inc ebx
0040113A . 33F6 xor esi,esi
0040113C > 8A83 1A214000 mov al,byte ptr ds:[ebx+0x40211A]
00401142 . 3C 00 cmp al,0x0
00401144 . 74 09 je XDueList_.0040114F
00401146 . 3C 01 cmp al,0x1 ; 计算第2个0x1后的值
00401148 .^ 74 F2 je XDueList_.0040113C
0040114A . 03F0 add esi,eax
0040114C . 43 inc ebx
0040114D .^ EB ED jmp XDueList_.0040113C
0040114F > 81FE B2010000 cmp esi,0x1B2 ; 这里和前面类似,也要使得值满足一定要求
00401155 .^ 75 A0 jnz XDueList_.004010F7 ; 不满足要求就跳到错误处
算法相对简单:
1、一开始会判断文件里的二进制值中有几个0x01,如果少于两个就错误。
2、将第一个0x01之前的所有二进制值相加,要满足它们的和为0x1D5
3、将第一个0x01和第二个0x01中间的值进行异或计算,得到的内容用于注册成功后显示。
4、将第二个0x01之后的值进行相加,要满足它们的和为0x1B2
所以很简单就得到这个:
31 32 33 34 35 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D
0D 0D 0D 0D 13 01 56 5C 46 56 51 0D 0D 0D 0D 0D
0D 0D 0D 0D 0D 01 88 88 A2