Invoking the Target Part 2
We have managed to create a valid input file in XML format
that will be processed by Microsoft.Workflow.Compiler
and used to compile and load our C# code.
Now we must finish the work and figure out how we can achieve
execution of the newly compiled code.
In InternalCompileFromDomBatch we find a check for classes
that extend on the Activity.
Each located class will subsequently be instantiated
to an object through the CreateInstance method
by invoking the default constructor for the class.
This means that the file containing code we provide must
contain a class that inherits from the Activity class
of the System.Workflow.ComponentModel
namespace and must contain the code we want to execute
inside its constructor.
We have now managed to reverse engineer and develop the
required input files to achieve code execution.
There is, however, one missing step.
We determined that Microsoft.Workflow.Compiler
required two arguments:
The second command line argument is only used with the
WriteCompilerOutput method.
Following that call,
dnSpy reveals the following:
The argument is used as a file path,
and content is written to it in XML format.
Since we only care about obtaining code execution,
we can simply pass a random file name
as the second command line argument.
This concludes our analysis
and we now have all the information we need.
In summary, we must craft a file containing C# code,
which implements a class that is inherited from the
Activity class and has a constructor.
The file path must be inserted into the XML document along with
compiler parameters organized in a serialized format.
To create this correctly-serialized XML format, we’ll take advantage
of the SerializeInputToWrapper method in a PowerShell script.
Once the file is generated
we make sure the student user is able to read the file
With everything in place,
we can run the executable with the two input arguments.
The output reveals that that our efforts were successful.
We executed arbitrary C# code.
Excellent!
In this section, we have completed our analysis and
investigation of the chosen assembly and in the process,
created a working AppLocker bypass for managed code.
The downside to this attack is that we must provide both the
XML file and the C# code file on disk, and the C# code file
will be compiled temporarily to disk as well.
Despite these limitations,
this simple code can be applied to any existing C# tradecraft.