Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
SILVERPICK — Windows User-Mode Shellcode Development Framework (WUMSDF) | Kitploit
Tools/GitHubGitHub/winterknife/silverpick
ExploitationShellcodeRed TeamingShellcode GenerationPayload Development
GitHubwinterknife/silverpick

SILVERPICK

Windows User-Mode Shellcode Development Framework (WUMSDF)

View Repository
15817192 months agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

SILVERPICK

VERSION

  • v1.1

BRIEF

Project SILVERPICK is a Windows User-Mode Shellcode Development Framework (WUMSDF) whose sole purpose is to empower capability developers to build Position Independent Code (PIC) blobs for Windows x64 using C/C++ in an easy manner so as to reduce the development costs of such an endeavour.

It derives from project WILDBEAST and, as such, leverages:

  1. Visual Studio Code as the code editor
  2. MinGW-w64 toolchain as the compiler toolchain
  3. GNU Make as the build system

SETUP

You may find the setup instructions from here: GCC-Clang-Setup-Windows

Please note that this project is using MSYS2.

FEATURES

Writing shellcode in higher-level programming languages is nothing new, and countless blog posts and research papers have been published on the same since 2010. So, what is new in SILVERPICK?

Well, I am glad that you asked.

SILVERPICK has a nice little bag of tricks hidden up its sleeve, but most of all, this is my take on the subject.

So, without further ado, I present to you my first trick.

TRICK 01

Ever since Matt Graeber popularised writing shellcode in C, most people have been using his 16-byte stack alignment stub written in Assembly language.

While this is not a problem, seeing as how we aren't IKEA, assembly should not be necessary, and indeed it is not.

There exists a GCC Function Attribute that will emit the stack alignment stub for you.

Meet the force_align_arg_pointer function attribute in the form of a helpful ALIGN_STACK macro, which generates the following assembly:

Disassembly of section .init:

<PicEntry>:
	push   rbp
	mov    rbp,rsp
	and    rsp,0xfffffffffffffff0
	sub    rsp,0x20
	call   <PicEntry+0x11>	IMAGE_REL_AMD64_REL32	.text$payload
	leave
	ret

What's the .init section, you ask? Well, that serves as a nice segue into my second trick.

TRICK 02

Matt Graeber might have popularised writing shellcode in C at some point, but really, it was Paul Ungur who revived this black art with Stardust.

Now, Stardust uses a Binutils linker script to control the placement of functions and data into the appropriate PE section in the correct order. This technique itself is derived from Austin Hudson's work, and many people use a variant of his linker scripts.

While linker scripts are great for linker section ordering, if all you need is to place a certain function at the beginning of the code section, they are unnecessary.

Enter the section function attribute with a special section name called .init, which indicates to the linker that the function contains pre-main() runtime initialization code and must be first in the link order.

To this effect, the CODE_BEGIN macro has been created.

TRICK 03

For my third trick, I present to you the STACK_STRING macro.

In C, you can create a stack string (a string that is dynamically built on the stack) by declaring the string literal as an array of ANSI characters:

char charrHelloKitty[] = { 'H', 'e', 'l', 'l', 'o', 'K', 'i', 't', 't', 'y', '\0' };

In C++, you can create a stack string by simply marking a char array as constexpr:

constexpr char charrHelloKitty[]{ "HelloKitty" };

However, both of these techniques are rendered useless in the face of compiler optimizations if the string literals are sufficiently large, unlike our solution, which will work regardless of the string length and the level of compiler optimizations, thanks to some clever C++ template metaprogramming hack courtesy of Can Bölük.

Using this macro is pretty straightforward:

STACK_STRING(sstrText, "an extra long hello world!");
STACK_STRING(sstrCaption, "Demo");

MessageBoxA(nullptr, sstrText.data(), sstrCaption.data(), MB_OK);

This will generate the following assembly:

mov     [rsp+58h+var_23], 61h ; 'a'
mov     [rsp+58h+var_22], 6Eh ; 'n'
mov     [rsp+58h+var_21], 20h ; ' '
mov     [rsp+58h+var_20], 65h ; 'e'
mov     [rsp+58h+var_1F], 78h ; 'x'
mov     [rsp+58h+var_1E], 74h ; 't'
mov     [rsp+58h+var_1D], 72h ; 'r'
mov     [rsp+58h+var_1C], 61h ; 'a'
mov     [rsp+58h+var_1B], 20h ; ' '
mov     [rsp+58h+var_1A], 6Ch ; 'l'
mov     [rsp+58h+var_19], 6Fh ; 'o'
mov     [rsp+58h+var_18], 6Eh ; 'n'
mov     [rsp+58h+var_17], 67h ; 'g'
mov     [rsp+58h+var_16], 20h ; ' '
mov     [rsp+58h+var_15], 68h ; 'h'
mov     [rsp+58h+var_14], 65h ; 'e'
mov     [rsp+58h+var_13], 6Ch ; 'l'
mov     [rsp+58h+var_12], 6Ch ; 'l'
mov     [rsp+58h+var_11], 6Fh ; 'o'
mov     [rsp+58h+var_10], 20h ; ' '
mov     [rsp+58h+var_2F], 0
mov     [rsp+58h+var_F], 77h ; 'w'
mov     [rsp+58h+var_E], 6Fh ; 'o'
mov     [rsp+58h+var_D], 72h ; 'r'
mov     [rsp+58h+var_C], 6Ch ; 'l'
mov     [rsp+58h+var_B], 64h ; 'd'
mov     [rsp+58h+var_A], 21h ; '!'
mov     [rsp+58h+var_33], 44h ; 'D'
mov     [rsp+58h+var_32], 65h ; 'e'
mov     [rsp+58h+var_31], 6Dh ; 'm'
mov     [rsp+58h+var_30], 6Fh ; 'o'

TRICK 04

Speaking of C++, I present to you compile-time string hashing for my fourth trick.

While this is not a novel concept, SILVERPICK offers some improvements over existing public implementations.

Firstly, we use the 64-bit variant of the popular FNV-1a non-cryptographic hash function in order to reduce the probability of a successful hash collision attack.

Secondly, we use a modified parameter for the hash function to defend against precalculated hash table lookups, such as HashDB. Crucially, this does not change the properties of the hash function.

To hash a short string at run time, simply use the HASH_STRING_RUN_TIME macro.

To hash a short string literal at compile time, simply use the HASH_STRING_COMPILE_TIME macro. Compile-time only evaluation is guaranteed via consteval.

TRICK 05

It turns out that you can implement quite a handful of C Runtime Library (CRT) functions using x86 string instructions. So, of course, I had to implement them using a mix of compiler intrinsics and inline assembly.

Do you want to use the msvcrt!memset function in your code? Use the ZERO_MEMORY macro instead, which uses the rep stosb instruction emitted via a compiler intrinsic.

How about the msvcrt!memcpy function or the msvcrt!memmove function, you ask? Meet the COPY_MEMORY macro as a replacement, which uses the rep movsb instruction emitted via a compiler intrinsic.

But what about an alternative to the msvcrt!memcmp function? It turns out that there isn't exactly a compiler intrinsic available to emit the repe cmpsb instruction. So, we write a compare_memory function using inline assembly instead.

Download Tool