Getting started

Introduction

This is a quick reference to getting started with Shellcoding.

Shellcode Tester

Installing

git clone https://github.com/helviojunior/shellcodetester.git
cd shellcodetester/Linux
make

Assembling using shellcode tester

shellcodetester arquivo.asm

Adding a break-point before shellcode

shellcodetester arquivo.asm --break-point

For more information, windows version and releases see: Shellcode Tester

GDB Commands

Open an application

gdb -q [path_da_aplicação]

Using his coredump

gdb -q [path_da_aplicação] [path_core_dump]

Command help

(gdb) help [comando]
(gdb) help run

Run app without parameter

(gdb) run

Check permissions

(gdb) checksec

Run app with parameter

Hard-coded parameter

(gdb) run AAAAA

Parameter from an external command

(gdb) run $(echo -n “AAAA”)
(gdb) run $(python -c 'print "A" * 500 ')

Passing data to stdin from external command

(gdb) run < <(echo -n “AAAA”)
(gdb) run < <(python -c 'print "A" * 500 ')

Breakpoints

Adding an breakpoint

(gdb) b *main
(gdb) b *0x01020304

Adding conditional breakpoint

(gdb) b main.c:260 if (resp_pool->first==0x4141414141414141)

List previous breakpoints

(gdb) info breakpoints

Delete one

(gdb) del 1  # 1 is the breakpoint id
(gdb) del 5  # 5 is the breakpoint id

Delete all breakpoints

(gdb) del

Disassemble

Using function name

(gdb) disassemble main

Using memory position

(gdb) disassemble 0x000011e9
(gdb) disassemble 0x000011e9,+100

Displaying opcodes

(gdb) disassemble/r main

Displaying registers

(gdb) info registers
(gdb) info registers eax

Displaying memory data

Using memory address

(gdb) print 0x01020304

Using debug symbol of variable name

(gdb) print &nome_variavel

Struct

View struct members

(gdb) ptype struct [nome_da_struct]

View struct members and offset

(gdb) ptype/o struct [nome_da_struct]

Parsing memory data with struct

(gdb) print/x *(struct sockaddr_in *) &nome_variavel
(gdb) print/x *(struct sockaddr_in *) 0x01020304

Assembly

Registers

Register is a small space used by CPU to store information.

Registers - 32 bits

32 bits 16 bits 8 bits  
    High Low
eax ax ah al
ecx ax ch cl
edx dx dh dl
ebx bx bh bl
esp sp   spl
ebp bp   bpl
esi si   sil
edi di   dil

Registers - 64 bits

64 bits 32 bits 16 bits 8 bits  
      High Low
eax / r0 eax / r0d ax / r0w ah al / r0b
ecx / r1 ecx / r1d cx / r1w ch cl / r1b
rdx / r2 edx / r2d dx / r2w dh dl / r2b
rbx / r3 ebx / r3d bx / r3w bh bl / r3b
rsp / r4 esp / r4d sp / r4w   spl / r4b
rbp / r5 ebp / r5d bp / r5w   bpl / r5b
rsi / r6 esi / r6d si / r6w   sil / r6b
rdi / r7 edi / r7d di / r7w   dil / r7b
r8 r8d r8w   r8b
r9 r9d r9w   r9b
r10 r10d r10w   r10b
r11 r11d r11w   r11b
r12 r12d r12w   r12b
r13 r13d r13w   r13b
r14 r14d r14w   r14b
r15 r15d r15w   r15b

IP - Instruction Pointer

Points to next instruction to be executed

Register Description
ip 16 bits
eip 32 bits
rip 64 bits

SP - Stack Pointer

Points to top of stack

Register Description
sp 16 bits
esp 32 bits
rsp 64 bits

Assembly insctuctions

This table shows the main ASM instructions used to create shellcode

Instruction Description
INT3 Generate breakpoint trap
CALL Call a procedure
CLD Clear Direction Flag
DEC Decrement by 1
INC Increment by 1
JMP Jump
LEA Load Effective Address
MOV Move
NOP No Operation
POP Pop a Value from the Stack
PUSH Push Word, Doubleword or Quadword Onto the Stack
RET Return from Procedure
SHL Shift Left
SHR Shift Right
XOR Logical Exclusive OR

See: Intel® 64 and IA-32 Architectures Software Developer Manuals

ASM Code sample for 32 bits

This sample can be used to generate: Shellcode or ELF

[BITS 32]
global _start
section .text
_start:
    ; instructions
    nop
    nop

This sample can be used to generate: Windows PE

[BITS 32]
global _WinMain@16
section .text
_WinMain@16:
    ; instructions
    nop
    nop

ASM Code sample for 64 bits

This sample can be used to generate: Shellcode or ELF

[BITS 64]
global _start
section .text
_start:
    ; instructions
    nop
    nop

This sample can be used to generate: Windows PE

[BITS 64]
global _WinMain@16
section .text
_WinMain@16:
    ; instructions
    nop
    nop

Assembling for Shellcoding

Using shellcode tester

shellcodetester input_file.asm
shellcodetester input_file.asm --break-point

In order to assembly to Shellcode we must have only our instrunctions without ELF or PE structure.

nasm input_file.asm -o output_file.o

Display raw data in HEX format (does not matter if it is an 32 bit or 64 bits code)

cat output_file.o | msfvenom -p - -a x86 --platform win -e generic/none -f hex

Display raw data in Python array format (does not matter if it is an 32 bit or 64 bits code)

cat output_file.o | msfvenom -p - -a x86 --platform win -e generic/none -f python

Assembling for Execution

Linux 32 bits

nasm -f elf32 input_file.asm -o output_file.o
ld -o executable_file output_file.o -m elf_i386

Linux 64 bits

nasm -f elf64 input_file.asm -o output_file.o
ld -o executable_file output_file.o -m elf_x86_64

Windows 32 bits

nasm -f win32 input_file.asm -o output_file.o
gcc -o executable_file.exe output_file.o

Windows 64 bits

nasm -f win64 input_file.asm -o output_file.o
gcc -o executable_file.exe output_file.o

Tricks

Reverse text using python

texto = "Treinamento Shellcoding\n"
texto[::-1]
len(texto[::-1])
texto[::-1].encode('hex')

ASM to JMP, CALL, POP

This sample can be used to generate: Shellcode or ELF

[BITS 32]
global _start
section .text
_start:
    jmp step1
step2:
    pop ecx ; Save text addr at ECX
    nop
    ; Other instructions
step1:
    call step2                  
    db "Treinamento Shellcoding", 0x0a, 0x00

Debug Symbols

Extract debug symbol from an binary executable file

objcopy --only-keep-debug [elf_file] symbols.debug

Use debug symbol insed of GDB

(gdb) symbol-file symbols.debug

Disassemble raw file (shellcoding)

32 bits

objdump -D -Mintel,i386 -b binary -m i386 shellcode.bin

64 bits

objdump -D -Mintel,x86-64 -b binary -m i386 shellcode.bin

Calling convention

Syscall Linux 32 bits

When using syscall the parameters must be passed using registers. Return value, when exists, will be stored at EAX.

Follows pseudo-function:

eax = func1(ebx, ecx, edx, esi, edi)
Register Description
eax Syscall number
ebx 1st parameter
ecx 2nd parameter
edx 3rd parameter
esi 4th parameter
edi 5th parameter

Syscall number can be found at: /usr/include/x86_64-linux-gnu/asm/unistd_32.h Function desription can be fount with command man 2 [function_name]

Syscall Linux 64 bits

When using syscall the parameters must be passed using registers. Return value, when exists, will be stored at RAX.

Follows pseudo-function:

eax = func1(rdi, rsi, rdx, r10, r8, r9)
Register Description
rax Syscall number
rdi 1st parameter
rsi 2nd parameter
rdx 3rd parameter
r10 4th parameter
r8 5th parameter
r9 6th parameter

Syscall number can be found at: /usr/include/x86_64-linux-gnu/asm/unistd_64.h Function desription can be fount with command man 2 [function_name]

Windows and Linux 32 bits stack

All parameters must be pushed onto stack. Remember that parameters must be pushed in reverse order.

Return value, when exists, will be stored at EAX.

Follows pseudo-function:

eax = func1(ESP, ESP + 0x04, ESP + 0x08, ...)
Stack Position Description
esp + 0x00 1st parameter
esp + 0x04 2nd parameter
esp + 0x08 3rd parameter
esp + 0x0C 4th parameter
esp + 0x10 5th parameter
Other parameter

Windows and Linux 64 bits

When using ABI API the parameters must be passed using registers. Return value, when exists, will be stored at RAX.

Follows pseudo-function:

eax = func1(int a, int b, int c, int d, int e)
// a on RCX, b on RDX, c on R8, d on R9, e pushed onto stack

Where:

Register / Stack Position Description
rcx 1st parameter
rdx 2nd parameter
r8 3rd parameter
r9 4th parameter
esp + 0x00 5th parameter
esp + 0x04 6th parameter
Other parameter

AMD64 Application Binary Interface (ABI)

This section describes the standard processes and conventions that one function (the caller) uses to make calls into another function (the callee) in x64 code

See: x64 calling convention

ASM 64 bits tricks

[BITS 64]
global _start
section .text
_start:
    ; This 2 instructions must be always present at start of an shellcode
    cld                         ; Clear direction flag
    and rsp, 0xFFFFFFFFFFFFFFF0 ; Align stack at 16-byte

    ; Creating one shadow space (without NULL Byte)
    xor eax,eax                 ; Fill EAX with Zero
    push eax                    ; Push 0x00 onto stack

Also see