第72部分- Linux x86 64位汇编调用汇编库

第72部分- Linux x86 64位汇编调用汇编库

如果希望汇编语言函数和C以及C++程序一起工作,必须显式的遵守C样式的函数格式。

汇编语言函数的源代码文件包含在编译器命令行中。

例如:

gcc -o exe xx.c xx.s xx2.s xx3.s

创建汇编语言函数的目标文件时,不必使用ld命令连接代码,因为本身可能缺少_start标签。使用as进行汇编即可。

一起编译C文件和汇编文件

汇编文件asmfunc.s如下:

.section .data
testdata:
   .ascii "This is a test message from the asm function\n"
datasize:
   .int 45
.section .text
.type asmfunc, @function
.globl asmfunc
asmfunc:

   movl $1, %rax;//write系统调用
   movl $1, %rdi;//stdout
   movl $testdata, %rsi;//字符串
   movl datasize, %rdx;//字符串长度
   syscall;//系统调用

   ret

C文件mainprog.c如下:

#include <stdio.h>

int main()
{
        printf("This is a test.\n");
        asmfunc();
        printf("Now for the second time.\n");
        asmfunc();
        printf("This completes the test.\n");
        return 0;
}

进行编译连接如下:

# gcc -o mainprog mainprog.c asmfunc.s -no-pie

产生一个完整的可执行程序文件。

这里使用了参数-no-pie,因为不用会报错:

`.data' can not be used when making a PIE object;

tips:默认编译器是PIE(position independent executable)对象的,在支持它的目标上生成与位置无关的可执行文件, 生成一个可以在任意基地址处加载的可执行文件,而不是其加载地址在ld时间固定的“普通”可执行文件。PIE通常被认为是一种强化机制(允许地址随机化来影响主程序中代码和数据的地址),但它也可以具有其他用途,例如使二进制文件更适合于无MMU的系统。

这里-no-pie表示非PIE对象。

PIC和PIE

位置无关的代码(PIC)和位置无关的可执行文件(PIE)并不是什么新鲜事物,但是编译开关,可以忽略,直到我们不能使用为止。

位置无关代码(PIC)是很老的东西。 早在我们拥有MMU和分页之前,所有进程都必须共享物理地址空间,可以确保可以在任何地址加载程序。 当CPU演进并且每个进程可以将其自己的逻辑地址空间任意映射到任何物理地址时,PIC不再是必需的。

早期被教导要在构建.so文件时放置-fPIC的原因是为了确保多个进程可以使用同一代码,这些进程会将同一物理内存映射到各种虚拟地址。 实际上,它消除了所有绝对寻址,而用相对寻址或可以为每个进程分叉的小型跳转表代替它。

在2000年代初之前,PIC仅限于共享库。 可执行文件仍使用绝对寻址,不是PIC时可以依赖PIC,反之则不然。 随着地址空间布局随机化(ASLR)的出现,也使可执行文件与位置无关也变得有意义,这样攻击者就无法预测其内存映射,从而使缓冲区溢出漏洞更加复杂.

现在的操作系统将检查可执行文件是否与位置无关(PIE),如果启用,则启用ASLR。 默认情况下,编译器可能会或可能不会强制执行此操作,具体取决于您的系统。

实际上,位置独立共享库是从使用-fPIC构建的对象创建的,而位置独立可执行文件是从通过-fPIE构建的对象创建的。

这里需要注意的是如下几点:

  • 可以从PIC或PIE对象(.o)和PIC或PIE静态库(.a)创建位置独立PIE的可执行文件
  • 只能从PIC对象或静态库创建PIC共享库
  • 可以从任何对象或静态库中创建非PIE可执行文件1

Linux下编译共享库时,必须加上-fPIC参数,否则在链接时会有错误提示。

如果-fPIE和-shared同时使用,生成的结果即可作为动态库,也可作为可执行程序。作为动态库时,必须满足:不存在main函数且模块中不存在对外输出的全局变量。这是因为-fPIE默认总是将生成的位置无关代码看作是属于程序本身。

PIC是在生成动态链接库时使用(Linux中的so),PIE是在生成可执行文件时使用。

 

反汇编

使用反汇编查看二进制文件

objdump -D mainprog

可以看到有一个段是main,这个段包含来实现C程序代码在系统上生成的汇编语言代码。

00000000004004e7 <main>:

  4004e7:       55                      push   %rbp

  4004e8:       48 89 e5                mov    %rsp,%rbp

  4004eb:       48 8d 3d e2 00 00 00    lea    0xe2(%rip),%rdi        # 4005d4 <_IO_stdin_used+0x4>

  4004f2:       e8 f9 fe ff ff          callq  4003f0 <puts@plt>

  4004f7:       b8 00 00 00 00          mov    $0x0,%eax

  4004fc:       e8 29 00 00 00          callq  40052a <asmfunc>

  400501:       48 8d 3d dc 00 00 00    lea    0xdc(%rip),%rdi        # 4005e4 <_IO_stdin_used+0x14>

  400508:       e8 e3 fe ff ff          callq  4003f0 <puts@plt>

  40050d:       b8 00 00 00 00          mov    $0x0,%eax

  400512:       e8 13 00 00 00          callq  40052a <asmfunc>

  400517:       48 8d 3d df 00 00 00    lea    0xdf(%rip),%rdi        # 4005fd <_IO_stdin_used+0x2d>

  40051e:       e8 cd fe ff ff          callq  4003f0 <puts@plt>

  400523:       b8 00 00 00 00          mov    $0x0,%eax

  400528:       5d                      pop    %rbp

  400529:       c3                      retq

 

000000000040052a <asmfunc>:

  40052a:       48 c7 c0 01 00 00 00    mov    $0x1,%rax

  400531:       48 c7 c7 01 00 00 00    mov    $0x1,%rdi

  400538:       48 c7 c6 30 10 60 00    mov    $0x601030,%rsi

  40053f:       48 8b 14 25 5d 10 60    mov    0x60105d,%rdx

  400546:       00

第一列是程序内存空间中的内存位置。第二列显示汇编语言代码生产的指令代码。

可以看到另一个段就是asmfunc。我们编译的时候是合在一起了。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值