2012-03-31 43 views
6

我想要一个简单的C方法能够在Linux 64位机器上运行十六进制字节码。下面是我的C程序:如何让c代码执行十六进制字节码?

char code[] = "\x48\x31\xc0"; 
#include <stdio.h> 
int main(int argc, char **argv) 
{ 
     int (*func)(); 
     func = (int (*)()) code; 
     (int)(*func)(); 
     printf("%s\n","DONE"); 
} 

,我试图运行("\x48\x31\xc0")我通过书面方式这个简单的汇编程序(它不应该做任何事情)

​​

获得的代码然后编译并objdump-它获得字节码。

但是,当我运行我的C程序时,出现了分段错误。有任何想法吗?

+5

即使你的数据段是可执行的,或者你没有启用NX,你能指望这样做?它执行一条指令,然后执行后面的指令(你不控制),然后执行指令,直到它到达的内存不代表触发段错误的合法代码或代码。 – 2012-03-31 23:55:16

+1

您需要为'ret'添加字节码,因为您做的间接函数调用应该是一个'call',它将返回地址压入堆栈。至少,这是我受过最好教育的猜测,我从未见过这样的事情。 – Chris 2012-03-31 23:56:56

+0

我希望这样做什么都不做,但我希望它能够在不崩溃的情况下运行。 – Nosrettap 2012-03-31 23:58:52

回答

13

这是一个简单的例子。

的main.c:

#include <sys/mman.h> 
#include <string.h> 

int main() 
{ 
    /*                
     mov rax, 60   ; sys_exit 
     mov rdi, 2 
     syscall             
    */ 
    char code[] = { 
     0x48, 0xb8, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x48, 0xbf, 0x02, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x0f, 0x05 
    }; 

    void *buf; 

    /* copy code to executable buffer */  
    buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC, 
       MAP_PRIVATE|MAP_ANON,-1,0); 
    memcpy (buf, code, sizeof(code)); 

    /* run code */ 
    ((void (*) (void))buf)(); 

    return 0; 
} 

./main ;echo $? 

我选择了做一个_exit(2)在大会可以很容易地检查代码是否正确运行运行这一点。实际上,您需要在代码的最后添加一个ret来返回控制权。

+0

是的,'ret'对于返回到调用函数很重要。 – Chris 2012-04-01 19:22:02

+1

感谢您的帮助。我只想补充一点,objdump -d 可以让你获得可执行文件的字节码。 – Jeff 2013-10-24 19:00:36

4

您的机器代码可能是正确的,但是您的CPU对象。

现代CPUs分段管理内存。在正常操作中,操作系统将一个新程序加载到程序文本段中,并在数据段中设置堆栈。操作系统告诉CPU从不在数据段中运行代码。您的代码位于数据段中的code[]。因此段错误。

2

这将需要一些努力。

code变量存储在你的可执行文件的.data部分:

$ readelf -p .data exploit 

String dump of section '.data': 
    [ 10] H1À 

H1À是你的变量的值。

.data可执行:

$ readelf -S exploit 
There are 30 section headers, starting at offset 0x1150: 
Section Headers: 
    [Nr] Name    Type    Address   Offset 
     Size    EntSize   Flags Link Info Align 
[...] 
    [24] .data    PROGBITS   0000000000601010 00001010 
     0000000000000014 0000000000000000 WA  0  0  8 

所有64位处理器,我熟悉支持非可执行网页本身的pagetables。大多数较新的32位处理器(支持PAE的处理器)在页表中为操作系统提供足够的额外空间来模拟硬件非可执行页面。您需要运行古老的操作系统或古老的处理器,以获得标记为可执行文件的.data部分。

因为这些只是可执行文件中的标志,所以您应该能够通过其他一些机制来设置X标志,但我不知道该怎么做。而且你的操作系统甚至可能不会让你的页面可写可执行文件。