Saturday, December 12, 2009

Disabling Strong Naming - A Pirate Method

Note: It should be noted that this is the legit way to get caught. I have only tested this against .Net 3.5 sp1, and only assemblies that are in full trust can be skipped. Patching Strong Naming in mscorlib will get you further than this, without direct fear of being noticed.

Read this:

There are two ways to disable Strong Naming (a pirate way, and a ninja way). The pirate method is by using the built in Strong Naming Tool (sn.exe). The Ninja way is to patch what you need in the mscorlib assembly via Framework injection. Today we will learn to wear an eye patch.
It is possible to, completely or just partially, disable strong name verification for assemblies.

Sn.exe Argument dump for -Vr switch:

-Vr [] []
Register for verification skipping (with an optional, comma
separated list of usernames for which this will take effect and an
optional test public key in ).
can be specified as * to indicate all assemblies or *, to
indicate that all assemblies with the given public key token. Public key
tokens should be specified as a string of hex digits.

While putting your injected GAC assembly files in place and deleting the ngen derivatives, or in your injected method, just hop out and call

sn -Vr *

This will result in a verification skipping entry for all assemblies and all users.

You can, also target a specific assembly by public key token. To disable System.Windows.Forms.dll strong naming verification, you would run (as of .Net 3.5):

sn -Vr *,b77a5c561934e089

So there you have it. Now I am going to test if this works for getting something ngen'd that shouldn't be.

Friday, December 4, 2009

Framework Injection :: Part Two of Two

If you haven't yet, please read lesson one.

Alright, so we have our malicious method's code saved off in a text file malicious.txt. Now we need to generate a complete dump of the victim mscorlib.dll. In order to do this, copy the victim DLL from its GAC location under the \Windows\Assembly\GAC_32\mscorlib\ directory to a temp folder.

Now, if you haven't already, add your SDK location to your PATH environment variable, or just browse to the Microsoft .Net SDK bin folder. If you are running ildasm.exe from the SDK folder directly, remember to modify the location of mscorlib.dll in the following command.

ILDASM / /NOBAR /LINENUM /SOURCE \temp\mscorlib.dll

This will generate a fairly large text file of IL that is mscorlib. Open it and search for the signature line of our victim method. Copy our malicious code over the original code, from the .method to the last '}' bracket. Now, if you got the line renumbering right during lesson one, it will compile back into mscorlib.dll and we can move that back into the GAC. When it loads, the path information is what is used to verify any SN requirements on assembly load.

Compile the modified by running this command (modify this command with the location you wish the output to go):

\Windows\Microsoft.NET\Framework\V2.0.50727\ilasm.exe ILASM /DLL /QUIET /OUTPUT=\temp\maliciousdll\mscorlib.dll

This will generate a suitable malicious replacement for the mscorlib.dll in the GAC.

So copy the mscorlib.dll to the GAC. If you are in a remote shell and the OS is Vista or Win7 and the shell is not running as SYSTEM or builtin\Administrators, you must use the runas.exe command and use a local admin credential set to get this to run.

copy \temp\maliciousdll\mscorlib.dll

You must kill all processes using .Net (the FontCache Service in Vista needs to be stopped, if you get stuck). In Win7, you have to spray and pray on this. I am getting something [a tool] to bypass this together to make it painless.

Alright so now that you have the DLL in the GAC location for the version you are attacking, you must get rid of the ngen registration as well as the actual assemblies. To do this browse to the
C:\WINDOWS\assembly\NativeImages_v2.0.50727_32> .

First, to remove the registration - run the command

ngen uninstall mscorlib

If you are attacking another assembly, just add ' ni' between the filename and extension when running the ngen command.

Search for all files named by running

dir/w/s mscorlib*

Delete those files and their directories. If you are a whitehat and reading this, this is a point you can check - if ngen has no listing for your assembly and / or the directories are gone, it is a pretty good idea you have been infected.

Once you remove all references to the native images, your malicious code will now be ready to run. Execute the Console.Writeline(string) method in a test application and you will see it printed twice. No virus scanner or tool will alert a user that his mscorlib.dll is malicious in any way.

Keep hiding in the noise....


Host Protection and the CLR - How to Bypass It

Since we are in the middle of talking about modifying mscorlib.dll for our own malicious intent, I will tell you guys a little about Host Protection. Host Protection "allows an application hosting the CLR to declare some types of operations off limits for use by hosted code."

Microsoft describes this feature of the CLR as a 'reliability feature', more than a security feature. However 'use specifies definition' and it is used all over the place in mscorlib to restrict untrusted code from executing certain behaviors. Altering it does present a serious reliability issue, but in any case you need to - here is the simple way to remove it.

Fully trusted code will never be disallowed any HostProtectionCategory.

To read more on this subject go to

Take the writline(string):void method from the IL dump of the assembly mscorlib.

.method public hidebysig static void WriteLine(string 'value') cil managed
.permissionset linkcheck
= {class 'System.Security.Permissions.HostProtectionAttribute, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089' = {property bool 'UI' = bool(true)}}
// Code size 12 (0xc)
.maxstack 8
IL_0000: call class System.IO.TextWriter System.Console::get_Out()
IL_0005: ldarg.0
IL_0006: callvirt instance void System.IO.TextWriter::WriteLine(string)
IL_000b: ret
} // end of method Console::WriteLine

This code specifies the HostProtectionCategory 'UI'. If the calling code is not trusted for UI access, the operation fails to run and throws a HostProtectionException.

Simply delete the specified .permissionset opcode and its value, or alter it (this may cause trusted code to be denied if you are changing the boolean operation. coding...

The resultant code will be:

.method public hidebysig static void WriteLine(string 'value') cil managed
// Code size 12 (0xc)
.maxstack 8
IL_0000: call class System.IO.TextWriter System.Console::get_Out()
IL_0005: ldarg.0
IL_0006: callvirt instance void System.IO.TextWriter::WriteLine(string)
IL_000b: ret
} // end of method Console::WriteLine

Now compile mscorlib.dll using ILASM and stick it back into the GAC using a directory filesystem copy to all child directories c:\windows\assembly\gac_32\mscorlib. Remember to unregister the NGen copies of assembly from all of the c:\windows\assembly\nativeimage locations simply run
ngen uninstall mscorlib
Next delete the files from their locations in native images after you unregister them using ngen. Search for in c:\windows\assembly and delete all copies from the appropriate directories.

Now I have not had to alter this attribute just yet for any reason. If someone has any input to contribute on cases where this would be beneficial to violate... Internet Code in the unprotected zone, etc... don't be afraid to post.

Wednesday, December 2, 2009

Framework Injection Part One of Two - How to Patch mscorlib.dll and put it back in the GAC

“ What the F@#$! A rootkit where?!?!”


Microsoft .Net developers have, from the first iterations of the .Net Framework, taken shelter in a solid security ideology about the code they offer. Strong naming, assembly evidence, etc…. basically “Safety through managed code” was the general consensus. However some had their doubts. About 9 months ago, at a small security conference Erez Metula first gave a speech on .Net Framework Rookits, then he gave a revised version at BlackHat 2009.

Having taken a serious look at this for the past year or (Since DC16 ) I have decided to elaborate on his attempts, and make efforts to ensure a hybrid rootkit – one that can use traditional DKOM (Direct Kernel Object Manipulation) and SSDT/IAT patching to help obscure and persist a .Net Framework Rootkit. And then utilize the .Net Framework rootkit to help persist the unmanaged kit. The busiest code will be managed, making heuristics a very hard endeavor to say the least.

This ‘secure’ ideology is brought back down to earth by a key element in Microsoft’s implementation of the Global Assembly Cache. This fatal flaw brings about new vectors as to what you can do in application layered attacks – which is literally anything you want. I am talking undetected, unfettered, and persisted access to user land / kernel land. This enables you to root the box and along with it all business programs built in .Net. All it takes is some free software and you are set to writing your first .Net Framework rootkit.

I hope you can take more away from this than just another tool or paper. The point here is to transfer a basic understanding about what you can do after you exploit when you find yourself in the need to persist access to a system. No special script tool needed, just pay intimate attention to the detail. Please Enjoy.

-blakdayz ^t

Credits: Erez Metula for his BlackHat conference talk on this – way to bring awareness to this glorious fault

5houtz 2 v1ru5, DT, Carric, Queeg, datalus, Pyro, Ed, and Delchi (he throws one Hell of a party), and KingPin… and to the crew of DC225 & 303 … to the rest – much thanks to the beer and entertainment in the Red Stick & Vegas.

The Tools You Require

These are the droids you are looking for (your tools, go… get them… quickly now):

· ProcMon from SysInternals (Free)

· .Net Reflector by RedGate (Free)

· Visual Studio Express (Free)

· .Net Framework 2.0 SDK (Free)

· A text editor

· Ngen (Native Compiler)

All of these tools are free and easily located. Install them.

>Section A: The gist of the Strong Naming bypass that allows this is an extreme .Net Framework weakness
(read on, I will explain)

It seems that the touted reliance on SN (Strong Naming), and the promotion of its assembly integrity verification propaganda were not entirely truthful on Microsoft’s part. While gacutil.exe may look at this evidence when it is copying a dll to the GAC, nothing looks at evidence, or prevents a true file system copy of this Dll to its appropriate location in the GAC file system. For those that are new to the GAC, it resides at c:\windows\assembly location. If you browse to this location in Windows Explorer, you get a .Net representative interface into the file system. If you drag and drop just any DLL there, you will get the expected gacutil Strong Name violations for a non-strong named replacement.

Important Note

If you alter a .Net Framework assembly that is already strong named, it cannot load an assembly that is Strong Named. Doing so would cause lazy-loaded assemblies to fail the manifest checking of the CLR assembly load operations. You may be able to patch this loading process to the point where you can push yourself into DLLs that do depend on Strong Naming, if you first break the Strong Naming mechanism check.

How do you get around the Strong Naming mechanisms in the GAC and .Net? If you were to navigate to the GAC location directly via a command prompt (shell) you would see a completely different picture. Through the shell you can copy our malicious DLL over the one currently cached – without any interference (provided you have install rights to the box).

To get your new malicious code loaded another step is required. You must wipe any image of the victim DLL from the native images location. The native images location contains non-JIT code that is representative of the .Net managed library. This means there is a machine code variant of most .Net Framework DLLs. This optimizes the speed of the .Net Framework assemblies’ code via bypassing the JIT compiler and just running machine code.

To force load the malicious assembly when something requests it, you must delete this optimized dll from the Native Images location that corresponds to the framework dll you are injecting. This will force load the JIT compliant DLL that you have injected into the referencing clients app domain. We will talk more on this subject when we perform the injection of our target code.

Example: A Different Kind of Hello World Example

Browse to your GAC via the shell. Our example will victimize mscorlib.dll.

1. Change your location to the assemblies directory (it’s the filename of the assembly, minus the extension).

2. List the directory. Notice the version of the DLL and the public key token of the DLL form this directory? This is the VERSION_TOKEN. This is where a .Net assembly’s information in the GAC listing is derived from. When these are loaded, no evidence is looked at (normally it’s a native - not managed DLL - that is loaded). When you delete that native DLL, the system auto-magically looks for it in the GAC and loads it, no checking of the Strong Name of the DLL is done. This is a major design flaw that MS is aware of, but lacks the ability to fix (since, as an administrator, you have access to the file system directly).

7. In Reflector, Select File>Open then browse to the location you copied your DLL to. Click the Open button. Now you can expand the namespace mscorlib and browse to the library CommonLanguageRuntime. Browse to the namespace ‘System’, and find Console. Expand Console and right click the Writeline(string) function. Choose Disassemble from the menu.

Opening ILDASM – If you have installed the SDK at this point you can find it in the ‘Program Files\Microsoft.NET\SDK\v2.0\Bin’ location. In IL DASM select File > Open and locate the malicious code DLL. Expand the System tree menu until you find System.Console. Under System.Console find

WriteLine : void(string) . Double click that entry and you should get the ILASM dump of that function. Copy the entire contents of that file into your text editor.

The method’s IL ASM should look like this:

method public hidebysig static void WriteLine(string 'value') cil managed


.permissionset linkcheck

= {class 'System.Security.Permissions.HostProtectionAttribute, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089' = {property bool 'UI' = bool(true)}}

// Code size 12 (0xc)

.maxstack 8

IL_0000: call class System.IO.TextWriter System.Console::get_Out()

IL_0005: ldarg.0

IL_0006: callvirt instance void System.IO.TextWriter::WriteLine(string)

IL_000b: ret

} // end of method Console::WriteLine

Take a look at the line IL_0000 thru IL_0006. This code first selects an output method (stdout) and then calls TextWriter:WriteLine(string). We want this action to occur twice for our example project. Note that there is no .locals directive, and we do not wish to change the value of .maxstack, we just want the already encoded action to occur twice.

Injecting IL ASM Basics

Line Numbering

In regards to those line numbers of the IL dump. They are necessary to get right, because when we recompile they need to be straight. There are shortcuts around some of these steps, but line numbering skill is necessary as the research involved in accomplishing unlocks other nuggets of understanding.

Without using a tool there is a way to know what line comes next and it is based on what IL opcode is getting called on that particular line. You simply add up the number of bytes offset by calling that opcode and your result will be your following line number. This is necessary when we plan on injecting our code into Microsoft’s libraries. To get a good idea of this, look to ECMA 335 Partition III Opcode specification.


A very good example is the following code, taken from the System.Console.WriteLine(string) function IL above:

IL_0000: call class System.IO.TextWriter System.Console::get_Out()

IL_0005: ldarg.0

The first line here with “IL_0000:”. In this line of code, we have the ‘call’ opcode with 4 parameters which are (per the ECMA Specs):

the method to call, and the number, type, and order [implied] of the arguments that have been placed on the stack to be passed to that method, as well as the calling convention to be used”

So that’s four(4) parameters, plus the opcode itself (28 in this case), which is 5 total bytes .So, after the ‘call’ line, the next following line number should be 5 more than the line that contained the ‘call’ opcode. This is the line number offset (a 5 byte offset in the ‘call’ opcode case). When mating this code to another function, we would take a look at the line number immediately before the insertion and, if the preceding opcode was ‘call’, we would add 5 to the line number (in Hex) to get the new line number for our first line of code. This will be shown in an example later.

.maxstack Opcode/Directive

One of the topics where I and the original author of the first whitepaper on this attack differ is the .maxstack directive.. This opcode is a little confusing by its name - as it is not the maximum number of bytes on the stack, nor the number of items. The .maxstack directive helps a tracking tool (like a debugger or profiler) keep track of X amount of objects (if you wanted good debuggable or profilable code, then you would add your new IL maxstack to the value of the victim code and set the total). However, I would not like my malicious code to be compatible with debugging, thank you very much. Leave this alone.

For your reference in any ideological front where you may need to explain yourself, I include this snippet from page 17 of ECMA Partition III Specification:

“[Note: Maxstack is related to analysis of the program, not to the size of the stack at runtime. It does not specify

the maximum size in bytes of a stack frame, but rather the number of items that shall be tracked by an analysis

tool. end note]

[Rationale: By analyzing the CIL stream for any method, it is easy to determine how many items will be

pushed on the CIL Evaluation stack. However, specifying that maximum number ahead of time helps a CIL-tonative-

code compiler (especially a simple one that does only a single pass through the CIL stream) in allocating

internal data structures that model the stack and/or verification algorithm. end rationale]”

Like I said, if you don’t want easy debug analysis of your unfriendly code, leave this alone. If you want to build a debug/profiler enabled version, add your .maxstack value to the injection method’s .maxstack value.

How to Mate Your Code

Some functions are purely static - meaning that they instantiate no locals at all (you won’t need this info), such as in the example project’s Console.WriteLine(string) method. If this is the case with your victim code, but your malicious code has a .locals directive – you must include that .locals directive on the calling code. There is more information regarding locals at the end of the tutorial.

Altering the Assembly

In order to alter the assembly we must take the following steps

1. Renumber the lines via the documentation

2. Fix and remember the locals init order, as well as the stlocals (if required)

The resultant, ready to mate code for doubling the writeline() function would look like the following:

.method public hidebysig static void WriteLine(string 'value') cil managed


.permissionset linkcheck

= {class 'System.Security.Permissions.HostProtectionAttribute, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089' = {property bool 'UI' = bool(true)}}

// Code size 12 (0xc)

.maxstack 8

IL_0000: call class System.IO.TextWriter System.Console::get_Out()

IL_0005: ldarg.0

IL_0006: callvirt instance void System.IO.TextWriter::WriteLine(string)

IL_000b: call class System.IO.TextWriter System.Console::get_Out()

IL_0010: ldarg.0

IL_0015: callvirt instance void System.IO.TextWriter::WriteLine(string)

IL_001b: ret

} // end of method Console::WriteLine

...... Next post will show you how to edit, compile, and move the assembly back into the GAC.