Zberp is a stealthy banking trojan with an unconventional process injection technique. A hybrid of the ZeusVM and Carberp malware, Zberp uses a variety of techniques to prevent detection while it gathers information from infected systems.
Limor Kessem is an executive security advisor for IBM, and she's our guide.
Dave Bittner: [00:00:03] Hello everyone, and welcome to the CyberWire's Research Saturday. I'm Dave Bittner, and this is our weekly conversation with researchers and analysts tracking down threats and vulnerabilities, and solving some of the hard problems of protecting ourselves in a rapidly evolving cyberspace. Thanks for joining us.
Dave Bittner: [00:00:23] I'd like to tell you a little bit about our sponsor, Cybrary, the people who know how to empower your security team. Cybrary is the learning and assessment tool of choice for IT and security teams at today's top companies. They deliver the kind of hands-on training fifty-five percent of enterprises say is the most important qualification when they're hiring. And once you hire, you want to retain. And Cybrary helps there too, because seventy percent of employees say professional development is a big reason for staying on board. Visit www.cybrary.it/teams and see what they can do for your organization. Not only is it effective, it's affordable too, costing just about a twelfth of what legacy approaches to training would set you back. So contact Cybrary for a demo. That's www.cybrary.it/teams, and tell them the CyberWire sent you.
Limor Kessem: [00:01:20] Oh, it actually happened back in 2014, and maybe it's a good place to mention that IBM Security discovered it when it first emerged.
Dave Bittner: [00:01:29] That's Limor Kessem. She's an Executive Security Advisor for IBM Security. What she's referring to is the Zberp Trojan, a stealthy banking Trojan.
Limor Kessem: [00:01:38] So we found it back in 2014, which was apparently a good vintage year for other Trojans, like Dridex and Dyre that emerged at that time as well.
Dave Bittner: [00:01:48] So Zberp has an interesting history. It's sort of a combination of a couple of things. Can you describe that for us?
Limor Kessem: [00:01:54] You know, in the cyber crime arena, we've seen multiple times that codes were leaked and eventually reached the hands of the public, other developers, et cetera. You know, you can sometimes find them on public resources online.
Limor Kessem: [00:02:08] So firstly, the Zeus code was leaked somewhere in 2012, and a lot of different malware stemmed from it. One of those malware codes was called ZeusVM, and that malware was called that way because it would create a virtual machine type thing on the endpoint. That was ZeusVM. Then there was Carberp, which is a completely other malware that eventually got leaked when it's group that was operating it, some of them got arrested.
Limor Kessem: [00:02:37] And then you had these two different codes in the wild and someone apparently picked them up and decided to make a hybrid. And they took ZeusVM, they took Carberp, and he took some of the best of each worlds and put them together.
Dave Bittner: [00:02:51] Take us through, how does Zberp work?
Limor Kessem: [00:02:53] So, Zberp is a banking Trojan of its nature. It's almost like a Swiss army knife, where it's modular. It can bring in different capabilities, it can do code injection, it can do web injections, and other types of things in order to enable itself to commit financial fraud on online banking sites. This is the overall gist of it. What we blogged about in terms of Zberp in our, one of the blogs that we did recently, was how does it do code injection? Because it was more interesting and different.
Dave Bittner: [00:03:30] Well, let's dive into that. Walk us through the code injection.
Limor Kessem: [00:03:34] Let's start with the big picture in the beginning and at the end. So in the beginning, I'll just say code injection is what malware does to grab hold of the endpoint and achieve persistence. It hides inside legitimate processes, and it also lets it perform malicious activity ongoing with, you know, being undetected. So it's a very common malware tactic. So, in general terms, malware will use it in order to run its own code inside the address space of another system process. So it's of course of that nature.
Limor Kessem: [00:04:05] It's one of the ways for security solutions to look for evil activity on the endpoints. It can flag that activity, or block it, and at least know about it. And it can be automated, detection by certain rules and heuristics, because a lot of codes, just like Zberp did, copy from others. So it's even easier for security solutions to detect some of it.
Limor Kessem: [00:04:26] However, not every black hat developer can, or wishes to, reinvent the wheel in that sense. So when they don't, they reuse code. Their malware will probably get detected more easily, and when they do, they make changes. So most of them will use the usual suspects, and the usual suspects is, you know, different API calls and things we're going to discuss in this podcast. And Zberp does use the usual suspects, but not for the entire process. It shuffles in some really interesting things.
Limor Kessem: [00:05:00] So for thinking about, what are the usual suspects in malware, typically they will use APIs, functions. One of them is called "VirtualAllocEx" to allocate space, and WriteProcessMemory in order to kind of prepare room for the processes they're going to write into. These are two APIs which are used the most in code injection cases, because they let the malware write this stuff into a remote process and then run it. So it's like planting someone in a room inside somebody else's home, and then having them do things for you.
Limor Kessem: [00:05:37] There's a third API in this specific method, which is called "CRT", which is CreateRemoteThread, and that's used to execute the payload. So this is like giving it the command to to run the malicious code.
Limor Kessem: [00:05:49] Another very popular tactic is process hollowing, where the malware actually hollows out the existing process' code from the memory space, and it replaces it and operates it with its own malicious code. So that's like replacing somebody in the home, like literally just taking them out and putting the bad stuff in.
Limor Kessem: [00:06:05] And these methods are heavily monitored by security solutions. So malware developers who don't want to get detected will try not to use them. But we do see them still in older codes that are being reused, et cetera. So it gives us some initial context here, as to why we would research and write a blog about the code injection of the Zberp Trojan. After all, it's not new malware, and it's a hybrid of existing other older malware like ZeusVM and Carberp, and have been around for a while.
Limor Kessem: [00:06:34] So, why did we think it was such a good idea to talk about in 2017? So there are two reasons. The obvious one is that the injection method is interesting, different, and it has not been studied very much. And also this malware has been around since 2014, but really keeping itself under the radar and using limited campaigns, making its detection even less likely. And its operators are trying not to attract very much attention from law enforcement, let's say, comparing to gangs like Dridex or Gozi, and those kind of gangs.
Limor Kessem: [00:07:08] So at this point we say, okay, Zberp obviously doesn't use all the usual APIs, so let's see what it does do in order to keep the malicious operations it does secret. So, firstly, it did borrow quite a bit from the Carberp Trojan, like for the code injection. Those developers dispersed after a wave of cyber crime arrests that broke up their gang. They were not known to be a very quiet bunch. They were very involved in underground dealings, and eventually they got busted, but their code was actually pretty good.
Limor Kessem: [00:07:43] So Zberp, as I said, does use some of the usual stuff, it's called Asynchronous Procedure Calls (APC), and the CreateRemoteThread API. That's done in order to force another thread to execute their custom code by attaching it to the APC queue of the targeted thread.
Limor Kessem: [00:08:01] But it has additional tricks, and the additional tricks, their overall idea is to do remote API hooking, which is one of the methods that malware would use in order to make certain functions run its code for it from a remote location, so that it doesn't look like someone else is running the code.
Limor Kessem: [00:08:21] So Zberp remotely sets up a hook on a frequently used API. So it took a very, very common API. In our case, it's called "ZwClose." This function is a generic routine that operates on any type of object. Its job is to close an object handle after all the handles associated with it are no longer needed. So it's very commonly used by the OS. It does not raise any special suspicion, because it's used so much that if you try to zero in on it, it'll just be noise.
Limor Kessem: [00:08:53] So they chose that specific function, and they use it so that whenever this API is called from any thread in the targeted process, it's selected beforehand because it has to, in the previous CRT phase, actually select which process it wants to go to and invade.
Limor Kessem: [00:09:10] And then, what they do here is a detour. The hook detours the execution to the malware's shellcode function. In other words, when it tries to call it, instead of the actual API responding, there is shellcode that's going to get involved here. The shellcode is going to create a new local thread within that ZwClose process.
Limor Kessem: [00:09:32] And this just, you know, would sound, okay well yeah, this is just shellcode is going to do some malicious stuff, sounds simple. But it's actually not that easy to implement because it can cause conflicts in the way the operating system works, and if it does that then the malware's going to get detected, there's going to be all kinds of trouble.
Dave Bittner: [00:09:50] Right.
Limor Kessem: [00:09:51] So doing this kind of a detour can mean that two different threads, the malware thread and the original thread, are both working at the same time to modify the hook on the same function. And that can cause a crash, which will terminate the malware's ability to deploy, and will also draw suspicion, because malware doesn't want the user to go looking for what's wrong, or go clean up their machine.
Dave Bittner: [00:10:14] Right.
Limor Kessem: [00:10:15] So to avoid this problem, the malware actually has to implement a thread safety-locking mechanism that allows only one thread at a time to modify the code, while the other threads are forced to sleep, to stop working for, you know, a suspended amount of time.
Limor Kessem: [00:10:30] And only after it completes whatever it's doing there, which is called the patching, by the first thread, then all the other threads are finally going to be allowed to resume executing the original ZwClose function. So only after it's done, Zberp will set the lock flag back to 2, so that the sleeping threads can wake up and resume execution of that API after it's already been tampered with.
Limor Kessem: [00:10:57] Another thing they deal with here is access rights. So, this is another part where it's not so simple to do this, because memory pages of the code section in the system dynamic link libraries, the DLLs, they have certain access rights. And in this case, they have "PAGE_EXECUTE_READ" rights.
Limor Kessem: [00:11:17] But here the malware wants to do more than just read, right? It wants to modify, it wants to delete, overwrite whatever it's doing. So they have to adjust the access rights before ever attempting anything, because if they don't do that, there's going to be a rights violation that will be raised. And again there could be a crash and the whole thing of, you know, getting detected, or somebody going to go clean their machine and check what's going on.
Dave Bittner: [00:11:39] Right.
Limor Kessem: [00:11:40] So, the developer solved that. He found a way around it. Firstly, it chose different functions for the procedure to take place. It begins by calculating the size of another DLL, a very major DLL in the system, it's called "Ntdll," and calling the API functions CreateFileMapping and MapViewOfFile. And giving them the rights that are PAGE_EXECUTE_READWRITE. So they don't only read, they can also write stuff.
Limor Kessem: [00:12:10] And from the names of these APIs, CreateFileMapping, you know, they're looking to map address space for what the malware is going to do. And this step creates an empty file-mapping with the size of Ntdll that will be mapped to the malware process' memory space. This is called also a trampoline, which is a loop in the code where the developer can replace the initial part of a defined function code with their own malcode. And upon execution, the function jumps to a hook handler, which explains that word choice. It's like a jump over, that's why it's called a trampoline.
Dave Bittner: [00:12:47] Right.
Limor Kessem: [00:12:47] So why did they make this choice? Well actually, a lot of exploits like using Ntdll as a trampoline, because it's an easy way for user-mode processes to ask for services from the kernel. It's like a double agent-type thing. And many processes, if not all, have to load Ntdll, which makes it more likely for the attacker, if they use this, that they will end up getting an address space that corresponds with their desired opcodes, what they want to achieve. They have more choice.
Limor Kessem: [00:13:18] So, now that the trampoline is set and the file mapping is ready, the malware is ready to actually tamper with the ZwClose, because they already did all the preparation stuff not to get crashed. And the first thing it does is suspend the target process by calling NtSuspendProcess. Makes sense, everything that's NT is more like on the user-mode side. And it then uses ReadProcessMemory to make a replica of the target process' NTDLL, into the file mapping in its own memory space.
Limor Kessem: [00:13:49] So before setting the hook itself, the malware needs to calculate two addresses. The address of ZwClose in the file mapping, so it'll have the address that needs to be patched. And it also needs the address of the shellcode function in the remote process so it'll know where the hoax should point to.
Limor Kessem: [00:14:05] So it says, okay, I'm going to replace stuff here, I need to know where it's coming from and where it's going to. The next thing it does, it does a couple of technical things where it overwrites six bytes of the address of ZwClose in the mapped NTDLL, sets the hook. The first byte is overwritten with the 86-bit assembly code push instruction. The next four bytes are the address of the shellcode function in the remote process, and the last byte is the 86-bit return instruction. So the shellcode address will be pushed onto the stack, and the return instruction will return to it as if it were a return address of a function. So it kind of manipulates things in order to make sure that the hook does everything that they want to do.
Limor Kessem: [00:14:52] There's a final step here to this process. It's called a dynamic DLL replacement, and it's probably the most significant part of this whole runaround of how they use these APIs. After they prepare everything and, you know, their rights and all the memory space and everything, the remote hook can be now placed. In other words, making a remote process run the malware.
Limor Kessem: [00:15:19] But, since the remote process was previously suspended, the malware has to call other functions. One of them is called NtUnmapViewOfSection, with the address of Ntdll in the remote process. And then NtMapViewOfSection to reactivate it, to map the patched Ntdll instead. And that replaces it, and sets a hook on the ZwClose that we started with.
Limor Kessem: [00:15:42] As soon as the hook is set, the malware calls what's called "FlushInstructionCache" API. It's very self-explanatory. Flush instruction, in other words, clean the cache, make sure the code changes take place. And then it calls NtResumeProcess to continue the normal process execution. So, you know, go ahead and run the code.
Limor Kessem: [00:16:05] There are couple other safety nets here. One of those is a memory protection. Obviously, you know, the operating system wants to prevent a process from accessing memory that has not been allocated to it, it's not supposed to do that.
Dave Bittner: [00:16:20] Right.
Limor Kessem: [00:16:20] But this is exactly what the malware wants to do. So it needs to do a couple of things. Zberp manages to bypass that issue, and since the patch was set in the file mapping, and NtMapViewOfSection was called with read and write access rights. Then the replaced Ntdll already has the extra permissions to do whatever it likes, and that eliminates the need to adjust permissions for the memory. You know, they just can use VirtualProtectEx API, and they don't have to use it actually because they already have allocated the proper rights.
Limor Kessem: [00:16:56] The final idea is creating a local thread to the entry point of the malware's copied module. So then, the computer, the OS, is just going to run the malware.
Dave Bittner: [00:17:07] How successful is Zberp at evading detection?
Limor Kessem: [00:17:11] It could be successful with a lot of security solutions that base detection on static rules, and if they're not looking for those specific APIs. Because a lot of times they'll catch most of the APIs, and if they're not looking for these specific ways, then it's probably going to be missed. Combined with the way that the campaigns are not very large, and not attracting a lot of attention, it could be that a lot of security solutions just don't care enough about it in order to create special cases for it.
Dave Bittner: [00:17:45] You said at the outset that a good bit of this code is borrowed, you know, sourced from other places, but they made their own modifications. Do you have any sense for the sophistication of these folks who put this together? You know, comparing the types of things they did on their own versus what they borrowed, how skilled they actually are?
Limor Kessem: [00:18:05] So, I think that overall they're pretty skilled to have taken two pretty sophisticated malware codes and breed them together. It's not an easy task, and especially working with the Carberp code. Carberp was always known to be pretty sophisticated. It has its own stuff that it kind of, I'll call it invented, you know, it has these innovations that it had at the time called the invisible persistence, and and it has this special hooking technique.
Limor Kessem: [00:18:34] Overall, you know, the thing itself is already pretty sophisticated, so the person that developed Zberp didn't actually make a lot of changes at the end. He just found the way to put it together, make it work, and I guess maintain the code so there are no bugs and stuff. But he has not made substantial changes ever since, probably because he didn't need to. I do think that, you know, whoever maintains this sort of code knows his stuff inside and out.
Dave Bittner: [00:19:05] And as you said, this is a banking Trojan, they're going after financial information.
Limor Kessem: [00:19:11] Right. Banking Trojans are very powerful information stealers. Their job is to be spies on the endpoint. They're looking at communication to the Internet. And essentially they can do a lot of things, they can exfiltrate data from the endpoint, they can download other malware into the endpoint.
Limor Kessem: [00:19:30] Banking Trojans specifically are looking for ways to automate fraudulent transactions. So, when somebody goes to their bank's website, if the malware targets that bank, it'll go into action and start making changes to the session, the way the user is seeing it. And because the user is infected, they're going to see a completely different, you know, maybe a completely different bank page, or a different flow of the transaction. And all the while the malware is going to be stealing their access credentials, and the operator is going to try to initiate a transaction from their account to an account that they control, to a mule account.
Dave Bittner: [00:20:07] So, looking at the big picture with the information that you've gathered from Zberp, what are the takeaways for you?
Limor Kessem: [00:20:13] The takeaway here is actually pretty straightforward. Code injection and malware are two inseparable mates. There are always going to be code injection for malware, and since there's so much malware, and so many different developers and researchers that work with malware, we're always going to see new and interesting techniques to achieve the injection itself, and also the stealthy motif there.
Limor Kessem: [00:20:35] So one of the most recent examples that has emerged not long ago, this year actually, called "AtomBombing." And the method itself was discovered by researchers, but not very long after it was adopted by one of the pretty much worst banking Trojans out there, called the Dridex Trojan. So now it uses AtomBombing in order to do its code injection, and it completely renovated what it had before.
Limor Kessem: [00:20:58] Another recent example is Ursnif, or Gozi, third version of this malware, which is a new iteration where we saw the developer took the injection mechanism and modified it in order to evade detection. So he it took it, shuffled the elements to make it look different, and basically probably evades detection in a lot of places that don't know it yet.
Limor Kessem: [00:21:19] So there's always going to be another clever work-around and something new in the injection method that we can study and thwart. And that's the sort of stuff that we look at ongoing in order to protect our customers from these evolving malware codes. There's always going to be something that you have to keep on top of.
Dave Bittner: [00:21:38] Yeah, it's an endless game of cat and mouse, I guess.
Limor Kessem: [00:21:41] In a sense, this kind of stuff, yes. Because attackers are also looking constantly at how to break things, how to go around them, how to stay under the radar. And, in a sense, when it comes to malware, it's hard to kind of say, okay, how can you whack it on the head once and for all. It's a little tricky.
Dave Bittner: [00:22:02] Our thanks to Limor Kessem for joining us. You can read the full report, "Diving Into Zberp's Unconventional Process Injection Technique" on the IBM X-Force Research website, securityintelligence.com.
Dave Bittner: [00:22:15] And thanks again to our sponsor, Cybrary, for making this edition of Research Saturday possible. Visit www.cybrary.it/teams, and see what they can do for your organization.
Dave Bittner: [00:22:27] Don't forget to check out our CyberWire Daily News Brief and podcast, along with interviews, our glossary, and more on our website, thecyberwire.com. The CyberWire Research Saturday is proudly produced in Maryland, out of the startup studios of DataTribe, where they're co-building the next generation of cybersecurity teams and technology. It's produced by Pratt Street Media. The coordinating producer is Jennifer Eiben, editor is John Petrik, technical editor is Chris Russell, executive editor is Peter Kilpe, and I'm Dave Bittner. Thanks for listening.
Copyright © 2020 CyberWire, Inc. All rights reserved. Transcripts are created by the CyberWire Editorial staff. Accuracy may vary. Transcripts can be updated or revised in the future. The authoritative record of this program is the audio record.