首页
社区
课程
招聘
[原创]看雪CTF2017第七题 不问少年crackme writeup
2017-6-15 11:51 3576

[原创]看雪CTF2017第七题 不问少年crackme writeup

rxy 活跃值
1
2017-6-15 11:51
3576

所用工具:OllyDbg,CFF Explorer,ResourceHacker

说明:本人初学,写得不对的地方还请大家指正。

解题过程:

1,程序刚载入OD1.10就报错,提示“Don't know how to bypass command at address 00414429.后面省略”,但使用OD2.01不会报错,观察发现在EP(00414422)处的字节在OD1.10中为03H,但在OD2.01中为E8H。使用CFF Explorer查看程序后发现使用了TLS,只有一个callback,地址是0040C120,在OD中查看该函数,发现其主要作用是对EP开始的C8H个字节进行异或,EP处的字节异或后就应该是E8H,不明白为什么OD1.10中会变成03H?由于OD2使用不太方便,于是便将程序在TLS执行后,停在EP处时,将EP处的字节改为E8H,然后使用OllyDump插件将程序dump出来,再用CFF Explorer将PE头中TLS相关的两个字段TLS Directory RVA和TLS Directory Size的值清0,再保存后便可在OD1.10中正常运行。


2,将上一步得到的程序载入OD后运行,直接terminate,最终发现程序中使用MapFileAndCheckSumW计算校验和,如不符就退出,因为已经修改了程序,校验和自然不相等,于是绕过判断,再次保存为新程序。


3,将上一步得到的新程序载入OD,查看程序调用的API发现有GetDlgItemText,且调用时的控件ID为3E8H,和用ResourceHacker查看的输入框的控件ID一致,基本确定就是使用GetDlgItemText来获取用户输入(除非这个调用是幌子,根本不会被执行?)。GetDlgItemText上断点,随便输入key后敲回车,但并没有断下来,查找后发现GetDlgItemText只有在程序接收到0x464消息后才会执行,而0x464并非标准Windows消息,应该程序作者自定义的,查找后发现程序只有在0040DEE2开头的一个函数中会产生0x464消息,而0040DEE2在程序中被SetUnhandledExceptionFilter设置为异常处理函数,查看SetUnhandledExceptionFilter发现其所设置的异常处理函数只有进程在未被调试时才会执行,所以在OD中调试时自然不会执行,也就不会执行GetDlgItemText了,经过网上搜索发现HideOD这个插件可以解决这个问题(感谢作者)。


4,使用HideOD插件后,已经能够在GetDlgItemText断下,断下后便开始单步跟踪,过程中发现程序使用“PEDIY”对00411B30开始的1AAH个字节进行异或,而00411B30正是在对输入Key进行处理时会被调用的一个函数。


5,接下来分析程序对输入Key的处理:

1) 将输入的key记为key1,将key1的每个字节和0xCC异或,结果记为key2;

2) 查找key2的每个字节在下面数组a中的偏移量,将此偏移记为t,执行运算:t = t + (t / 5 + 5),且当前处理的是key2的第几个字节(从1数起),这个运算就执行几次,最后记下key2[t];

  a=[0x89,0xBC,0x95,0xFC,0xFB,0xBA,0xED,0x9A,0xBB,0xAE,
     0xFE,0x99,0xA2,0x98,0xB9,0xF9,0x9F,0x84,0x9C,0xFD,
     0x83,0xAD,0xB6,0xA9,0xA5,0xF5,0x8C,0xA7,0x9E,0x96,
     0x8A,0xF4,0x85,0xBE,0xA8,0x8F,0x86,0xAF,0x88,0x9D,
     0x87,0xBF,0xFF,0xA1,0x8B,0x81,0xA0,0xAB,0x8E,0xBD,
     0xB5,0xAA,0x82,0x94,0xA4,0x8D,0xA3,0xF8,0xB4,0xFA,
     0x9B,0xA6,0xB8,0x80]

(将数组a中每个字节和0xCC异或,发现其实是0-9A-Za-z!@这个64个字符,所以出入key时的字符也应该在这范围中)

3) 将上一步中得到的所有key2[t]按先后顺序连接在一起,记为key3;

4) 将key3中的每个字节先和0xCC异或,再循环左移3位,结果记为key4;

5) 接下生产key5,key5的长度为key1长度的4倍。

规则为:key5[0]=key4[0]的高四位 / 4

             key5[1]=key4[0]的高四位 % 4

             key5[2]=key4[0]的低四位 / 4

             key5[3]=key4[0]的低四位 % 4

             key5[4]=key4[1]的高四位 / 4

             ……

key的处理到此结束;


6, 接下来程序判断key5的长度是否为80(即key1的长度是否为20),若是,判断key5的每个元素是否和下面的数组b相等,若相等,将00411A9C开始的94H个字节复制到一块动态内存,然后使用key1异或动态内存中的这94H个字节,然后用key1[8]异或动态内存的第94个字节,然后程序转到该这个动态内存执行。

  b=[02,02,00,03,00,00,02,03,00,01,02,03,02,00,00,02,02,00,02,02
     02,03,02,03,01,00,02,02,02,01,02,03,02,02,02,01,02,03,02,03,
     02,01,00,03,02,02,02,02,02,02,00,03,01,02,02,03,02,00,00,02,
     02,02,02,02,00,00,00,02,01,00,02,02,02,03,00,02,01,00,00,03]


经过上述分析,可以看出key长度需为20,且通过数组b可以倒推出正确的key,但由于一个key3可能倒推出多个key2,最终倒推出以下20个集合,按顺序每个集合对应key的1位:

c0 = ['B']
c1 = ['w','j']
c2 = ['n']
c3 = ['d','s']
c4 = ['Y','l','A']
c5 = ['b','t']
c6 = ['P','i']
c7 = ['H','e']
c8 = ['d','c','s']
c9 = ['P','i']
c10 = ['y']
c11 = ['2','5']
c12 = ['0','g','o']
c13 = ['1','a']
c14 = ['7','B','4']
c15 = ['@','r','K']
c16 = ['J','G','X']
c17 = ['9','I','D']
c18 = ['O']
c19 = ['k','F']

经过排列组合、观察猜测、尝试,最终得到正确Key:BwnsAtPediy2017KX9Ok


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞2
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回