汇编后将ld找不到符号_start错误并将.asm文件链接到64位可执行文件

时间:2017-11-17 05:29:05

标签: linux gcc assembly gdb ld

我有一个shellcode文件。 然后使用ndisasm构建汇编代码。

 ndisasm -b 64 shellcode > shellcode.asm 
 cat shellcode.asm | cut -c29->key.asm 

我在key.asm文件中添加了2行

  

global_start:
       _start:

$vi key.asm
global_start:
_start:
xor eax,eax
push rax
push qword 0x79237771
push qword 0x76772427
push qword 0x25747320
.    .     .
.    .     .
.    .     .
push qword 0x20757577
push rsp
pop rsi
mov edi,esi
mov edx,edi
cld
mov ecx,0x80
mov ebx,0x41
xor eax,eax
push rax
lodsb
xor eax,ebx

然后我组装并将其链接到64位可执行文件

$nasm -f elf64 -g -F stabs key.asm 
$ld -o key key.o

它给了我一个警告

ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080

我用gcc

测试了它
gcc -o key key.o

我仍然得到与第一个错误几乎相同的错误

/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In 
function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

当我使用$ ld NOT $ gcc

后,我用gdb运行./key
$gdb -q ./key
$run

我得到一个段错误

Starting program: /mnt/c/Users/owner/Documents/U
M/Computer_Security/ExtraCredit/key
Program received signal SIGSEGV, Segmentation fault.
0x000000000040013a in global_start ()

如果我在使用gcc运行后进行调试,则由于退出状态

,将无法找到该文件

你能解释一下为什么会这样吗?我该如何解决这个问题呢?感谢

2 个答案:

答案 0 :(得分:2)

  

它给了我一个警告

ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080

这实际上不是问题,只要你的入口点是文本段的开头(即shellcode中的第一条指令)就可以了。

您收到错误是因为您遗漏了global关键字和_start符号名称之间的空格。即使用global _start,或者不要打扰。您所做的事情定义了一个名为global_start的标签,您可以从后面的错误消息中看到。

您在lodsb上进行了段错误,因为您使用mov edi,esi而不是mov rdi, rsi截断了堆栈地址。如果你修复了这个问题,那么你就会把代码的末尾放到垃圾指令中,因为你没有进行exit系统调用。你已经在gdb里面运行它,使用它!

  

我用gcc测试了它:gcc -o key key.o

     

我仍然得到与第一个错误几乎相同的错误

 /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: 
In function `_start':
(.text+0x20): undefined reference to `main'

不,这是一个完全不同的错误。如果您已正确导出_start,则会因_start的定义(代码与CRT起始文件之间)的冲突而出错。

此错误是_start中的crt1.o定义(由gcc提供)引用了main,但您的代码未提供main。当您尝试编译未定义main的C或C ++程序时会发生这种情况。

要与gcc链接,请使用-nostdlib省略CRT启动文件和所有其他库。 (即链接与您使用ld手动完全一样。)

gcc -nostdlib -static key.o -o key   # static executable: just your code

使用_start

在没有CRT起始文件的情况下动态链接
gcc -nostdinc -no-pie key.o -o key

您可以从以这种方式链接的代码调用libc函数,但只能在Linux或其他动态链接负责运行libc初始化函数的平台上调用。

如果静态链接libc,如果首先调用普通CRT启动代码所执行的所有libc init函数,则只能调用printf等函数。 (此处不再详述,因为此代码不使用libc)

答案 1 :(得分:0)

你的代码错了。 global _start 之间必须有空格。这是你的一个问题。

section .text

global _start

_start:
    xor eax,eax
    push rax
    ...

此外,为了解决分段错误发生的原因,您必须对其进行调试。您可以查看执行segfault的汇编指令。

x/5i $eip