1.天津垓
有一些反调试措施和加壳的保护,但是总体逻辑非常简单
1.1 “Authorize:”求解
核心逻辑是:
v39是一个数组,长度为14,具体值为:
arrlist = [0x52,0x69,0x73,0x69,0x6e,0x67,0x5f,0x48,0x6f,0x70,0x70,0x65,0x72,0x21]
其中*(&v39+i%14)就是 arrlist[i%14]
v1也是一个数组,长度为18,具体值为:
target = [17,8,6,10,15,20,42,59,47,3,47,4,16,72,62,0,7,16]
其中*(&v1+i)就是target[i]
那么,str[i]就可以通过遍历可视字符[0x20~0x7f]来求解,只要满足v43==target[i]即可,代码如下:
def main():
arrlist = [0x52,0x69,0x73,0x69,0x6e,0x67,0x5f,0x48,0x6f,0x70,0x70,0x65,0x72,0x21]
target = [17,8,6,10,15,20,42,59,47,3,47,4,16,72,62,0,7,16]
idx = 0
flag1 = ""
for idx in range(0,18):
for c in range(0x0,0xff):
t = ~(c & arrlist[idx%14]) & (c|arrlist[idx%14])
if t== target[idx]:
print(idx,chr(c))
flag1 += chr(c)
print(flag1)
得出flag1 = Caucasus@s_ability
1.2 壳
相关逻辑如下:
地址0x164d是被加壳的内容,大小为1045。sub_1506函数在解壳,之后在第5行即可直接调用unk_164d()函数。
解壳的逻辑如下:
其中第18行就是解码过程,其中*(lpAddress+i)就是unk_164d[i],然后*(v8+i%18)就是str[i%18],可以先把解码之后的内容dump出来,代码如下:
import idc
from binascii import *
s = "Caucasus@s_ability"
def main():
count = 1045
start = 0x10040164D
addr = start
fp = open('origin','wb')
for i in range(0,1045):
c = s[i%18]
addr = start + i;
res = idc.Byte(addr)
res ^= ord(c)
fp.write(a2b_hex(hex(res)[2:].rjust(2,'0')))
fp.close()
if __name__ == '__main__':
main()
用ida打开origin文件,发现不能反编译函数,如下
很明显,解码是正确的,符合函数的特征,尤其是第一个push指令,现在想要反编译这个代码,方便分析逻辑,于是直接将内容patch到原始exe文件上,代码如下:
def rewrite():
fp = open('tjh.exe','rb')
fp2 = open('origin','rb')
data2 = fp2.read()
data=fp.read()
idx = data.find('\x16\x29\xf4\x8f') #是地址0x164d的内容,找到index,可以准确替换
out_data = data[:idx]
for i in range(0,1045):
out_data+=data2[i]
out_data += data[idx+1045:]
fp3 = open('out.exe','wb')
fp3.write(out_data)
fp3.close()
最后用IDA打开out.exe文件,可以看到反编译成功了,逻辑如下:
flag是51个字符,验算过程和Authorize类似,这里就不重复说明了,代码如下:
s=r"""
v9 = 2007666;
v10 = 2125764;
v11 = 1909251;
v12 = 2027349;
v13 = 2421009;
v14 = 1653372;
v15 = 2047032;
v16 = 2184813;
v17 = 2302911;
v18 = 2263545;
v19 = 1909251;
v20 = 2165130;
v21 = 1968300;
v22 = 2243862;
v23 = 2066715;
v24 = 2322594;
v25 = 1987983;
v26 = 2243862;
v27 = 1869885;
v28 = 2066715;
v29 = 2263545;
v30 = 1869885;
v31 = 964467;
v32 = 944784;
v33 = 944784;
v34 = 944784;
v35 = 728271;
v36 = 1869885;
v37 = 2263545;
v38 = 2283228;
v39 = 2243862;
v40 = 2184813;
v41 = 2165130;
v42 = 2027349;
v43 = 1987983;
v44 = 2243862;
v45 = 1869885;
v46 = 2283228;
v47 = 2047032;
v48 = 1909251;
v49 = 2165130;
v50 = 1869885;
v51 = 2401326;
v52 = 1987983;
v53 = 2243862;
v54 = 2184813;
v55 = 885735;
v56 = 2184813;
v57 = 2165130;
v58 = 1987983;
v59 = 2460375;
"""
def solve():
res = s.split('\n')
n_list = []
for item in res[1:-1]:
number = item.split('=')[1].strip(';')
n_list.append(int(number))
v61 = 19683
v62 = 0x8000000b
flag = ""
for i in range(0,51):
for c in range(0x20,0x7f):
t = v61 * (c%v62)
if t == n_list[i]:
flag += chr(c)
print(flag)
最后解出flag为flag{Thousandriver_is_1000%_stronger_than_zero-one}