【吾爱破解2014CrackMe大赛】【第十一组】
本帖最后由 L4Nce 于 2014-11-3 02:03 编辑珍惜生命,远离海风!!!
海风前辈的cm,简直无情。还要自带vm,分析过去绝对能把人弄死。不带这样玩的吧,不带这样玩的吧!!
废话说多了就不好了,估计大家都想看一下这个cm的分析。咳咳,就让我慢慢说明。
大牛的想法我不懂,大牛的世界我更加不懂。不过从中抽取一点有用的信息出来,也是可以的。
首先,还是得有一个虚拟机的思想。这个程序有两段是加了VM的,虽然架构与我们熟知的不太一样就是了。
首先看一下main主体
00401089|.C785 0CF5FFFF C2C7F>MOV , 0x97F6C7C2 ;初始化vEip
00401093|.898D 04F5FFFF MOV , ECX
-------------------> 循环 <------------------------------> 循环 <----------------------------------------------
00401099 >|>8B85 0CF5FFFF /MOV EAX, ;取vEip
0040109F|.89C1 |MOV ECX, EAX
004010A1|.81E9 005CC17F |SUB ECX, 0x7FC15C00
004010A7|.8985 00F5FFFF |MOV , EAX ;Set TempEip
...
0041397A >|> \8B85 00F5FFFF |MOV EAX, ; -> 取vEip值
00413980|.2D C2C7F697 |SUB EAX, 0x97F6C7C2 ; 判断vEip == 97F6C7C2
00413985|.8985 94CAFFFF |MOV , EAX
0041398B|.0F84 E2F70000 |JE <CrackMe.loc_423173> ; 跳向该vEip的处理函数
...
00423173 >|> \B8 11A51829 |MOV EAX, 0x2918A511 ; 两个跳转常数,用于更新vEip
00423178|.B9 3D774A50 |MOV ECX, 0x504A773D
...
004231CF|.0F45F1 |CMOVNEESI, ECX ;设置vEip的跳转常数
004231D2|.89B5 0CF5FFFF |MOV , ESI ;更新下一步vEip
004231D8|.E9 3B7F0400 |JMP <CrackMe.loc_46B118> ;跳向循环
...
0046B118 >\>^\E9 7C5FF9FF \JMP <CrackMe.loc_401099> ; End jmp Loop
就是这样,完成了一次vEip的处理后,根据处理结果更新vEip,接着又进行下一个处理,这样来完成程序的功能。
并且,这里每一个vEip的处理函数里面都有两个跳转常数,并且根据运算结果进行选择,所以硬要弄下去的话可以弄出非常多的vEip分支的。哈哈,简直得跪。
还有另外一段完成Name与Pass校验的代码也是类似的,应该很容易就能看出来。
我分析了一下,发现这段vm是用于处理数据输入的,真正的验证还在另外一段VM中:0046B120
于是,我们就去分析vm吧。。。也不太现实。能不能降低一下工作量呢?可以的。
现在我们已经知道了有vEip,以及跳转常数,以及他们之间的关系,那么自然就可以通过跳转常数计算出跳转地址,有了这些,就能基本上弄清楚程序的流程了,所以,这里我写了一段脚本来解析验证函数段的跳转地址:
//该脚本用于52CM大赛海风月影前辈CM解析。
// By F8LEFT 2014.11.1
LOG ""
LOG "该脚本由F8LEFT制作,用于解析第四届52CM大赛中海风前辈的CM"
LOG "不确定会有什么bug,咳咳,真蛋疼"
VAR CStart //解析开始地址
VAR CEnd //解析结束地址
jmp Omain
CheckProc: //验证段主体
VAR Ceip //更新的当前地址
MOV Ceip, CStart
VAR Temp
VAR Tempeip //中间变量
VAR TempAddr //中间变量
VAR ConstEAX //常数1
VAR ConstEDX //常数2
VAR JmpAddr1
VAR JmpAddr2
VAR Strbuf
VAR AddrChara
MOV AddrChara, #B8????????B9# //mov eax,DWORD, mov edx, DWORD
VAR ConstChara
MainLoop:
FIND Ceip, AddrChara
MOV Ceip, $RESULT
CMP Ceip, 0
JE MainEnd //退出地址
MOV Tempeip, Ceip
ADD Tempeip, 1 //定位到常数中
MOV ConstEAX, //取常数1
ADD Tempeip, 5
MOV ConstEDX, //取常数2
MOV TempAddr, CStart
FindLoop:
FIND TempAddr, ConstEAX
MOV TempAddr, $RESULT
SUB TempAddr, 1
//CMP , #2D#,1
ADD TempAddr, 0D
MOV Temp,
ADD Temp, TempAddr
ADD Temp, 4
MOV JmpAddr1, Temp
MOV TempAddr, CStart
FIND TempAddr, ConstEDX
MOV TempAddr, $RESULT
SUB TempAddr, 1
//CMP , #2D#,1
ADD TempAddr, 0D
MOV Temp,
ADD Temp, TempAddr
ADD Temp, 4
MOV JmpAddr2, Temp
//Log out
MOV Tempeip, Ceip
EVAL "jmp {JmpAddr1}"
CMT Tempeip, $RESULT
ADD Tempeip,5
EVAL "jmp {JmpAddr2}"
CMT Tempeip, $RESULT
EVAL "{Ceip} : jmp {JmpAddr1}jmp {JmpAddr2}"
MOV Strbuf, $RESULT
LOG Strbuf
WRTA "Analyse.txt", Strbuf
MOV Ceip, Tempeip
JMP MainLoop
MainEnd:
ret
Omain:
MOV CStart, 46B120
MOV CEnd, 49156F
CALL CheckProc
ret
输出的结果大致如下,(部分),有部分地址没有解析出来,不过不影响阅读
477025 : jmp 48E1F4jmp 477054
477054 : jmp 48E1F4jmp 477127
477136 : jmp 48E203jmp 4771DF
4771DF : jmp 48E203jmp 4772EC
4772FB : jmp 48E212jmp 47739D
47739D : jmp 48E212jmp 47748A
477499 : jmp 48E221jmp 477544
477544 : jmp 48E221jmp 477634
这里我只复制了一部分,不过也能看出一点规律。首先,两个跳转地址相差都非常大。实际上 48E000以后的跳转都是用来退出vm的,而之前的vm则是代表这vm正常进行。
并且,最为重要的是,你将会看到,除了部分以外,这里的跳转都是跳向下一个地址的,所以大致上程序是顺序执行的。所以每当你看到它跳向vm分配的地方时,就可以直接在下一个地点F4了。
而那些特殊的跳转地址,如:
479231 : jmp 4793F2jmp 479252
则需要得到关注了,因为这些是属于条件跳转,程序流程产生分支都是从这里开始的。而我爆破的地方都是从这种地方选的。
准备工作结束了,下面就是无脑的跟踪了。虽说如此,但是不实际上跟踪一下的话是不会懂的。咳咳,我下面直接贴出修改的地方:
验证
004856C4 .8A96 173C0000 MOV DL, BYTE PTR DS: ; --> SetTo0
00485A1C .8A96 273C0000 MOV DL, BYTE PTR DS: ; SetTo0
004863EA .8A96 2E3C0000 MOV DL, BYTE PTR DS: ; set 0
00489ED0 .8A96 123D0000 MOV DL, BYTE PTR DS: ; set0
0048CFE6 .8A96 533D0000 MOV DL, BYTE PTR DS: ; Set1
Pass长度:
00479164 .813F 30000000 CMP DWORD PTR DS:, 0x30 ;比较长度
0047916A .0F95C6 SETNE DH-> xor dh,dh
这里都改一改,就成功了,名字长度为,Pass长度在48以内就可以了。附上成功的图
爆的好:lol@海风月影 最后成绩:101
评委评价:爆破有效
谢谢参与。 这个程序还是挺发杂的,怎么看呢 学习大牛思路。 看不太懂,能详细说说吗? 学习楼主方法 大神真厉害啊 楼主好厉害啊 膜拜大神