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

如何将包含32位asm的C程序编译成.o文件?,c,gcc,assembly,gnu-assembler,C,Gcc,Assembly,Gnu Assembler,导言 我正在学习Linux二进制分析这本书。我有一些使用32位汇编和C的经验,但是我仍然认为自己是新手。然而,我在如何编译一个c程序方面遇到了麻烦和困惑,该程序包含32位汇编到一个对象文件.o中。所以我猜这只是我的编译问题 源代码是基于代码注入的二进制修补示例的一部分 源代码 c:汇编程序消息: 邪恶的puts.c:5:错误:“推送”的指令后缀无效 邪恶的puts.c:8:错误:“pop”的指令后缀无效 我以前在使用气体处理32组件时收到过此消息。为了解决这个问题,我在编译和链接时使用了“-32

导言

我正在学习Linux二进制分析这本书。我有一些使用32位汇编和C的经验,但是我仍然认为自己是新手。然而,我在如何编译一个c程序方面遇到了麻烦和困惑,该程序包含32位汇编到一个对象文件.o中。所以我猜这只是我的编译问题

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

源代码

c:汇编程序消息:

邪恶的puts.c:5:错误:“推送”的指令后缀无效

邪恶的puts.c:8:错误:“pop”的指令后缀无效

我以前在使用气体处理32组件时收到过此消息。为了解决这个问题,我在编译和链接时使用了“-32”标志。我猜这就是问题所在?但是,我不完全确定,如果是这样的话,我不知道如何用C和gcc以32位编译它

我还尝试将其更改为64位,以查看它是否可以工作,方法是将每个命令的“l”替换为“q”,并将寄存器更改为以“r”开头。这似乎有效。然而,这本书使用了32位。所以我希望保持这样。有什么想法吗?抱歉,如果这是一个非常基本的问题

也尝试了'-m32',但收到以下消息:

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

使用gcc-m32-c邪恶放置.c-o邪恶放置.o

您会收到该错误,因为您没有安装32位库

如果使用Ubuntu:

sudo apt get安装gcc多库

使用gcc-m32-c-evil_-put.c-o-evil_-put.o

您会收到该错误,因为您没有安装32位库

如果使用Ubuntu:


sudo apt get install gcc multilib

针对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;
}

我不太清楚你为什么不写。但是如果您真的需要避免syscall2,在汇编中实现单个函数仍然比在任何地方编写汇编要容易得多。

目前,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;
}

我不太清楚你为什么不写。但是,如果您真的需要避免使用syscall2,那么在汇编中实现单个函数比在任何地方编写汇编都要容易得多。

我想您应该使用-m32…不要在刚开始学习时将32b更改为64b,这通常比更换寄存器要费劲得多,在这种特殊情况下,不应在64b中使用int 0x80,并且没有简单的替换。正确的系统调用可以替换int 0x80,但它需要不同的参数,因此您仍然需要全部重写。因此,您按照本书的要求使用32b二进制文件是一个很好的决定,将32b移植到64b目标平台需要相当多的经验和时间。@Ped7g:同样重要的是,您不能在64位代码中安全地从内联asm推送/弹出,因为这会破坏红色区域。对于64位模式下的int$0x80,请看,我想您应该使用-m32…在刚刚学习的时候不要将32b更改为64b,这通常比仅仅替换寄存器要花费更多的精力,在这种特殊情况下,int 0x80不应该在64b中使用,并且没有简单的替换。正确的系统调用可以替换int 0x80,但它需要不同的参数,因此您仍然需要全部重写。因此,您按照本书的要求使用32b二进制文件是一个很好的决定,将32b移植到64b目标平台需要相当多的经验和时间。@Ped7g:同样重要的是,您不能在64位代码中安全地从内联asm推送/弹出,因为这会破坏红色区域。有关64位模式下的int$0x80,请参阅
#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;
}