栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

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

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

在Linux上,熟悉的C语言

argc
argv
变量始终由内核传递到堆栈上,甚至可以用于完全独立的汇编程序,并且不与C库中的启动代码链接。这在i386
System V ABI中进行了记录
,同时还介绍了流程启动环境的其他详细信息(寄存器值,堆栈对齐)。

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

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

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

我将展示如何阅读

argv
argc[0]
在GDB中。

cmdline-x86.S

#include <sys/syscall.h>    .global _start_start:        int $0x03        mov $SYS_exit_group, %eax    mov $0, %ebx    int $0x80

cmdline-x86.gdb

set confirm offfile cmdline-x86run# We'll regain control here after the breakpoint trapprintf "argc: %dn", *(int*)$espprintf "argv[0]: %sn",  ((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:88   mov $SYS_exit_group, %eaxargc: 1argv[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版本

差异很小:

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

命令行

#include <sys/syscall.h>    .global _start_start:        int $0x03        mov $SYS_exit_group, %rax    mov $0, %rdi    syscall

cmdline.gdb

set confirm offfile cmdlinerunprintf "argc: %dn", *(int*)$rspprintf "argv[0]: %sn",  ((char**)($rsp + 8))[0]quit

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

您可以

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

$ gdb -q /bin/trueReading symbols from /usr/bin/true...Reading symbols from /usr/lib/debug/usr/bin/true.debug...done.done.(gdb) disassemble _startDump of assembler pre 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. RSI
    argc
    ,您可以看到它是如何从堆栈中弹出的第一件事
  3. RDX
    argv
    ,价值 RSP 权后,
    argc
    被弹出。(
    ubp_av
    在GLIBC来源中)

x86 _start 非常相似:

Dump of assembler pre 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,%axEnd of assembler dump.


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/415390.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号