【问题标题】:loop 0xb7 assembles but won't link循环 0xb7 组装但不会链接
【发布时间】:2019-05-08 22:29:32
【问题描述】:

我在 Debian 上尝试编译以下 ASM 代码,但在 ldgcc 上都有问题。

uname -a: Linux kali 4.18.0-kali3-amd64 #1 SMP Debian 4.18.20-2kali2 (2018-11-30) x86_64 GNU/Linux

我首先运行:nasm -f elf shellcode.asm

这完全没有问题。

GCC 问题... 命令:gcc -m32 -o key shellcode.o 错误:

/usr/bin/ld: shellcode.o: in function `_start':
shellcode.asm:(.text+0x0): multiple definition of `_start'; /usr/lib/gcc/x86_64-linux-gnu/8/../../../../lib32/Scrt1.o:(.text+0x0): first defined here
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../../lib32/Scrt1.o: in function `_start':
(.text+0x28): undefined reference to `main'
/usr/bin/ld: shellcode.o: in function `_start':
shellcode.asm:(.text+0xbc): relocation truncated to fit: R_386_PC8 against `*UND*'
collect2: error: ld returned 1 exit status

我也试过ld

命令:ld -m elf_i386 -s -o key shellcode.o

错误...

ld: shellcode.o: in function `_start':
shellcode.asm:(.text+0xbc): relocation truncated to fit: R_386_PC8 against `*UND*'

后者似乎不太充满错误,并指出 ASM 语法存在问题。

那么我的问题是,这些命令中哪一个是正确的,我做错了什么?

shellcode.asm

global _start
_start:
    xor eax,eax
    push eax
    push dword 0x76767975
    push dword 0x22717172
    push dword 0x22737972
    push dword 0x77207922
    push dword 0x78272079
    push dword 0x27277976
    push dword 0x77707470
    push dword 0x22777272
    push dword 0x22277622
    push dword 0x79727473
    push dword 0x27727377
    push dword 0x75747078
    push dword 0x70227479
    push dword 0x75222073
    push dword 0x24747176
    push dword 0x74782324
    push dword 0x72727320
    push dword 0x27762779
    push dword 0x20277777
    push dword 0x22207573
    push dword 0x70247827
    push dword 0x70277479
    push dword 0x24712379
    push dword 0x77742027
    push dword 0x76242379
    push dword 0x22702270
    push dword 0x73762577
    push dword 0x24752272
    push dword 0x20277172
    push dword 0x23712720
    push dword 0x72722478
    push dword 0x70252723
    push esp
    pop esi
    mov edi,esi
    mov edx,edi
    cld
    mov ecx,0x80
    mov ebx,0x41
    xor eax,eax
    push eax
    lodsb
    xor eax,ebx
    stosb
    loop 0xb7
    push esp
    pop esi
    int3
    db 0x0a

【问题讨论】:

  • 你为什么要做loop 0xb7。在您希望循环返回的位置放置一个标签,并将该标签与loop 指令一起使用。这就是重定位错误的原因。有点不清楚您首先要使用 loop 指令做什么。
  • 您是在组装,而不是在编译。编译用于高级语言,这些语言被编译成汇编,然后汇编成十六进制。
  • @MichaelPetch 谢谢你。该代码是使用 gdb 提取密钥的挑战的一部分,因此这只是提供的示例。我会按照您的建议进行编辑
  • 感谢您澄清这一点,@Rob

标签: linux gcc assembly x86 ld


【解决方案1】:

要使用 gcc 构建,您定义的是 _start 而不是 main,因此您需要使用 -nostdlib。喜欢gcc -m32 -nostdlib -static -o key shellcode.o。这将使 gcc 以手动方式调用 ld


loop 仅适用于 rel8 位移,因此它无法从 ld 将其置于代码段中的更高地址到达绝对地址 0xb7

如果你确实想要这样做(但你几乎肯定不想这样做),你可以使用dec ecx / jnz 0xb7,它会使用jcc rel32 编码因此可以通过EIP + rel32 到达任何绝对地址。或者使用链接器脚本将 TEXT 段链接到一个非常低的虚拟地址,以便loop rel8 可以到达。

(但无论哪种方式都不是与位置无关的。通常shellcode应该在注入未知地址后工作。如果你真的想跳转到与位置无关的shellcode中的绝对地址,比如触发特定的页面错误(?),你需要在寄存器中的地址并使用jmp eax


但您更有可能希望跳转到代码中的其他位置,而不是跳转到某个低绝对地址。 在您的分支目标上放置标签并使用dec ecx / jnz label。 (或者使用 loop 指令,因为您可能正在优化代码大小,而不管它很慢。)


如果你从某个地方借用了这段代码,可能是在一个汇编器中,loop 0xb7 设置了rel8 位移的值。或者也许是 NASM 与 org 0x0BITS 32 制作平面二进制文件?但是如果你想分支回到这段代码中的某个地方,那么使用标签会更有意义。

【讨论】:

  • 太好了,今天晚些时候我会检查您的建议。谢谢!
  • 您能否澄清一下,dec ecx / jnz 是一条要附加内存地址的指令吗?即:dec ecx / jnz 0xmyAddress。还是应该将其拆分为各个组成部分?
  • @RichC:这是两条独立的指令,dec 和 `jnz。如果这不明显,请参阅 x86 指令参考:felixcloutier.com/x86/index.html。但它们在现代英特尔 CPU 上解码为单个微指令。
  • 谢谢,不知道我在敲什么把它们组合成一个指令!感谢您的链接,很好的参考
猜你喜欢
  • 1970-01-01
  • 2020-03-21
  • 2014-10-17
  • 1970-01-01
  • 2020-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-02
相关资源
最近更新 更多