问题

我希望有人可以帮助我确定为什么该二进制文件无法执行。

它是一个开源的,剥离的ARM二进制文件。就是说,它可以在Internet上免费下载,因此在本文的底部有指向它的链接。

目标是从固件映像中提取的ARM二进制文件。我已经设置了ARM VM,但也尝试在Pi上运行二进制文件,结果相同。

这是我所看到的:

root@debian-armel:/tmp/squashfs-root/usr/bin# ./my_arm_bin 
Illegal instruction


“非法指令”错误没有太大帮助...所以我更深入地研究了。

我的VM

我不认为问题是我的虚拟机。这是一个非常标准的ARM VM安装程序。来自:https://people.debian.org/~aurel32/qemu/armel/

使用debian_squeeze_armel_standard.qcow2initrd.img-2.6.32-5-versatilevmlinuz-2.6.32-5-versatile。它与QEMU一起启动,并转发了一些端口(sdb,http,31337(用于gdb的东西))。我能够在系统上执行其他ARM二进制文件,而不会出现问题,包括从同一固件映像中提取的其他二进制文件。 。我既在pi上也以root身份尝试过,也尝试在chroot的环境中使用提取的固件映像的rootfs,结果相同:Illegal Instruction
rabin2 -I my_arm_bin

Warning: Cannot initialize dynamic strings
arch     arm
binsz    44831825
bintype  elf
bits     32
canary   false
class    ELF32
crypto   false
endian   little
havecode true
lang     c
linenum  false
lsyms    false
machine  ARM
maxopsz  16
minopsz  1
nx       false
os       linux
pcalign  0
pic      false
relocs   false
rpath    NONE
static   true
stripped true
subsys   linux
va       true


附加调试(Pi上带有gef的gdb)

因此,该花时间连接调试器并确切地查看什么指令了实际抛出该错误。这是在Pi上完成的。

启动并进入后中断,使用ni进行单步操作,我看到:

gef> x/20i $pc
=> 0x796a0: mov r11, #0
   0x796a4: mov lr, #0
   0x796a8: pop {r1}        ; (ldr r1, [sp], #4)
   0x796ac: mov r2, sp
   0x796b0: push    {r2}        ; (str r2, [sp, #-4]!)
   0x796b4: push    {r0}        ; (str r0, [sp, #-4]!)
   0x796b8: ldr r12, [pc, #16]  ; 0x796d0
   0x796bc: push    {r12}       ; (str r12, [sp, #-4]!)
   0x796c0: ldr r0, [pc, #12]   ; 0x796d4
   0x796c4: ldr r3, [pc, #12]   ; 0x796d8
   0x796c8: bl  0x4021a0
   0x796cc: bl  0x401fa0
   0x796d0: andeq   r2, r12, #200, 2    ; 0x32
   0x796d4: andeq   r10, r1, r12, lsl #11
   0x796d8: andeq   r2, r12, #40, 2
   0x796dc: ldr r3, [pc, #20]   ; 0x796f8
   0x796e0: ldr r2, [pc, #20]   ; 0x796fc
   0x796e4: add r3, pc, r3
   0x796e8: ldr r2, [r3, r2]
   0x796ec: cmp r2, #0
gef> 


它全部看起来像有效的ARM指令。

如果相关-执行时,gdb中的所有ldr指令(0x796b8、0x796c0、0x796c4)都给出此消息:Cannot access memory at address 0x0。一些mov指令也会抛出该错误。

0x796c8: bl 0x4021a0处:

->   0x796c8                  bl     0x4021a0
   \->    0x4021a0                  ldr    pc,  [pc,  #-4]  ; 0x4021a4


最后我们到达这里:

gef> x/20i $pc
=> 0x20c1b30:   push    {r4, r5, r6, r7, lr}
   0x20c1b34:   sub sp, sp, #300    ; 0x12c
   0x20c1b38:   movw    r12, #0                 
   0x20c1b3c:   mov r5, r3                          --> Here is our illegal instruction
   0x20c1b40:   movt    r12, #0
   0x20c1b44:   str r1, [sp, #4]
   0x20c1b48:   movw    r1, #65336  ; 0xff38
   0x20c1b4c:   cmp r12, #0
   0x20c1b50:   ldr r3, [sp, #4]
   0x20c1b54:   str r2, [sp, #8]
   0x20c1b58:   ldrne   r12, [r12]
   0x20c1b5c:   add r2, r3, #1
   0x20c1b60:   str r0, [sp, #12]
   0x20c1b64:   movw    r3, #56376  ; 0xdc38
   0x20c1b68:   ldr r7, [sp, #8]
   0x20c1b6c:   movw    r0, #3092   ; 0xc14
   0x20c1b70:   ldr lr, [sp, #328]  ; 0x148
   0x20c1b74:   clzne   r12, r12
   0x20c1b78:   movt    r0, #685    ; 0x2ad
   0x20c1b7c:   movt    r1, #827    ; 0x33b


当然可以在这里找到二进制文件的副本:https://mega.nz/#!CKxBQKaI!T__d9pjpOn_rPtfvPNkkPsFWHTjg7u-vDt5AK6610ug

那么寄存器是否没有初始化为正确的值?怎么可能呢?

用阿切尔的话来解释:我不明白什么?...我认为是核心概念。 。我希望有人可以帮助您填补空白。

更新1:

在@ 0xC0000022L的建议下,我调查了一下确保我的VM /的ARM版本。 Pi与二进制匹配。据我所知他们做到了。只是将VM中的二进制文件与我的ARM二进制文件进行比较,我试图运行它们的ABI匹配(32位ARMv5):

$ file my_arm_bin 
my_arm_bin: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.16, stripped
 $ file /usr/bin/id
/usr/bin/id: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, stripped


更新2:

在@perror建议下,我尝试强制二进制文件以拇指模式执行。对于上下文,这里是在“手臂”(非拇指)模式下运行时的拆卸:

gef> x/10i $pc
=> 0x20c1b38:   movw    r12, #0
   0x20c1b3c:   mov r5, r3
   0x20c1b40:   movt    r12, #0
   0x20c1b44:   str r1, [sp, #4]
   0x20c1b48:   movw    r1, #65336  ; 0xff38
   0x20c1b4c:   cmp r12, #0
   0x20c1b50:   ldr r3, [sp, #4]
   0x20c1b54:   str r2, [sp, #8]
   0x20c1b58:   ldrne   r12, [r12]
   0x20c1b5c:   add r2, r3, #1


强制拇指模式,我现在看到:

gef> set arm force-mode thumb
gef> x/10i $pc
=> 0x20c1b38:   stmia   r0!, {}
   0x20c1b3a:   b.n 0x20c213e
   0x20c1b3c:   str r3, [r0, r0]
   0x20c1b3e:   b.n 0x20c1e82
   0x20c1b40:   stmia   r0!, {}
   0x20c1b42:   b.n 0x20c21c6
   0x20c1b44:   asrs    r4, r0, #32
   0x20c1b46:   b.n 0x20c1664
   0x20c1b48:   subs    r0, r7, #4
   0x20c1b4a:   b.n 0x20c216c


在执行之前强制使用拇指模式,程序会立即退出,并出现以下错误:

[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x6ac


启动可执行文件,中断和切换模式以非法指令错误退出。

评论

尽管我在阅读您的帖子时有些随意,您是否尝试过检查是否处于拇指模式?您的反汇编是在32位模式下完成的,这很可能是gdb假定的。但是,如果CPU以拇指模式执行怎么办?要进行检查,您还可以简单地通过si(stepi)命令执行程序直到崩溃。它可能会给您更深刻的错误消息。

想到的另一件事是,您的CPU的版本可能与您尝试执行的ARM代码的版本不同。想想ARMv5与ARMv7 ...

您对自己在做什么的描述不清楚。错误在哪里显示?在什么装配线上?您究竟要执行什么命令才能从一个代码片段到另一个代码片段?

@NirIzr我所看到的错误是“这里是我所看到的:”之后立即显示的内容。在我使用gdb进行调试的部分中,我使用ni逐步完成说明。谢谢@perror和@ 0xC0000022L-非常感谢您的见解。今天晚些时候,我将深入研究拇指模式和ARM版本,并将发布和更新。我当时使用ni跳过函数调用并使之保持简单,但是si可能会给我更多上下文。

您是否愿意将此作为问题的一部分?

#1 楼

通过初步分析,该二进制文件看起来至少是ARMv7。它可以在qemu-user下运行,而不会出现问题。深入挖掘,确实有一些指令在ARMv5下是无效的。现在,movw r12, #0在ARMv7中引入,在ARMv5中不可用。类似地,在v5中,0x20c1b38指令也无效。因此,要运行二进制文件,您至少需要一个具有ARMv7处理器的ARMv7 QEMU vm或Raspberry Pi2。

评论


先生是我的英雄我使用文件告诉我文件使用哪个版本的ARM,这是不正确的。对于以后遇到此问题的任何人:请改用readelf -A my_arm_bin,专门检查Tag_CPU_arch标志输出。在这种情况下,它是v7。

–gatorface
18年6月19日在19:27



非常感谢,我和您的处境完全相同-我什至下载了相同的全能pb映像。 Tag_CPU_name:“ CORTEX-A8” Tag_CPU_arch:v7-是时候找到v7 QEMU映像了....

– i336_
19年5月27日在15:41