现在基本上系统都是64位了,而64位系统下的汇编和32位有了较大的变化,无论是系统调用的接口还是C标准库的接口都和32位汇编有所不同;下面简单谈一下在64位linux下如何利用汇编直接调用系统调用。
需要准备的有:
1.一台linux机器:我的系统是ubuntu 14.10 x64版;
2.还要一个汇编器;我没有使用gas,而是使用了跨平台的nasm;
3.一个调试器;这里选择的不多,要不就是gdb,要不就是lldb,不过这里选择前者。
4.一个编辑器,linux下有很多优秀的语法编辑器,这里用的是sublime,不过可选的还有很多,比如geany,scite,atom等等,大家可以自便。
5.最好还要一个C的编译环境,这样方便参考;linux下可选的貌似也不少我常用的有code::blocks和codelite,这里选择后者:一方面其动态调试的汇编支持还不赖,另一方面其本身版本迭代比较快,至少比codeblocks要快得多。
6.还有神马!?如果可以搞到的话,ida pro也有linux版本哦!其静态调试的功能那是超级优秀啊!正版价高达几百美刀啊!不过网上可以觅到xx版本的,不过ida一贯的做法是将32和64位反汇编器分开啊,貌似64位的xx版逆向器比较难搞到。
下面讲一下linux汇编中基本的尝试新问题,首先linux下32位和64位的syscall table调用号是完全不同的,对于本猫的系统来说调用号文件可以用:
locate unistd_32
//或者
locate unistd_64
命令快速定位,如果系统曾安装过多个内核版本,则可能会找到多个文件,选择当前系统内核版本的就可以了。比如我的32位syscall table文件路径和前几个调用号如下:
head -n10 /usr/src/linux-headers-3.16.0-33-generic/arch/x86/include/generated/uapi/asm/unistd_32.h
#ifndef _ASM_X86_UNISTD_32_H
#define _ASM_X86_UNISTD_32_H 1
#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
而对应的64位syscall内容如下:
head -n20 /usr/include/x86_64-linux-gnu/asm/unistd_64.h
#ifndef _ASM_X86_UNISTD_64_H
#define _ASM_X86_UNISTD_64_H 1
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4
#define __NR_fstat 5
#define __NR_lstat 6
#define __NR_poll 7
#define __NR_lseek 8
#define __NR_mmap 9
#define __NR_mprotect 10
#define __NR_munmap 11
#define __NR_brk 12
#define __NR_rt_sigaction 13
#define __NR_rt_sigprocmask 14
#define __NR_rt_sigreturn 15
#define __NR_ioctl 16
注意32位中wrtie调用号是4,而64位下是1,这个千万别搞错了,否则自然一塌糊涂。