linux - Termux 上的汇编可执行文件现在会产生非法指令错误
问题描述
你能告诉我我做错了什么吗?
我是汇编编程的新手,不熟悉ld
.
最初我一直在尝试使用yasm
编译器,但后来意识到这是在编写符合 GNU 的汇编代码时采用 ARM 架构的方式。
as
从binutils
包运行,即 GNU 汇编器,祝你好运。但汇编代码必须与 ARM 兼容。
以下是 内的代码arm.s
:
.text /* Start of the program code section */
.global main /* declares the main identifier */
.type main, %function
main: /* Address of the main function */
/* Program code would go here */
BR LR
/* Return to the caller */
.end /* End of the program */
以上是抛出一个非法指令错误。这可以通过替换
ret
来解决BR LR
。这是 ARM V8 的新功能。
ARM 是一种 RISC 架构,不受 YASM 支持。
我的构建文件如下:
#/usr/bin/env bash
#display usage
[ $# -eq 0 ] && { echo "Usage: $0 <File Name without extension> ";exit 1; }
set +e
rm -f $1.exe $1 $1.o
as -o $1.o $1.s
[ -e $1.o ] && { file $1.o;}
gcc -s -o $1.exe $1.o -fpic
ld -s -o $1 -pie --dynamic-linker /system/bin/linker64 /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o $1.o -lc -lgcc -ldl /data/data/com.termux/files/usr/lib/crtend_android.o
[ -e $1.exe ] && { file $1.exe;nohup ./$1.exe; }
[ -e $1 ] && { file $1;nohup ./$1;}
set -e
该代码之前导致了分段错误或总线错误。
使用上面更新的构建文件,我能够运行一个或两个程序而没有任何分段或总线错误。我将构建文件设置为生成两个可执行文件,一个使用 gcc,另一个使用 ld,因为一些在线教程使用 ld 而不是 gcc 进行链接步骤。使用 gcc 的详细设置,您可以查看传递给链接器的选项,从而独立地为链接器模拟相同的选项。
可能有一些我错过的冗余设置。
您可以在Learn Assembly访问源代码和构建文件的更新 。
在此处查看 Keil 的此资源。arm Keil 产品指南
更多资源:
https://thinkingeek.com/2016/10/08/exploring-aarch64-assembler-chapter1/
如何在不使用 gcc 的情况下将使用 C 标准库的气体汇编程序与 ld 链接?
虽然上述问题目前似乎已解决,但运行以下代码时出现错误:
.text
.global main
main:
mov w0, #2
mov w7, #1 // request to exit program
svc 0
尝试执行代码时出现非法指令错误。
其次,如果我将 main 更改为 _start(因为我不想一直使用 main),那么 buildrun 脚本会出现以下错误。
./buildrun myprogram
/data/data/com.termux/files/usr/bin/aarch64-linux-android-ld: myprogram.o: in function `_start': (.text+0x0): multiple definition of `_start'; /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o:crtbegin.c:(.text+0x0): first defined here /data/data/com.termux/files/usr/bin/aarch64-linux-android-ld: /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o: in function `_start_main': crtbegin.c:(.text+0x38): undefined reference to `main
/data/data/com.termux/files/usr/bin/aarch64-linux-android-ld: crtbegin.c:(.text+0x3c): undefined reference to `main' clang-8: error: linker command failed with exit co
de 1 (use -v to see invocation)
ld: myprogram.o: in function `_start': (.text+0x0): multiple definition of `_start'; /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o:crtbegin.c:(.text+0x0): first defined here ld: /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o: in function `_start_main': crtbegin.c:(.text+0x38): undefined reference to `main'
ld: crtbegin.c:(.text+0x3c): undefined reference to `main'
如何创建具有除 main 以外的入口点的程序?
我希望能够:
创建一个有效的静态链接可执行文件。
创建一个可执行文件,它有一个名为 _start 而不是 main 的函数。
此文件构建不使用 main 或调用任何库调用的静态可执行文件。
使用除 main 之外的入口点创建动态链接的可执行文件。 我的构建文件处理这个,有点,入口点作为第二个参数。
创建一个使用主管调用
svc
退出而不抛出非法指令错误的可执行文件,而不是使用ret
.
我可以svc
通过在寄存器 X8 中设置系统调用号来调用版本 7 ARM 中的 W7。此外,ARM 64 已根据以下头文件重新编号系统调用号。
https://github.com/torvalds/linux/blob/v4.17/include/uapi/asm-generic/unistd.h
https://reverseengineering.stackexchange.com/q/16917
.data
.balign 8
labs: .asciz "Azeria Labs\n" //.asciz adds a null-byte to the end of the string .balign 8 after_labs: .set size_of_labs, after_labs - labs .balign 8 addr_of_labs: .dword labs .balign 8 .text
.global main
main:
mov x0, #1 //STDOUT ldr x1,addr_of_labs //memory address of labs mov w2, #size_of_labs //size of labs mov x8,#64 svc #0x0 // invoke syscall _exit: mov x8, #93 //exit syscall
svc #0x0 //invoke syscall
上面的代码是从下面列出的示例代码中移植而来的。 https://azeria-labs.com/writing-arm-shellcode/ 将数据部分压缩为一个,而不是像网站示例中那样将其拆分,以减轻链接时的重定位错误。
其他有用的参考资料:
https://thinkingeek.com/2013/01/09/arm-assembler-raspberry-pi-chapter-1/
*查看 ehrt74 对上述帖子的评论,了解进一步探索 svc 调用的动机。*
解决方案
Yasm 是一个 x86 汇编程序。它不能为 ARM 处理器生成可执行文件。
您正在使用的教程正在描述 x86 程序集。它们旨在在 x86 系统上遵循。
推荐阅读
- sql - 从 SQL 中单列中的过滤值创建多列
- python - 通读python中的连接文件
- snowflake-cloud-data-platform - 如何使用来自 Oracle 的数据更新雪花中的表?
- android - 启用麦克风后,一台设备无法通过听筒播放音频通话
- python - 使用属性函数定义 Python 类时出现属性错误
- react-native - 如何解决snack.expo上的按钮不起作用但没有错误的问题
- azure - 如何从 blob 存储触发 azure 函数中删除流参数
- python - listdir 仅调用 CSV 文件
- haskell - 为什么参数可以接受类型类的任何构造,但不能有条件地构造其值?
- oracle - 如何通过使用带有 PLSQL 的触发器来修改包含特定值的 CLOB 行?