linux - x86 Linux 汇编程序从_start 获取程序参数

标签 linux assembly x86 gnu-assembler

我正在尝试创建一个程序来将参数写入屏幕。 我创建了一些程序来获取 C 函数参数,或者我使用 C 将参数发送到我的 asm 程序。 有没有办法只使用汇编程序获取程序参数

例如:

./Program "text"

我正在使用(Gnu 汇编程序)

通常我会使用这些参数

[esp+4]

因为esp是程序/函数调用指针,但是在纯asm中它并没有获取命令行参数。

有办法吗?

我用谷歌搜索过,但找不到太多信息

最佳答案

在 Linux 上,来自 C 的熟悉的 argcargv 变量总是由内核在堆栈上传递,甚至可用于完全独立的汇编程序t 与 C 库中的启动代码链接。这记录在 i386 System V ABI 中,以及进程启动环境的其他细节(寄存器值、堆栈对齐)。

在 x86 Linux 可执行文件的 ELF 入口点(又名 _start):

  1. ESP 指向argc
  2. ESP + 4 指向 argv[0],数组的开始。即,您应该作为 char **argv 传递给 main 的值是 lea eax, [esp+4],而不是 mov eax, [esp+4])

最小汇编程序如何获取argc和argv

我将展示如何在 GDB 中读取 argvargc[0]

cmdline-x86.S

#include <sys/syscall.h>

    .global _start
_start:
    /* Cause a breakpoint trap */
    int $0x03

    /* exit_group(0) */
    mov $SYS_exit_group, %eax
    mov $0, %ebx
    int $0x80

cmdline-x86.gdb

set confirm off
file cmdline-x86
run
# We'll regain control here after the breakpoint trap
printf "argc: %d\n", *(int*)$esp
printf "argv[0]: %s\n",  ((char**)($esp + 4))[0]
quit

示例 session

$ cc -nostdlib -g3 -m32 cmdline-x86.S -o cmdline-x86
$ gdb -q -x cmdline-x86.gdb cmdline-x86
<...>  
Program received signal SIGTRAP, Trace/breakpoint trap.
_start () at cmdline-x86.S:8
8   mov $SYS_exit_group, %eax
argc: 1
argv[0]: /home/scottt/Dropbox/stackoverflow/cmdline-x86

说明

  • 我放置了一个软件断点 (int $0x03),使程序在 ELF 入口点 (_start) 之后立即陷入调试器。
  • 然后我在 GDB 脚本中使用 printf 来打印
    1. argc 表达式 *(int*)$esp
    2. argv 与表达式 ((char**)($esp + 4))[0]

x86-64 版本

差异很小:

  • RSP替换ESP
  • 将地址大小从 4 更改为 8
  • 当我们调用exit_group(0) 以正确终止进程时,符合不同的Linux 系统调用调用约定

命令行.S

#include <sys/syscall.h>

    .global _start
_start:
    /* Cause a breakpoint trap */
    int $0x03

    /* exit_group(0) */
    mov $SYS_exit_group, %rax
    mov $0, %rdi
    syscall

命令行.gdb

set confirm off
file cmdline
run
printf "argc: %d\n", *(int*)$rsp
printf "argv[0]: %s\n",  ((char**)($rsp + 8))[0]
quit

常规C程序如何获取argc和argv

您可以从常规 C 程序反汇编 _start 以查看它如何从堆栈中获取 argcargv 并在调用时传递它们__libc_start_main。以我的 x86-64 机器上的 /bin/true 程序为例:

$ gdb -q /bin/true
Reading symbols from /usr/bin/true...Reading symbols from /usr/lib/debug/usr/bin/true.debug...done.
done.
(gdb) disassemble _start
Dump of assembler code for function _start:
   0x0000000000401580 <+0>: xor    %ebp,%ebp
   0x0000000000401582 <+2>: mov    %rdx,%r9
   0x0000000000401585 <+5>: pop    %rsi
   0x0000000000401586 <+6>: mov    %rsp,%rdx
   0x0000000000401589 <+9>: and    $0xfffffffffffffff0,%rsp
   0x000000000040158d <+13>:    push   %rax
   0x000000000040158e <+14>:    push   %rsp
   0x000000000040158f <+15>:    mov    $0x404040,%r8
   0x0000000000401596 <+22>:    mov    $0x403fb0,%rcx
   0x000000000040159d <+29>:    mov    $0x4014c0,%rdi
   0x00000000004015a4 <+36>:    callq  0x401310 <__libc_start_main@plt>
   0x00000000004015a9 <+41>:    hlt    
   0x00000000004015aa <+42>:    xchg   %ax,%ax
   0x00000000004015ac <+44>:    nopl   0x0(%rax)

__libc_start_main() 的前三个参数是:

  1. RDI:指向main()
  2. 的指针
  3. RSI:argc,你可以看到它是如何从堆栈中弹出的第一件事
  4. RDX:argvargc 弹出后 RSP 的值。 (GLIBC 源代码中的 ubp_av)

x86 _start 非常相似:

Dump of assembler code for function _start:
   0x0804842c <+0>: xor    %ebp,%ebp
   0x0804842e <+2>: pop    %esi
   0x0804842f <+3>: mov    %esp,%ecx
   0x08048431 <+5>: and    $0xfffffff0,%esp
   0x08048434 <+8>: push   %eax
   0x08048435 <+9>: push   %esp
   0x08048436 <+10>:    push   %edx
   0x08048437 <+11>:    push   $0x80485e0
   0x0804843c <+16>:    push   $0x8048570
   0x08048441 <+21>:    push   %ecx
   0x08048442 <+22>:    push   %esi
   0x08048443 <+23>:    push   $0x80483d0
   0x08048448 <+28>:    call   0x80483b0 <__libc_start_main@plt>
   0x0804844d <+33>:    hlt    
   0x0804844e <+34>:    xchg   %ax,%ax
End of assembler dump.

关于linux - x86 Linux 汇编程序从_start 获取程序参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16721164/

相关文章:

linux - grep 两个文件之间

php - Ubuntu PHP href 链接不工作

linux - 比较两个不同的文件

linux - 表中元素的总和与汇编

x86 - CPU 寄存器内的字节顺序

linux - 为什么 bash 插入额外的引号

macos - 为什么我的程序集中的系统调用错误检查无法工作?

c - 索引数组时循环变量类型会影响效率吗?

x86 - 在 Atom N450 上,rdtsc 的返回值是 _always_ mod 10 == 0

linux - 2020 年 Intel x86-64 CPU 用户空间的 TSC(时间戳计数器)有多稳定?