阅读 99

如何将汇编语言转化为机器码

很简单,使用gcc即可,我们写如下程序:

pop eax
复制代码

保存为文本文件,命名为test.s 然后使用gcc在32位的环境下编译

gcc test.s
复制代码

结果会报错,为什么呢?

/usr/bin/ld: /tmp/ccj87S8M.o: relocation R_X86_64_32S against undefined >symbol eax' can not be used when making a PIE object; recompile with -fPIC /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function_start': (.text+0x20): undefined reference to `main' /usr/bin/ld: final link failed: Invalid operation collect2: error: ld returned 1 exit status

因为gcc默认汇编是要编译链接一气呵成的。这里我们使用参数-c,即可只编译不链接。

gcc -c test.s
复制代码

这样就出来了一个test.o文件,里面只有pop eax的机器码,我们可以使用objdump -d查看。

objdump -d test.o

复制代码

可以看到pop eax被转化为了popq,为什么呢?因为gcc采用的是AT&T 语法pop eax要写成pop %eax再编译才行

在这里插入图片描述
既然gcc编译这个并不准确,那么有什么是准确的呢?我们可以采用nasm,nasm使用intel语法,兼容这个格式。 没安装的可以安装下,很快

apt install nasm
复制代码

之后使用nasm编译这个文件

nasm -f elf32 test.s
复制代码

之后生成的test.o文件就可以用objdump正常分析。

在这里插入图片描述
我们也可以在objdump后面加-M intel来转化为intel语法,这种语法没有百分号。
在这里插入图片描述
除此之外,直接使用pwntools里面的函数似乎更加方便,比如

from pwn import *
context.arch='i386' #指定架构
print(asm('mov eax, 0'))
复制代码

结果

b'\xb8\x00\x00\x00\x00'

复制代码

如果有报错没装binutil,请参考这个页面安装对应的,比如安装在Mac OS:

brew install https://raw.githubusercontent.com/Gallopsled/pwntools-binutils/master/osx/binutils-$ARCH.rb
复制代码

这里的$ARCH一般只要填i386或者amd64就行了。