RCTF-WriteUp

充当炮灰去被虐了一场,做了几个题,感觉挺有收获,涨了些姿势,就来记录下姿势吧。

Re100

唔,ELF,看了下流程,有两个Check的地方。

signed int __cdecl check1(int a1)
{
int j; // [sp+0h] [bp-14h]@4
int v3; // [sp+4h] [bp-10h]@4
int i; // [sp+8h] [bp-Ch]@1
int v5; // [sp+Ch] [bp-8h]@1

v5 = 0;
for ( i = 0; i <= 1024 && *(_DWORD *)(4 * i + a1); i = v5 * (v5 + 1) / 2 )
{
v3 = 0;
for ( j = 0; j <= v5; ++j )
v3 += *(_DWORD *)(4 * (j + i) + a1);
if ( 1 << v5 != v3 )
return -1;
++v5;
}
return v5;
}

跟着为了过check1,你会慢慢地写出1 1 1 1 2 0之类的一串。然而,师傅说了句杨辉三角,过check2需要20行,意思是,把20行杨辉三角一个字符空一格输入进去,以0结尾。所以,flag是去掉空格的字符串的md5。

Re200

不知道你信不信,反正我就是会玩游戏的,你看:
Alt text
分分钟玩到11关,可是说好的flag呢?怎么不弹出来了?正在吐槽呢,看到游戏目录下有个flag.txt。
所以flag是RCTF{U_9et_Th3_f1@g_0F_TankGame},好吧,其实,你不会信的,仔细看上面的图,你会发现出敌方坦克的地方都有栅栏,是的,他们被困住了。原因是,地图文件里,00-06有对应的物体放到对应的像素上。游戏界面是一个13*13的矩阵,00代表空白,04代表栅栏,03代表绿色的草,01是墙,06是你老家那座标志。然后我把第十关所有出坦克的地方用04堵住,再把这张地图复制十几份,因为怕程序做其他判定,就用第十关的地图。当然那,我并没有去逆程序,一直在打游戏呢~~~

Re300-Winer CrackMe

怎么说呢,纯体力活的一道题吧,反正我没找到什么其他的技巧。
程序是UPX加壳的,就带壳调试吧。找个工具脱了下壳,然后丢到ida里静态辅助看。
随意输入个密码,提示“wrong flag”。那先从ida里定位到string,再看调用处:
Alt text
其实,第一个jnz是长度比较,输入的flag经过一系列运算后,长度需要为108,随手测了几次,发现,是4倍的关系。于是,flag长度应该是27字节。下一个jz则是与程序中保存的加密后的数据对比。

22722272222227272222727a2222222222272222272222222222cfdceeeebb9fdbcdbbedfdede7ce9bebe0bb1e2ceab9e2bbbdecf9d8

若两个判断都通过,则提示flag正确。
那,就从2272这里逆回去吧。
刚开始尝试的是,输入1、11、211看看数据相关性如何,结果发现,位数少的时候,似乎可以明文密文一一对应,开心了一下。再试一个27个1,和2与26个1,直接GG了,108位几乎全变了。不能投机取巧就好好逆吧。
其实加密函数也就两三个。分别是sub_401020sub_401080sub_4011E0sub_401020好理解,F8过一次就知道是返回ASCII码的。比如输入123,返回313233sub_401080传入313233和长度,返回的是*()_+之类的符号,先不详细看具体算法。而后再经过一次sub_401020,得到2722……。这些都好理解,也能逆回去。重点在于后面004013C4处的一个循环,他会在内存0040ADF8处生成一个类似置换表一样的东西。如图:
Alt text
在此后,sub_4011E0中会完成置换过程。
先前一直在想,输入的密码和生成的置换表之间有什么关联。在单步调了一两次之后,很惊奇的发现,居然没有关系,这也就是说,这个置换表是不会变的。我可以任意构造一个27字节的flag,来导出置换表。
我的比较笨的做法是,在0040120A处下断,记录次数与对应的EAX的值,如此获取到了置换表。
得到置换表之后,就是把程序中提供的密文先置换回去。

f = open('dic.txt', 'rb')
con = f.readlines()
dic = {}

cipher = '22722272222227272222727a2222222222272222272222222222cfdceeeebb9fdbcdbbedfdede7ce9bebe0bb1e2ceab9e2bbbdecf9d8'

for i in range(len(con)):
dic[str(int(con[i].replace('\r\n', '')))] = str(i+1)

xx = []
for i in range(len(cipher)):
xx.append(cipher[int(dic[str(i + 1)]) - 1])

print "".join(xx)

得到置换前的密文是:

2a792b2e2b7b2d7e2d2d2d7e2e2f2b2b2f2c2d7e2f2c2e202e2d2d7e2c2b2f2b2e292e2b2e7a2c7c2b2b2d7e2e2e2b292c282b212b29

再就是转ASCII,得到密文如下:

*y+.+{-~---~./++/,-~/,. .--~,+/+.).+.z,|++-~..+),(+!+)

再然后,就是逆sub_401080了,可以从代码可以看到,他似乎只做了个异或,那在od里直接把上面字符串传入,返回得:

2a363c5f555f6733745f7468655f437361636b4d335f6631403931

再把它转ASCII看:
*6<_U_g3t_the_CsackM3_f1@91
看起来是flag,输入也对,但是提交不对~~
也就是说,401080中结果不唯一。再跟着好好看了遍,得到flag:
RCTF{*&*_U_g3t_the_CrackM3_f1@9!}

Re300-OldB

一个VB程序,很蛋疼的下载了个vb decompiler,然后就开始坑爹之旅。折腾了两三小时,无果,准备放弃了。只知道,用了个算法,加密了输入的flag,得到的结果是:

E5FCA9488F7EE37112F5576EA5CEF21A  45AD0423DC81C526F370E8639DC73CC1

而且稍微测试了下,输入的flag长度大于16的时候,才会生成64字节的加密结果。也就是说flag长度大于16.
给出的hint叫做猜算法。
而vb decompiler里看到的是des,然后根据里面给出的看起来像key的东西}@$&]_#{a_b*lr=(猜,算法应该是3des。
然后就去解密,嗯,无果~~~
都快要放弃不做了的时候,大神说,都猜一猜吧。我拿出peid扫,并没有找到啥结果。
后来想了想,要不要dump内存来试试。
就直接把程序跑起来,调出任务管理器,然后转存程序。再用peid试试:
Alt text
发现了好多算法,MD5、SHA1、CRC32、BASE64、AES、DES等等,排除校验、哈希、BASE64,就只剩下AES和DES了。会是谁呢?
都试试,发现AES也不能解密。密码错了?
刚好论文就是写这方面,于是拿出aeskeyfinder。
Alt text
唔,还真找到了,7e4327255e5c2078625c61296f713e2b,就是~C'%^\ xb\a)oq>+。能确定算法和密钥了。
然后解密,tm还是不对。
然后自己用,密钥加密了一次purplerocpurpleroc,与程序中生成的进行对比,在00402C7A处下断点:
Alt text
也就是说,他把加密后的内容逆序了一次。
于是:
Alt text
flag:RCTF{VB6_i5_3a5y_rIgHt}

Mobile 100

其实我是不会做安卓的,下下来一个ab啥的,看不懂。超级鸡说那是安卓备份.ab文件。就去网上搜了下怎么解包。看到了这个:http://bobao.360.cn/learning/detail/169.html。于是,跟着教程一步步的解开了.ab文件。apps文件夹里有com.example.mybackupcom.example.zi,都放jeb里看了看,最后认为是com.example.mybackup比较有用,这里边有data文件,有数据库文件,也有apk。想着,flag应该是藏到数据库中了,winhex打开,想都不用想,肯定加密了的。
首先想到的就是内存dump,做法是:

原因也很简单,运行过程中,apk肯定会解密数据库,让其存放在内存中,如果是每操作一次数据库再去解密一次,未免太复杂。

然后我就这么做了,然后就dump出了一个1G的raw文件。
然后就用winhex搜purpleroc。能搜到,但是居然找不到flag,什么鬼。当然,肯定不能搜flag作为关键字,我想的是,我插入的数据肯定是在数据库中已存在的数据周围的,因为SQLite3的文件格式曾经分析过~

难道有问题?反复试了一两次后,发现还有个问题,就是替换db后,程序启动就奔溃,尝试了好久,发现时权限设置的问题,于是把databases文件夹和BOOKS.db文件的权限都设置好后,成功启动。可还是找不到flag。

怎么办?无奈,把apk丢到jeb里,开始了坑爹之旅。来来回回找密码,先直接找dex头部的签名信息,再hook拿密码。
Alt text

找完之后用sqlcipher也好,用python的sqlcipher库也罢,都打不开,就差自己写个apk来读数据了。坑了一晚上之后,再次打开dump文件,还是搜我添加的purpleroc,然后发现,有个地方出现了两次,但winhex只找到其中一处。艾玛,感情是被它坑了啊,然后换一种搜索方式,不搜字符串了,改成搜ASCII码,于是~就找到了: