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

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

例如:

./Program "text"

我正在使用(Gnu汇编器)

通常我使用

[esp+4]

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

有没有办法做到这一点?

我用谷歌搜索,但是我找不到很多信息

回答:

在Linux上,熟悉的C语言argcargv变量始终由内核传递到堆栈上,甚至可以用于完全独立的汇编程序,并且不与C库中的启动代码链接。这在i386

System V ABI中进行了记录,同时还介绍了流程启动环境的其他详细信息(寄存器值,堆栈对齐)。

_startx86 Linux可执行文件的ELF入口点(aka ):

  1. 指向argc
  2. 指向argv[0],数组的开始。即,数值应该传递给主为char **argvlea eax, [esp+4],不是mov eax, [esp+4]

回答:

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

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

样品会议

$ 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)之后放置了一个软件断点(),以使程序重新陷入调试器。
  • 然后我printf在GDB脚本中使用了打印

    1. argc 与表达 *(int*)$esp
    2. argv 与表达 ((char**)($esp + 4))[0]


x86-64版本

差异很小:

  • 用 *
  • 将地址大小从4更改为8
  • 当我们调用exit_group(0)以正确终止进程时,请遵循不同的Linux syscall调用约定

命令行

#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

cmdline.gdb

set confirm off

file cmdline

run

printf "argc: %d\n", *(int*)$rsp

printf "argv[0]: %s\n", ((char**)($rsp + 8))[0]

quit


回答:

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

$ 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. :指向的指针main()
  2. argc,您可以看到它是如何从堆栈中弹出的第一件事
  3. argv,价值 权后,argc被弹出。(ubp_av在GLIBC来源中)

x86 非常相似:

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.

以上是 x86 Linux汇编器从_start获取程序参数 的全部内容, 来源链接: utcz.com/qa/420932.html

回到顶部