Reverse .NET Software IX
Reverse .NET Software IX
Reverse .NET Software IX
Rongchaua
Page 1 of 18
Rongchaua
Introduction It has been a long time since I wrote my 8th article in Reverse .Net Software serie. This serie was written in Vietnamese because at the beginning I did not intend to publish it to internet community. It is just for members in REA group. In this serie I would like to dicuss about the protection ways of .net applications and their weaknesses but the .net protectors and obfuscators changed their methods day by day, the present is not like the past anymore. It gets harder to reverse a .net application than before so I decide to continue my series with this article with hoping that it will helps the others to understand more about .Net Framework and .Net Protectors. First, I would like to send a great thank to TQN. He helped me a lot by giving me much important information that he got during his reversing work. Without his help I can not finish this article, an article about Unpacking .Net Reactor 3.9.8.0. .NET Reactor is a powerful .NET code protection & licensing system which assists developers in protecting their .NET software. Developers are able to protect their software in a safe and simple way now. This way developers can focus more on development than on worrying how to protect their intellectual property. Many reversers around the world had tried to unpack this packer and most of them had done their jobs successfully. The fact is that .Net Reactor is anyway not the powerful packer for .Net. He wrapped the original assembly and unpacked it again in memory. This method will lead, of course, to a security hole that a reverser can easily dump assembly from memory and get it back. The developers of .Net Reactor know about this hole but they can not prevent a reverser from dumping so they tried to modify the memory so that after dumping the memory to file the reverser can not easily start their reverse process because the format of file is now destroyed. A visible result of this anti-dump technique is that the dumped file can not be viewed with .Net Reflector. Therefore after dumping, the reverser must always fix their dump so that the file is exactly constructed again. This terrible job can be executed manually (which causes 100% a nightmare with calculation) or automatically through a tool (for example I wrote a tool .Net Reactor Unpacker to do something like that). I also used this method for 2 years to unpack many packers (for example Themida .Net, Cli Secure) but I really do not like it. It is just so common, it does not tell me at least how the packer works. I just dump the assembly from memory and try to fix the header information to get the original back. It is the work of a PE fixer. However thank to this job now I have a good knowledge about .Net Pe File and write myself a library to parse a .net assembly and use this library in my tools (for example .Net Id). So I would like to introduce in this article a method to unpack .Net Reactor without fixing anything after dumping. That means I will dig deeper to find out how .Net Reactor work and dump the original assembly back which does not need any fixing after that. The version of .Net Reactor which I used is 3.9.8.0 which was
Page 2 of 18
Rongchaua
released on 12-Nov-2008. This new method is only academic. It will help us to understand more about how .Net Reactor works, but it can not be applied to unpack an application packed by .Net Reactor because it is time-consuming. 2 Unpacking with old method Before introducing new method I would like to use the current one which is used around the world (as I know) to unpack .Net Reactor. The target is my typical SampleCrackme which is packed with a demo version of .Net Reactor. You can find it as attachments of this article. I use OllyIce as my debugger. And lets start. Open OllyIce, load the target until it runs. Press Alt M to open Memory Window, right click at the top of window, choose Search and enter the pattern to find Assembly in memory. The pattern can be the Windows name, caption of lable, caption of button or Assembly Version (as suggested by CodeRipper) or something like that.
Scroll up to the beginning of memory section well see the MZ-Word. MZ is for MaZic Word? Oh no, it is the initial of Mark Zbikowski, one of the developers
Page 3 of 18
Rongchaua
of MS-DOS. It indicates that this memory section contains a PE (Portable Executable) file.
If there is a MZ Word at memory section then scroll down slowly through the memory section to see if this section may be the assembly which we want. If not then search next. How do we know that this memory section is what we need? Then use our feeling, the wanted section will contain strings which are related to the assembly, for example name of assembly, caption of windows, name of company which writes the application. The size of section can say something too. With this target, the section which we found above is the right one. Lets dump it to file. I save it under the name _012E0000.exe.
OllyIce finishes his job, turn him off. Open Reflector and load our dump file.
Page 4 of 18
Rongchaua
We know that .Net Reactor destroyed the header of assembly. Such errors are what we are looking for. This is evidence telling us that .Net Reflector has destroyed the metadata so that we can not decompile file anymore after dumping. The .Net Reflector tells us that there is an error at RVA of a metadata element. Use CFF Explorer to open the dump file, go through and we found something wrong with MetaData RVA. It can not be 0x00000000.
Lets fix it. In CFF Explorer, go to Address Converter, search string BSJB, we found it at offset 0x9400, enter this value in textbox offset well get its RVA is 0XA400. Copy this value and paste it to MetaData RVA. This magic number BSJB refers to some of the original developers of the .NET Framework, Brain Harry, Susan Radke-Sproull, Jason Zander and Bill Evans. It seems that Microsoft like to honor their developers by adding their names to the file format. This magic string points to the first entry in the metadata table. Two figure below show result of searching and modify the MetaData RVA.
Page 5 of 18
Rongchaua
Save our modifications and overwrite the original file. Use .Net Reflector to open it and now we got .Net Reflector to work. Reflector can now decompile the assembly. How easy it is! However how does .Net Reactor really work? When did he unpack the assembly to memory? When did he destroy the Metadata header? Well find out in next section.
Page 6 of 18
Rongchaua
The assembly can be view with Reflector. No error with Metadata anymore.
Page 7 of 18
Rongchaua
Unpack with new method To find out more about how .Net Reactor works, we need to debug the .Net Framework, set breakpoint at some important functions and see what happened. To do that we need to make our OllyIce to be able to load with symbol file of .Net Framework which provides much useful information about the functions of a file? The symbol file may be achieved in many ways but I know only one way through WinDbg. If you know more, then please share your way with me. So go to download WinDbg, install it. Open command console, browse to the folder where we installed WinDbg. For example I install it under the folder Programme\Debugging Tools for Windows (x86)
Enter this command symchk /v "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll". It will load the symbol file of mscorwks.dll from Microsoft server. The link to your mscorwks.dll at local computer may vary with mine. So please be sure that you provide the correct link to symchk. If not, symchk can not load the symbol file to our local computer. After execution of symchk, it will give the result back. In my result, symchk did his job successfully. No failed file and one passed/ignored file because I downloaded the symbol for mscorwks before. Symchk just check to find out if there are any updates for this file, he found no update so he just passed. Mscorwks.dll and Mscorjit.dll are two significant DLLs of .net framework. When a assembly is loaded, mscorwks.dll will validate its PE Header, IL format, verify strong name, So we will load its symbol to provide more info to OllyIce so that we can make our debug better.
Page 8 of 18
Rongchaua
We have now the symbol file of mscowks; in next step we must configure our Olly so that he can work with this symbol file. A command plugin for OllyDbg of anonymouse can do this job perfectly. Before using this plugin we need to configure it. Lets add an environment variable _NT_SYMBOL_PATH with the value C:\Windows\Symbols. The value of this environment variable is the path to where symchk saved the symbol file at local computer. This value stands in the result of symchk command
Page 9 of 18
Rongchaua
after execution too. For example, we can find it in the figure above at some first rows.
With this help of this plugin, OllyIce can now work with the symbol file. Open OllyIce, go to Debugging Options, be sure that Make first pause at: System breakpoint and Break on new module (DLL) and all exceptions must be passed
Page 10 of 18
Rongchaua
Open Command line plugin, enter this command loadpdb C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll. This command will load the symbol file into OllyIce and well have more information when debugging mscorwks.dll.
Page 11 of 18
Rongchaua
Press F9 so that OllyIce starts to run SampleCrackme. Everytime when a module loads, OllyIce will stop. Just press F9 until mscorwks is loaded.
It is very beautiful. We have the names of all functions. They are very meaningful. Itll surely help us a lot in reversing .Net application. After going through this list, lets set breakpoint on the function AssemblyNative:LoadImage. It looks so interesting and may bring us much useful information. Press F9 so that OllyIce continues his job until we break at AssemblyNative:LoadImage, right click on ECX register, follow in dump and we see
Page 12 of 18
Rongchaua
A great jump, ECX pointed to an unknown struct. This struct contains an unknown pointer (DWORD), the size of assembly and the complete assembly. We can now easily dump assembly from memory with the exact size (no redundant bytes anymore) and the dumped file can be an original one with the probability up to 90%. However it is not easy to find out when we can get the assembly that we need. As you know, when an assembly is loaded, the .Net framework will load it references so when this breakpoint stops OllyIce, it does not mean that ECX points to the assembly which we want but it can be its references, the loader or something like that. So we must to be sure that ECX points to our wanted assembly. In this example, I packed my Sample Crackme with a demo version of .Net Reactor. Hence a nag reminding me to buy a full version comes always up before my Sample Crackme runs. So I take this nag as a signal telling me that the breakpoint which breaks after this nag will point to my assembly. Or like AS Protect, you can count the number of times that this breakpoint breaks and the last break before the assembly completely runs will lead us to the memory section of the assembly.
After this nag is loaded, OllyIce will break at the breakpoint AssemblyNative:LoadImage again. We have now ECX point to our assembly with size of 0xF000 as shown in figure below.
Page 13 of 18
Rongchaua
Lets dump this memory to file; I use LordPE to do that. At my local computer the address is 0x14B2F8C and size is of course 0xF000.
Lets view the dumped file in Reflector. Oh, we have a correct header. Everything looks beautiful, no crashes, no need to fix any value in header file but where is our IL code? Did .Net Reactor hide it anywhere? Is there any IL Code in file or are they all changed to native code?
Page 14 of 18
Rongchaua
Return to OllyIce windows, browse to the section of IL Code which starts normally at offset 0x1050. We see that the Method Header of each method is destroyed through replacing 4 bytes at the beginning with 0xBDAC0000. You can read more about Method Header (Fat Header/Tiny Header) in the documentation of Microsoft about .Net PE File Format.
.Net Reactor must anywhere restore these bytes back so that CLR can compile the code. A breakpoint at WriteProcessMemory should be a good candidate to find out where .Net Reactor tries to write the original value back.
Page 15 of 18
Rongchaua
Scroll up to 0x12F0000 we see a magic word MZ, scroll down to take a look at whole memory section we see that it may be contain the assembly which we want.
The offset 0x1000 starts usually the MetaData Header of .Net Directory. With the WriteProcessMemory function, .Net Reactor try to write garbage value into this MetaData Header and restore the Method Header of each method back. To stop him to do what he wants, everytime when he tries to modify value from offset 0x1000 to 0x1050 (a usual range for MetaData Header of .net application) , we modify the BytesToWrite to 0 so that he can not write any value to destroy the header and with that way we only allow him to restore the method header back. .Net Reactor will modify the MetaData Header first and hell restore the method header back and at last he will modify the MetaData Header again. So to get our original assembly back, at the first round when he modifies our
Page 16 of 18
Rongchaua
MetaData Header, we modify the BytesToWrite to 0. In the second round when he starts to restore our method header back, we just press F9 to go through. In the last round, when he wants to modify our metadata header again, we have already let him fix all Method Header. We just dump the original assembly back and well get full working file which can be viewed in Reflector. 4 Conclusion We have tried to unpack .Net Reactor with old method and new method. You can realize that the new one is just for studying how .Net Reactor works actually. It can not be applied in reality because for example unpacking a file with more than thousands of method, we can not sit and press F9 until the third round (WriteProcessMemory tries to write at offset 0x1000 to 0x1050 again). However the new method provides us a deeper look about .Net Framework and the way .Net Reactor works. There are a lot of interesting functions of mscorwks.dll which we can set a breakpoint and see what happens. I am looking forward to see other articles showing the art of playing with mscorwks.dll and mscorjit.dll file. Links in article REA http://reaonline.net/index.php .Net Reactor http://www.eziriz.com/ .Net Reflector http://www.red-gate.com/products/reflector/ .Net Reactor Unpacker http://rongchaua.net/tools-mainmenu-36/80-reacfixer .Net PE Library http://rongchaua.net/tools-mainmenu-36/117-net-pe-fileformat-library .Net Id http://rongchaua.net/tools-mainmenu-36/131-net-id Command Line Plugin of anynomouse http://www.openrce.org/downloads/details/206/Modified_CmdLine_Plug-in .Net PE File Format http://download.microsoft.com/download/7/3/3/733AD403-90B2-4064-A81E01035A7FE13C/MS%20Partition%20II.pdf References http://portal.acm.org/citation.cfm?id=579355 The end I wrote this documentation just for storing my thinking flow during reverse process. It is just a notice and I do not intend to write it as an article. Therefore in some section I just discuss main idea and of course it is not completely explained. I hope you can emphatize with me. I do write something wrong please contact to correct me. This artice was written as a reference for member in REA so I would like to present REA members with this one.
Page 17 of 18
Rongchaua
This artice is aimed for education. I am not responsible for the readers activity when the reader use it for their aims.
Rongchaua My Email : [email protected] My Website: www.rongchaua.net If I make a mistake in this article, please correct me. 12.04.2009-13.04.2009
Page 18 of 18