一、64位寄存器需要注意的
1.用户模式的系统调用依次传递的寄存器为:
rdi,rsi,rdx,rcx,r8和r9;
2.内核接口的系统调用一次传递的寄存器为:
rdi,rsi,rdx,r10,r8和r9;注意这里和用户模式的系统调用只有第4个寄存器不同,其他都相同。
3.系统调用通过syscall指令进入,不像32位下的汇编使用的是int 0x80指令;
4.系统调用号放在rax寄存器里;
5.系统调用限制最多6个参数;
6.系统调用的返回结果,也就是syscall指令的返回放在rax寄存器中;
7.只有整形值和内存型的值可以传递给内核
8、同时相对于32位的EAX AX AH AL ....EDX (32位)DX(16位) DH(8位) DL(8位),DI(16位),SI(16位),64位系统增加DIL和SIL用于表示RDI和RSI的低8位。。主要用于传参的时候,避免shellcode中出现不必要的\x00字符
二、编写汇编代码
调用32位write系统调用的例子(效果是向屏幕打印输出abcd,最后会报错,但是可以打印):
root@metasploitable:~# cat write.asm
section .text
global _start
_start:
xor eax,eax
push eax ;补结尾字符
push 0x64636261 ;压栈字符串
mov ecx,esp ;传字符串参数到ecx
xor ebx,ebx
mov bl,0x1 ;传stdout到ebx
xor edx,edx
mov dl,0x5 ;打印输出五个字符,赋给edx
xor eax,eax
mov al,0x4 ;系统调用号
int 0x80 ;write(1,"abcd",5) 参数分别对应ebx,ecx,edx
对应64位的版本:
section .text
global _start
_start:
xor rax,rax
push rax
push 0x64636261
mov rsi,rsp
xor rdi,rdi
mov dil,0x1
xor rdx,rdx
mov rdx,0x5
xor rax,rax
mov al,0x1
syscall
三、汇编并提取shellcode
nasm -f elf write.asm 如果是64位则 nasm -f elf64 write.asm,否则指令格式不一致,会报错
然后 ld -o write write.o 生成可执行文件
接下来,可以objdump -d write 反汇编以对照检查
最后,od -tx1 write 就可以提取 shellcode,效果如下: -tx1 表示以一位16进制表示,对应地,-tx2或者-h表示两位16进制显示
如果需要将shellcode赋给程序输入,还需要借助Python -c 'print "\x48\x31\xc0……"' 技巧是把od的结果拷贝到编辑器,然后用\x替换空格就OK了。