BUUCTF Youngter-drive WriteUp

进程是啥?

题目地址

https://buuoj.cn/challenges#Youngter-drive

题解

先用upx脱壳。

upx -d 要脱壳的文件名

拖入IDA,主函数如下:

0

进入第6行函数可知,Source是我们输入的字符串。第7行的Mutex的意思是互斥锁。第9和第10行创建了两个进程。从第9行的StartAddress一步步进入,直到报错。

1

来到汇编窗口,先通过Options→General→Disassembly→勾选Stack Pointer使得sp可见。

3

然后通过Search→text,查找411940

1-5

据网上大佬们的wp,这是堆栈不平衡(我还不懂)

发现retn那里的sp为-04,那么点击上面的call,Alt+K修改sp为-0x4(网上也有修改retn的sp为0的wp,但是我在retn这行Alt+K会报错,不知道为什么)

4

这样就可以查看sub_411940的内容了。

5

而主函数第9和10行两个进程内的操作分别见下面两张图

6        7

其中dword_418008初始值为1Dh,即10进制的29。

关于进程我其实不懂,结合其他大佬的wp,我抽象地理解一下,有误请指正:先进行主函数第9行的进程,即使用sub_411940进行加密,然后dword_418008自减1,进程休眠64ms,然后第10行的进程执行,dword_418008自减1,进程休眠,然后又是第9行的进程执行。两个进程交替进行,都对dword_418008进行减去1的操作,但第9行的还对Source进行加密的操作。

我们再回到主函数

0

第10行是判断经过处理后的Source等于off_418004的值时,将Dest(即我们输入的字符串的值)作为flag打包输出。

加密和判断用到的两个字符串值如下(我很疑惑什么时候要将字符串翻转再使用,以前做的题说是因为小端所以要翻转,不过一般是用int64表示的字符串会有那种情况,这里不需要)

image

然后就可以写脚本解题了。一开始索引dword_418008为29的时候要加密,那么索引i为0的时候不解密,为1的时候解密。阅读sub_411940可以得知,我们要找到最后与Dest相比较的字符串off_418004的每一位字符在加密函数中的字符串off_418000中出现的位置,再根据索引的奇偶,和位置+38是否大于等于65来判断是否进行解密以及如何解密。注意off_418004字符串只有29位,而我们需要30位,所以最后要添加一位。(根据答案,最后一位字符解密后为’E’)

  1 test = "TOiZiZtOrYaToUwPnToBsOaOapsyS"
  2 test1 = "TOiZiZtOrYaToUwPnToBsOaOapsySy" # 随便添加一位(说随便其实也不随便)
  3 key = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasd"
  4 Source=""
  5 for i in range(0,30):
  6     if i%2==1: # 加密
  7         # x = key.find(test[d]) # 会报错,out of range,test只有29位
  8         x = key.find(test1[i])
  9         if x+38 >= 65: 
 10             Source+=chr(x+38)
 11         else: 
 12             Source+=chr(x+96)
 13     else: # 不加密
 14         Source+=test1[i]
 15 print(Source)

参考

安恒杯-7月月赛-Reverse-Youngter-drive

BUUCTF re:Youngter-drive

posted @ 2020-04-15 23:26  平静的雨田  阅读(733)  评论(0编辑  收藏  举报