Cookie Consent by Free Privacy Policy Generator Let's Analyze: Dridex (Part 2)
Paypal Spenden für Projekt | Google Playstore Download Button für Team IT Security

Theme Auswahl



➠ Let's Analyze: Dridex (Part 2)

In the previous article we went over how to dump the names of the majority of functions dridex resolves dynamically to complicate analysis. Today we will be using some similar methods to get the other main piece of the puzzle (encrypted string).

Encrypted Strings

As we've already got a nice list of functions called, we can look for those involved in string operations such as MultiByteToWideChar or CompareStringA in order to find encrypted strings. I went with CompareStringA as it takes two input strings so there's a better chance of finding one that's recently been decrypted.

I got lucky and the first call to CompareStringA I looked at appeared to be a wrapper function that the bot implements for easy string comparison (taking both strings as input parameters). 
A simple string comparison function

By right clicking on the function and selecting "jump to xrefs to", we can just pick one at random and trace back each of the two string arguments and see if any start off as encrypted. 


This one is promising because var_24 (the second parameter to our CompareString function) is a stack variable which is not written to at any point during the function, the only reference is the lea eax, [var_24] in the excerpt above (so it must be written somewhere in sub_40C47C). Even more promising is the fact that right above the lea operation is a mov operation which moves a pointer to some non ASCII data into edx (looks encrypted); the assumption here is that the function sub_40C47C decrypts the data in the pointer stored in edx into the one stored in eax; but is that assumption correct?


Without going overboard with screenshots, I can tell you that the empty stack variable in eax is moved into ebx which is stored and restored by all functions called from inside sub_40C47 (that is, it doesn't change at any point during the function until the end where its' value is moved into eax and the original register is restored). If all assumptions and facts remain correct, we can put a breakpoint at the end of the function and eax should be a pointer to a string.
 Whoever said assumptions get you nowhere?

If you're not familiar with WinDbg the command "da poi(eax)" breaks down to "da" (display as ascii) "poi(eax)" (the address pointed to by the value in eax). Which should be (and is) our decrypted string! 

Dridex actually uses both ASCII and Unicode strings but the function we have found only deals with ASCII, we could go back and look for a Unicode function called like CompareStringW then repeat the previous process, or we could do a binary search (ALT + B) of the function and hope to get another that looks similar. I liked the look of that "push 2800h; mov ebp, edx" so I grabbed the bytes using the WinDbg command "u 0x0040c485 L2" and entered them into the binary search (make sure to check find all occurrences).


Again, for those unfamiliar with WinDbg "u <address>" disassembles an  address and "L2" tells the disassembler to only dissemble two instructions.



After a quick binary search we are presented with two identical functions (the one we've already found and another, the unicode version.), it's almost too easy. All that's left is to write a script similar to the one in the previous article and dump the encrypted string + the address the decrypter was called from.
import idc
import idautils
import idaapi

strings_info = []

def DumpStrings():
for string in strings_info:
print("%s at 0x%X" % (string[1], string[0]))

def BreakpointHandler(dec_string):
call_loc = PrevHead(Dword(GetRegValue("ESP")), 0)
string_info = (call_loc, dec_string)

if string_info not in strings_info:
strings_info.append(string_info)
print("Got string: %s @ %x" % (dec_string, call_loc))

def BreakpointHandlerAscii():
dec_string = GetString(Dword(GetRegValue("EAX")), -1, ASCSTR_C)
BreakpointHandler(dec_string)

def BreakpointHandlerUnicode():
dec_string = GetString(Dword(GetRegValue("EAX")), -1, ASCSTR_UNICODE)
BreakpointHandler(dec_string)

def main():
func_ascii = 0x0040C4A9 #Last byte of the ascii function
func_unicode = 0x0040F1C9 #Last byte of the unicode decrypted function

#Lets us use python functions for breakpoint conditions
RunPlugin("python", 3)

AddBpt(func_ascii)
SetBptCnd(func_ascii, "BreakpointHandlerAscii()")
print("Breakpoint at: %x" % func_ascii)

AddBpt(func_unicode)
SetBptCnd(func_unicode, "BreakpointHandlerUnicode()")
print("Breakpoint at: %x" % func_unicode)

if __name__ == '__main__':
main()

This code is pretty much the same as the previous one, except instead of setting breakpoints on the xrefs to the decryptor function "func_ascii" and "func_unicode" are the address of the last instruction of both function. We get the xref address by doing "PrevHead(Dword(GetRegValue("ESP")), 0)" which gets the return address off the stack and then find the instruction prior to it (the call to the decrypter).

The following snippet creates a tuple containing the decrypted string and thhe address of the call, this is then pushed to an array if it hasn't already which allows us to output call_loc:dec_string combinations we've not already handled; it also allows us to call DumpString() from the python command line to dump all the unique decrypted string combinations.
    string_info = (call_loc, dec_string)

if string_info not in strings_info:
strings_info.append(string_info)
print("Got string: %s @ %x" % (dec_string, call_loc))

Once we've run the script and gotten some data, we might notices that multiple calls came from the same address but decrypted different strings.

To resolve this, lets look back to how the decryption function is called.


There is a number in ecx which could be some kind of id or offset into a block which specifies to the decrypter which string gets returned. The next step would be to find some strings you're interested in, head to the address the call came from, then disassemble it to find out how the target string is determined and where in the call chain it was decided that specific string was needed. Once you've gotten all that information, you can merge some of the code from the last article and this one to comment all the places in which a given string is referenced.

Next we'll start looking at the C&C code, which will require you to have a good handle on how the strings are referenced. I've walked you through the first step and explained what the next step entails, so you should have something to work on while you wait for the next article! Hint: focus on HTTP related strings as the C&C protocol is encrypted XML over HTTPS (you can check you're in the right place by cross-referencing the string with calls to functions which might send data to a remote host).


...


➦ Reverse Engineering ☆ malwaretech.com

➠ Komplette Nachricht lesen


Zur Startseite

Kommentiere zu Let's Analyze: Dridex (Part 2)











➤ Ähnliche Beiträge für 'Let's Analyze: Dridex (Part 2)'

AA19-339A: Dridex Malware

vom 1724.3 Punkte
Original release date: December 5, 2019SummaryThis Alert is the result of recent collaboration between Department of the Treasury Financial Sector Cyber Information Group (CIG) and the Department of the Treasury’s Financial Crimes Enforcement Network (FinCEN

Pure GraphQL OAuth

vom 541.39 Punkte
Before starting, this is my first article in Rust, I try my best to follow best practices, but unlike TypeScript, that I have been using for 3 years at this point. I have only learnt Rust 1 year ago, so my skills are a bit rusty pun intended. Hence, if you ar

Angular Directive Grammar & Microsyntax: Demystifying the Hidden Parts

vom 231 Punkte
Introduction <div *ngFor="let leaf of ['🍀', '🍀🍀', '🍀🍀🍀']; let i = index;"> <p>{{i + 1}}. {{leaf}}</p> </div> 1. 🍀 2. 🍀🍀 3. 🍀🍀🍀 If you've worked with Angular, I'm sure you've com

Mastering Angular Structural Directives - Micro-syntax demystified

vom 222.44 Punkte
In the previous article of this series, we took a closer look at the context object and how we can use it to expose all kinds of data and even functions to our template. Combined with @Input()s and dependency injection, we got a first glimpse of how p

How to build a Barcode Widget in React Native (part II: iOS)

vom 221.45 Punkte
In this tutorial we are going to learn how to build a barcode widget for an iOS device. In the previous part we focused on Android and Java, while in this part we're going to be using Swift. The process will be similar in many ways, except for the br

3D Orbiting Split Images

vom 215.82 Punkte
Just messing around with 3D transforms and splitting images into pieces.. What is a 3d orbiting split images? How do you make a 3d orbiting split images? 3D Orbiting Split Images - HTML Code: <!DOCTYPE html> <html > <head> <me

Recreating the Apple Calculator in Rust using Tauri, Yew and Tailwind

vom 214.58 Punkte
Introduction In this tutorial, we will be rebuilding the Apple calculator using Rust. This project is designed to be a stimulating challenge, providing a hands-on experience with several key technologies: Tauri: An innovative framework for building lightweight

Regular Expressions aka REGEX crash course

vom 203.75 Punkte
Regex aka Regular expressions Regular expressions, also known as "regex", are patterns that help search, match or replace character combinations in strings. They are really powerful and hard to read at the same time. Many developers just decide

Introduction to Code Generation in Rust

vom 201.13 Punkte
This article is about generating Rust code from other Rust code, not for the code generation step of the rustc compiler. Another term for source code generation is metaprogramming, but it will be referred to as code generation here. The reader is expect

Rust Tutorial 4: Let's build a Simple Calculator! (Part 1)

vom 195.54 Punkte
Reading time: 20 minutes Welcome back to the Rust Tutorial Series! In this tutorial, we will be building a simple calculator! On the way, we will learn some more concepts like functions, generics, tuples, arrays, and more! This tutorial will be a 2-parter sinc

Rust Tutorial 4: Let's build a Simple Calculator! (Part 1)

vom 195.54 Punkte
Reading time: 20 minutes Welcome back to the Rust Tutorial Series! In this tutorial, we will be building a simple calculator! On the way, we will learn some more concepts like functions, generics, tuples, arrays, and more! This tutorial will be a 2-parter sinc

Understanding the basics of Smart Pointers in Rust

vom 194.9 Punkte
In today's post we'll delve into the basics of smart pointers in Rust, while we build from scratch a simple linked list - starting from a singly linked list and then evolving to a doubly one. It's not intended to be an introduction about Rust. For that,