JJK96/PIClin
From C, Rust or Zig to binary shellcode compiler based on Mingw gcc. It allows using Win32 APIs and standard libraries without any changes to the sour...
PIClin, short for Position Independent Code Linker. Allows compiling C, Rust or Zig code to shellcode while allowing the use of Win32 APIs without changes to the source code. In addition, strings and other data can be used without special encoding like stack strings.
The Win32 APIs and standard library functions that you use are automatically detected at link time, after which a winlib.c file is generated containing definitions for these functions. Currently only functions in kernel32.dll, ntdll.dll and msvcrt.dll are supported, because these DLLs can reasonably be expected in every process. However, if you need other DLLs, you need to load your required DLL using LoadLibrary, change piclin/winlib.py to include functions from your required DLL and extend win32-db to generate a function definition database for your DLL.
git clone --recurse-submodules https://github.com/jjk96/piclin
cd piclin
pip install -e .
or
make install
Copy settings.example.toml to settings.toml and fill the necessary values.
You can also install a settings file in ~/.config/piclin/settings.toml
piclin compile payload.c
This will compile the payload in the build directory. The resulting files are:
payload.bin: The shellcode.loader.exe: A trivial loader to test the shellcode.The output format is shellcode by default. You can also change the format to PE to generate a PE file that can be executed directly.
piclin compile -f PE payload.c
Ensure that you have a Rust toolchain installed. You can use rustup to install the toolchain.
piclin compile payload.rs
piclin compile -f PE payload.rs
I have to be honest, I have not tested every edge-case and I might have taken some shortcuts here and there. Below follows a list of caveats that I can think of at the moment:
winlib.c) assumes that all used DLLs are already loaded in the process. If your DLL is not loaded, you can load it manually using LoadLibrary. You can also resolve this generally by including the logic for loading missing DLLs from BOF2Shellcode. The reason I did not do that here is that I want to avoid storing unnecessary strings in the shellcode.winlib.c. This might be fixed in the future by including an actual C parser.WinExec, CreateProcessA, ExpandEnvironmentStringsA, VirtualAlloc, VirtualProtect and printf). I'm assuming my code works for any other Windows API function, but I might be wrong. If you encounter anything, it should not be too hard to fix.Mingw headers and libraries. These might have subtle differences with Windows SDK headers. If you run into such issues, you can adapt the win32-db project to use the Windows SDK headers or generate similar JSON output yourself.#![no_std] attribute because that requires manually implementing a panic handler, which results in extra boiler-plate code.Not implemented yet. Test your shellcode before deloyment!
make tests