Skip to main content

Assignment 4

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: SLAE64-1434

Target Operating System: 64 bit Linux (x86_64 GNU/Linux)

 Assignment 4:

Create a custom encoding scheme like the "Insertion Encoder" we showed you. PoC (proof of concept) with execve-stack as the shellcode to encode with your schema and then write the decoder to decode and run it.

GitHub Link: https://github.com/rtaylor777/nasm/blob/master/Encode1434.zip

Intro

Encoders and their corresponding decoders serve more than one purpose.
  1. They can be used to remove bad bytes from shellcode.
  2. They can be used to disguise the shellcode and hide it from malware scanners.
Different types of malware scanners can still detect the encoded shellcode.
  1. Because they can have a signature of the decoder.
  2. Because they can analyze the behavior of the decoder.
See these documents for a detailed discussion of the topic:
  1. https://www3.cs.stonybrook.edu/~mikepo/papers/nemu.virology.pdf 
  2. https://www.fp6-noah.org/publications/papers/nemu_raid07.pdf

One of the indicators I have seen referred to by the various documents discussing detection of an encoded shellcode is that they can execute the shellcode in a pseudo processor and see if the shellcode modifies itself. The modifications can be in the form of the shellcode simply rewriting itself as it executes, or in the form of decrypting the payload.

I have a few ideas for how to cope with this sort of detection. I will only implement one of my ideas for this sort of evasion, which is that instead of having my decoder modify the code within itself, I will have the decoder push the changed code onto the stack and when it is completely decoded, start executing the code from the stack.

Quickstart

In case you are impatient or perhaps you have arrived here before I have completed writing my blog here is a quick, high level introduction to the Encode1434.zip and it's contents.


Starting with an empty directory, unzip the Encode1434.zip. You will find that the contents are 2 scripts. The Encode script is used to generate the shellcode from an object file. The Encode script will automatically update the Encoder1434.py python script to use this newly generated shellcode.

Then when you run the Encoder1434.py python script, it will encode the shellcode and generate a Decoder1434.nasm assembly language file.

You can see the above example used my ExecveStack1434 shellcode. Hopefully that counts as a PoC (proof of concept) with the "execve-stack as the shellcode to encode".

Moving on with the assembling and linking...

















Finally we are ready to test:


In the example above I used my helper scripts to do the assembly and link steps among other things. See: http://a41l4.blogspot.ca/2017/02/slae-helper-scripts.html

If you would rather assemble and link yourself:
Assemble
nasm -felf64 Decoder1434.nasm -o Decoder1434.o

Link
ld Decoder1434.o -o Decoder1434

Run
./Decoder1434

shellcode.c

Overview

Now that you know basically how to use what I have created I would like to describe what I have created in more detail. The encoding scheme that I am using first reverses the shellcode so that when it is pushed onto the stack it will be able to run. This already causes the shellcode to look like gibberish or nonsensical code. But the result is pretty static for any particular shellcode.

So I have additionally encoded the shellcode with XOR. On 64 bit Linux I can XOR a full 8 bytes at a time since that is the size of the registers, so I grow the shellcode size so that it will evenly divide by 8. This is also required since after I reverse the shellcode it would be difficult to know where to start executing it if I wasn't aware of exactly where the start of the code is.

The 8 byte key that I XOR the shellcode with, is generated by the Python command "os.urandom"
https://docs.python.org/2/library/os.html. From the Python description for os.urandom "Return a string of n random bytes suitable for cryptographic use."

 When I grow the shellcode to be evenly divisible by 8, I use the os.urandom command to generate the bytes that I append to the shellcode. This way when the shellcode is reversed, the starting bytes before encryption are already random. It works like this unless the shellcode is already evenly divisible by 8.

I created a python function to test the bytecode for nulls. I use this function to test the 8 byte key, to test the bytes generated to append to the shellcode, and most importantly to test the resultant encoded shellcode. For each python function that could produce nulls, the function tests for nulls and repeats its execution until the result is null free. If there were other bytes that I did not want in the result, I could have eliminated them in the same way. There is no need to keep increasing the size of the encoded result just to eliminate certain byte values.

With the way that I designed the python script Encoder1434.py, every time that you run the script, a new Decoder1434.nasm is generated, with a new key, new random bytes that are tacked on to the shellcode, and a new resultant encoded payload.

Decoder1434.nasm

As mentioned above, this file, Decoder1434.nasm, is automatically generated every time that the python script Encoder1434.py is run.


The python script calculates the value required for the push 3 line based on how many times the payload can be divided by 8 (the size loaded and XORed in the register). The python script formats the key used for the XOR and puts the newly generated key on the mov rbx line. The python script formats the db line where the payload is encoded. The rest of the file is just written as static text.

The nasm file uses the jmp, call, pop method of getting the address of the payload into the RSI register. The loop which loads 8 bytes at a time of the payload into RAX will run 3 times, the value that we put into RCX.

Lodsq will read 8 bytes from the payload (pointed to by RSI) into RAX. Lodsq reverses the data that it reads into RAX which is a problem because we needed it backwards before pushing onto the stack.

The bswap rax command reverses the bytes again for us. The xor rax, rbx line is XORing our Key with the 8 bytes of payload that are in RAX.

The push RAX line is building our payload on the stack in reverse order.

The last bit of magic is pushing the pointer to the stack (RSP) onto the stack, so that the ret instruction will pop that address and continue execution at the address it popped. This is slightly more obscure than just doing a "jmp rsp" which would be too obvious. Also, if you wanted to disguise what is happening, you can put bogus code between the push rsp command and the ret.

Encoder1434.py

I'll spare you the tedium of going through the python script line by line. There are 198 lines after all.
The main function has these function calls:
    init()
    extend_shell()
    encode()
    test_decipher()
    set_push_str()
    set_key_mov_str()
    set_db_str()
    create_decoder()

The init() function is mostly just setting up the shellcode_array (bytearray) as a copy of the shellcode.

The extend_shell() is all about generating enough random bytes and tacking them onto the end of the shellcode_array to get the length of the shellcode_array evenly divisible by 8.

The encode() function actually calls the key generation function, and does the reversing of the shellcode_array storing the result in a my_ciphered bytearray, and then the XOR of the key with the my_ciphered bytearray. If any nulls are found in the result of the key generation or the encoded my_ciphered bytearray the respective function calls itself to repeat the process.

The test_decipher() function tests returning the my_ciphered bytearray back to it's pre encoded state. The result is saved in a my_deciphered bytearray and that is compared with the shellcode_array. If the results match there is no further action or output. If the results don't match the error is printed on the screen.

The functions set_push_str(), set_key_mov_str(), and set_db_str() are just building the push, mov, and db lines for the Decoder1434.nasm file and saving them in variables.

The create_decoder() function writes the Decoder1434.nasm file.

Encode

If you understand bash this is a pretty basic script. We are capturing the output of the objdump command with some of it's output that we do not want removed using the grep and the cut commands.

Then we process each byte (two hex characters) that were automatically separated out using "space" as the separator, by the for command. Space in this case includes tabs, spaces, newline characters etc..
Tacking 4 slashes the character x and these hex characters onto the end of the variable "line" which we are building.

Why so many slashes? Bash expects the slashes to mean something and the way to escape the slash so that it doesn't mean something special is to escape it with a slash. Bash removes the leading slash leaving the slash it has not interpreted as something special. But each command, like printf, or sed, also expects the slash to mean something so we have to escape the slash again, and Bash would see that slash as something special if we didn't escape it again. Ya, if something isn't working out you just add more slashes.

Some commands like Echo would not remove the slashes, that is why I had to use printf so that the output to the screen is exactly right. 

The sed command is doing an in place edit "-i" of the file Encoder1434.py and replacing the line that matches "shellcode=" with the "$line" variable we built.

In summary this magical script allows us to easily use the Encoder1434.py script with any shellcode that we have object code for without having to manually copy and past the shellcode text.

Summary

I have created 2 scripts which automate generating shellcode text, including it in an encoder and generating the corresponding decoder assembly language. I have tested the scripts with my version of the execve_stack shellcode as a PoC (proof of concept) but they have been designed to easily be tested with any shellcode.

If you wish to learn more about assembly language, I highly recommend the "SecurityTube Linux Assembly Expert course and certification."

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




Comments

Popular posts from this blog

GIAC GXPN Review – SANS SEC660 (Advanced Penetration Testing, Exploit Writing, and Ethical Hacking)   Intro  SANS is a well respected and premier cyber security training company that employs industry experts as instructors. GIAC is a company that produces testing to validate the skills of security professionals. GIAC exams validate the learning outcomes of the SANS courses. Prerequisites Before attempting this course you should be familiar with penetration testing as this is an advanced course. I would say that you should also be familiar with assembly language and shellcoding. It would be best if you have studied basic stack overflow exploits prior to this course. You will need a basic understanding of programming in C or C++ (preferably both). Scripting using Python would be a useful prerequisite. If you could learn a bit of Ruby scripting it would help for the Metasploit module creation. Be familiar with various routing and networking protocols. Course Coverage This course covers ma

PolySetuidExecve1434

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: SLAE64-1434 Target Operating System : 64 bit Linux (x86_64 GNU/Linux) This blog post is part of Assignment 6: http://a41l4.blogspot.ca/2017/03/assignment-6.html The Original Version: http://shell-storm.org/shellcode/files/shellcode-77.php My Version: GitHub Link : https://github.com/rtaylor777/nasm/blob/master/PolySetuidExecve1434.nasm Published : https://www.exploit-db.com/exploits/41498/ Original Shellcode bytes = 49 My version: Number of bytes = 31 Number of nulls = 0 PolySetuidExecve1434.nasm Intro This shellcode when executed will first setuid(0) and then execute /bin/sh and provide you with a shell. The purpose of calling setuid(0) is, suppose that you have managed to inject this shellcode into an executable that is Set-UID root. I

PolyFlushIPTables1434

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: SLAE64-1434 Target Operating System : 64 bit Linux (x86_64 GNU/Linux) This blog post is part of Assignment 6: http://a41l4.blogspot.ca/2017/03/assignment-6.html The Original Version: http://shell-storm.org/shellcode/files/shellcode-683.php Original size: 50 bytes (don't believe what he says :) My Version: GitHub Link : https://github.com/rtaylor777/nasm/blob/master/PolyFlushIPTables1434.nasm Published : https://www.exploit-db.com/exploits/41503/ My version: Number of bytes = 47 Number of nulls = 0 PolyFlushIPTables1434.nasm  Intro This shellcode basically just executes /sbin/iptables -F without any other parameters. man iptables "-F, --flush [chain]               Flush  the  selected  chain (all the chains in the table if none i