笑死,除了比赛,buu真没动多少:smile:
[SUCTF2019]hardcpp
这题不难,耐心分析一下就行,就只用一个坑点:
首先是用了llvm混淆,这个没啥,用d810插件一下就去掉了:
就很清晰的分析了。
加密就是
1
| enc[i] == ((flag[i+1] + flag[i] % 7) ^ ((flag[i] ^ 18) * 3 + 2))
|
就是拿前面的数据加密后面的数据
坑点:
注意s和input在栈上的位置,所有这里的调用一个是input[i-1],一个是input[i-2]。
脚本爆破,居然有数值爆了,注意and 0xff:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| enc = [0xF3, 0x2E, 0x18, 0x36, 0xE1, 0x4C, 0x22, 0xD1, 0xF9, 0x8C, 0x40, 0x76, 0xF4, 0x0E, 0x00, 0x05, 0xA3, 0x90, 0x0E, 0xA5]
for i in range(32, 127): if enc[0] == (ord('f') + i % 7) ^ ((i ^ 18) * 3 + 2): print("flag = '{}'".format(chr(i))) print() flag = [ord('#')]
for i in range(len(enc)): for ch in range(32, 127):
if enc[i] == ((ch + flag[i] % 7) ^ ((flag[i] ^ 18) * 3 + 2)) & 0xff: flag.append(ch) break print(bytes(flag))
|
Dig the way
这道题目考的是栈溢出,先分析程序:
在开头给函数地址赋值,到后面进行使用,不难发现fun2的返回值是恒大于等于2的,此时v5的值是3,根据堆栈来看,v7[3] -> v8,所以正常运行这个程序是不可能到达getkey处。
但是发现了个可以无限读取的地方:
1 2 3 4
| for ( i = 0; i < (int)v13; ++i ){ v4 = i; Str[v4] = fgetc(v14); }
|
一看Str的位置,在栈上,这意味着可以实现栈溢出。
分析三个fun,发现是将数值交换和两个计算:
虽然fun2不能返回0的值,但是fun1可以做到:
|-1 + 2| - |2| - |-1| + 2 = 0
由于存在栈溢出,而且v9,v10这两个参数在读取前面就实现了赋值,于是可以栈溢出输入参数,利用fun0将v7后面任意两个数据转换位置,所以可以让fun1最后执行,这样结果能够返回0然后写入到v8(v7[3])。
然后就是造v7的数据使得最后的计算结果为0:
|0 + 0| - |0| - |0| + 2 = 2
|-1 + 2| - |2| - |-1| + 2 = 0
所以v7[4]的数据为:
为了使得先执行fun2在执行fun1,fun0的参数很简单,一个7(fun1),一个8(fun2),在制造数据的时候注意一下大小端序就行。
v11就不可以动了,这里保存了关键的fun函数位置。
剩下的随意填充:
如果使用栈溢出强行从main返回到getkey,那就记得多把两个参数压一下,v13是0,v12是8
不过都知道是这两个数了,前面也会了,这两参数是解密用的。
[MRCTF2020]Shit
这题居然给了源码,一定程度上教了我花指令怎么写的,涉及的花指令见这篇文章
去完花分析即可:
上图我patch过反动调的检查。
24位输入,然后进行简单的移位异或
key由前面产生。
有个这个神奇的函数:
不知道有什么用。。
对dword_FC5030进行了--,这个函数是必执行的?
最后key是动调过的,在start前面有个初始化的函数
如果在这里之前就动调了,就会在initterm这个函数里面无限循环,只能通过attach的方法来进行动调
查明了,里面写了个无限递归的,检测到动调就进行无限递归,用全局变量复制调用的
然后记得绕一下反动调就能得到key,写个解密就行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| key = [3, 0x10, 0xD, 4, 0x13, 0xB] enc = [0x8C2C133A, 0xF74CB3F6, 0xFEDFA6F2, 0xAB293E3B, 0x26CF8A2A, 0x88A1F279]
for i in range(5, 0, -1): enc[i] ^= enc[i - 1] enc[i] &= 0xffffffff
flag = '' for i in range(len(enc)): enc[i] ^= (1 << key[i]) low = ((enc[i] & 0xffff0000) >> 16) & 0xffff high = (~(enc[i] & 0x0000ffff) & 0xffff) << 16 enc[i] = (high | low) & 0xffffffff enc[i] = ((enc[i] << key[i]) & 0xffffffff) | (enc[i] >> (32 - key[i])) res = '' for ii in range(4): res = chr(enc[i] & 0xff) + res enc[i] >>= 8 flag += res print(flag)
|