D:*******\考核\CTF\ReverseMe
不同长度的答案对应不同的结果,可知,答案长度有限制:拖进ida里看具体代码:
可知答案长度在19到30之间,还经过了一个函数的判断才能输出congratulations,这个函数有两个参数,第一个是v5,内存里有,第二个是我们输入的字符,所以点进去看看这个函数:
由a3=25,知道key长度25,然后经过了循环左移2位(第二个参数是循环左移的位数),又和sub_401460(a2, v7)函数返回值异或,然后当v36(异或后的数据)和v8(v10)相等,则返回1,则输出congratulations
逆向思维,我们现在知道了v8,也就知道了v36,经过sub_401460(a2, v7)函数异或再循环右移2位就可以得到我们想要的key了:
v10我们知道(有的是负数,带符号的char型,换成16进制就行),关键sub_401460(a2, v7)函数到底经过了什么运算?点进去看一下
有点复杂,不过我们可以用OD直接跟到这个函数返回值:
先按要求输入25位key:然后修改几次跳转来到异或的地方:
最后跟出来的是:
0x1a,0xa2,0x2f,0xf9,0x94,0x43,0x3c,0xc4,0x4d,0xd8,0x8c,0xc5,0x5b,0xb6,0x6e,0xea,0xa3,0x3c,0xc9,0x9b,0xbc,0xca,0xad,0xd7,0x7e
最后,还有循环右移的操作,我们可以写脚本,写完存起来,以后很可能还用,当做小工具脚本
所以我们现在可以写脚本了:
脚本1:
a=[15,135,98,20,1,198,240,33,48,17,80,208,130,35,174,35,238,169,180,82,120,87,12,134,139]
b=[0x1a,0xa2,0x2f,0xf9,0x94,0x43,0x3c,0xc4,0x4d,0xd8,0x8c,0xc5,0x5b,0xb6,0x6e,0xea,0xa3,0x3c,0xc9,0x9b,0xbc,0xca,0xad,0xd7,0x7e]
c=[]
d=[]
for i in range(len(a)):
c.append(bin(a[i]^b[i]))
for i in c:
d.append(i[2:] )
print(d)
输出:
['10101', '100101', '1001101', '11101101', '10010101', '10000101', '11001100', '11100101', '1111101', '11001001', '11011100', '10101', '11011001', '10010101', '11000000', '11001001', '1001101', '10010101', '1111101', '11001001', '11000100', '10011101', '10100001', '1010001', '11110101']
每个二进制都是8位:不满的手动以0补全,自动的脚本还没写出来,先一步一步写出来吧!
脚本2:
def xol(s): #循环左移2位
s1=s << 2
s2=(s1&768)>>8
s3=(s1|s2)&255
return s3
def xor(s): #循环右移2位
s1=s&3
s2=s>>2
s3=s1<<6
s4=s3|s2
return s4
a=['00010101', '00100101', '01001101', '11101101', '10010101', '10000101','11001100', '11100101', '01111101', '11001001', '11011100', '00010101','11011001', '10010101', '11000000', '11001001', '01001101', '10010101','01111101', '11001001', '11000100', '10011101', '10100001', '01010001','11110101']
for i in a:
print(chr(xor(int(i,2))),end='')
#输出:EIS{ea3y_r7Eve0rSe_r1ghT}