ROP学习记录
ROP的全称为Return-oriented programming(返回导向编程)
保护机制:
DEP(堆栈不可执行)
ASLR(内存地址随机化)
Stack Protector(栈保护)
NX:No-eXecute(不可执行),基本原理是将数据所在的内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。
主要思想:在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程
ROP攻击一般条件:
- 程序存在溢出,并且可以控制返回地址
- 可以找到满足条件的 gadgets(不相邻的程序已有的代码 ) 以及相应 gadgets 的地址
ret2text
原理
ret2text 即控制程序执行程序本身已有的的代码 (.text)
练习:
pwn1_1
checksec:


ida分析后发现这里读入是通过read,且这里的读取长度4096>buf的定义16,可造成溢出
这里可见后门函数:
这里分析buf函数以找出返回地址

exp:
1 | from pwn import * |
CTFHUB_ret2text:
checksec:

ida分析代码



EXP如下:
1 | from pwn import * |
ret2shellcode
原理:
即控制程序执行 shellcode 代码。shellcode 指的是用于完成某个功能的汇编代码
**注意:**要想执行shellcode,需要对应的程序在运行时shellcode所在的位置具有可执行权限,
基本思路: 先找到溢出点,确定溢出位后看是否可在bss段写数据,确定可写后将shellcode的数据发送到bss段,最后通过覆盖跳转地址跳转到shellcode所在的地址进行执行
BSS段(bss segment)通常是指用来存放程序中未初始化的或者初始化为0的全局变量和局部静态变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配
练习
ret2shellcode

程序几乎没有开启任何保护
这里ida分析:
看到将s的数据复制到了buf2,而buf2在.bss段:
exp:
1 | #!/usr/bin/env python |
pwn2_2

这里修改了phone_number所在的bss段的权限,权限7表示可读可写可执行

exp:
1 | #!/usr/bin/env python |
关于这里的context:
context 是 pwntools 用来设置环境的功能。在很多时候,由于二进制文件的情况不同,我们可能需要进行一些环境设置才能够正常运行exp,比如有一些需要进行汇编,但是32的汇编和64的汇编不同,如果不设置context会导致一些问题,一般来说我们设置context只需要简单的一句话:
1 >context(os='linux', arch='amd64', log_level='debug')或者
context(os='linux', arch='amd64')
- os设置系统为linux系统,在完成ctf题目的时候,大多数pwn题目的系统都是linux
- arch设置架构为amd64,可以简单的认为设置为64位的模式,对应的32位模式是’i386’
- log_level设置日志输出的等级为debug,这句话在调试的时候一般会设置,这样pwntools会将完整的io过程都打印下来,使得调试更加方便,可以避免在完成CTF题目时出现一些和IO相关的错误。
ret2syscall
原理:
ret2syscall,即控制程序执行系统调用,获取 shell

前置条件:可以找到更改eax的gadget
32位程序:
目的是为了执行execve(“bin/sh”,NULL,NULL)
eax ebx ecx edx
0xb ”bin/sh"的地址 0 0
最后要以int 0x80结尾
其中eax存储0xb是execve函数对应的系统调用号
1 | //系统调用号的查看 |
通过ROPgadget工具进行查找gadget
1 | 1.ROPgadget找gadget |
练习:
ctfwiki_ret2syscall
该程序是一个32位的程序:


通过ROPgadget查找需要的语句

1 | #!/usr/bin/env python |
pwn3_1


ret2libc
原理:
ret2libc 即控制函数的执行 libc 中的函数,通常是返回至某个函数的 plt 处或者函数的具体位置 (即函数对应的 got 表项的内容)。一般情况下,我们会选择执行 system(“/bin/sh”),故而此时我们需要知道 system 函数的地址。
练习:
ret2libc1(有’/bin/sh‘和system函数)

找到ststem函数的地址和’/bin/sh‘的地址


1 | #!/usr/bin/env python |
ret2libc2(有system函数无’/bin/sh’)

没有开PIE,地址固定,所以可以将’bin/sh’写在bss段上


思路:通过gets函数溢出,再次调用gets函数,使得用户可以输入’/bin/sh‘,并通过gadget将’/bin/sh’写进bss段的buf2(不写在栈上是由于栈的地址不可控,而没有开PIE时,bss段地址时不变的),再通过调用system函数,执行system(‘/bin/sh’)

1 | #!/usr/bin/env python |

ret2libc3(无system函数无’/bin/sh’)
待完善…(在学)