1

[原创]看雪CTF2017第五题 独行孤客CrackMe writeup

rxy 2017-6-12 11:53 845

所用工具:OD

说明:程序载入OD后,发现下了断点会报错退出,进过一番摸索,发现进行以下2处修改似乎可绕过反调试(新人能力有限,对其中原理还不太清除):


然后就开始跟踪程序对输入key的处理,初步分析有如下发现:key会被逆序、长度为6、字母数字符号均可(大写字母会被转成小写,由于按照出题要求key不应包含符号故后续不再考虑符号)、程序中还使用了IsDebuggerPresent 。见图:


程序接下来会把上述处理过的key写进设备\Device\vmxdrv(通过vmxdrv.sys模拟出来的设备?),然后再从该设备读16字节的内容出来,见图:


观察读出来的16字节内容,似乎为MD5值(PEID发现程序也确实使用了MD5),但并不是在WriteFile时所写内容的MD5,通过某MD5解密网站查询明文,发现程序似乎是把WriteFile时的key进行了某种变化,然后计算其MD5,经过多次选取不同输入(字母、数字)并观察输出,发现变化规律为:对key的第一个字符ASCII码加1,后面5个字符分别对ASCII码加1、2、3、4、5,例如变换前key为"000000",则变换后为"112345";变换前为"999999",变换后为"::;<=>"。


然后程序会对刚才得到MD5再进行一次MD5运算,取结果的第2到11位(共10位)与888aeda4ab进行比较,若相等,则key正确。见图:


最后开始暴力破解,字符范围是数字及小写字母,长度6位,Python代码如下:

# -*- coding: utf-8 -*-
#代码省去了反转的操作,故找到key后手工反转一次
import hashlib
loop = '0123456789abcdefghijklmnopqrstuvwxyz'#字符包含数字和小写字母
def conv(n):
    a = []
    while n != 0:
        a.append( loop[n % 36] )
        n = n / 36
    a.reverse()
    return ''.join(a)
def check(num):
    snum = conv(num)
    if(len(snum) < 6):
        snum = snum.rjust(6, '0')
    print snum
    snum = plus(snum)
    m = hashlib.md5()
    m.update(snum)
    m2 = hashlib.md5()
    m2.update(m.hexdigest())
    if(m2.hexdigest()[2:12] == '888aeda4ab'):
        return True
    return False 
def plus(s):
    ll = list(s)
    ll[0] = chr(ord(ll[0])+1)
    for i in range(1,6):
        ll[i] = chr(ord(ll[i])+i)
    return ''.join(ll)
	
#共有36^6=2176782336种可能,但2176782336超过了xrange范围,
#故分2次计算,注释起来的为第二次的
#for i in xrange(0,1088391168):
#    i += 1088391169
#    if(check(i)):
#        print 'key:',i
#        break
for i in xrange(0,1088391169):
    if(check(i)):
        print 'key:',i
        break
print 'done'

最后得到正确key:su1986

最新回复 (0)
返回