为什么execstack需要在堆上执行code? [英] Why is execstack required to execute code on the heap?

查看:1514
本文介绍了为什么execstack需要在堆上执行code?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了code以下测试壳code(对于取消链接的/ tmp / passwd文件),用于安全类的任务。

当我与的gcc -o测试-g test.c的编译,我得到一个段错误就跳入壳code。

当我用后处理 execstack -s测试二进制,我不再得到段错误和外壳code正确执行,取消的/ tmp / passwd文件

我正在 GCC 4.7.2 。现在看来似乎是坏主意要求堆栈可执行以使堆可执行文件,因为有较前者后者的有更多的合法使用例

这是预期的行为?如果有,是什么道理呢?

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
字符*外壳code;
诠释主(){
    外壳code =的malloc(67);
    FILE * code =的fopen(壳code.bin,RB);
    FREAD(壳code,1,67,code);    INT(* FP)(无效)=(INT(*)(无效))外壳code;
    FP();
}

下面是 XXD壳code.bin 输出:

  0000000:。eb28 5e89 760C注音字母扩展8846 0bfe c0fe c0fe(^ v.1..F ......
0000010:c0fe c0fe c0fe c0fe c0fe c0fe c0fe C089 ................
0000020:f3cd 8031​​ db89 D840 CD80 e8d3 FFFF ff2f ... 1 ... @ ....... /
0000030:746D 702f 7061 7373 7764 TMP / passwd文件


解决方案

真正的意外的行为是设置标志,使的的可执行程序以及堆栈。该标志用于与(当你把一个嵌套函数的地址,如GCC),不应真正影响堆中生成基于堆栈的可执行文件的thunk使用。但是,Linux的全球通过使所有可读的网页可执行实现此。

如果你想更细粒度的控制,你可以改用则mprotect 系统调用来控制每个页面的基础上可执行的权限 - 添加code状

  uintptr_t的页面大小=的sysconf(_SC_PAGE_SIZE);
的#define PAGE_START(P)的((uintptr_t形式)(P)及〜(页大小-1))
PAGE_END的#define(P)(((uintptr_t形式)(P)+页面大小 - 1)及〜(PAGESIZE-1))
则mprotect((无效*)PAGE_START(壳code),PAGE_END(壳code + 67) - PAGE_START(壳code)
         PROT_READ | PROT_WRITE | PROT_EXEC);

I wrote the code below to test shellcode (for unlinking /tmp/passwd) for an assignment in a security class.

When I compile with gcc -o test -g test.c, I get a segfault on the jump into the shellcode.

When I postprocess the binary with execstack -s test, I no longer get a segfault and the shellcode executes correctly, removing /tmp/passwd.

I am running gcc 4.7.2. It seems like it is bad idea to require the stack to be executable in order to make the heap executable, since there are many more legitimate use cases of the latter than the former.

Is this expected behavior? If so, what is the rationale?

#include <stdio.h>                                     
#include <stdlib.h>                                    


char* shellcode;                                       


int main(){                                            
    shellcode = malloc(67);                            
    FILE* code = fopen("shellcode.bin", "rb");      
    fread(shellcode, 1, 67, code);                     

    int (*fp)(void) = (int (*) (void)) shellcode;      
    fp();                                              
}    

Here is the output of xxd shellcode.bin:

0000000: eb28 5e89 760c 31c0 8846 0bfe c0fe c0fe  .(^.v.1..F......           
0000010: c0fe c0fe c0fe c0fe c0fe c0fe c0fe c089  ................           
0000020: f3cd 8031 db89 d840 cd80 e8d3 ffff ff2f  ...1...@......./           
0000030: 746d 702f 7061 7373 7764                 tmp/passwd                 

解决方案

The real "unexpected" behavior is that setting the flag makes the heap executable as well as the stack. The flag is intended for use with executables that generate stack-based thunks (such as gcc when you take the address of a nested function) and shouldn't really affect the heap. But Linux implements this by globally making ALL readable pages executable.

If you want finer-grained control, you could instead use the mprotect system call to control executable permissions on a per-page basis -- Add code like:

uintptr_t pagesize = sysconf(_SC_PAGE_SIZE);
#define PAGE_START(P) ((uintptr_t)(P) & ~(pagesize-1))
#define PAGE_END(P)   (((uintptr_t)(P) + pagesize - 1) & ~(pagesize-1))
mprotect((void *)PAGE_START(shellcode), PAGE_END(shellcode+67) - PAGE_START(shellcode),
         PROT_READ|PROT_WRITE|PROT_EXEC);

这篇关于为什么execstack需要在堆上执行code?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆