加载ELF文件到内存
load ELF file into memory
我正在尝试将一个elf文件放入内存然后执行它,这些是步骤:
1- 要放入内存的文件
int main()
{
printf("Hello world! \n");
return 0;
}
2-编译它gcc -o hello hello.c -static
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x8120
Start of program headers: 52 (bytes into file)
Start of section headers: 119864 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 4
Size of section headers: 40 (bytes)
Number of section headers: 18
Section header string table index: 17
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00008000 0x00008000 0x16828 0x16828 R E 0x1000
LOAD 0x016840 0x0001f840 0x0001f840 0x00250 0x02660 RW 0x1000
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0
EXIDX 0x015f40 0x0001df40 0x0001df40 0x008e8 0x008e8 R 0x4
3- 我写了一个 Loader(为 ARM 编译)
mmap2(0x8000, 92200, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x8000
mmap2(0x1f000, 65536, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x1f000
3.1- 然后我将所有的精灵字节复制到分配中
3.2-跳转到主函数
ldr r0, =0x008160
blx r0
.text:00008160 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00008160 EXPORT main
.text:00008160 main ; DATA XREF: _start+8o
.text:00008160 ; .text:off_8150o
.text:00008160 STMFD SP!, {R11,LR}
.text:00008164 ADD R11, SP, #4
.text:00008168 LDR R3, =(aHelloWorld - 0x8174)
.text:0000816C ADD R3, PC, R3 ; "Hello world! "
.text:00008170 MOV R0, R3
.text:00008174 BLX puts
.text:00008178 MOV R3, #0
.text:0000817C MOV R0, R3
.text:00008180 LDMFD SP!, {R11,PC}
.text:00008180 ; End of function main
问题是每次我到达0x8174行,然后跳进去,经过一些指令后我总是在随机位置有一个SIGSEGV,更多时候崩溃指令是=> 0x9cc0: ldr r0, [r0, #4]
r0=0x70a34
00008000-0002f000 rwxp 00000000 00:00 0
80000000-80001000 r-xp 00000000 b3:18 129754 /data/local/tmp/main
80001000-8001a000 rwxp 00001000 b3:18 129754 /data/local/tmp/main
becdf000-bed00000 rwxp 00000000 00:00 0
ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
这些是崩溃后的更多说明:
.text:00009CB4 loc_9CB4 ; CODE XREF: pthread_mutex_lock_impl+18j
.text:00009CB4 MOV R3, #0xFFFF0FE0
.text:00009CBC BLX R3
.text:00009CC0 LDR R0, [R0,#4]
在0x9CB4
这个位置,r0
的值为0x1f96c
(可以),blx后r0
的值为0x70a34
(gdb) x/10x 0xffff0fe0
0xffff0fe0: 0xee1d0f70 0xe12fff1e 0xee1d0f70 0x00000000
0xffff0ff0: 0x00000000 0x00000000 0x00000000 0x00000005
0xffff1000: Cannot access memory at address 0xffff1000
谢谢!
I'm trying to put an elf file into memory and then execute it,
对于完全静态链接的可执行文件,您的步骤是可行的(除了您需要跳转到 _start
== 入口点 0x8120
,not main
).
Then I have copied all the elf bytes into the allocations
另一个可能的问题是没注意.p_offset
。您的 memcpy
ies 应该看起来像这样:
unsigned char buf1[0x16828]; // read 0x16828 bytes from start of file
memcpy(0x8000, buf1, 0x16828);
unsigned char buf2[0x250]; // read 0x250 bytes from offset 0x016840 into the file
memcpy(0x0001f840, buf2, 0x250);
您的问题是您需要使用正确的入口点,并且需要像 OS 一样初始化程序的堆栈(可能还有寄存器)。您需要使用正确的入口点以便初始化 C 运行时库,否则您对 printf
(或 puts
视情况而定)的调用几乎肯定会崩溃。您需要正确设置堆栈,因为 C 运行时库的初始化代码将在此处查找程序的参数和环境(可能还有其他内容)。
您没有说明您使用的是什么操作系统,但如果您使用 Linux,您可能希望将其视为对 CesarB describing the initial state of the stack on ARM Linux 给出的不同问题的回答。
我正在尝试将一个elf文件放入内存然后执行它,这些是步骤:
1- 要放入内存的文件
int main()
{
printf("Hello world! \n");
return 0;
}
2-编译它gcc -o hello hello.c -static
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x8120
Start of program headers: 52 (bytes into file)
Start of section headers: 119864 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 4
Size of section headers: 40 (bytes)
Number of section headers: 18
Section header string table index: 17
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00008000 0x00008000 0x16828 0x16828 R E 0x1000
LOAD 0x016840 0x0001f840 0x0001f840 0x00250 0x02660 RW 0x1000
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0
EXIDX 0x015f40 0x0001df40 0x0001df40 0x008e8 0x008e8 R 0x4
3- 我写了一个 Loader(为 ARM 编译)
mmap2(0x8000, 92200, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x8000
mmap2(0x1f000, 65536, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x1f000
3.1- 然后我将所有的精灵字节复制到分配中
3.2-跳转到主函数
ldr r0, =0x008160
blx r0
.text:00008160 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00008160 EXPORT main
.text:00008160 main ; DATA XREF: _start+8o
.text:00008160 ; .text:off_8150o
.text:00008160 STMFD SP!, {R11,LR}
.text:00008164 ADD R11, SP, #4
.text:00008168 LDR R3, =(aHelloWorld - 0x8174)
.text:0000816C ADD R3, PC, R3 ; "Hello world! "
.text:00008170 MOV R0, R3
.text:00008174 BLX puts
.text:00008178 MOV R3, #0
.text:0000817C MOV R0, R3
.text:00008180 LDMFD SP!, {R11,PC}
.text:00008180 ; End of function main
问题是每次我到达0x8174行,然后跳进去,经过一些指令后我总是在随机位置有一个SIGSEGV,更多时候崩溃指令是=> 0x9cc0: ldr r0, [r0, #4]
r0=0x70a34
00008000-0002f000 rwxp 00000000 00:00 0
80000000-80001000 r-xp 00000000 b3:18 129754 /data/local/tmp/main
80001000-8001a000 rwxp 00001000 b3:18 129754 /data/local/tmp/main
becdf000-bed00000 rwxp 00000000 00:00 0
ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
这些是崩溃后的更多说明:
.text:00009CB4 loc_9CB4 ; CODE XREF: pthread_mutex_lock_impl+18j
.text:00009CB4 MOV R3, #0xFFFF0FE0
.text:00009CBC BLX R3
.text:00009CC0 LDR R0, [R0,#4]
在0x9CB4
这个位置,r0
的值为0x1f96c
(可以),blx后r0
的值为0x70a34
(gdb) x/10x 0xffff0fe0
0xffff0fe0: 0xee1d0f70 0xe12fff1e 0xee1d0f70 0x00000000
0xffff0ff0: 0x00000000 0x00000000 0x00000000 0x00000005
0xffff1000: Cannot access memory at address 0xffff1000
谢谢!
I'm trying to put an elf file into memory and then execute it,
对于完全静态链接的可执行文件,您的步骤是可行的(除了您需要跳转到 _start
== 入口点 0x8120
,not main
).
Then I have copied all the elf bytes into the allocations
另一个可能的问题是没注意.p_offset
。您的 memcpy
ies 应该看起来像这样:
unsigned char buf1[0x16828]; // read 0x16828 bytes from start of file
memcpy(0x8000, buf1, 0x16828);
unsigned char buf2[0x250]; // read 0x250 bytes from offset 0x016840 into the file
memcpy(0x0001f840, buf2, 0x250);
您的问题是您需要使用正确的入口点,并且需要像 OS 一样初始化程序的堆栈(可能还有寄存器)。您需要使用正确的入口点以便初始化 C 运行时库,否则您对 printf
(或 puts
视情况而定)的调用几乎肯定会崩溃。您需要正确设置堆栈,因为 C 运行时库的初始化代码将在此处查找程序的参数和环境(可能还有其他内容)。
您没有说明您使用的是什么操作系统,但如果您使用 Linux,您可能希望将其视为对 CesarB describing the initial state of the stack on ARM Linux 给出的不同问题的回答。