执行从C二进制机器code [英] execute binary machine code from C

查看:304
本文介绍了执行从C二进制机器code的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这的我已成功地生产出只有528个字节的指令在大小的a.out(当GCC main.c中给了我8539个字节开始大文件)。

main.c中是:

  INT主(INT ARGC,字符** argv的){    返回42;
}

但我的a.out从这个汇编文件,而不是建:

main.s:

 ; tiny.asm
  BITS 64
  GLOBAL _start
  .text段
  _开始:
                MOV EAX,1
                MOV EBX,42
                INT 0x80的

 我@#补偿NASM -f ELF64 tiny.s
我@#补偿GCC -Wall -s -nostartfiles -nostdlib tiny.o
我@#补偿./a.out;回声$?
42
我@#补偿WC -c的a.out
528的a.out

因为我需要机器code我做的:

  objdump的-d的a.outa.out格式:文件格式ELF64,X86-64
.text段拆卸:00000000004000e0<的.text计算值:
  4000e0:B8 01 00 00 00 $ MOV为0x1,%eax中
  4000e5:BB 2A 00 00 00 $ MOV 0x2a,EBX%
  4000ea:CD 80 INT 0x80的$>#objdump的-hrt的a.outa.out格式:文件格式ELF64,X86-64部分:
IDX名称大小VMA LMA文件ALGN关闭
 0 .note.gnu.build-ID 00000024 00000000004000b0 00000000004000b0 000000b0 2 ** 2
                  内容ALLOC,LOAD,只读,DATA
 1的.text 0000000c 00000000004000e0 00000000004000e0 000000e0 2 ** 4
                  内容ALLOC,LOAD,只读,code
符号表:
无符号

文件是小端约定:

 我@#补偿-a rea​​delf的a.out
ELF头:
  魔术:7F 45 4C 46 02 01 01 00 00 00 00 00 00 00 00 00
  类别:ELF64
  数据:2的补,小尾数
  版本:1(电流)
  OS / ABI:UNIX - 系统V
  ABI版本:0
  类型:EXEC(可执行文件)
  机床:Advanced Micro Devices公司X86-64
  版本:为0x1
  入口地址:0x4000e0
  程序头开始:64(字节到文件)
  节头的开始:272(字节到文件)
  标志:为0x0
  这个头的大小:64(字节)
  程序头的尺寸:56(字节)
  程序头数:2
  节头的大小:64(字节)
  节头数:4
  节头字符串表指数:3

现在我想执行这个是这样的:

 的#include<&unistd.h中GT;
 //哪个版本(更多)是否正确?
 //这可能(???)涉及到字节序
字符code [] =\\ X01 \\ XB8 \\ X00 \\ X00 \\ XBB \\ X00 \\ X00 \\ X2A \\ X00 \\ X00 \\ X80 \\ XCD \\ X00
字符code_v1 [] =\\ XB8 \\ X01 \\ X00 \\ X00 \\ X00 \\ XBB \\ X2A \\ X00 \\ X00 \\ X00 \\ XCD \\ X80 \\ X00INT主(INT ARGC,字符** argv的)
{
/ *创建一个函数指针* /
INT(* FUNC)();
FUNC =(INT(*)())code;
(INT)(* FUNC)();返回0;
}

但是我得到分段错误。 我的问题是:这个文本栏目

  4000e0:B8 01 00 00 00 $ MOV为0x1,%eax中
  4000e5:BB 2A 00 00 00 $ MOV 0x2a,EBX%
  4000ea:CD 80 INT 0x80的$

(本机code)所有我真的需要吗我做的不对(字节序?),也许我只需要SIGSEGV以来以不同的方式来调用这个?


解决方案

我得到了这个工作。在code必须是标记为可执行code。做到这一点的方法之一是这个二进制机器code复制到可执行的缓冲区。

 的#include<&unistd.h中GT;
#包括LT&; SYS / mman.h>
#包括LT&;&string.h中GT;字符code [] = {0x55,0x48,0x89,0xe5,0x89,0x7d,0xFC有,0x48,
    0x89,0x75,0xf0,0xb8,0x2a,0x00,0x00,0x00,0xc9,0xc3,0x00};
/ *
 * 00000000004004b4<主> 55推%RBP
00000000004004b5<主+为0x1> 48 89 E5 MOV%RSP,RBP%
00000000004004b8<主+为0x4> 89 FC 7D MOV%EDI,-0x4(RBP%)
00000000004004bb<主+ 0x7的> 48 89 75 F0 MOV%RSI,-0x10(RBP%)
/NetBeansProjects/examples/tiny_c/tiny.c:15
    返回42;
00000000004004bf<主+ 0XB> B8 2A 00 00 00 $ MOV 0x2a,EAX%
/NetBeansProjects/examples/tiny_c/tiny.c:16
}
00000000004004c4<主+ 0×10> C9 leaveq
00000000004004c5<主+ 0×11> C3 retq
 * /
INT主(INT ARGC,字符** argv的)
{
    无效* BUF;  / *副本code到可执行的缓冲区* /
  BUF = MMAP(0,sizeof的(code),PROT_READ | PROT_WRITE | PROT_EXEC,
              MAP_PRIVATE | MAP_ANON,-1,0);
  的memcpy(BUF,code,sizeof的(code));  / *运行code * /
  INT I =((INT(*)(无效))BUF)();
  的printf(完成这件事返回:%D,我);
返回0;
}


  

输出:


  
  

完成这件事。返回:42


  
  

成功运行(总时间:57ms)


following this instructions I have managed to produce only 528 bytes in size a.out (when gcc main.c gave me 8539 bytes big file initially).

main.c was:

int main(int argc, char** argv) {

    return 42;
}

but I have built a.out from this assembly file instead:

main.s:

; tiny.asm
  BITS 64
  GLOBAL _start
  SECTION .text
  _start:
                mov     eax, 1
                mov     ebx, 42  
                int     0x80

with:

me@comp# nasm -f elf64 tiny.s
me@comp# gcc -Wall -s -nostartfiles -nostdlib tiny.o
me@comp# ./a.out ; echo $?
42
me@comp# wc -c a.out
528 a.out

because I need machine code I do:

objdump -d a.out

a.out:     file format elf64-x86-64


Disassembly of section .text:

00000000004000e0 <.text>:
  4000e0:   b8 01 00 00 00          mov    $0x1,%eax
  4000e5:   bb 2a 00 00 00          mov    $0x2a,%ebx
  4000ea:   cd 80                   int    $0x80

># objdump -hrt a.out

a.out:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
 0 .note.gnu.build-id 00000024  00000000004000b0  00000000004000b0  000000b0 2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 1 .text         0000000c  00000000004000e0  00000000004000e0  000000e0 2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
SYMBOL TABLE:
no symbols

file is in little endian convention:

me@comp# readelf -a a.out
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4000e0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          272 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         2
  Size of section headers:           64 (bytes)
  Number of section headers:         4
  Section header string table index: 3

now I want to execute this like this:

#include <unistd.h>
 // which version is (more) correct?
 // this might be related to endiannes (???)
char code[] = "\x01\xb8\x00\x00\xbb\x00\x00\x2a\x00\x00\x80\xcd\x00";
char code_v1[] = "\xb8\x01\x00\x00\x00\xbb\x2a\x00\x00\x00\xcd\x80\x00";

int main(int argc, char **argv)
{
/*creating a function pointer*/
int (*func)();
func = (int (*)()) code;
(int)(*func)();

return 0;
}

however I get segmentation fault. My question is: is this section of text

  4000e0:   b8 01 00 00 00          mov    $0x1,%eax
  4000e5:   bb 2a 00 00 00          mov    $0x2a,%ebx
  4000ea:   cd 80                   int    $0x80

(this machine code) all I really need? What I do wrong (endiannes??), maybe I just need to call this in different way since SIGSEGV?

解决方案

I got this done. The code must be marked as executable code. One way to do it is to copy this binary machine code into executable buffer.

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

char code[] = {0x55,0x48,0x89,0xe5,0x89,0x7d,0xfc,0x48,
    0x89,0x75,0xf0,0xb8,0x2a,0x00,0x00,0x00,0xc9,0xc3,0x00};
/*
 * 00000000004004b4 <main> 55                       push   %rbp
00000000004004b5 <main+0x1> 48 89 e5                mov    %rsp,%rbp
00000000004004b8 <main+0x4> 89 7d fc                mov    %edi,-0x4(%rbp)
00000000004004bb <main+0x7> 48 89 75 f0             mov    %rsi,-0x10(%rbp)
/NetBeansProjects/examples/tiny_c/tiny.c:15
    return 42;
00000000004004bf <main+0xb> b8 2a 00 00 00          mov    $0x2a,%eax
/NetBeansProjects/examples/tiny_c/tiny.c:16
}
00000000004004c4 <main+0x10> c9                     leaveq 
00000000004004c5 <main+0x11> c3                     retq 
 */
int main(int argc, char **argv)
{   
    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 */
  int i = ((int (*) (void))buf)();
  printf("get this done. returned: %d", i);
return 0;
}

output:

get this done. returned: 42

RUN SUCCESSFUL (total time: 57ms)

这篇关于执行从C二进制机器code的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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