MSBuild Inline Task Execution
Attackers abuse the signed MSBuild.exe to compile and run inline C# tasks from a project file, executing code under a trusted developer binary.
MSBuild.exe is the signed, Microsoft-shipped build engine that ships with the .NET Framework and Visual Studio. Its legitimate job is to read a project file (.csproj, .proj, .xml) and execute the build tasks it describes. Because MSBuild can compile and run arbitrary C# defined inline in that project file — through the Microsoft.Build.Tasks.CodeTaskFactory "inline task" feature — it doubles as a fully featured code-execution and compilation engine that lives on disk as a trusted binary.
Attackers favour this because the malicious source never has to be a PE on disk: the payload is plain C# embedded in an XML project file, compiled in memory at build time by a Microsoft-signed process. This bypasses application allow-listing that trusts MSBuild, defeats signature-based AV scanning of the dropped file (it is text), and blends into environments where developer tooling is expected. Analysts encounter it as an MSBuild process loading a .csproj or oddly-named project file from a user-writable path.
How it works
The attacker drops an XML project file containing a UsingTask with an inline Task body, then points MSBuild at it:
MSBuild.exe C:\Users\Public\build.csprojInside build.csproj, a CodeTaskFactory task wraps C# in a <Code Type="Class" Language="cs"> block. At build time MSBuild compiles that snippet and invokes its Execute() method — which is where the shellcode loader or beacon lives. There is no compiler invocation visible on the command line and no second binary: the build engine itself does the compiling.
The recognisable indicators are MSBuild.exe run with a single project-file argument from %TEMP%, %APPDATA%, \Public\, or a Downloads folder, and a project file whose contents reference CodeTaskFactory, Microsoft.Build.Tasks.v4.0.dll, <Code, or P/Invoke strings like VirtualAlloc and CreateThread — none of which belong in a normal build.
Detection & analysis
Static analysis:
- Triage the referenced project file as the real sample: it is XML text. Search it for
CodeTaskFactory,UsingTask,<Code Type=,Language="cs", and inline C# that importskernel32/ntdllor contains base64/hex blobs. Legitimate build files orchestrate compilers and copy outputs; they rarely contain raw P/Invoke shellcode loaders. - Flag project files in user-writable directories, with mismatched extensions (
.xml,.txt,.logthat are actually MSBuild XML), or that are launched standalone rather than as part of a solution build.
Dynamic analysis:
- In a sandbox, watch for
MSBuild.exewriting compiler temp artifacts to%TEMP%and then allocating executable memory, spawning children, or opening outbound sockets. A build engine making C2 connections or injecting into another process is the giveaway. - Inspect the parent/child tree. Benign MSBuild is spawned by
devenv.exe,dotnet.exe, CI agents, orcmd/powershellinside a developer context with a solution. Malicious instances are commonly spawned by Office apps,wscript.exe,mshta.exe, or a phishing-delivered loader, on hosts with no developer footprint.
Detection rule hint:
Alert on Sysmon Event ID 1 where Image ends with \MSBuild.exe AND the command line references a project file outside normal source/build directories (e.g. under \Users\Public\, \AppData\, \Temp\, \Downloads\), OR the parent process is an Office application or script host. Correlate with Event ID 7 (image loaded — Microsoft.Build.Tasks*.dll), Event ID 11 (file create of compiler temp output), and Event ID 3 (network connection) from the same PID to confirm inline-task abuse rather than a real build.