• Stars
    star
    180
  • Rank 212,430 (Top 5 %)
  • Language
    C
  • Created about 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An easily modifiable shellcode template for Windows x64 written in C

Shellcode Template for Windows x64

An easily modifiable shellcode template that loads LoadLibraryA and GetProcAddress and exposes the HMODULE to kernel32.dll written in C.

There are a lot of comments in the shellcode_template function to better explain what's going on. If you don't want to clone the repository, here's the important part:

  // Load Process Environment Block.
  PEB *pProcessEnvironmentBlock = (PEB *)__readgsqword(0x60);

  // `pProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList` contains a double linked list.
  // `Flink` and `Blink` are pointers to the next and previous element.
  //
  // All Windows executables should have the following module order.
  //  1. The module of the current executable.
  //  2. `ntdll.dll` (`%windir%\System32\ntdll.dll`)
  //  3. `kernel32.dll` (`%windir%\System32\kernel32.dll`)
  //
  //  ... followed by other modules.
  //
  // In order to get the `GetProcAddress` function we need to therefore get the third item (`Flink->Flink->Flink`).
  // We use the `CONTAINING_RECORD` macro to retrieve the associated table entry.
  LDR_DATA_TABLE_ENTRY *pKernel32TableEntry = CONTAINING_RECORD(pProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList.Flink->Flink->Flink, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

  // We've ended up at the base address of `kernel32.dll`.
  IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER *)pKernel32TableEntry->DllBase;

  // In order to get the exported functions we need to go to the NT PE header.
  IMAGE_NT_HEADERS *pNtHeader = (IMAGE_NT_HEADERS *)((size_t)pDosHeader + pDosHeader->e_lfanew);

  // From the NtHeader we can extract the virtual address of the export directory of this module.
  IMAGE_EXPORT_DIRECTORY *pExports = (IMAGE_EXPORT_DIRECTORY *)((size_t)pDosHeader + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

  // The exports directory contains both a list of function _names_ of this module and the associated _addresses_ of the functions.
  const int32_t *pNameOffsets = (const int32_t *)((size_t)pDosHeader + pExports->AddressOfNames);
  
  // We will use this struct to store strings.
  // We are using a struct to make sure strings don't end up in another section of the executable where we wouldn't be able to address them in a different process.
  struct
  {
    uint64_t text0, text1;
  } x;

  // We're now looking for the `GetProcAddress` function. Since there's no other function starting with `GetProcA` we'll just find that instead.
  x.text0 = 0x41636F7250746547; // `GetProcA`

  int32_t i = 0;

  // We're just extracting the first 8 bytes of the strings and compare them to `GetProcA`. We'll find it eventually.
  while (*(uint64_t *)((size_t)pDosHeader + pNameOffsets[i]) != x.text0)
    ++i;

  // We have found the index of `GetProcAddress`.

  // The entry at an index in `AddressOfNames` corresponds to an entry at the same index in `AddressOfNameOrdinals`, which resolves the index of a given name to it's corresponding entry in `AddressOfFunctions`. (DLLs can export unnamed functions, which will not be listed in `AddressOfNames`.)
  // Let's get the function name ordinal offsets and function offsets in order to retrieve the location of `GetProcAddress` in memory.
  const int16_t *pFunctionNameOrdinalOffsets = (const int16_t *)((size_t)pDosHeader + pExports->AddressOfNameOrdinals);
  const int32_t *pFunctionOffsets = (const int32_t *)((size_t)pDosHeader + pExports->AddressOfFunctions);

  // Now resolve the index in `pFunctionOffsets` from `pFunctionNameOrdinalOffsets` to get the address of the desired function in memory.
  typedef FARPROC(*GetProcAddressFunc)(HMODULE, const char *);
  GetProcAddressFunc pGetProcAddress = (GetProcAddressFunc)(const void *)((size_t)pDosHeader + pFunctionOffsets[pFunctionNameOrdinalOffsets[i]]);

  // Now that we've got `GetProcAddress`, let's use it to get `LoadLibraryA`.

  // A HMODULE is just a pointer to the base address of a module.
  HMODULE kernel32Dll = (HMODULE)pDosHeader;

  // Get `LoadLibraryA`.
  x.text0 = 0x7262694C64616F4C; // `LoadLibr`
  x.text1 = 0x0000000041797261; // `aryA\0\0\0\0`

  typedef HMODULE(*LoadLibraryAFunc)(const char *);
  LoadLibraryAFunc pLoadLibraryA = (LoadLibraryAFunc)pGetProcAddress(kernel32Dll, (const char *)&x.text0);

There's also an example application that demonstrates how the generated shellcode can be executed inside a child process.

Get Started

git clone https://github.com/rainerzufalldererste/windows_x64_shellcode_template.git
cd windows_x64_shellcode_template
git submodule update --init --recursive
create_project.bat

Choose your compiler toolset. (VS 2015 / VS 2017)

The shellcode_template project includes everything to start developing custom shellcode.

How to retrieve the shellcode?

There are many ways to retrieve the generated shellcode. The easiest way is probably to just step into void shellcode_template() in the Visual Studio Debugger and open the Disassembly View (Ctrl+Alt+D). Make sure to turn on displaying code bytes and turn off displaying source code and addresses to simplify the output.

48 89 5C 24 08       mov         qword ptr [rsp+8],rbx  
57                   push        rdi  
48 83 EC 30          sub         rsp,30h  
65 48 8B 04 25 60 00 00 00 mov         rax,qword ptr gs:[0000000000000060h]  
33 D2                xor         edx,edx  
49 B8 47 65 74 50 72 6F 63 41 mov         r8,41636F7250746547h  
48 8B 48 18          mov         rcx,qword ptr [rax+18h]  
48 8B 41 20          mov         rax,qword ptr [rcx+20h]  
48 8B 08             mov         rcx,qword ptr [rax]  
48 8B 01             mov         rax,qword ptr [rcx]  
48 8B 78 20          mov         rdi,qword ptr [rax+20h]  
48 63 47 3C          movsxd      rax,dword ptr [rdi+3Ch]  
44 8B 8C 38 88 00 00 00 mov         r9d,dword ptr [rax+rdi+0000000000000088h]  
41 8B 44 39 20       mov         eax,dword ptr [r9+rdi+20h]  
48 03 C7             add         rax,rdi  
48 63 08             movsxd      rcx,dword ptr [rax]  
4C 39 04 39          cmp         qword ptr [rcx+rdi],r8  
 ...

Now you can just remove the labels and disassembly and you're left with the shellcode:

48 89 5C 24 08
57
48 83 EC 30
65 48 8B 04 25 60 00 00 00
33 D2
49 B8 47 65 74 50 72 6F 63 41
48 8B 48 18
48 8B 41 20
48 8B 08
48 8B 01
48 8B 78 20
48 63 47 3C
44 8B 8C 38 88 00 00 00
41 8B 44 39 20
48 03 C7
48 63 08
4C 39 04 39
 ...

Alternatively you can just paste your code into an online compiler like godbolt.org and copy the generated MSVC assembly (that doesn't call any internal functions for i.e. buffer security cheacks or memcpy) (ie. x64 msvc v19.latest with /O2 /GS-) into an online assembler like https://defuse.ca/online-x86-assembler.htm. Then just copy the generated shellcode.

When using online compilers you will probably have to clean up the assembly a bit, like this:

x$ = 32
void shellcode_template(void) PROC               ; shellcode_template, COMDAT
$LN10:
        mov     QWORD PTR [rsp+8], rbx
        push    rdi
        sub     rsp, 48                             ; 00000030H
        mov     rax, QWORD PTR gs:96
        xor     edx, edx
        mov     r8, 4711732171926431047             ; 41636f7250746547H
        mov     rcx, QWORD PTR [rax+24]
        mov     rax, QWORD PTR [rcx+32]
        mov     rcx, QWORD PTR [rax]
        mov     rax, QWORD PTR [rcx]
        mov     rdi, QWORD PTR [rax+32]
        movsxd  rax, DWORD PTR [rdi+60]
        mov     r9d, DWORD PTR [rax+rdi+136]
        mov     eax, DWORD PTR [r9+rdi+32]
        add     rax, rdi
        movsxd  rcx, DWORD PTR [rax]
        cmp     QWORD PTR [rcx+rdi], r8
        je      SHORT $LN3@shellcode_
        npad    2
$LL2@shellcode_:
        movsxd  rcx, DWORD PTR [rax+4]
        lea     rax, QWORD PTR [rax+4]
        inc     edx
        cmp     QWORD PTR [rcx+rdi], r8
        jne     SHORT $LL2@shellcode_
$LN3@shellcode_:
        mov     ecx, DWORD PTR [r9+rdi+36]
        mov     rax, 8242266044863967052      ; 7262694c64616f4cH
        ...

can through a bit of find and replace be turned into this: (keep in mind, the defuse.ca assembler doesn't seem to like comments)

shellcode_template:
        mov     qword ptr [rsp+8], rbx
        push    rdi
        sub     rsp, 48
        mov     rax, qword ptr gs:96
        xor     edx, edx
        mov     r8, 4711732171926431047
        mov     rcx, qword ptr [rax+24]
        mov     rax, qword ptr [rcx+32]
        mov     rcx, qword ptr [rax]
        mov     rax, qword ptr [rcx]
        mov     rdi, qword ptr [rax+32]
        movsxd  rax, DWORD ptr [rdi+60]
        mov     r9d, DWORD ptr [rax+rdi+136]
        mov     eax, DWORD ptr [r9+rdi+32]
        add     rax, rdi
        movsxd  rcx, DWORD ptr [rax]
        cmp     qword ptr [rcx+rdi], r8
        je      SHORT _function_found
        
        ; `npad    2` can be turned into two `nop`s.

        nop
        nop


_find_next_function:
        movsxd  rcx, DWORD ptr [rax+4]
        lea     rax, qword ptr [rax+4]
        inc     edx
        cmp     qword ptr [rcx+rdi], r8
        jne     SHORT _find_next_function


_function_found:
        mov     ecx, DWORD ptr [r9+rdi+36]
        mov     rax, 8242266044863967052
        ...

Just interested in the generated shellcode?

This is the example shellcode. It performs the following actions:

  • It finds GetProcAddress in kernel32.dll,
  • retrieves LoadLibraryA from kernel32.dll,
  • loads user32.dll,
  • retrieves MessageBoxA from user32.dll,
  • displays a message box,
  • retrieves ExitProcess from kernel32.dll,
  • calls ExitProcess.
  0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60, 
  0x00, 0x00, 0x00, 0x33, 0xD2, 0x49, 0xB8, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x41, 0x48, 
  0x8B, 0x48, 0x18, 0x48, 0x8B, 0x41, 0x20, 0x48, 0x8B, 0x08, 0x48, 0x8B, 0x01, 0x48, 0x8B, 0x78, 
  0x20, 0x48, 0x63, 0x47, 0x3C, 0x44, 0x8B, 0x8C, 0x38, 0x88, 0x00, 0x00, 0x00, 0x41, 0x8B, 0x44, 
  0x39, 0x20, 0x48, 0x03, 0xC7, 0x48, 0x63, 0x08, 0x4C, 0x39, 0x04, 0x39, 0x74, 0x12, 0x66, 0x90, 
  0x48, 0x63, 0x48, 0x04, 0x48, 0x8D, 0x40, 0x04, 0xFF, 0xC2, 0x4C, 0x39, 0x04, 0x39, 0x75, 0xF0, 
  0x41, 0x8B, 0x4C, 0x39, 0x24, 0x48, 0xB8, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x48, 
  0x03, 0xCF, 0x48, 0x63, 0xD2, 0x4C, 0x0F, 0xBF, 0x04, 0x51, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x41, 
  0x8B, 0x4C, 0x39, 0x1C, 0x48, 0x03, 0xCF, 0x4A, 0x63, 0x1C, 0x81, 0x48, 0x8B, 0xCF, 0x48, 0x03, 
  0xDF, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x61, 0x72, 0x79, 0x41, 0xFF, 
  0xD3, 0x48, 0xB9, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x48, 0xC7, 0x44, 0x24, 0x28, 
  0x6C, 0x6C, 0x00, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0xD0, 
  0x48, 0xB9, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x6F, 
  0x78, 0x41, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x8B, 0xC8, 
  0xFF, 0xD3, 0x48, 0xB9, 0x48, 0x61, 0x73, 0x74, 0x61, 0x20, 0x6C, 0x61, 0x4C, 0x8D, 0x44, 0x24, 
  0x2F, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0xB9, 0x20, 0x76, 0x69, 
  0x73, 0x74, 0x61, 0x21, 0x00, 0x45, 0x33, 0xC9, 0x48, 0x89, 0x4C, 0x24, 0x28, 0x33, 0xC9, 0xFF, 
  0xD0, 0x48, 0xB8, 0x45, 0x78, 0x69, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x48, 0xC7, 0x44, 0x24, 0x28, 
  0x65, 0x73, 0x73, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0x8B, 
  0xCF, 0xFF, 0xD3, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48, 
  0x83, 0xC4, 0x30, 0x5F, 0xC3

More Repositories

1

hypersonic-rle-kit

The fastest Run-Length-Encoding on the Planet (for x64)
C
29
star
2

silverpp

A lightweight dynamic user mode profiler for Windows x64
C++
11
star
3

zydec

An instruction-level Decompiler for x64
C++
10
star
4

hypersonic-rANS

Some of the fastest decoding range-based Asymetric Numeral Systems (rANS) codecs for x64
C++
10
star
5

execution-flow

A CPU-performance analysis tool based on LLVM, retrieving simulated per-instruction resource utilization over multiple iterations
C++
6
star
6

slapcodec2D

A simple YUV420 video codec optimized for single threaded decoding performance for Windows x64
C
5
star
7

llscript

Custom Language intended for Shellcode Injection and Low-Level / Embedded Scenarios
C#
5
star
8

admin

Runs a console command as administrator - just like sudo on linux
C#
5
star
9

range_tree

2d range tree with fractional cascading
C++
4
star
10

LamestWebserver

A lightweight C# Webserver & Web Application Framework
C#
4
star
11

slapcodec

A 3D video codec optimized for decoding performance on Windows x64
C
4
star
12

simd_dct

Fast SIMD DCT with Options for Partial Reordering / Stereo Interleaving by DCT Component to improve RLE compression
C++
3
star
13

lemontree

A small telemetry collection and evaluation framework for C/C++
C++
3
star
14

mediaLib

A general purpose C/C++ library for Windows x64.
C++
3
star
15

optim8-web

Website for optim8 performance analysis platform
JavaScript
3
star
16

limg

An experimental image codec based on linear factor decomposition
C++
3
star
17

swapcodec

A low level implementation of a slapcodec-style 3D high performance video codec for Windows x64
C
2
star
18

console_addons

A collection of helpful command line applications
C#
2
star
19

rans_opencl

Basic OpenCL decoder for rans_static_32x16 (encoded by https://github.com/jkbonfield/rans_static)
C
2
star
20

sformat

An easily-integrable, extendable, typesafe, UTF-8 compliant, non-copyleft string formatter for C++17
C++
2
star
21

weboptsrv

optim8 server
C++
2
star
22

rle_samples

Samples for Testing RLE Codecs
2
star
23

ook

A simple, fast, dynamically recursive Sudoku Solver
C++
2
star
24

premakeBuild

Premake executable (See https://premake.github.io/)
1
star
25

rotate_equirectangular

Equirectangular Rotation GLSL Fragment Shader
GLSL
1
star
26

codeless

A tiny programming language that executes 0 byte files.
C#
1
star
27

bootsector

Simple x86 Bootsector Example
Assembly
1
star
28

gtestBuild

gtest Windows x64 static library & includes
C++
1
star
29

VolumeTrace

nothing.
C
1
star
30

glewBuild

glew Windows x64 static library & includes
C
1
star
31

blah

A weird programming language
C#
1
star
32

DBFiller

FillsDBWithSickPeople
C#
1
star
33

update

revert to or update from another directory
C#
1
star
34

SDL2build

SDL2 Windows x64 binaries & includes
C
1
star
35

TODO

A task tracking web application
C#
1
star
36

findpaths

Recursive Direction Flood Fill based Path Finder
C
1
star
37

RTSJam

C#
1
star
38

MultiJsonExtract

Small Tool to extract specific Parameters from JSON files to CSV
C#
1
star
39

rainerzufalldererste

Profile README, yay!
1
star
40

utf8procBuild

utf8proc Windows x64 static library & includes
C
1
star
41

ffmpeg-frames

A tool to transcode single channel 3D YUV420 video to slap using ffmpeg & slapcodec
C
1
star
42

render-portfolio

Portfolio of recent Rendering, 3D, Simulation and Video Game things
HTML
1
star