如何将包含 32 位 asm 的 C 程序编译成 .o 文件?
How to Compile a C program which contains 32bit asm into .o file?
简介
我正在阅读“学习Linux二进制分析”一书。我有一些使用 32 位汇编和 C 的经验(但仍然认为自己是新手)。然而,我在如何编译一个包含 32 位程序集的 c 程序到目标文件 .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 [=10=]x80\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: Assembler messages:
evil_puts.c:5: Error: invalid instruction suffix for `push'
evil_puts.c:8: Error: invalid instruction suffix for `pop'
我以前在用气体处理 32 组件时收到过这个。为了解决这个问题,我在编译和链接时放置了“-32”标志。我猜哪个是问题所在?但是不完全确定,如果是这样的话,不知道如何用 C 和 gcc 在 32 位中编译它?
我还尝试将其更改为 64 位以查看它是否有效,方法是将每个命令的 'l' 替换为 'q' 并将寄存器更改为以 'r' 开头。这似乎有效。但是这本书使用 32 位。所以我希望保持这种状态。有任何想法吗?抱歉,如果这是一个非常基本的问题。
也试过“-m32”但收到这个:
fatal error: sys/syscall.h: No such file or directory
使用gcc -m32 -c evil_puts.c -o evil_puts.o
您收到该错误是因为您没有安装 32 位库。
如果使用 Ubuntu:
sudo apt-get install gcc-multilib
如今,针对 32 位 x86 的知识用处有限,因为基本上每个人都已切换到 64 位(这是一件好事 - 32 位有很多寄存器压力和地址 space压力)。
幸运的是,您实际上不需要任何 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)
,那么在汇编中实现单个功能仍然比编写汇编 everywhere.
容易得多
简介
我正在阅读“学习Linux二进制分析”一书。我有一些使用 32 位汇编和 C 的经验(但仍然认为自己是新手)。然而,我在如何编译一个包含 32 位程序集的 c 程序到目标文件 .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 [=10=]x80\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: Assembler messages:
evil_puts.c:5: Error: invalid instruction suffix for `push'
evil_puts.c:8: Error: invalid instruction suffix for `pop'
我以前在用气体处理 32 组件时收到过这个。为了解决这个问题,我在编译和链接时放置了“-32”标志。我猜哪个是问题所在?但是不完全确定,如果是这样的话,不知道如何用 C 和 gcc 在 32 位中编译它?
我还尝试将其更改为 64 位以查看它是否有效,方法是将每个命令的 'l' 替换为 'q' 并将寄存器更改为以 'r' 开头。这似乎有效。但是这本书使用 32 位。所以我希望保持这种状态。有任何想法吗?抱歉,如果这是一个非常基本的问题。
也试过“-m32”但收到这个:
fatal error: sys/syscall.h: No such file or directory
使用gcc -m32 -c evil_puts.c -o evil_puts.o
您收到该错误是因为您没有安装 32 位库。
如果使用 Ubuntu:
sudo apt-get install gcc-multilib
如今,针对 32 位 x86 的知识用处有限,因为基本上每个人都已切换到 64 位(这是一件好事 - 32 位有很多寄存器压力和地址 space压力)。
幸运的是,您实际上不需要任何 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)
,那么在汇编中实现单个功能仍然比编写汇编 everywhere.