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

小编典典

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

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

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

ESP 指向argc

ESP + 4 指向argv[0],数组的开始。即,数值应该传递给主为char **argv是lea eax, [esp+4],不是mov eax, [esp+4])

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

我将展示如何阅读argv和argc[0]在GDB中。

cmdline-x86.S

#include

.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脚本中使用了打印 argc 与表达 *(int*)$esp

argv 与表达 ((char**)($esp + 4))[0]

x86-64版本

差异很小:

用 RSP*替换 ESP*

将地址大小从4更改为8

当我们调用exit_group(0)以正确终止进程时,请遵循不同的Linux syscall调用约定

命令行

#include

.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

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

您可以_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 : xor %ebp,%ebp

0x0000000000401582 : mov %rdx,%r9

0x0000000000401585 : pop %rsi

0x0000000000401586 : mov %rsp,%rdx

0x0000000000401589 : and $0xfffffffffffffff0,%rsp

0x000000000040158d : push %rax

0x000000000040158e : push %rsp

0x000000000040158f : mov $0x404040,%r8

0x0000000000401596 : mov $0x403fb0,%rcx

0x000000000040159d : mov $0x4014c0,%rdi

0x00000000004015a4 : callq 0x401310 <__libc_start_main>

0x00000000004015a9 : hlt

0x00000000004015aa : xchg %ax,%ax

0x00000000004015ac : nopl 0x0(%rax)

前三个参数__libc_start_main()是:

RDI :指向的指针main()

RSI :argc,您可以看到它是如何从堆栈中弹出的第一件事

RDX :argv,价值 RSP 权后,argc被弹出。(ubp_av在GLIBC来源中)

x86 _start 非常相似:

Dump of assembler code for function _start:

0x0804842c : xor %ebp,%ebp

0x0804842e : pop %esi

0x0804842f : mov %esp,%ecx

0x08048431 : and $0xfffffff0,%esp

0x08048434 : push %eax

0x08048435 : push %esp

0x08048436 : push %edx

0x08048437 : push $0x80485e0

0x0804843c : push $0x8048570

0x08048441 : push %ecx

0x08048442 : push %esi

0x08048443 : push $0x80483d0

0x08048448 : call 0x80483b0 <__libc_start_main>

0x0804844d : hlt

0x0804844e : xchg %ax,%ax

End of assembler dump.

2020-06-02

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值