0

我正在尝试在 ArchLinux 下的第一个 Raspberry Pi 上执行存储在数组中的机器代码。我已经在 x86 下完成了它,但是在 ARMv6 下我无法理解我做错了什么。问题是数组中的代码无关紧要,执行第一条指令后它总是会崩溃。在 gcc 5.2.0 下禁用 Thumb interworking 编译代码。

这是我用于测试的代码:

#include <stdio.h>

char shellcode[] = {
 0x04, 0xb0, 0x2d, 0xe5, // push {r11}
 0x00, 0xb0, 0x8d, 0xe2, // add r11, sp, #0
 0x00, 0x00, 0xa0, 0xe1, // nop
 0x00, 0x00, 0xa0, 0xe1, // nop
 0x00, 0x00, 0xa0, 0xe1, // nop
 0x00, 0xd0, 0x4b, 0xe2, // sub sp, r11, #0
 0x04, 0xb0, 0x9d, 0xe4, // pop {r11}
 0x1e, 0xff, 0x2f, 0xe1  // bx lr
};

void shellcode2() {
 asm("mov r0, r0");
 asm("mov r0, r0");
}

typedef void (*entry_t)();

int main() {
 entry_t entry = (entry_t)(shellcode);
 entry();

 return 0;
}

机器代码取自shellcode2函数反汇编,我不知道这样做是否正确,但问题是即使 shellcode 中的第一条指令是 nop - 它也会崩溃。

Program received signal SIGSEGV, Segmentation fault.
0x00020704 in shellcode ()
(gdb) disas /r
Dump of assembler code for function shellcode:
=> 0x00020704 <+0>:     04 b0 2d e5     push    {r11}           ; (str r11, [sp, #-4]!)
   0x00020708 <+4>:     00 b0 8d e2     add     r11, sp, #0
   0x0002070c <+8>:     00 00 a0 e1     nop                     ; (mov r0, r0)
   0x00020710 <+12>:    00 00 a0 e1     nop                     ; (mov r0, r0)
   0x00020714 <+16>:    00 00 a0 e1     nop                     ; (mov r0, r0)
   0x00020718 <+20>:    00 d0 4b e2     sub     sp, r11, #0
   0x0002071c <+24>:    04 b0 9d e4     pop     {r11}           ; (ldr r11, [sp], #4)
   0x00020720 <+28>:    1e ff 2f e1     bx      lr
End of assembler dump.

我错过了什么或者只是在 ARMv6 上做错了吗?如果有人能指出我正确的方向,我将不胜感激。

提前致谢。

4

2 回答 2

0

将评论放在答案中,以便将来的用户可以找到它。

ARMv6 支持“从不执行”区域,可用于防止包含数据的页面作为代码执行。

这是作为一种安全措施完成的,因为它可以防止各种黑客攻击。但这对于尝试进行自我修改代码的程序(这实际上是 OP 正在尝试做的事情)来说可能是一个问题。

查看 ARMv6 文档了解详细信息。

于 2015-11-11T23:11:07.370 回答
0

您需要在链接描述文件中指定一段内存,以便从中执行代码。例如:

.umem : {
    . = ALIGN(4);
    _umem = .;
    . = . + 48k;    
} > RAM  

其中 ram 是至少标记为 rx 的部分,_umem 应该是这个 48k 缓冲区开始的地址处的符号,并且可以使用 extern 语句添加到您的头文件中。

于 2015-11-11T23:32:40.510 回答