能力值:
( LV2,RANK:10 )
|
-
-
2 楼
呃~~~~ 追到UPX1里 要吐血了~~~
|
能力值:
( LV6,RANK:80 )
|
-
-
3 楼
00401240 $ 68 00E04500 push CrackMe_.0045E000 00401245 .- E9 B6CD0400 jmp CrackMe_.0044E000 45E000就是pcode,操作码与操作符混合在一起
esi是veip
eax是操作码(操作码只有1位 lea esi,dword ptr ds:[esi+0x1])
0044E029 FEC8 dec al 0044E02B C0C8 04 ror al,0x4 0044E02E C0C8 00 ror al,0x0 0044E031 C0C8 02 ror al,0x2 0044E034 F6D0 not al 0044E036 FEC8 dec al 0044E038 FEC8 dec al 0044E03A C0C8 0C ror al,0xC 0044E03D FEC8 dec al 0044E03F 80F0 0C xor al,0xC 0044E042 80F0 0A xor al,0xA 0044E045 F6D8 neg al 0044E047 FEC8 dec al 0044E049 80F0 07 xor al,0x7 0044E04C 80F0 01 xor al,0x1
解码操作码,过程是可逆的。
通过查表,进入操作码对应的handle
比如
A1 = push(这个略坑,各种跳)
…………
可能得把所有的操作码弄明白,才能破解出程序吧。 或者取巧的办法,就是记录VEIP,根据跳转,爆破?
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
验证的逻辑判断就几个if判断。 加了VMP
给一组可以弹ok的码先
用户名 V5555555
序列号 C666
(前后没有空格)
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
第一次玩 就碰到个带VM的 回去补习一下VM的知识 再来挑战一下。
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
这个虚拟机太恶心了,判断很简单
用户名第一个字符是V,注册码第一个字符是C,用户名长度是注册码长度两倍就行
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
膜拜,解出来了。
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
这个还真有难度。。。
|
能力值:
( LV2,RANK:10 )
|
-
-
9 楼
我的技术比较水,或者说根本就没什么技术,我只找到了比较V和C 还有 两个字符串长度相减,至于结果等于多少才能成功我还是看了你给出的一组可以弹出ok的注册码才猜到的
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
开眼界了,虽然搞不太明白呵呵~但爆破好像很简单:
方法1)OD载入,输入用户名和序列号,点注册,下面由于 ESI = 0 出现异常:
00456000 F7FE IDIV ESI
改为 F7FB IDIV EBX
就算爆破了!(难道这个异常是个bug?)
方法2)
0044FF0B 85C8 TEST EAX,ECX
需要NOP掉,否则序列号不对的话,ZF=1
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
那个 ESI为0我觉得不是BUG应该是故意的
0044FF0B 85C8 TEST EAX,ECX 这个你是怎么找到的?能说下思路吗
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
我是从后往前找的
以错误的序列号为例。当(操作码)EAX= 77, (VEIP) ESI = 45E829 时(略过JMP):
0044FE99 8B0424 MOV EAX,DWORD PTR SS:[ESP] //[17F0E0] = 0 送 EAX
0044FEA9 8B8C24 04000000 MOV ECX,DWORD PTR SS:[ESP+4] //[17F0E4] = 0 送 ECX
0044FEFD 50 PUSH EAX
0044FED6 8B87 24000000 MOV EAX,DWORD PTR DS:[EDI+24] //5C 送 EAX
0044FEC4 8B0438 MOV EAX,DWORD PTR DS:[EDI+EAX] // 202 ->EAX
0044FE79 50 PUSH EAX -|
0044FEBD 9D POPFD -----| 标志寄存器EFL初始化为202
0044FF04 50 PUSH EAX
0044FF0B 85C8 TEST EAX,ECX //如果序列号不对,两者都是0,ZF=1;否则,都是1, ZF=0
0044FE8D 8B87 24000000 MOV EAX,DWORD PTR DS:[EDI+24]
0044FEB6 9C PUSHFD // 这个很关键。保存判断后的EFL标志
/* 这里序列号不对, EFL =246 (ZF=1);对的话 EFL = 202 (ZF=0) */
0044FECD 8F0438 POP DWORD PTR DS:[EDI+EAX] //将EFL(246)保存到[EDI+EAX]
/* 由于EAX是变量,所以保存的地址或许会不同;用内存断点搞它会很痛苦呵 */
接着,在EAX=0D9,ESI=45E837时:
0044EF72 8B0438 MOV EAX,DWORD PTR DS:[EDI+EAX] //将246 从[EDI+EAX]读出->eax
0044EF7B 50 PUSH EAX
0044EF82 9D POPFD //映射到EFL标志
0044EF89 58 POP EAX //45E892 -> EAX
0044EFB7 0F443424 CMOVE ESI,DWORD PTR SS:[ESP]
/* 如果序列号错误则条件满足,然后 [17F0E4]中的45E892 -> ESI;
序列号对的话,条件不满足, 还是原来的 ESI=45E838; */
后面,如果ESI=45E838,记得有个偏移变量就指向"ok";如果ESI=45E892 则指向"fail"。
很变态的感觉~~,建议大家用conditional log把EAX,ESI记录下来,便于分析。
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
[QUOTE=moonlite;1201141]我是从后往前找的
以错误的序列号为例。当(操作码)EAX= 77, (VEIP) ESI = 45E829 时(略过JMP):
0044FE99 8B0424 MOV EAX,DWORD PTR SS:[ESP] //[17F0E0] = 0 送 EAX
0...[/QUOTE]
一开始我也是从后往前找但是不知道是从什么地方跳转过来的
从后往前找怎么知道是从哪跳过来的?用conditional log? 这个是啥怎么用?
|
能力值:
( LV2,RANK:10 )
|
-
-
14 楼
就是内存断点,很不易,因为地址总在变化。
右键-Breakpoint-conditional log (或者 Shift + F4)
它的作用就是自动追踪地址,寄存器的变化,设定条件来中断。
|
能力值:
( LV2,RANK:10 )
|
-
-
15 楼
[QUOTE=moonlite;1201141]我是从后往前找的
以错误的序列号为例。当(操作码)EAX= 77, (VEIP) ESI = 45E829 时(略过JMP):
0044FE99 8B0424 MOV EAX,DWORD PTR SS:[ESP] //[17F0E0] = 0 送 EAX
0...[/QUOTE] 膜拜,爆破就可以了。 花指令模板还没写完,现在只是把handle乱序了一下。
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
这个VM只是拿来加自己写的一些程序, 因为没有加壳的程序用来加一些demo来测试跟踪,
所以楼上的几位爆破。我个人感觉已经很强大了。 再次膜拜。 明天去公司发crackme的源码。
|
能力值:
( LV2,RANK:10 )
|
-
-
17 楼
BOOL Check(const char* pName, const char* pPassword)
{
BOOL bret = FALSE;
int nameLen = 0;
int pawsswordlen = 0;
__try
{
while(*(pName + nameLen))
{
++nameLen;
}
while(*(pPassword + pawsswordlen))
{
++pawsswordlen;
}
bret = (nameLen + pawsswordlen) / bret;
}
__except(1)
{
if (pName[0] == 'V'
&& pPassword[0] == 'C'
&& pawsswordlen == (nameLen - pawsswordlen))
{
bret = TRUE;
//return bret;
}
else
{
bret = FALSE;
}
}
char szbuf[MAX_PATH] = {0};
szbuf[0] = 'o';
szbuf[1] = 'k';
char szbuf2[MAX_PATH] = {0};
szbuf2[0] = 'f';
szbuf2[1] = 'a';
szbuf2[2] = 'i';
szbuf2[3] = 'l';
if (bret)
{
::MessageBoxA(NULL, szbuf, szbuf, 0);
}
else
{
::MessageBoxA(NULL, szbuf2, szbuf2, 0);
}
return bret;
}
void CCrackMeDlg::OnButton1()
{
// TODO: Add your control notification handler code here
UpdateData();
if (m_name.GetLength() == 0
|| m_pwd.GetLength() == 0)
{
::MessageBoxA(NULL, "名字和密码不能为空", "名字和密码不能为空", 0);
}
else
{
if (Check(m_name, m_pwd))
{
}
else
{
}
}
}
顺路问问爆破的亲, 你是正确的码和错误的码比较得到不同的ESI跳转, 还是只从错误的码从后往前一步一步看handle的?
|
能力值:
( LV2,RANK:10 )
|
-
-
18 楼
明白了 谢谢
|
能力值:
( LV2,RANK:10 )
|
-
-
19 楼
我是从后者推断出前者的,呵呵
另外谢谢你的分享!
|
|
|