BUUCTF Youngter-drive WriteUp
进程是啥?
题目地址
https://buuoj.cn/challenges#Youngter-drive
题解
先用upx脱壳。
upx -d 要脱壳的文件名
拖入IDA,主函数如下:
进入第6行函数可知,Source是我们输入的字符串。第7行的Mutex的意思是互斥锁。第9和第10行创建了两个进程。从第9行的StartAddress一步步进入,直到报错。
来到汇编窗口,先通过Options→General→Disassembly→勾选Stack Pointer使得sp可见。
然后通过Search→text,查找411940
据网上大佬们的wp,这是堆栈不平衡(我还不懂)
发现retn那里的sp为-04,那么点击上面的call,Alt+K修改sp为-0x4(网上也有修改retn的sp为0的wp,但是我在retn这行Alt+K会报错,不知道为什么)
这样就可以查看sub_411940的内容了。
而主函数第9和10行两个进程内的操作分别见下面两张图
其中dword_418008初始值为1Dh,即10进制的29。
关于进程我其实不懂,结合其他大佬的wp,我抽象地理解一下,有误请指正:先进行主函数第9行的进程,即使用sub_411940进行加密,然后dword_418008自减1,进程休眠64ms,然后第10行的进程执行,dword_418008自减1,进程休眠,然后又是第9行的进程执行。两个进程交替进行,都对dword_418008进行减去1的操作,但第9行的还对Source进行加密的操作。
我们再回到主函数
第10行是判断经过处理后的Source等于off_418004的值时,将Dest(即我们输入的字符串的值)作为flag打包输出。
加密和判断用到的两个字符串值如下(我很疑惑什么时候要将字符串翻转再使用,以前做的题说是因为小端所以要翻转,不过一般是用int64表示的字符串会有那种情况,这里不需要)
然后就可以写脚本解题了。一开始索引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)