Week 2

$> shellcode

Today’s Agenda

  • Kahoot’nt
  • Content Review
    • Assembly Code
    • cdecl
    • Shellcode
    • Egg Hunters
    • /bin/////////sh
    • NOP sleds
  • Activities

Kahoot’nt

joinmyquiz.com

Good Faith Policy

“These courses expects a high standard of professionalism from its students with regard to how security testing is conducted. We expect all students to act in good faith at all times […]”

TL;DR Don’t be mean

https://sec.edu.au/good-faith-policy

Content Review

Assembly

Your common assembly instructions

mov a, b        # a = b
add a, value    # a = a + value
sub a, value    # a = a - value
xor a, b        # a = a ^ b
and a, b        # a = a & b
push a          # push a onto the stack, then dec esp - 4
pop a           # pop into a from the stack, then add esp + 4
int 0x80        # syscall

 

Syscalls

Syscall Table

cdecl

void mycoolfunc(char *a, int b, char *c)

What assembly would I write to call this function?

  • push address_c
  • push value_b
  • push address_a
  • call mycoolfunc

Shellcode TL;DR

Shellcode is a sequence of assembly instructions that carry out a task. If we can make the instruction pointer (EIP) point to our shellcode, we have code execution!

  • Functions are just assembly
  • Assembly are just bytes
  • We can send bytes :)

Generally we want to pop a shell

Demo

./runner

🥚 Egghunter

Sometimes we do not have enough space in an execute-vulnerable buffer to inject our payload.

Instead, we put our payload (the egg) somewhere else, and write an ‘egg hunter’ - assembly instructions that finds and execute the egg.

My Little Pwn-y

Demo time!

#include <stdio.h>   // Compile with:
#include <stdlib.h>  //   gcc -o eggHunterDemo -z execstack -m32 -g eggHunterDemo.c
#include <time.h>    //                        \__________/
#include <unistd.h>  // -- Andrew                   | allow stack execution

int main() {
    char mem[256] = { 0 }, shellcode[512] = { 0 };
    srand(time(NULL));

    // Set some random position in mem to [0, 255]
    mem[(u_int8_t)rand()] = 0xFF;  // eggu desu ~

    puts("Find that egg!\nEnter up to 512 bytes of shellcode");
    read(0, shellcode, 512);
    // Your shellcode should accept a buffer (esp+4), and return an index via eax
    u_int8_t i = ((u_int8_t(*)(u_int8_t * a)) shellcode)(mem);

    printf("mem[i = %hhu] = 0x%2x\n", i, mem[i] & 0xFF);
    puts(mem[i] & 0xFF == 0xFF ? "nice!" : "nope.");
}

🍳 Omelette Egghunter

A fancy egghunter that finds multiple payloads / eggs and combines them together.

Useful when we have multiple regions of controllable memory that can collectively hold the entire payload.

/bin/////////sh

Sometimes we cannot inject /bin/sh directly.

Why?

  • An input parser that stops after the NULL character
    • How do we check if we are at the end of a string?
  • An input sanitiser that removes the NULL character
                                      !! uh oh, null char!
                                      vv
_hs/ | push 0x0068732f | 68 2f 73 68 [00]
nib/ | push 0x6e69622f | 68 2f 62 69  6e 

We have ways around this!

Pad our /bin/sh to /bin//sh

// BEFORE
_hs/ | push 0x0068732f | 68 2f 73 68 00
nib/ | push 0x6e69622f | 68 2f 62 69 6e
// AFTER
hs// | push 0x68732f2f | 68 2f 2f 73 68
nib/ | push 0x6e69622f | 68 2f 62 69 6e
some shellcode yadda yadda / b i n / / s h ... int 0x80 

How do we push 0's onto the stack?

xor eax, eax
push eax

etc…

Sometime in the future…

Maybe /bin/sh is already in the program???

 

idk ¯\_(ツ)_/¯

NOPsleds

NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP
NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP
NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP
NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP
NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP
NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP
NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP
NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP
NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP

In order to execute our shellcode, we need to know the exact start address of it… sometimes we can’t do that, but we can jump near it and nop-sled away.

The nop instruction (\x90) is a single byte instruction that does nothing

Where we start execution      Where our shellcode actually is
|                             |
v                             v 
\x90 \x90 \x90 \x90 \x90 \x90 \x68 \x2f \x2f \x73 \x68 \x68..

Activities

Lab 2 - Shellcode Exercices

Home