Post

How to create your own shellcode Part I

Hello everyone. Today, we’ll talk about what shellcode is and how to make it.

How does Shellcode work?

In hacking, a shellcode is a small piece of code that is used as the payload when a software flaw is exploited. It is called “shellcode” because it usually starts a command shell from which the attacker can handle the compromised machine. However, any piece of code that does the same thing can be called “shellcode.” Some people think that the name “shellcode” isn’t good enough because a payload’s purpose isn’t just to start a shell. But most people don’t like the alternatives that have been tried. Machine code is often used to write shellcode. Machine code is often used to write shellcode.

What should you know before you begin?

You need to know x86/x64 assembly, C, and the Linux and Windows operating platforms.

On the x64 OS, General Purpose Registers:

RegisterDescription
raxAccumulator
rbxBase
rcxCounter
rdxData
rsiSource Index
rdiDestination Index
rbpBase Pointer
rspStack Pointer
r8General Purpose Register 8
r9General Purpose Register 9
r10General Purpose Register 10
r11General Purpose Register 11
r12General Purpose Register 12
r13General Purpose Register 13
r14General Purpose Register 14
r15General Purpose Register 15

Registers for general use on the x32 platform:

RegisterDescription
eaxAccumulator
ebxBase
ecxCounter
edxData
esiSource Index
ediDestination Index
ebpBase Pointer
espStack Pointer
r8dGeneral Purpose Register 8
r9dGeneral Purpose Register 9
r10dGeneral Purpose Register 10
r11dGeneral Purpose Register 11
r12dGeneral Purpose Register 12
r13dGeneral Purpose Register 13
r14dGeneral Purpose Register 14
r15dGeneral Purpose Register 15

Get the x16 bits at the top of the GPRs.

RegisterDescription
axAccumulator
bxBase
cxCounter
dxData
siSource Index
diDestination Index
bpBase Pointer
spStack Pointer
r8wGeneral Purpose Register 8
r9wGeneral Purpose Register 9
r10wGeneral Purpose Register 10
r11wGeneral Purpose Register 11
r12wGeneral Purpose Register 12
r13wGeneral Purpose Register 13
r14wGeneral Purpose Register 14
r15wGeneral Purpose Register 15

Access the GPRs’ lower x8 bits.

RegisterDescription
alAccumulator Low
blBase Low
clCounter Low
dlData Low
silSource Index Low
dilDestination Index Low
bplBase Pointer Low
splStack Pointer Low
r8bGeneral Purpose Register 8
r9bGeneral Purpose Register 9
r10bGeneral Purpose Register 10
r11bGeneral Purpose Register 11
r12bGeneral Purpose Register 12
r13bGeneral Purpose Register 13
r14bGeneral Purpose Register 14
r15bGeneral Purpose Register 15

When making Linux syscalls, ESI and EDI are used.

Using XOR EAX, EAX to clear a register is a great way to avoid the dangerous NULL bit!

In Windows, all function inputs are put on the stack based on how the function is called.

If you want to learn more about syscall, click on this link: (syscalls).

Example of Shellcode!

First, we’ll write a small program in assembly code that will show Ev1l T3jv1l h4ck 1337?

You are probably using an operating system with a random stack and address space, and there may be a security feature that stops you from running code on the stack. Not every Linux-based operating system is the same, so I’ll show you a method for Ubuntu that should be easy to adapt.

echo 0 > /proc/sys/kernel/exec-shield (to turn it off)

echo 0 > /proc/sys/kernel/randomize_va_space (to turn it off)

echo 1 > /proc/sys/kernel/exec-shield (turn on)

echo 1 > /proc/sys/kernel/randomize_va_space [[make it work]]

First, we use the touch command to make a file with the name *.asm and then we use the nano editor to write code. This is an example for 32 bit! You need to put in:

1
sudo apt-get install lib32z1 lib32ncurses5

Assembly code for our shellcode:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
global _start

section .text

_start:
jmp message

proc:
    xor eax, eax
    mov al, 0x04
    xor ebx, ebx
    mov bl, 0x01
    pop ecx
    xor edx, edx
    mov dl, 0x16
    int 0x80

    xor eax, eax
    mov al, 0x01
    xor ebx, ebx
    mov bl, 0x01
    int 0x80

message:
    call proc
    msg db "Ev1l h4ck T3jv1l 1337?"

The global _start directive specifies that the symbol _start is globally accessible. The section .text directive indicates that the following instructions belong to the .text section, which typically contains executable code. _start is the entry point of the program. It is the first instruction executed when the program starts. In this case, it jumps to the message label.

The proc is a label that defines a procedure or function. The first block of instructions sets up a system call to write to the standard output.

Here’s a breakdown of the instructions:

  • xor eax, eax sets eax (the register for the system call number) to zero.
  • mov al, 0x04 moves the value 0x04 (system call number for write) into the lower 8 bits of eax.
  • xor ebx, ebx sets ebx (the register for the file descriptor) to zero.
  • mov bl, 0x01 moves the value 0x01 (file descriptor for standard output) into the lower 8 bits of ebx.
  • pop ecx retrieves the value from the top of the stack and stores it in ecx. This is likely used to obtain the address of the msg string.
  • xor edx, edx sets edx (the register for the data length) to zero.
  • mov dl, 0x16 moves the value 0x16 (length of the string) into the lower 8 bits of edx.
  • int 0x80 triggers a software interrupt, invoking the system call.

The second block of instructions sets up a system call to exit the program. Here’s a breakdown of the instructions:

  • xor eax, eax sets eax (the register for the system call number) to zero.
  • mov al, 0x01 moves the value 0x01 (system call number for exit) into the lower 8 bits of eax.
  • xor ebx, ebx sets ebx (the register for the exit status) to zero.
  • mov bl, 0x01 moves the value 0x01 (exit status) into the lower 8 bits of ebx.
  • int 0x80 triggers a software interrupt, invoking the system call to exit the program.
  • message is a label that marks the start of the msg string.
  • call proc calls the proc procedure, executing the code inside it.
  • msg db "Ev1l h4ck T3jv1l 1337?" defines a string named msg with the value “Ev1l h4ck T3jv1l 1337?”.

This time, we need to use the next command to compile this code:

1
2
nasm -f elf32 Asamblare.asm -o shellcode.o
ld -m elf_i386 -s -o T3jv1l shellcode.o

shellcode

We can see the machine code called opcode to see how the program operate:

1
objdump -d T3jv1l 

shellcode

To extract all the opcode we can use next command:

1
for i in `objdump -d T3jv1l | tr '\t' ' ' | tr ' ' '\n' | egrep '^[0-9a-f]{2}$' ` ; do echo -n "\\x$i" ; done 

shellcode

Ok, let’s make a small program in the computer language C to see if this shellcode will run.

This is how the C code will look:

1
2
3
4
5
6
7
8
9
10
11
#include <"stdio.h">

char shellcode[] ="\xeb\x19\x31\xc0\xb0\x04\x31\xdb\xb3\x01\x59\x31\xd2\xb2\x16\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xb3\x01\xcd\x80\xe8\xe2\xff\xff\xff\x45\x76\x31\x6c\x20\x68\x34\x63\x6b\x20\x54\x33\x6a\x76\x31\x6c\x20\x31\x33\x33\x37\x3f\x20";

int main(int argc, char **argv) int main(int argc, char **argv){

int *ret;

ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}

Okay, we know that char shellcode[] saves the opcodes for our shellcode in hexadecimal format. Then, the main method does some kind of trick to run this shellcode. If we run the program after building it as an ELF32 binary with the -z execstack flag set, we get our shell.

First, it uses the main() method to set up a variable of type int *ret, which is a pointer of type int. This value will be right after the saved ebp register in the main’s stack frame.

Because our ret variable is right after the saved ebp register, the return address that was saved before calling the main() method will be found before the saved ebp register.

So, it looks like we can use our ret pointer to point to the saved return address and replace it with the address of our shellcode.

Now let’s see if the C program works by compiling it.

1
gcc -m32 -z execstack T3jv1l.c -o shellcode

shellcode

BONUS!!!

I made my own extract opcode tool in Python, which you can find at https://github.com/T3jv1l/Sh3llshock.

shellcode

If you look, you’ll see that it’s the same shellcode as the one above, and this tool makes it just as easy to extract.

This might not be the best example of Shellcode, but it might help you understand how they are made and how they can be run. We appreciate your time. (Please excuse my English, I’m not a native speaker.)

Reference

http://www.vividmachines.com/shellcode/shellcode.html

https://en.wikipedia.org/wiki/Shellcode

https://www.amazon.com/Shellcoders-Handbook-Discovering-Exploiting-Security/dp/047008023X

https://www.exploit-db.com/building-your-own-ud-shellcodes-part-1.pdf

This post is licensed under CC BY 4.0 by the author.