Crackme5

还是和去年一样的比赛规则,分值到一定程度才能继续开题。从能看160的题开始就开始琢磨了,可,情况似乎不那么乐观,没静下心来看,因为是比赛总想着去找其他的方法去突破。结果是,一直想着靠它翻盘,然后就没然后了。好吧,结束了也还是想知道它大概怎么做的,就再看了看。
还是先从当天的思路开始说起吧,拿到题目后照样peid查查壳、看看有啥算法、看看区段是否正常。然后发现如下:
peid
居然52pojie,这壳是什么鬼?然后队友说了下52pojie和数字的关系。于是被科普了。
再然后,就直接双击运行了下,随意输入了个用户名密码,点确定后,“按钮”变灰,两秒后正常,然后~~~就在想着,难不成是有个好屌的算法,要算2秒才能出结果进行判定?就在看看源程序要啥算法呗。是的,不用看了,并没有,因为,加壳了啊亲,你能看到啥呢?
再然后错误的密码也如预期中的没有任何反应。所以,我们并不能通过返回信息来定位到判定点。
看样子,脱壳是第一要务哇,不过一贯来说,比赛不会考脱壳能力的,然后~这次还真有了。看了看,的确是人家自己写的防御措施,又有何不可呢。于是拿出OD,一路跟了下去,折腾了会儿后觉得,照这样单步下去估计是比赛结束了都搞不定。那就换个思路吧,拿出OD attach到进程后,把常见的GetDlgItem、GetWindowText之类的全bp了一遍。恩,结果你也知道,不可能会断下来。不能断下,就不能从处理用户名开始分析。那该从哪里开始跟呢?该怎么跟呢?
经过几次尝试后,发现程序似乎也并没有做什么反调试,而加壳的作用是防静态分析,可我还是想看看脱壳后的程序内容。于是拿出对付vmp的方法来。 先运行程序,然后用OD attach上去,就直接dump下来,然后用OD静态分析。看了会儿,头都晕了,觉得也不靠谱。再回头去证实前面的两个问题,有啥算法:
md5
MD5,什么鬼?干吗用的?并不知道~~~然后想着去看看Strings啊,结果~~~并发现没有什么有用信息~~~
到这里是得到了能够用IDA分析的脱壳后的代码,虽然不能运行、Import表没修复,但影响不大,我只是想用IDA做做记录、做做注释、还可以看看交叉引用,适当的时候还可以F5。
然后,似乎就卡这儿了,看到小水滴还在直播,就去玩手机看互动去了。再然后,突然灵光一闪,要不,去dump下内存看看,因为,它必定会要跟我输入的密码做比较,倘若,在某一个函数中进行的对比呢?倘若,作者刚好不记得擦出呢?倘若,明文的呢?于是,立马dump了一个,就开始搜输入的密码,然后就在它周围翻了起来,是的,密码的确出现过,但与它对比的那个,的确没有。就这么折腾了个把小时。并没有什么~~~
再然后,又突然想起一个神器(是不是坑我并不知道,因为从没用它来做过逆向),就是CE,恩,当时的思路是:我们不是找不到判定点么?不知道从哪开始跟么?而它必定会要跟我输入的密码做比较,至少会访问一次吧,那,如果我们把所有访问的地方记录下来呢?OD不好实现的东西,CE能够很好实现啊,而那会儿发现CE还可以动态。然后就这么做了。打开CE,内存搜输入的密码,共有两个地方。通过测试,发现第一个地方是实时显示我输入的字符,第二处是点击确定后才有的。
于是,重点就在第二个了。下内存访问记录后,得到结果如下:
exec
前面的系统空间的指令,用OD定位了下:

然后大家都应该更关注0042AF6E那里,以及到底是在哪里调用了那两个API。然后,通过分析,发现,这个点其实就是得到输入字符的长度。而且那天比赛的时候脑抽,一直用CE+IDA来玩的。再然后,那天就在这折腾了一下午,因为我总觉得会用到输入的用户名,总想以它为突破口继续分析下去~~然后,比赛就结束了~~~其实那天也看到了些加解密的东西,不过,想投机,就静下来分析。
再次打开这个程序,就到今天上午了,再次定位到上次看到的字符串处:
aes
然后,看引用:
crypt
因为,IDA里分析的是dump出来的值,所以,哪些系统空间的东西并不能解析。不过没关系,我们可以直接用OD的Ctrl+G定位过去,看看到底是调用了什么。注释完了后。知道这是个解密的地方,那,解密的内容是啥?解密后是不是就直接和输入的内容对比呢?想法还是要有的,万一是真的呢~~~我们暂且叫这个函数为crypt吧。
OD加载,在crypt开始的地方下段,运行程序。点击确定后,发现,咦,断了两次。
第一次如下: c1
第二次如下: c1
第一次是用输入的用户名“rooter”hash后的值当key去解密,第二次是用一个好莫名的值去做这件事的。而且你还会明显发现第二次调用crypt是2秒以后。也就是说,这第二次调用才是有猫腻的。那,先还是继续看看这两次执行完后分别做了什么吧。
同时也在调用crypt的两个地方分别下断点:

_52pojie:00406470 ; signed int __usercall crypto@<eax>(int lenth@<edx>, int pdata@<ecx>, const char *value_to_hash)
_52pojie:00406470 crypto proc near        ; CODE XREF: sub_4065C0+147p
_52pojie:00406470                         ; _52pojie:00406B7Cp

这里直接bp 4065C0,bp 00406B7C。
看了下调用处的后面一些代码,其实就是检测返回值是否符合规定,若不是,就:
set
我尝试改跳转,让程序执行到这里,然后它会在“确定”按钮旁边输出一个“error”。那,这是不是意味着,输入的key正确的时候,也会setwindow一个值呢?那,第二次crpyt函数之后,是否也有这个东西呢?无奈,各种搜索都没有找到right,congratulation,之类的值~~~再看SetWindowText的调用,也没有,下断也不行。似乎这条路就走不下去了。
可接着,又在这后面找到了另一个很有意思的东西。他后面00406C4F处居然跟了个CreateThread。这立马引起了好奇心,看看参数有哪些:
create
自然的,转过去看StartAddress吧,这单步肯定是不行的,那就直接Ctrl+G到00406C90,F2断点。然后F9运行一下。然后他还真断下来了。
然后这地方又不能单步了,但是,还是通过断点,F9弄清楚这里是干嘛的了。
thread
再然后,当我F9运行过sleep的时候,又有件诡异的事情发生了,还记得我们先前bp了两个断点么?对,另外一个断下来了。程序运行到004065C0了。然后这个时候,IDA似乎没那么好用了,OD各种跟着调试后,加了些注释,来看看OD分析后的数据吧,似乎要好看的多。

CPU Disasm
Address   Hex dump          Command                                  Comments
004065C0    55              PUSH    EBP
004065C1    8BEC            MOV     EBP,ESP
004065C3    81EC 40020000   SUB     ESP,240
004065C9    A1 F0264500     MOV     EAX,DWORD PTR DS:[CrackMe5.4526F
004065CE    33C5            XOR     EAX,EBP
004065D0    8945 FC         MOV     DWORD PTR SS:[EBP-4],EAX
004065D3    56              PUSH    ESI
004065D4    33C0            XOR     EAX,EAX
004065D6    33F6            XOR     ESI,ESI
004065D8    68 06020000     PUSH    206
004065DD    50              PUSH    EAX
004065DE    66:8985 D4FDFFF MOV     WORD PTR SS:[EBP-22C],AX
004065E5    8D85 D6FDFFFF   LEA     EAX,[EBP-22A]
004065EB    50              PUSH    EAX
004065EC    E8 0F430200     CALL    CrackMe5.0042A900                ; memset
004065F1    83C4 0C         ADD     ESP,0C
004065F4    8D85 D4FDFFFF   LEA     EAX,[EBP-22C]
004065FA    68 08020000     PUSH    208
004065FF    50              PUSH    EAX
00406600    56              PUSH    ESI
00406601    FF15 CCF24300   CALL    NEAR DWORD PTR DS:[CrackMe5.43F2 ; GetModuleFileName
00406607    85C0            TEST    EAX,EAX
00406609    0F84 AA010000   JE      CrackMe5.004067B9
0040660F    56              PUSH    ESI
00406610    68 80000000     PUSH    80
00406615    6A 03           PUSH    3
00406617    56              PUSH    ESI
00406618    6A 01           PUSH    1
0040661A    68 00000080     PUSH    80000000
0040661F    8D85 D4FDFFFF   LEA     EAX,[EBP-22C]
00406625    50              PUSH    EAX
00406626    FF15 C8F24300   CALL    NEAR DWORD PTR DS:[CrackMe5.43F2 ; CreatFileW
0040662C    8985 C0FDFFFF   MOV     DWORD PTR SS:[EBP-240],EAX
00406632    83F8 FF         CMP     EAX,-1
00406635    0F84 7E010000   JE      CrackMe5.004067B9
0040663B    53              PUSH    EBX
0040663C    57              PUSH    EDI
0040663D    56              PUSH    ESI
0040663E    50              PUSH    EAX
0040663F    FF15 C4F24300   CALL    NEAR DWORD PTR DS:[CrackMe5.43F2 ; GetFileSize
00406645    8BD8            MOV     EBX,EAX
00406647    53              PUSH    EBX
00406648    E8 02250000     CALL    CrackMe5.00408B4F
0040664D    8BF8            MOV     EDI,EAX
0040664F    83C4 04         ADD     ESP,4
00406652    85FF            TEST    EDI,EDI
00406654    0F84 51010000   JE      CrackMe5.004067AB
0040665A    53              PUSH    EBX
0040665B    56              PUSH    ESI
0040665C    57              PUSH    EDI
0040665D    E8 9E420200     CALL    CrackMe5.0042A900                ; memset
00406662    83C4 0C         ADD     ESP,0C
00406665    89B5 C8FDFFFF   MOV     DWORD PTR SS:[EBP-238],ESI
0040666B    8D85 C8FDFFFF   LEA     EAX,[EBP-238]
00406671    56              PUSH    ESI
00406672    50              PUSH    EAX
00406673    53              PUSH    EBX
00406674    57              PUSH    EDI
00406675    FFB5 C0FDFFFF   PUSH    DWORD PTR SS:[EBP-240]
0040667B    FF15 C0F24300   CALL    NEAR DWORD PTR DS:[CrackMe5.43F2 ; ReadFile
00406681    85C0            TEST    EAX,EAX
00406683    0F84 19010000   JE      CrackMe5.004067A2
00406689    8B57 3C         MOV     EDX,DWORD PTR DS:[EDI+3C]
0040668C    03D7            ADD     EDX,EDI
0040668E    0FB742 06       MOVZX   EAX,WORD PTR DS:[EDX+6]
00406692    8D0C80          LEA     ECX,[EAX*4+EAX]
00406695    0FB742 14       MOVZX   EAX,WORD PTR DS:[EDX+14]
00406699    03C2            ADD     EAX,EDX
0040669B    8B54C8 04       MOV     EDX,DWORD PTR DS:[ECX*8+EAX+4]
0040669F    8B04C8          MOV     EAX,DWORD PTR DS:[ECX*8+EAX]
004066A2    2BD8            SUB     EBX,EAX
004066A4    2BDA            SUB     EBX,EDX
004066A6    899D CCFDFFFF   MOV     DWORD PTR SS:[EBP-234],EBX
004066AC    8D0C10          LEA     ECX,[EDX+EAX]
004066AF    03CF            ADD     ECX,EDI
004066B1    898D D0FDFFFF   MOV     DWORD PTR SS:[EBP-230],ECX
004066B7    85C9            TEST    ECX,ECX
004066B9    0F84 E3000000   JE      CrackMe5.004067A2
004066BF    8039 00         CMP     BYTE PTR DS:[ECX],0
004066C2    0F84 DA000000   JE      CrackMe5.004067A2
004066C8    E8 C3FCFFFF     CALL    CrackMe5.00406390                ; get crc32  47A4D141
004066CD    6A 10           PUSH    10
004066CF    6A 20           PUSH    20
004066D1    8D4D DC         LEA     ECX,[EBP-24]
004066D4    C645 DC 00      MOV     BYTE PTR SS:[EBP-24],0
004066D8    0F57C0          XORPS   XMM0,XMM0
004066DB    8975 F5         MOV     DWORD PTR SS:[EBP-0B],ESI
004066DE    51              PUSH    ECX
004066DF    50              PUSH    EAX
004066E0    F30F7F45 DD     MOVDQU  DQWORD PTR SS:[EBP-23],XMM0
004066E5    66:8975 F9      MOV     WORD PTR SS:[EBP-7],SI
004066E9    660FD645 ED     MOVQ    QWORD PTR SS:[EBP-13],XMM0
004066EE    C645 FB 00      MOV     BYTE PTR SS:[EBP-5],0
004066F2    E8 793C0200     CALL    CrackMe5.0042A370                ; hex to ascii  47a4d141
004066F7    8B8D D0FDFFFF   MOV     ECX,DWORD PTR SS:[EBP-230]
004066FD    8D45 DC         LEA     EAX,[EBP-24]
00406700    50              PUSH    EAX
00406701    8D95 CCFDFFFF   LEA     EDX,[EBP-234]
00406707    E8 64FDFFFF     CALL    CrackMe5.00406470                ; crypt
0040670C    83C4 14         ADD     ESP,14
0040670F    85C0            TEST    EAX,EAX
00406711    0F84 8B000000   JE      CrackMe5.004067A2
00406717    8B85 CCFDFFFF   MOV     EAX,DWORD PTR SS:[EBP-234]       ; eax=len
0040671D    C1E0 02         SHL     EAX,2
00406720    50              PUSH    EAX
00406721    8985 C4FDFFFF   MOV     DWORD PTR SS:[EBP-23C],EAX
00406727    E8 23240000     CALL    CrackMe5.00408B4F                ; AllocatHeap
0040672C    8BD8            MOV     EBX,EAX
0040672E    83C4 04         ADD     ESP,4
00406731    85DB            TEST    EBX,EBX
00406733    74 6D           JE      SHORT CrackMe5.004067A2
00406735    FFB5 C4FDFFFF   PUSH    DWORD PTR SS:[EBP-23C]
0040673B    56              PUSH    ESI
0040673C    53              PUSH    EBX
0040673D    E8 BE410200     CALL    CrackMe5.0042A900                ; memset
00406742    FFB5 CCFDFFFF   PUSH    DWORD PTR SS:[EBP-234]
00406748    8D85 C4FDFFFF   LEA     EAX,[EBP-23C]
0040674E    FFB5 D0FDFFFF   PUSH    DWORD PTR SS:[EBP-230]
00406754    50              PUSH    EAX
00406755    53              PUSH    EBX
00406756    E8 35CAFFFF     CALL    CrackMe5.00403190                ; check something
0040675B    83C4 1C         ADD     ESP,1C
0040675E    85C0            TEST    EAX,EAX
00406760    75 37           JNE     SHORT CrackMe5.00406799
00406762    83EC 0C         SUB     ESP,0C
00406765    8BCB            MOV     ECX,EBX
00406767    E8 841B0000     CALL    CrackMe5.004082F0                ; key
0040676C    83C4 0C         ADD     ESP,0C
0040676F    85C0            TEST    EAX,EAX
00406771    74 26           JE      SHORT CrackMe5.00406799
00406773    8D95 D0FDFFFF   LEA     EDX,[EBP-230]
00406779    C785 D0FDFFFF 4 MOV     DWORD PTR SS:[EBP-230],OFFSET Cr
00406783    8BC8            MOV     ECX,EAX
00406785    E8 961D0000     CALL    CrackMe5.00408520                ; ???
0040678A    85C0            TEST    EAX,EAX
0040678C    A3 50914500     MOV     DWORD PTR DS:[CrackMe5.459150],E
00406791    B9 01000000     MOV     ECX,1
00406796    0F45F1          CMOVNE  ESI,ECX
00406799    53              PUSH    EBX
0040679A    E8 AB230000     CALL    CrackMe5.00408B4A                ; HeapFree
0040679F    83C4 04         ADD     ESP,4
004067A2    57              PUSH    EDI
004067A3    E8 A2230000     CALL    CrackMe5.00408B4A                ; HeapFree
004067A8    83C4 04         ADD     ESP,4
004067AB    FFB5 C0FDFFFF   PUSH    DWORD PTR SS:[EBP-240]
004067B1    FF15 BCF24300   CALL    NEAR DWORD PTR DS:[CrackMe5.43F2 ; closehandle
004067B7    5F              POP     EDI
004067B8    5B              POP     EBX
004067B9    8B4D FC         MOV     ECX,DWORD PTR SS:[EBP-4]
004067BC    8BC6            MOV     EAX,ESI
004067BE    33CD            XOR     ECX,EBP
004067C0    5E              POP     ESI
004067C1    E8 D2370200     CALL    CrackMe5.00429F98                ; to_return
004067C6    8BE5            MOV     ESP,EBP
004067C8    5D              POP     EBP
004067C9    C3              RETN

是的,一个大秘密就被发现了,先是开辟空间然后读自身,然后计算Crc32,得到我们先前看到的第二次调用crypt函数时传入的值,之后把得到的Crc32的值传入crypt函数。
然而,我们关心的重点是,这次解密了什么数据:
decrypt
拿着需要解密的数据去原文件中搜了下,还真有。也就是说,这段的功能就是读程序中某一段的数据,然后用自身的Crc32值作为密钥,进行解密。那问题来了,解密后,他要干嘛?
首先看到在解密后,程序申请了一段内存空间,并且memset了一次。不妨在解密后的数据上下一个r/w/e断点,看看谁会来用这段数据吧。
然后在00403473断下来了,就是我前面汇编代码里的00403473处的call中,而其中似乎一直在做某种检测,推测应该是pe结构检测。知道了前面的call都是些什么意思后,我们更加关注00406767和00406767了。
然后,这里IDA又不管用了,所以,老老实实F8单步走完看到底做了什么吧。这里只依次记录调用的API:
virtualalloc
开辟了一段空间。大小为0x20000。若没有开辟成功,就再来了一次,这次不指定地址。然后依次调用了下面的API。

GetProcessHeap
RtlAllocateHeap
GetNativeSystemInfo
VirturalAlloc

然后memcpy了一个pe头,在这之后还调用了一次memcpy,复制过来了一段数据:
memcpy1 而后使用virtualprotect,给10001000加了可执行权限:
virtualprotect
于是,这个cm瞬间变得好玩了起来,他要干嘛?可以看到10001000始终没有数值,但,他后面有啊,来看这里,程序call了一个eax。
call
于是就跟了进去,结果,更好玩的事情来了。他在自解密:
selfdecode
手动跟着让它解密完似乎不靠谱。它刚不是给10001000段加了可执行权限么?那它肯定要执行的哇。既然要执行,我们不妨直接在10001000下个断点,然后F9了一下。结果,异常了。那么我们退回到call eax的下一句下断点,等10001000段全部解密完成。然后再给10001000下断点,再F9运行,结果,奇迹出现了。他断下来了。本来还想dump出10000000这段的代码放到IDA里去分析一下的,后来想了想,直接在当前堆栈中去搜索我们输入的密码,看有没有,结果还真搜到了一串:
purpleroc
那,直接下内存访问断点,然后F9,并没有访问输入的密码的样子,但是,总在10001000停了下来,说明有多次调用。然后有一串字符每次F9冒出来几个:
key
这东西怎么那么像key呢?拿到完整的字符串后,去试了下,结果是不对的。再然后,再摁了下F9,再另一个地方断下来了。发现,是将其转ASCII码了一下。于是,我们对ASCII和UNICODE两个地方都下断点。同时也对刚得到的那个字符串下段。F9跑起来。断了好几次后,终于,看到了一个cmp~~~
cmp
于是,好屌屌的发现,他是把输入的密码逆序后与刚得到的“8a88d08f41b8f4bacfaf”进行一一对比。那,对了会如何呢?先不调,直接输入“fafcab4f8b14f80d88a8”,得到:
success
tm。。。终于success了。用了什么算法?不知道~~~怎么玩的?好像好难玩~~~
为了分析一下这货,就又把10000000这段dump了出来。
dump
发现是个dll,丢到IDA,发现导出了一个LSG函数~~~
lsg
而这个函数应该是在:
lsg1 调用的。

然后就没有然后了~~~没再继续分析下去了。我对这程序所有的理解就是:

哎,没读多少书,也没有啥专业名词,就觉得,这东西好复杂~~然后,逆向嘛,都是考揣测、猜的,前面的所有就当是我猜的吧,我也说不出个所以然,所以~~~大牛就飘过吧,不喜勿喷。
然后,可能比赛的时候压力大些吧,一般轻易解决不了的都会换题做,所以,整个一天这个cm5就没哪个队解出来。最后,膜拜LSG。

2015年6月8日18:08:34
——Tracy_梓朋