dmd-50

做题实录

附件dMd是个64位ELF文件,运行一下,让输入key,随便输入一个,报错。

1565588951505

IDA打开看一下

2019-08-12_135045

直接看if判断,发现字符串780438d5b6e29db0898bc4f0225935c0,分析代码,看到第50行是个MD5加密,所以想到尝试MD5解密上面这个字符串,在这个网站解密的结果如下:

1565589413006

然后我运行程序输入grape,程序报错,好吧,看来没这么简单

进到MD5函数里看看,也没发现什么

1565590696742

做题一度陷入了僵局。后来又进入一个解密网站解密,发现居然解密的结果不一样

这次的结果是

1565590901116

运行程序输入b781cbb29054db12f88f08c6e161c199,成功。所以flag就是b781cbb29054db12f88f08c6e161c199。

后来我发现grape在MD5加密之后就是b781cbb29054db12f88f08c6e161c199,可能第一个网站比较牛逼,直接给你解析到最开始的字符串

分析总结

这个就是简单的看源码分析找到MD5解密就行了,没什么难度。

Shuffle

题目描述:找到字符串在随机化之前.

做题实录

这是个32位elf文件,运行跑出来是乱码

放到IDA里看一下

这……不说了

直接出答案SECCON{Welcome to the SECCON 2014 ctf!}

re2-cpp-is-awesome

题目描述:他们说c++是复杂的,证明他们说的是错的!

做题实录

上来先一顿基操

1565595113757

IDA,开启!进入main函数

2019-08-12_190525

分析函数,可以发现第35行是主要的判断函数,v9就是我们输入的flag。那么flag的线索就藏在off_6020A0[asc_6020C0[v15]]里,那先看看off_6020A0里是什么吧。

1565608274123

看到一个像flag的东西,突然兴奋了起来,不会这么简单吧。继续看

1565608360037

好吧,本来以为是flag,但是看到这发现事情果然没有那么简单

接着看asc_6020C0,发现是一些数据

1565609099770

后面其实本来一开始也是db,只不过我改成dd了(按D键),至于为什么要改,是我马后炮做完题才发现的,在写脚本的时候我会说到。

从分析可以看出flag应该就是从off_6020A0处的str(下文都叫str)中生成的。

先通过v15找出对应的asc_6020C0中的值,再以asc_6020C0的值为偏移量在str中找对应的字母,最终拼成flag。

有了这个思路后我就开始试着看一下flag是什么,发现asc_6020C0第一个是“$”,按D键转成ASCII码是24h,数出来是A,接着动态调试一下看看对不对。在判断的地方下断点,然后在Debugger->Process Option->Parameters中填入要输入的参数Adawda(除了开头的A后面是随便填的),开始调试

1565609766817

调试中我又下了两个断点,调试之后发现A是对的,那就印证了我的猜想,那下一步就是把所有的字符找出来。

asc_6020C0的数据提取出来,我直接按照反汇编的结果写的脚本如下:

offset=[36,00,00,00,00,00,00,00,5,00,00,00,54,00,00,00,
        101,00,00,00,7,00,00,00,39,00,00,00,38,00,00,00,
        45,00,00,00,1,00,00,00,3,00,00,00,00,00,00,00,
        13,00,00,00,86,00,00,00,1,00,00,00,3,00,00,00,
        101,00,00,00,3,00,00,00,45,00,00,00,22,00,00,00,
        2,00,00,00,21,00,00,00,3,00,00,00,101,00,00,00,
        00,00,00,00,41,00,00,00,68,00,00,00,68,00,00,00,
        1,00,00,00,68,00,00,00,43] #这是最后字符串的偏移量 注意刚提取出来的时候数都是16进制的,我改成了10进制

str = 'L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t_345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_1F_Y0u_g0t_1t'

for eax in range(0,31):
    i = offset[eax*4]
    print(str[i], end = "")  #后面的end是让打印不自动换行

#得出结果:   ALEXCTF{W3_L0v3_C_W1th_CL45535}

在这一步我卡了好久,因为我在手动把16进制修改成10进制的时候不小心删了个00,然后卡了半天。后来终于发现少了个00补上了但是补错了位置……导致得出了一个这样的flag:ALEXCTF{W3_L0v3LC_W1th_CL45535}

这完全就是一个flag该有的亚子好吗?然后我就怀着激动的心情提交了,然后,系统告诉我,错了

所以说:

细心真的很重要很重要。

不过,我后来发现,特喵的这不是dd双字字形吗,难怪eax要乘4,难怪那么多的0。就因为漏了个0卡了我好久我去

所以我在写这篇文章的时候才把asc_6020C0的数据用dd表示出来,这样就非常直观简洁了

分析总结

实际上做完再回过头来再看这道题,可以看出这道题其实并不算难,但是这道题花了我很多的时间,我很早就注意到了off_6020A0[asc_6020C0[v15]]这个关键点,但是当时看到asc_6020C0的不知道是干啥的数据时有点懵逼,最后硬是汇编调试了半天才反应过来,然后就没有顾其他的直接按照汇编语言写脚本了。实际上做完题之后一看到++v15,每次只自增1,就明白了数据是双字存放的,如果当时冷静下来再思考一下,应该就能很快把这道题做出来。

这个题让我认识到:1.汇编还得好好学。2.IDA真NB,而我连D键咋用都不知道。不行,IDA PRO权威指南,打开!3.我确实是个菜狗,还得多做题

crackme

做题实录

IDA看看源码:

1567172093090

根本不知道这是什么玩意儿,看来是加了壳,PEiD看一下有什么。

1567172218601

可以看到壳是nSPack 3.7,那么就先用UnPackNsPack3.7脱壳,脱完壳之后再分析:

1567172355880

可以看到就是简单的算法逆向,关键语句是第15句,我们看看Notflag和arg(名字我改过了):

1567172454937

可以看到Notflag是字符串,arg是一个数组,那么就写个脚本跑出来就行了:

notflag = 'this_is_not_flag'
arg = ['12', '4', '8', '14', '24', '5C', '4A', '3D', '56', '0A', '10', '67', '0', '41', '0', '1', '46', '5A', '44', '42', '6E',
    ¦  '0C', '44', '72', '0C', '0D', '40', '3E', '4B', '5F', '2', '1', '4C', '5E', '5B', '17', '6E', '0C', '16', '68', '5B', '12']

arg2 = []
for i in range(len(arg)):
    arg2.append(int(str('0x') + arg[i],16))
print(arg2)

flag = ''
for i in range(len(arg2)):
   flag += chr(arg2[i] ^  ord(notflag[i % 16]))  
print(flag)
#得出结果:flag{59b8ed8f-af22-11e7-bb4a-3cf862d1ee75}

分析总结

实际上我认为这道题的难点在于脱壳,我直接用了大佬的工具,具体脱壳流程我还不会,还需要继续学习。

大佬的工具参见这篇文章《[原创]NsPack 3.7 浅析 (7.3更新脱壳机和源码)》


"Imagination will take you everywhere."