📚 Let's Analyze: Dridex (Part 2)
💡 Newskategorie: Reverse Engineering
🔗 Quelle: malwaretech.com
Encrypted Strings
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.
Whoever said assumptions get you nowhere? |
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()
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).