如何将包含32位asm的C程序编译成.o文件?

时间:2017-09-13 22:30:23

标签: c gcc assembly gas

简介

我正在阅读“学习Linux二进制分析”一书。我有一些使用32位汇编和C的经验(但仍然认为自己是新手)。但是我遇到了麻烦和混淆如何编译一个c程序,它包含32位汇编到一个目标文件.o。所以我猜这只是我的编译问题。

源代码是基于代码注入的二进制修补示例的一部分。

源代码

#include <sys/syscall.h>
int _write (int fd, void *buf, int count)
{
  long ret;
  __asm__ __volatile__ ("pushl %%ebx\n\t"
  "movl %%esi,%%ebx\n\t"
  "int $0x80\n\t""popl %%ebx":"=a" (ret)
                          :"0" (SYS_write), "S" ((long) fd),
  "c" ((long) buf), "d" ((long) count));
    if (ret >= 0) {
        return (int) ret;
 }
 return -1;
}
int evil_puts(void)
{
        _write(1, "HAHA puts() has been hijacked!\n", 31);
}

问题

我尝试将evil_puts.c编译为.o文件。然后将用于注入另一个简单的程序。

gcc -c evil_puts.c
  

evil_puts.c:汇编程序消息:

     

evil_puts.c:5:错误:“push”

的指令后缀无效      

evil_puts.c:8:错误:“pop”

的指令后缀无效

在使用32气体装配工作之前,我已经收到了这个。为了解决这个问题,我在编译和链接时添加了'-32'标志。我猜哪个是问题?但是不完全确定,如果是这样的话,不知道如何使用C和gcc在32位编译它?

我还试图通过将每个命令的'l'替换为'q'并将寄存器更改为以'r'开头,将其更改为64位以查看它是否可行。这似乎工作。然而,这本书使用32位。所以我希望保持这种方式。有任何想法吗?对不起,如果这是一个非常基本的问题。

还试过'-m32',但收到了这个:

  

致命错误:sys / syscall.h:没有这样的文件或目录

2 个答案:

答案 0 :(得分:3)

使用gcc -m32 -c evil_puts.c -o evil_puts.o

您收到该错误是因为您没有安装32位库。

如果使用Ubuntu:

sudo apt-get install gcc-multilib

答案 1 :(得分:1)

特定于32位x86的知识现在的用处有限,因为基本上每个人都已切换到64位(这是一件好事--32位有很多寄存器压力和地址空间压力)。

幸运的是,你实际上并不需要任何asm来做你正在做的事情。我还做了几个健全的修复:

#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>

#define write_str(fd, s) my_write(fd, s, strlen(s))
static ssize_t my_write(int fd, const void *buf, size_t count)
{
    return syscall(SYS_write, (long)fd, (long)buf, (long)count);
}

int puts(const char *s __attribute__((unused)))
{
    write_str(STDOUT_FILENO, "HAHA puts() has been hijacked!\n");
    return strlen(s) + 1;
}

我不确定你为什么要避免write(2)。但是如果你真的需要避免syscall(2),那么在汇编中实现单个函数比在任何地方编写汇编 要容易得多。