avatar

目录
ROP Emporium guide ROP攻击入门教程

ROP Emporium

ROP Emporium 是一个ROP攻击入门教学网站,提供了一系列的挑战任务,这些挑战对逆向工程或debug的要求不高,因此对初学者十分友好,适合初学者了解ROP攻击。网站中共有8个挑战任务,每个挑战都引入了一个新概念/知识点,其复杂性和难度逐渐增加,循序渐进,而且每个挑战都有32/64位两个版本的程序,适合初学者了解二者之间的差异。

本文提供ROP Emporium所有挑战的说明文件、二进制文件、在线动态靶机环境以及一些相关解题线索。读者可前往动态靶场完成任务后,再返回本文查看相应题目的知识点、解题思路以及解题脚本。

附件下载:rop_emporium_all_challenges.zip

动态靶场:CTFq动态靶机练习平台

靶机环境:Ubuntu 18.04


读者可前往动态靶场完成任务后,再返回本文查看相应题目的知识点、解题思路以及解题脚本。

ret2win

ret2win means ‘return here to win’ and it’s recommended you start with this challenge.

ret2win就是利用漏洞直接将程序控制流劫持到程序预置的后门函数win

win函数通常是可以打印flag,或者getshell

知识点

  • 缓冲区溢出(覆盖返回地址)

思路

  • 使用ida或cutter反编译程序
  • 找到后门函数ret2win的地址
  • 利用缓冲区溢出覆盖返回地址为后门

题解

建议完成任务后再查看题解

备注

本地测试64位程序时可能遇到的问题:

Code
1
movaps xmmword ptr [rsp + 0x40], xmm0

出现这个问题的原因是执行某些libc函数(如printf, system)时,栈指针rsp没有对齐0x10字节,解决方法如下:

  • ret2win时尽量避开栈操作指令:

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    .text:0000000000400811 ret2win  proc near
    .text:0000000000400811 ; __unwind {
    .text:0000000000400811 push rbp
    .text:0000000000400812 mov rbp, rsp
    .text:0000000000400815 mov edi, offset aThankYouHereSY ; "Thank you! Here's your flag:"
    .text:000000000040081A mov eax, 0
    .text:000000000040081F call _printf
    .text:0000000000400824 mov edi, offset command ; "/bin/cat flag.txt"
    .text:0000000000400829 call _system
    .text:000000000040082E nop
    .text:000000000040082F pop rbp
    .text:0000000000400830 retn
    .text:0000000000400830 ; } // starts at 400811
    .text:0000000000400830 ret2win endp

    0x400811处的push rbp将使得rsp=rsp-0x8,导致rsp不能对齐0x10

    稍作调整,跳过栈操作,改用0x400815即可

  • 使用gadget (ret) 调整栈指针

split

Combine elements from the ret2win challenge that have been split apart to beat this challenge. Learn how to use another tool whilst crafting a short ROP chain.

ret2win相比,这题将后门执行的命令由cat flag改为了/bin/ls,因此不能直接获取flag,但程序中给出了/bin/cat flag.txt这个字符串,因此可以通过构造简单的ROP链获取flag

/bin/cat flag.txt作为参数传给system函数

知识点

  • 简单ROP链的编写

思路

  • 使用ida或cutter反编译程序
  • 找到指令call system的地址
  • 找到字符串/bin/cat flag.txt的地址
  • 构造rop链
  • 利用缓冲区溢出覆盖返回地址为rop链

题解

建议完成任务后再查看题解

callme

Chain calls to multiple imported methods with specific arguments and see how the differences between 64 & 32 bit calling conventions affect your ROP chain.

这题提供了一个自定义的动态链接库,其中包含callme_one,callme_twocallme_three,读者需要通过ROP配置好相应的参数,并依次调用这三个函数来解密并输出flag。

知识点

  • 动态链接库、PLT表

思路

  • 使用ida或cutter反编译程序、动态链接库
  • 在动态链接库中大致了解三个callme函数的功能
  • 在程序中找到三个callme函数在PLT表中的地址
  • 构造rop链,配置函数参数
  • 利用缓冲区溢出覆盖返回地址为rop链

题解

建议完成任务后再查看题解

write4

Find and manipulate gadgets to construct an arbitrary write primitive and use it to learn where and how to get your data into process memory.

在这道题中,通过gadget可以实现内存任意写,目标是将字符串/bin/sh$0写入内存。

知识点

  • 任意写gadget

思路

  • 使用ida或cutter反编译程序
  • 找出可用于任意写的gadget
  • 构造rop链,将字符串写入bss
  • 利用缓冲区溢出覆盖返回地址为rop链

题解

建议完成任务后再查看题解

备注

$0 的含义是第0个参数,即argv[0],默认情况下程序是通过/bin/sh启动的,因此argv[0]就是/bin/sh,在本题32位程序的题解中,使用$0代替/bin/sh作为system执行的命令。

badchars

Learn to deal with badchars, characters that will not make it into process memory intact or cause other issues such as premature chain termination.

这道题与③write4相比,新增了对badchar的检测,并且将用于任意写的gadget换成了具有异或(写内存)功能的gadget,因此目的是练习通过异或对badchar进行绕过。

badchar为 b i c / f n s,所以其实也可以通过$0绕过

知识点

  • 异或功能gadget

思路

  • 使用ida或cutter反编译程序
  • 找出可用于异或写内存的gadget
  • 构造rop链,通过多次异或绕开badchar,将字符串写入bss
  • 利用缓冲区溢出覆盖返回地址为rop链

题解

建议完成任务后再查看题解

懒得写异或的exp了,大概就那个意思…

fluff

Sort the useful gadgets from the fluff to construct another write primitive in this challenge. You’ll have to get creative though, the gadgets aren’t straight forward.

这题还是和③write4类似,与之相比,去掉了可以直接写内存的gadget,换成了一些更为复杂的gadget,因此需要利用多个gadget组合、配合实现写内存的功能。

知识点

  • 组合gadget,间接实现任意写

思路

  • 使用ida或cutter反编译程序
  • 找出可用于写内存的gadget(这题多个gadget组合才能完成任意写)
  • 构造rop链,将字符串写入bss
  • 利用缓冲区溢出覆盖返回地址为rop链

题解

建议完成任务后再查看题解,出于练习的目的,建议使用预期解再看一遍

32位程序的解法是预期解,64位的我偷了个懒:-p

pivot

Stack space is at a premium in this challenge and you’ll have to pivot the stack onto a second ROP chain elsewhere in memory to ensure your success.

这题给了一个自定义的动态库,要求调用其中的ret2win函数,此外栈溢出的可利用空间不足,需要利用题目中给出的gadget进行栈迁移(交换rax和rsp)

知识点

  • 栈迁移、动态链接库、GOT表

思路

  • 使用ida或cutter反编译程序
  • 栈迁移至题目给出的新缓冲区
  • 构造rop链:
    • 从foothold_function的GOT表泄漏libpivot地址
    • 根据偏移量计算ret2win的真实地址
    • 执行ret2win

题解

建议完成任务后再查看题解,出于练习的目的,建议使用预期解再看一遍

ret2csu

Learn a ROP technique that lets you populate useful 64 bit calling convention registers like rdi, rsi and rdx even in an environment where gadgets are sparse.

知识点

  • __libc_csu_init中的gadget

思路

  • 使用ida或cutter反编译程序
  • 构造rop链:
    • 通过__libc_csu_init中的gadget给rdx赋值
    • 调用fini_array中的函数,保持rdx不变
    • 执行ret2win函数
  • 利用缓冲区溢出覆盖返回地址为rop链

题解

建议完成任务后再查看题解,出于练习的目的,建议使用预期解再看一遍

文章作者: TaQini
文章链接: http://taqini.space/2020/06/07/ROP-Emporium-guide/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 TaQini
打赏
  • Wechat
    Wechat
  • Alipay
    Alipay

评论