【破解作者】 analog
【作者邮箱】 yuchaochina@hotmail.com
【使用工具】 OllyDbgV1.10,PEidV0.93
【破解平台】 WinXP
【软件名称】 aescul.exe(CrackMe)
【加壳方式】 无
【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)
--------------------------------------------------------------------------------
【破解内容】
代码段的开头可以找到DialogBoxParam
00401024 |. 68 84314000 push aescul.00403184 ; |DlgProc = aescul.00403184
;窗口处理程序,在地址004030184下面附近下断点
输入注册名,注册码后点OK,来到下面的代码段
0040320A > \833D F6444000 0>cmp dword ptr ds:[4044F6],1 ; 数据段是否自修改过
00403211 . 74 11 je short aescul.00403224 ; 修改过则跳
00403213 . BE 00404000 mov esi,aescul.00404000
00403218 . 8BFE mov edi,esi
0040321A . B9 160B0000 mov ecx,0B16
0040321F . E8 41020000 call aescul.00403465 ; 自修改子程序(数据段修改)
00403224 > 6A 40 push 40 ; /Count = 40 (64.)
00403226 . 68 BA414000 push aescul.004041BA ; |Buffer = aescul.004041BA ;注册名存放地址
0040322B . 68 E8030000 push 3E8 ; |ControlID = 3E8 (1000.)
00403230 . FF75 08 push dword ptr ss:[ebp+8] ; |hWnd
00403233 . E8 89020000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA ;获得注册名
00403238 . BF BA414000 mov edi,aescul.004041BA
0040323D . 33C0 xor eax,eax
0040323F . 83C9 FF or ecx,FFFFFFFF
00403242 . F2:AE repne scas byte ptr es:[edi]
00403244 . F7D1 not ecx
00403246 . 2BF9 sub edi,ecx
00403248 . 890D 064B4000 mov dword ptr ds:[404B06],ecx ; 存注册名长度
0040324E . 803D BA414000 0>cmp byte ptr ds:[4041BA],0 ; 比较注册名第一个字节是否为\0
00403255 . 6A 40 push 40 ; /Count = 40 (64.)
00403257 . 68 BA424000 push aescul.004042BA ; |Buffer = aescul.004042BA ;注册码存放地址
0040325C . 68 E9030000 push 3E9 ; |ControlID = 3E9 (1001.)
00403261 . FF75 08 push dword ptr ss:[ebp+8] ; |hWnd
00403264 . E8 58020000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA ;获得注册码
00403269 . BF BA424000 mov edi,aescul.004042BA
0040326E . 33C0 xor eax,eax
00403270 . 83C9 FF or ecx,FFFFFFFF
00403273 . F2:AE repne scas byte ptr es:[edi]
00403275 . F7D1 not ecx
00403277 . 2BF9 sub edi,ecx
00403279 . 890D 0A4B4000 mov dword ptr ds:[404B0A],ecx ; 存注册码长度
0040327F . 803D BA424000 0>cmp byte ptr ds:[4042BA],0 ; 比较注册码第一个字节是否为\0
00403286 . 68 0E4B4000 push aescul.00404B0E ; /pHandle = aescul.00404B0E
0040328B . 6A 01 push 1 ; |Access = KEY_QUERY_VALUE
0040328D . 6A 00 push 0 ; |Reserved = 0
0040328F . 68 00404000 push aescul.00404000 ; |Subkey = "Software\Microsoft\Windows\CurrentVersion"
00403294 . 68 02000080 push 80000002 ; |hKey = HKEY_LOCAL_MACHINE
00403299 . E8 71020000 call <jmp.&ADVAPI32.RegOpenKeyExA> ; \RegOpenKeyExA ;打开注册表子键
0040329E . 68 124B4000 push aescul.00404B12 ; /pBufSize = aescul.00404B12
004032A3 . 68 BC434000 push aescul.004043BC ; |Buffer = aescul.004043BC
004032A8 . 6A 00 push 0 ; |pValueType = NULL
004032AA . 6A 00 push 0 ; |Reserved = NULL
004032AC . 68 33404000 push aescul.00404033 ; |ValueName = "ProductId"
004032B1 . FF35 0E4B4000 push dword ptr ds:[404B0E] ; |hKey = FFFFFFFF
004032B7 . E8 4D020000 call <jmp.&ADVAPI32.RegQueryValueExA>; \RegQueryValueExA ;取键值
004032BC . BF BA434000 mov edi,aescul.004043BA
004032C1 . 33C0 xor eax,eax
004032C3 . 83C9 FF or ecx,FFFFFFFF
004032C6 . F2:AE repne scas byte ptr es:[edi]
004032C8 . F7D1 not ecx
004032CA . 2BF9 sub edi,ecx
004032CC . 890D BC444000 mov dword ptr ds:[4044BC],ecx
004032D2 . 833D FA444000 0>cmp dword ptr ds:[4044FA],1 ; FLAG,为1表示代码已修改
004032D9 . 74 11 je short aescul.004032EC ; 不为1则跳转
004032DB . BE 50304000 mov esi,aescul.00403050
004032E0 . 8BFE mov edi,esi
004032E2 . B9 34010000 mov ecx,134
004032E7 . E8 8E010000 call aescul.0040347A ; 自修改子程序(代码段自修改)
004032EC > E9 8F000000 jmp aescul.00403380 ; 跳到EndDialog
下面是自修改的子程序:(简单的循环左移加密)
00403465 /$ 33C0 xor eax,eax ; 清eax值
00403467 |. AC lods byte ptr ds:[esi] ; 取字节
00403468 |. D2C0 rol al,cl ; al循环左移cl次
0040346A |. F6D0 not al ; al取反
0040346C |. AA stos byte ptr es:[edi] ; 代码重新存回
0040346D |.^ E2 F6 loopd short aescul.00403465 ; 循环
0040346F |. C705 F6444000 0>mov dword ptr ds:[4044F6],1
00403479 |. C3 retn
0040347A |$ 33C0 xor eax,eax ; 代码自修改
0040347C |. AC lods byte ptr ds:[esi] ; 取字节
0040347D |. D2C0 rol al,cl ; al循环左移cl次
0040347F |. F6D0 not al ; al取反
00403481 |. AA stos byte ptr es:[edi] ; 代码重新存回
00403482 |.^ E2 E1 loopd short aescul.00403465 ; 循环
00403484 |. C705 FA444000 0>mov dword ptr ds:[4044FA],1
0040348E \. C3 retn
00401000 . /EB 14 jmp short aescul.<ModuleEntryPoint>
00401002 . |58344000 dd aescul.00403458
00401006 . |5C344000 dd aescul.0040345C
0040100A . |8F344000 dd aescul.0040348F
0040100E . |9E344000 dd aescul.0040349E
00401012 . |A0344000 dd aescul.004034A0
00401016 a>/$ \6A 00 push 0 ; /pModule = NULL
00401018 |. E8 CE240000 call <jmp.&KERNEL32.GetModuleHandleA>; \GetModuleHandleA
0040101D |. A3 87414000 mov dword ptr ds:[404187],eax
00401022 |. 6A 00 push 0 ; /lParam = NULL
00401024 |. 68 84314000 push aescul.00403184 ; |DlgProc = aescul.00403184 ;
00401029 |. 6A 00 push 0 ; |hOwner = NULL
0040102B |. 6A 65 push 65 ; |pTemplate = 65
0040102D |. FF35 87414000 push dword ptr ds:[404187] ; |hInst = FFFFFFFF
00401033 |. E8 7D240000 call <jmp.&USER32.DialogBoxParamA> ; \DialogBoxParamA
00401038 |. 90 nop ; EndDialog之后返回到这
00401039 |. 90 nop
0040103A |. 90 nop
由EndDialog返回后再系统dll中绕了半天才跳到这
经过n多的nop到00403038,就是刚才SMC之后的代码段,MessageBox也在这,爆破是不行了
00403038 |. 33C0 xor eax,eax
0040303A |. 68 93334000 push aescul.00403393
0040303F |. 64:FF30 push dword ptr fs:[eax]
00403042 |. 64:8920 mov dword ptr fs:[eax],esp
00403045 |. 9C pushfd
00403046 |. 9C pushfd
00403047 |. 58 pop eax ; eax=246H
00403048 |. 0D 00010000 or eax,100 ; eax=346H
0040304D |. 50 push eax
0040304E |. 9D popfd
0040304F |. 90 nop
00403050 |. 33F6 xor esi,esi ; 清空寄存器
00403052 |. 33FF xor edi,edi ; 清空寄存器
00403054 |. 33D2 xor edx,edx ; 清空寄存器
00403056 |. 8B2D 124B4000 mov ebp,dword ptr ds:[404B12] ; 循环次数24
0040305C |. BF 02454000 mov edi,aescul.00404502 ; 变换后的正确注册码的地址
00403061 |> 55 /push ebp
00403062 |. 57 |push edi
00403063 |. 56 |push esi
00403064 |. BD C0444000 |mov ebp,aescul.004044C0 ; ASCII "0I5LZ7G123RXCV9OPAS6TBN48YUHJKDF0QWEM"(字符串2)
00403069 |. BB BA434000 |mov ebx,aescul.004043BA ; ASCII "WS55661-640-0059266-23364"
0040306E |. 8A0433 |mov al,byte ptr ds:[ebx+esi] ; 取"WS"+ProductID的一个字节放到al
00403071 |. C1F8 04 |sar eax,4 ; eax算术右移4次
00403074 |. 83E0 0F |and eax,0F ; eax和0F做与运算(取该字节的高四位)
00403077 |. E8 BF000000 |call aescul.0040313B
0040307C |. 8807 |mov byte ptr ds:[edi],al
0040307E |. 8A0C33 |mov cl,byte ptr ds:[ebx+esi] ; 取"WS"+ProduceID的一个字节放到cl
00403081 |. 83E1 0F |and ecx,0F ; 取ecx的低四位(取该字节的低四位)
00403084 |. 8BC1 |mov eax,ecx ; 移动到eax
00403086 |. E8 B0000000 |call aescul.0040313B
0040308B |. 8847 01 |mov byte ptr ds:[edi+1],al
0040308E |. 5E |pop esi
0040308F |. 5F |pop edi
00403090 |. 5D |pop ebp
00403091 |. 46 |inc esi
00403092 |. 83C7 02 |add edi,2
00403095 |. 3BEE |cmp ebp,esi
00403097 |.^ 75 C8 \jnz short aescul.00403061
00403099 |. 33F6 xor esi,esi ; 下面依次取码比较
0040309B |. 8B86 BA424000 mov eax,dword ptr ds:[esi+4042BA] ; 注册码
004030A1 |. 8B9E 02454000 mov ebx,dword ptr ds:[esi+404502] ; 变化后的字符串
004030A7 3BC0 cmp eax,eax ; 第一次比较
004030A9 |. 75 45 jnz short aescul.004030F0
004030AB |. 83C6 04 add esi,4
004030AE |. 8B86 BA424000 mov eax,dword ptr ds:[esi+4042BA]
004030B4 |. 8B9E 02454000 mov ebx,dword ptr ds:[esi+404502]
004030BA |. 3BC3 cmp eax,ebx ; 第二次比较
004030BC 74 32 je short aescul.004030F0 ; 不一样则跳
004030BE |. 83C6 04 add esi,4
004030C1 |. 8B86 BA424000 mov eax,dword ptr ds:[esi+4042BA]
004030C7 |. 8B9E 02454000 mov ebx,dword ptr ds:[esi+404502]
004030CD |. 3BC3 cmp eax,ebx ; 第三次比较
004030CF 74 1F je short aescul.004030F0 ; 不一样则跳
004030D1 |. 83C6 04 add esi,4
004030D4 |. 8B86 BA424000 mov eax,dword ptr ds:[esi+4042BA]
004030DA |. 8B9E 02454000 mov ebx,dword ptr ds:[esi+404502]
004030E0 |. 3BC3 cmp eax,ebx ; 第四次比较
004030E2 74 0C je short aescul.004030F0 ; 不一样则跳
004030E4 |. C705 F2444000 0>mov dword ptr ds:[4044F2],1 ; 注册成功标志置1
004030EE |. EB 0A jmp short aescul.004030FA
004030F0 |> C705 F2444000 0>mov dword ptr ds:[4044F2],0 ; 置0(表示注册失败)
004030FA |> 9D popfd
004030FB |. 33C0 xor eax,eax
004030FD |. 64:8F00 pop dword ptr fs:[eax]
00403100 |. 83C4 04 add esp,4
00403103 |. 833D F2444000 0>cmp dword ptr ds:[4044F2],1 ; 时否成功
0040310A |. 75 15 jnz short aescul.00403121
0040310C |. 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040310E |. 68 3D404000 push aescul.0040403D ; |Title = "Congratulations..."
00403113 |. 68 AB414000 push aescul.004041AB ; |Text = "Registered to: yuchao"
00403118 |. 6A 00 push 0 ; |hOwner = NULL
0040311A |. E8 A8030000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA ;注册成功
0040311F |. EB 13 jmp short aescul.00403134
00403121 |> 6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00403123 |. 68 50404000 push aescul.00404050 ; |Title = "Error"
00403128 |. 68 56404000 push aescul.00404056 ; |Text = "Wrong Serial Number!"
0040312D |. 6A 00 push 0 ; |hOwner = NULL
0040312F |. E8 93030000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA ;注册失败
00403134 |> 6A 00 push 0 ; /ExitCode = 0
00403136 \. E8 C8030000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
0040313B /$ 8935 EE444000 mov dword ptr ds:[4044EE],esi
00403141 |. 8B15 EA444000 mov edx,dword ptr ds:[4044EA] ; 读出上次保存的位置记录
00403147 |. 8B0D E6444000 mov ecx,dword ptr ds:[4044E6] ; 字符串长度37
0040314D |. 3BD1 cmp edx,ecx ; 上次call时有没有遍历完字符串
0040314F |. 72 02 jb short aescul.00403153 ; 遍历完了则重新遍历
00403151 |. 33D2 xor edx,edx
00403153 |> 0FBE7415 00 /movsx esi,byte ptr ss:[ebp+edx] ; 取字符串2的字节
00403158 |. 81E6 0F000080 |and esi,8000000F ; 取esi的低四位
0040315E |. 79 05 |jns short aescul.00403165 ; 符号位为0时跳
00403160 |. 4E |dec esi
00403161 |. 83CE F0 |or esi,FFFFFFF0
00403164 |. 46 |inc esi
00403165 |> 3BF0 |cmp esi,eax ; 找到与eax相等的esi
00403167 |. 74 09 |je short aescul.00403172 ; 跳出
00403169 |. 42 |inc edx ; 计数器加1
0040316A |. 3BD1 |cmp edx,ecx ; 是否循环了37次
0040316C |.^ 7C E5 |jl short aescul.00403153 ; 没到则跳回
0040316E |. 33D2 |xor edx,edx ; 清edx
00403170 |.^ EB E1 \jmp short aescul.00403153 ; 跳回去再次遍历(字符串2)
00403172 |> 8915 EA444000 mov dword ptr ds:[4044EA],edx ; 把所找到的位置记录下
00403178 |. 8B35 EE444000 mov esi,dword ptr ds:[4044EE]
0040317E |. 0FBE042A movsx eax,byte ptr ds:[edx+ebp] ; 取那个字节
00403182 |. 42 inc edx
00403183 \. C3 retn
【算法总结】
1.修改数据段,其中有重要数据"0I5LZ7G123RXCV9OPAS6TBN48YUHJKDF0QWEM"(字符串2),注册表子键名键值名"ProductId"
2.取输入的注册名,注册码
3.取注册表值(操作系统的ProductId号),并在在它前面加上"WS"==>(字符串1)
4.修改代码段,EndDialog
5.算法部分:1.从字符串1中提取一个字节(依次从第1个到第24个字符)
2.取该字节的高四位,依次和字符串2中字符的低四位比较,相同则记录下位置和该字符
3.取该字节的低四位,从字符串2记录位置开始向后和字符的低四位比较,记录下该字符(当比较完后未找到,则从数组开始位置向后比较)
4.重复123(共24遍)
5.生成48字节的注册序列
6.注册码比较时只比较128bit(16字节),所以注册码也只要十六位
【注册机】
#include <windows.h>
#include <iostream.h>
BOOL QueryValue(BYTE,char*,int);
char szCode[17]={0};
int nPosition;
int Num;
void main()
{
char szProductId[26]={'W','S'};
char szProductIdTemp[24]={0};
BYTE bByte=0,bByteTemp=0;
char szBase[38]={'0','I','5','L','Z','7','G','1','2','3','R','X','C','V','9','O','P','A','S','6','T','B','N','4','8','Y','U','H','J','K','D','F','0','Q','W','E','M'};
char szSubKey[]="Software\\Microsoft\\Windows\\CurrentVersion";
DWORD nLenght=sizeof(szProductIdTemp);
HKEY hResultKey;
if(ERROR_SUCCESS==RegOpenKeyEx(HKEY_LOCAL_MACHINE,szSubKey,0,KEY_QUERY_VALUE,&hResultKey))
if(ERROR_SUCCESS==RegQueryValueEx(hResultKey,"ProductId",0,0,(PBYTE)szProductIdTemp,&nLenght))
{
strcat(szProductId,szProductIdTemp);
for(int i=0;i<8;i++)
{
bByte=szProductId[i];
bByteTemp=(bByte&0xf0)/16;
QueryValue(bByteTemp,szBase,nPosition);
bByteTemp=bByte&0x0f;
QueryValue(bByteTemp,szBase,nPosition);
}
cout<<szCode<<endl;
}
}
BOOL QueryValue(BYTE bByte,char* szBase,int nPositionTemp)
{
for(int i=nPositionTemp;i<37;i++)
{
if(bByte==(szBase[i]&0x0f))
{
szCode[Num++]=szBase[i];
nPosition=i;
break;
}
if(i==36)
i=-1;
}
return 0;
}
该CrackMe思路相当清晰,也比较简单很适合新兵练手(我?),新手的文章难免有误,万望高手赐教
贴上全文以供各位高手嘲笑!!!
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课