Fork me on GitHub

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

我先吐槽一句,这题真是巨坑==

Step1: 脱UPX

首先file一下,发现有upx壳,这是第一关。

二话不说upx -d Youngter-drive.exe脱掉。

Step2: 修复F5

然后拖进IDA看源码,主函数如下

然后这点一点那点一点发现StartAddress里有猫腻,跟进去发现关键函数sub_411940无法F5,提示positive sp value has been found

出现这个报错的原因是堆栈不平衡,我们可以通过修改sp value使堆栈平衡。

IDA中Options->General选中Stack pointer可以查看堆栈指针

可以看到,就是因为411A04处堆栈指针为-4导致无法F5,Alt+K可以修改此处的sp value

修改之后如下图,此时堆栈平衡,可以F5。

然后就可以看到关键函数sub_411940的源码

Step3: 逆向解密

这个函数相当于一个加密,逻辑很简单,先判断是否是字母,如果不是直接终止程序;之后判断如果是大写字母则进行替换,小写字母进行另一种替换。

加密完成之后和字符串off_418004进行明文比较,相等即正确。

看到这里我兴奋的一批,直接写脚本跑一发,结果发现交了贼多次都不对。。。

后来注意到main函数写了一个多线程(双线程),然而自己也还不会写多线程,于是疯狂百度函数的作用,才有了上面第二张图主函数的简单注释。

仔细分析会注意到,线程hObject是进行加密,线程v1就是减个下标dword_418008。而dword_418008初始值为0x1d即29,这相当于如果dword_418008是奇数,进行加密,如果是偶数,密文和明文相同。

之后还有个坑,下标从29开始的话意味着输入长度有30,而在函数sub_411880进行check时只比较前29个字符,相等即正确。那么我们只需还原明文的前29位,加上一个任意字母即可。

exp如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'L1B0'

off_418000 = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm\0"

off_418004 = "TOiZiZtOrYaToUwPnToBsOaOapsyS"
print len(off_418004),len(off_418000)

def decode(a):

flag = ""

for i in range(len(a)):
if i %2 == 0:
flag += a[i]
continue
for j,k in enumerate(off_418000):
if a[i] == k:
print i,j
if chr(j+38).isupper():
flag += chr(j+38)
else:
flag += chr(j+96)
break

return flag

def encode(flag):

cipher = ""
for j,i in enumerate(flag):
if j %2 == 0:
cipher += i
continue
if ord(i) < ord('a') or ord(i) > ord('z'):
cipher += off_418000[ord(i)-38]
else:
cipher += off_418000[ord(i)-96]
return cipher

if __name__ == "__main__":
flag = off_418004
flag = decode(flag)
print flag
cipher = encode(flag)

print cipher == off_418004

Flag: ThisisthreadofwindowshahaIsES加一个任意字母

如:ThisisthreadofwindowshahaIsESE

References