Conference DEFCON 17. Laugh at your viruses! Part 1
  • Transfer
Michael: welcome everyone, I'm Michael Lai, this is Matthew Richard, you can call him Matt or Richard, because he has two names, but that doesn't matter.

Matt: The topic of our conversation today is mocking malware, and this is exactly what we are trying to do.

So, not everyone who writes code does it well, people make a lot of mistakes. And not everyone who uses a virus does it right. There are also people who fail in both of these cases. So sit down comfortably, relax and listen, perhaps this information will be useful to you.

Just in case, we included in the presentation of the actual technical material, so that you at least learn something, if the conversation does not seem funny to you. I note that this is just our opinion, which may not coincide with the opinion of our employers.

Michael: The first story is called "Honey, I have reduced entropy!" She talks about how the author of Silent Banker, a very sophisticated encryption algorithm, forgot to create entropy using PRNG, a pseudo-random number generator. On the slide, you see a snippet of the Zeus code from September 2007, in which PRNG is used to prevent hash-based detection. Generation is the initiation of this global variable called ddTickCount: first, it places it in the EAX register, from where the function is called the first time. Then it is checked whether the value of the function is equal to zero, and if it is not equal, then TickCount is called to generate SEED, that is, to initiate a pseudo-random number, with the command GetTickCount.

We were not surprised when we saw similarities with this code in the binary file of Silent Banker from February 2008. It uses PRNG to generate temporary file names. Here, too, there is the same global variable ddTickCount, which checks whether there is a zero, and if it exists, a pseudo-random number is initiated with the help of GetTickCount. At first, before I saw the msvsrt rand, the pseudo-random number generator used by the rand () function of the Microsoft Windows C Runtime library, I thought that there was a connection between Zeus and Silent Banker, simply based on HEX numbers coded into a binary . But in fact, they were both just statically linked to msvsrt.

Now we get to the recipe for disaster. This is a code snippet from the Silent Banker version of July 2008, released a few months after the February version.

They updated their code and posted a new version of Silent Banker, which was significantly different from what we saw earlier. In this program, PRNG is used to generate an encryption key. Here you no longer see that a global variable named CurrentSeed is checked for equality to zero and, depending on this, a pseudo-random number is generated, in this code it is simply used.

It is possible that somewhere in the binary file, even before this place, the value of this global variable is generated in the form of some type of number. Therefore, I turn to disassembling this code and see if the CurrentSeed value is used elsewhere in the program before it is used in this rand () function. You see that initially dd starts from zero, and we will check cross references to this variable.

In column T, the value w means that there is only one valid operation for this global variable in the entire binary file — this is the rand function itself. I’ll go over these things because I’ve already talked about them at last year’s DefCon. On the slide “Disaster Recipe”, the line “Seed the PRNG”, or “Initiation of a Pseudorandom Number Generator”, is shown in gray to show that the author of Silent Banker did not do this initiation.

The next step is that they generate a 16-byte key, making 1000 system calls to the MyRand () function. Then from a 16-byte key, they generate an 8-byte number — a key using a certain formula.

After that, they generate another 8-byte number to create a secondary key from the first 8-byte number, add an arbitrary value to it from the INI configuration file, and get a tertiary key, which is also an 8-byte number. Finally, they use an arbitrary precision mathematical function to turn an 8-byte key into a 32-byte key.

After that, they encrypt the stolen data such as the user's password using the original 16-byte key. But they do not transfer this 16-byte number with the stolen data to “their” attacker, because sending the key together with the encrypted message is not a good idea. Instead, the author of Silent Banker places a 32-byte number inside the stolen data and sends it to the addressee, who must have a program that converts this number back to a 16-byte original key. However, we do not have this program!

The next slide shows a recipe for how to use this catastrophe with number 1 - the lack of a PRNG generator - in its favor.

Let's start with equating the PRNG value to zero. The next four steps we can automate using the Python script for the debugger, because we have a formula that calculates a 16-byte key, an 8-byte key, the next 8-byte key, and a 32-byte key. This formula is not in C code, but we have it, because we have a copy of the Silent Banker binary file in which it exists.

I'll show you the demo how this Python script works. We have a good scenario: here I have Silent Banker and an independent debugger to which I am attached, as well as Internet Explorer, in which Silent Banker is running. I noted four functions that generate encryption keys. I connect this Python script shown on the previous slide, which I invoke by typing bang keygen. You can see that the debugger simply “loses” these several functions that I want to perform for this demonstration 5 times. But in real life, we performed this action 5,000 times to get a larger set of keys.

On the log panel, you can see that for each iteration of the loop, the primary 16-byte key is output, which is then associated with the 32-byte key. At the same time as the script prints information in the log, a text file is also created on the disk, which includes pairs of 16 and 32 byte related keys. This is just a hexadecimal HEX file, so we can use our Python script to process this file, we also have a directory of logs that we recovered from the stolen command-and-control node.

At the top, you see several certificates of encrypted private keys, and below them are several text files that contain encrypted data. We can simply launch the program and search inside these text files, extracting this 32-byte key and the associated 16-byte original key.

As soon as the program finds a 16-byte key, it decrypts the information contained in it and presents it as a text file. You see this file on the screen, and it is impossible to read it.

But then we have a bunch of readable temporary .tmp files, from where we can get this information and return it to the "legitimate" owners. So all the hard work of protecting information was done by the author of Silent Banker, because they forgot to initiate a pseudo-random number generator.

Now I will show the best part of the above - this is the Silent Banker function, which I called Why_Not_Use_This (Why didn't they use it?).

In fact, inside their own program, they have a GetCursorPos function (determine the position of the cursor) to generate entropy, which can be used to initiate PRNG, and we can check the cross references to this function within the program.

We see that it is used in 10-15 other places in the code. Thus, it turns out that the authors of Silent Banker did not forget to insert a pseudo-random number generator into the program; they simply forgot to start this function in the encryption process using the call operator.

The next slide is called “That that slipped away ...” and it shows how this program should work if the author had not forgotten anything.

The following story, called “DES or non-DES”, is about a malware author who doesn’t even know how to properly use the Windows programming interface or doesn’t know what the maximum DES key size is. As a result, due to the inadmissible size of this key, its trojan is by default used with the logical operator xor.

So, for the CryptDeriveKey API function, the two low bytes of the dwFlags parameter, the flags that set what the resulting URL will look like, determine the size of your encryption key.

So, if the low bytes are 0080, then the encryption key that we request will be a 128-bit RC4 key. It's like shooting yourself in the foot, and I'll show you why.

On the slide, you see a string with the wrong size of the 128-bit dwFlags key - 800000 and the string with the wrong MSCryptoAPI value. I will show you the disassembly of this thing. You see a function called "encryption subsystem initialization": the trojan calls the encrypted context and then creates a container for the MD5 hash, then creates the MD5 hash of the hard-coded password in the binary file and tries to use the output of this hash function to create a 128-bit DES key. However, no key is created at the same time, because there is no such thing as a 128-bit DES key.

If any of these API functions fail, it jumps to that place, which I marked in yellow, and gives a message that the key cannot be obtained. And this place is right here, where it moves the value that is in ebp and at that time is 0, that is, directly to this boolean value bUseMSCryptoAPI.

Let's see what effect it causes during program execution. Follow this element of the code structure to see where else it is used in the program, and how much this artifact of the Trojan behaves differently when the function is true and when the wound is false.

We see that the logical value is checked in the function that I called encrypt data, “data encryption”, and if it is true, then it comes to this block, where DES and CryptEncrypt MSAPI encryption is used.

However, if this value is 0, and as we know, it will always be early zero, the function enters this block, which is xor by default.

I was curious at what point in time the author of the malicious program decided to backup all of this. It was possible that people were pressed on him from above, so he was forced to get rid of the malware, but at the last minute he realized that DES did not work, so he used xor for backup recording. In general, it was quite funny, so the moral of this story - always make backup copies!

The following story is called “What have you done with what?”. I tried to come up with a term describing how Coreflood trojan encryption works, and decided to call it location-dependent encryption. In short, the authors of this Trojan invented a new encryption method. I thought maybe someone had already written an article about it and it should be “google”? Google gave me a link to the US patent site, where someone filed a patent for "location-dependent encryption." This scheme is quite complicated, so it will take a lot of time to study it. Here's how it works: I send you an encrypted message, and in order to decrypt and read it, you need to take a GPS device and go to a point with the latitude and longitude specified by me. Typically, encryption is a trade-off between security and usability, but in this method there is nothing

This is definitely not safe and requires you to go where the sender points to to read the message. Matt joked that if you fight online via email and really want to get rid of someone, send him an encrypted message that he can read somewhere in Iraq and you will no longer have problems with him.

How is this method used in the Coreflood Trojan? The slide shows a snippet of code from which it follows that after the trojan has stolen the user's information, it encrypts it and writes it to disk so that the trojan can later retrieve this information and upload command-and-control to its website.

This function is called SetFilePointer (set file pointer), and its return value is dWord, indicating the offset in the file to which the pointer was set if it was exceeded. Next, the function takes the number of bytes to encrypt nNumberOfBitesToWrite and moves it to the ecx register. It then takes the data pointer to encrypt and moves it to the edx register.

After that, the xor operator is used, which places each byte in the buffer al and ah, which means the low and high bytes returned from SetFilePointer. Thus, the encryption key in this scheme is the offset in the file in which the data exists. This is just amazing!

The next slide is called “How to dump a core dump”. It shows the dumpCore program I wrote, which has just been released. You can download it, there is all the source code. This program will help you if your computer is infected with the Coreflood virus, which for some reason could not get to the command-and-control server to download the stolen data. So you can get these files that he saved on the disk and decrypt them using my program to find out what was stolen from you, for example, if you need to inform the client.

The red frame on the slide circled the logs of the stolen data.

What else is interesting in Coreflood: although it has a rather weak encryption algorithm, it still tries to transfer all the stolen information about the configuration of the victim’s computer, all the targeted information from banks and credit unions, and so on. So another way to take a core dump is called "How to remove a core dump using Wireshark." Wireshark is a program that analyzes Ethernet network traffic, or TCP data traffic.

The next slide shows exactly how Coreflood works. These are dlls that are entered into Explorer and Internet Explorer. They modify the registry, require the application to restart, but do not require a system restart. There are various ways to inject these dlls into the process.

Important for hackers who want to implant the virus imperceptibly is how the virus is introduced into the user's computer: whether the system needs to be rebooted for the effect that the malware had, or for the user to simply restart the application, in this case Explorer.

And now quietly, so that no one can hear!

This is the code that we reconstructed using the reverse engineering method. This shows how Coreflood manually shuts down the explorer in order for the changes to take effect immediately. You are probably familiar with what happens when the explorer exploits on the computer - the taskbar disappears, the windows of all open applications, all the icons on the desktop, and then one by one they start to return to the site.

The authors of Coreflood obviously knew about this, so they placed a system call at a given location to establish the “correct” explorer error mode right before the OpenProcess call.

What does the SetErrorMode function do? It prevents a specific failure of notifications sent to the system, which create a small pop-up window and send an error message that caused the application to terminate. All they did with this error message was to prevent a pop-up window from appearing before the user crashed in Explorer. Tell me what looks more suspicious to the user: a small pop-up window, accompanied by the disappearance of everything that is displayed on the screen, and then reappearing, or the disappearance and appearance of everything without any error message? I hear you say, "both events."

I called the next slide "With arms and legs, but without a head." Coreflood, when loaded as a dll, does not appear in the list of loaded modules. He allocates some memory in the heap and copies himself to this place of the heap - I placed it in the red frame.

Then he deletes his PE header, so if you encounter a computer infected with this trojan, you say: "my next step should be to remove the dump of this executable file and load it into IDA for analysis", but it is very difficult to remove the executable dump, if there is no its PE header. So, when Coreflood calls the virtual alloc, from top to bottom it defines the mem flag, which causes the system to return the highest, not the lowest available address. This allows the trojan to hide the opening / closing of quotes in a higher user-mode memory area among other system dlls. Therefore, I called the following demo "How to make all that is hidden useless."

When you encounter something like Coreflood, which uses stealth, and there are no ready-made tools to work with such viruses, you must create your own.
If you are familiar with unpacking, then using a debugger is common for you. Especially if there is no automatic unpacker, as this is not a common algorithm. In this case, you can use the debugger to go to the original entry point and then dump the trojan using ProcDump or another utility. After that, you can restore the import of the PE file using the Import Reconstructor program, and finally, as a result of all the work you have done, you can get a binary file that you can open and examine.

The following demonstration shows working with a tool that I recently wrote. It is not finished yet and therefore is not publicly available. This is a plugin for the Volatility command line platform, and right now I am connecting to Internet Explorer in a debugger. Since I know where to find Coreflood, I will go straight to it in order not to delay the demonstration. Here it is, hiding in memory at 7FF81000.

We can double click on this line to view the actual HEX data and then see where Coreflood is located. I apologize for the fact that the information on the screen is difficult to read, I was preparing a demonstration on a computer with a higher screen resolution. But you can download this demo and play it on your own computer with the best resolution.

So, I take a memory dump of the system infected with Coreflood, and analyze it with the Volatility command line right now. First, I print a list of processes by which I can determine the process ID of Internet Explorer. Now there is information on the screen that shows that this PID is 1732. Next, I use the Malfind plugin, which searches for virtual address descriptors that contain similar information about how much memory in the debugger contains all of the memory areas allocated to processes. For each allocated memory region, this plugin checks the VAD tags and permissions to see if the executable code is there. If it is there, the plugin tries to disassemble it.

Now you see that there is a certain executable code defined by the corresponding disassembly at 7FF81000. Naturally, the next step is to use a new plug-in called IAT Fix, which proceeds to the PID 1732 Internet Explorer context and indicates the beginning of the memory range where Coreflood is hidden.

This plugin lists all the dlls loaded into Internet Explorer’s memory, along with their base addresses and size, and then analyzes the export table to determine the RBA functions exported from these modules and stores them.

It then disassembles all information, starting with the memory area at 7FF81000, and searches for system calls that lead to any of these exported functions. Thus, it recreates the table of imported addresses even without PE headers. You can see that the result issued by it resembles the result of the work of the Import Reconstructor: there is a module, the first function and each function imported from the modules. The output of this IAT Fix script is not executable, so you can open it in the PE view viewer and then see that the import table has been successfully restored.


Conference DEFCON 17. Laugh at your viruses! Part 2

Thank you for staying with us. Do you like our articles? Want to see more interesting materials? Support us by placing an order or recommending to friends, 30% discount for Habr users on a unique analogue of the entry-level servers that we invented for you: The whole truth about VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps from $ 20 or how to share the server? (Options are available with RAID1 and RAID10, up to 24 cores and up to 40GB DDR4).

VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps until December for free if you pay for a period of six months, you can order here .

Dell R730xd 2 times cheaper? Only we have 2 x Intel Dodeca-Core Xeon E5-2650v4 128GB DDR4 6x480GB SSD 1Gbps 100 TV from $ 249in the Netherlands and the USA! Read about How to build an infrastructure building. class c using servers Dell R730xd E5-2650 v4 worth 9000 euros for a penny?

Also popular now: