系统 : Windows xp
程序 : unabexcm5fl
程序下载地址 :http://pan.baidu.com/s/1pJYaNUV
要求 : 爆破
使用工具 :OD
可在“PEDIY CrackMe 2007”中查找关于此程序的破文,标题为“菜鸟必看的破解文章(2)-追出软件注册码”。
看上去是个很小的程序所以直接OD载入,对GetDlgItemTextA下断并运行程序,返回用户领空后的汇编指令如下:
0040106C |> 6A 25 push 25 ; /Count = 25 (37.)
0040106E |. 68 24234000 push 00402324 ; |Buffer = unabexcm.00402324
00401073 |. 6A 68 push 68 ; |ControlID = 68 (104.)
00401075 |. FF75 08 push dword ptr [ebp+8] ; |hWnd
00401078 |. E8 F4000000 call <jmp.&USER32.GetDlgItemTextA> ; GetDlgItemTextA
0040107D |. 6A 00 push 0 ; /pFileSystemNameSize = NULL
0040107F |. 6A 00 push 0 ; |pFileSystemNameBuffer = NULL
00401081 |. 68 C8204000 push 004020C8 ; |pFileSystemFlags = unabexcm.004020C8
00401086 |. 68 90214000 push 00402190 ; |pMaxFilenameLength = unabexcm.00402190
0040108B |. 68 94214000 push 00402194 ; |pVolumeSerialNumber = unabexcm.00402194
00401090 |. 6A 32 push 32 ; |MaxVolumeNameSize = 32 (50.)
00401092 |. 68 5C224000 push 0040225C ; |VolumeNameBuffer = unabexcm.0040225C
00401097 |. 6A 00 push 0 ; |RootPathName = NULL
00401099 |. E8 B5000000 call <jmp.&KERNEL32.GetVolumeInformat>; GetVolumeInformationA
0040109E |. 68 F3234000 push 004023F3 ; /StringToAdd = "4562-ABEX"
004010A3 |. 68 5C224000 push 0040225C ; |ConcatString = "曙?
004010A8 |. E8 94000000 call <jmp.&KERNEL32.lstrcatA> ; lstrcatA
004010AD |. B2 02 mov dl, 2 ; ↑↑GetVolumeInformation获取磁盘信息
004010AF |> 8305 5C224000>/add dword ptr [40225C], 1 ; 存放卷标的内存每个字节+1
004010B6 |. 8305 5D224000>|add dword ptr [40225D], 1
004010BD |. 8305 5E224000>|add dword ptr [40225E], 1
004010C4 |. 8305 5F224000>|add dword ptr [40225F], 1
004010CB |. FECA |dec dl ; 循环两次
004010CD |.^ 75 E0 jnz short 004010AF ; ↓‘L2C-5781’+累加处理之后的卷标名就是序列号啦。
004010CF |. 68 FD234000 push 004023FD ; /StringToAdd = "L2C-5781"
004010D4 |. 68 00204000 push 00402000 ; |ConcatString = "L2C-5781曙?
004010D9 |. E8 63000000 call <jmp.&KERNEL32.lstrcatA> ; lstrcatA
004010DE |. 68 5C224000 push 0040225C ; /StringToAdd = "曙?
004010E3 |. 68 00204000 push 00402000 ; |ConcatString = "L2C-5781曙?
004010E8 |. E8 54000000 call <jmp.&KERNEL32.lstrcatA> ; lstrcatA
004010ED |. 68 24234000 push 00402324 ; /String2 = "fewagweag"
004010F2 |. 68 00204000 push 00402000 ; |String1 = "L2C-5781曙?
004010F7 |. E8 51000000 call <jmp.&KERNEL32.lstrcmpiA> ; lstrcmpiA
004010FC |. 83F8 00 cmp eax, 0
004010FF |. 74 16 je short 00401117
00401101 |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
00401103 |. 68 34244000 push 00402434 ; |Title = "Error!"
00401108 |. 68 3B244000 push 0040243B ; |Text = "The serial you entered is not correct!"
0040110D |. FF75 08 push dword ptr [ebp+8] ; |hOwner
00401110 |. E8 56000000 call <jmp.&USER32.MessageBoxA> ; MessageBoxA
00401115 |. EB 16 jmp short 0040112D
00401117 |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
00401119 |. 68 06244000 push 00402406 ; |Title = "Well Done!"
0040111E |. 68 11244000 push 00402411 ; |Text = "Yep, you entered a correct serial!"
00401123 |. FF75 08 push dword ptr [ebp+8] ; |hOwner
00401126 |. E8 40000000 call <jmp.&USER32.MessageBoxA> ; MessageBoxA
0040112B |. EB 00 jmp short 0040112D
0040112D |$ 6A 00 push 0 ; /Result = 0
0040112F |. FF75 08 push dword ptr [ebp+8] ; |hWnd
00401132 |. E8 22000000 call <jmp.&USER32.EndDialog> ; EndDialog
00401137 |. C9 leave
00401138 . C2 1000 retn 10
这里有个陌生的函数调用,其定义如下:
BOOL WINAPI GetVolumeInformation(
_In_opt_ LPCTSTR lpRootPathName,
_Out_opt_ LPTSTR lpVolumeNameBuffer,
_In_ DWORD nVolumeNameSize,
_Out_opt_ LPDWORD lpVolumeSerialNumber,
_Out_opt_ LPDWORD lpMaximumComponentLength,
_Out_opt_ LPDWORD lpFileSystemFlags,
_Out_opt_ LPTSTR lpFileSystemNameBuffer,
_In_ DWORD nFileSystemNameSize
);
这里主要就是获取程序所在磁盘的信息,比如本次在D盘下运行,就获取了卷标“软件”这个字串,再对字串做一些操作然后连接一个固定字串就是正确的序列号了。
这里,我们直接将4010FF处的指令修改为JNE,然后选择保存,这样爆破就完成了:
-------------------------------------------------------------------------------------------------------------------
后记:之前存放程序的盘卷标名是中文,所以该cm连接字符时出了问题,这次写出了注册机也是专门把卷标名“软件”改成了“SoftWarre”配合。
算法很简单,所以直接用c写一个无界面的注册机:
#include <windows.h>
#include <stdio.h>
int main(int argc,char **argv)
{
DWORD VolumeSerialNumber;
char VolumeName[256];
GetVolumeInformation( NULL,VolumeName,12,&VolumeSerialNumber,NULL,NULL,NULL,10);
printf( "本程序所在盘的卷标:%s
",VolumeName);
VolumeName[0] += 2;
VolumeName[1] += 2;
VolumeName[2] += 2;
VolumeName[3] += 2;
printf( "经过累加之后的卷标:%s
",VolumeName);
char* Prefix = "L2C-5781";
char* Suffix = "4562-ABEX";
printf( "生成的序列号:%s%s%s
",Prefix,VolumeName,Suffix);
getchar();
return 0;
}
运行效果: