linux下在进程中加载执行纯2进制可执行文件bin

此博客来自他人,下面是自己的见解,因为正好用到相关内容

objdump对纯2进制文件(hello.bin)反汇编

objdump -m i386 -b binary -D hello.bin

-m:指出反汇编目标架构

-b:文件格式

在进程中加载执行纯2进制可执行文件bin

  1. mmap把2进制文件映射到进程用户内存空间,
  2. 将程序控制权交给bin

linux下用汇编通过中断调用api打印一个hello world (nasm版本),

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[section .data]
output: db "Hello World",0
length db 12
[section .text]
global _start

_start:
mov eax,4
mov ebx,1
mov ecx,output
mov edx,[length]
int 0x80 ;sys_write(1,buf,size)
mov eax,1
mov ebx,0 ;sys_exit
int 0x80

软中断调用api 参数意义

1. 编译成.o可重定位文件 `nasm -f elf64 hello.s -o hello.o`
  1. 因为bin文件被映射到进程内存空间,控制流jmp到映射的内存首地址就能够继续执行可执行二进制文件bin,
  2. 因为编译的时候指定bin的text段入口地址是0x00000000,链接完后text段的符号重定位值是根据入口地址=0决定的,(对此hello.s文件而言)
  3. 那么如果映射到虚拟内存空间地址A时,bin中的在链接期间可重定位符号的偏移量要加上A,

​ 查看hello.o中的重定位信息,objdump -D -r hello.o

1

​ 看到的符号在section中的偏移量分别是0x0B和0x12,并且在link前值都是0

3

  1. 静态链接: 将.data和.text合成一个.text section

    link script test.ld

    1
    2
    3
    4
    5
    6
    7
    8
    SECTIONS
    {
    . = 0x00000000;
    .text : {
    *(.text)
    *(.data)
    }
    }

    ld -T test.ld hello.o -o hello.elf

    2

    原来的重定位符号之被link修改,(根据.text的入口地址

所以在进程中加上加载到的虚拟地址就能成功执行纯2进制代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

int main()
{
int fd;
int ret;
unsigned char *buf;
struct stat stat;
void *res;
unsigned int ImageBase;
int rebase[2] = {0x0B,0x12};
unsigned char *temp;

//ImageBase = 0x50000000;
ImageBase = 0x00010000;

fd = open("hello.bin",O_RDWR);
if (fd < 0)
{
perror("fd");
return -1;
}

ret = fstat(fd,&stat);
if (ret < 0)
{
perror("fstat");
return -1;
}

buf = (unsigned char *)malloc(stat.st_size);
if (buf == NULL)
{
perror("allocate");
return -1;
}

ret = read(fd,buf,stat.st_size);
if (ret < 0 || ret != stat.st_size)
{
perror("read");
return -1;
}

res = mmap((void*)ImageBase,stat.st_size,PROT_EXEC | PROT_WRITE | PROT_READ,MAP_PRIVATE,fd,0);
if (res == MAP_FAILED)
{
perror("mmap");
return -1;
}

printf("%p \n",res);

for (int i=0; i<2; i++)
*(unsigned int *)((char *)res + rebase[i]) += ImageBase;

temp = (unsigned char *)res;
for (int i=0; i<0x100; i++)
printf("%02X%s",*temp++,(i+1)%0x10?" " : "\n");

// __asm__ volatile ("\n\t"\
// "movl $1,%%eax\n\t"\
// "jmp *%0\n\t"\
// ::"mem"(res):
// );
__asm__ volatile ("\n\t"\
"jmp *%0\n\t"\
::"mem"(res):
);
printf("done\n");
return 0;
}

4


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!