简介
我正在阅读“学习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:没有这样的文件或目录
答案 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)
,那么在汇编中实现单个函数比在任何地方编写汇编 要容易得多。