During the reversing process I found one part of Dyre functionality worthy of a post. As with most banking trojans Dyre contains functionality to hook APIs to log browser traffic. Typically to get the addresses of the APIs the sample will call GetProcAddress or manually traverse the portable executable file format to resolve symbols. If you are unfamiliar with the later technique I'd highly recommend reading section 3.3 of "Understanding Windows Shellcode" by Skape [1]. Dyre attempts to hook APIs in firefox.exe, chrome.exe and iexplorer.exe. It uses the standard GetProcAddress approach for resolving symbols in firefox.exe, is unsuccessful in chrome.exe and uses the GetProcAddress approach for the APIs LoadLibraryExW and CreateProcessInternalW in iexplorer.exe. Dyre hooks two APIs in WinInet.dll but it does it in a unique way. Dyre will read the image header timedatestamp [2] from WinInet. This value contains the time and date from when Wininet was created by the linker during compiling. It will then compare the timedatestamp to a list of timedatestamps stored by Dyre. The list contains presumably every time stamp for WinInet.dll since '2004-08-04 01:53:22' to '2014-07-25 04:04:59'. Below is an example of the values that can be found in the list.
seg000:00A0C05F db 0 seg000:00A0C060 TimeStampList dd 4110941Bh ; DATA XREF: TimeStamp:_loopr seg000:00A0C064 dword_A0C064 dd 0 ; DATA XREF: TimeStamp+1Cr seg000:00A0C064 ; TimeStamp:loc_A07A0Dr ... seg000:00A0C068 dd 411095F2h <- Time stamp seg000:00A0C06C dd 0 <- WinInet index seg000:00A0C070 dd 4110963Fh seg000:00A0C074 dd 0 seg000:00A0C078 dd 4110967Dh seg000:00A0C07C dd 0 seg000:00A0C080 dd 411096D4h seg000:00A0C084 dd 0 seg000:00A0C088 dd 411096DDh seg000:00A0C08C dd 0 seg000:00A0C090 dd 41252C1Bh seg000:00A0C094 dd 0 ..... seg000:00A0C0AC dd 1 seg000:00A0C0B0 dd 435862A0h seg000:00A0C0B4 dd 2 seg000:00A0C0B8 dd 43C2A6A9h seg000:00A0C0BC dd 3 .... seg000:00A0D230 dd 4CE7BA3Fh seg000:00A0D234 dd 78h seg000:00A0D238 dd 53860FB3h seg000:00A0D23C dd 79h seg000:00A0D240 dd 53D22BCBh seg000:00A0D244 dd 7Ah
Values converted to time
>>> datetime.datetime.fromtimestamp(0x411095F2).strftime('%Y-%m-%d %H:%M:%S') '2004-08-04 01:53:22' >>> datetime.datetime.fromtimestamp(0x53D22BCB).strftime('%Y-%m-%d %H:%M:%S') '2014-07-25 04:04:59'
If the timedatestamp is not present or an error occurs Dyre will send the hash of WinInet to the attackers server. If the hash is not found it will send WinInet back to the attackers. Below are some of the strings responsible for displaying errors for the command and control.
'/%s/%s/63/file/%s/%s/%s/' "Check wininet.dll on server failed" "Send wininet.dll failed"
If the timedatestamp is found in the list the next value is used as an index into another list. For example if the timedatestamp was 4802A13Ah it would be found at the 49th entry and the next value would be 0x15 or 21.
Data
seg000:00A0C1E8 dd 4802A13Ah <- '2008-04-13 18:11:38' seg000:00A0C1EC dd 15h <- 21 index
Assembly to read index value
seg000:00A07A0D movsx edx, word ptr ds:TimeStampIndex[eax*8] ; edx = 21 seg000:00A07A15 lea edx, [edx+edx*2] ; edx = 63 seg000:00A07A18 mov edx, ds:offset[edx*4] seg000:00A07A1F mov [ecx], edx ; save off value
Python: calculate offset
Python>hex(0x0A0D3E0 + (21+21* 2) * 4) 0xa0d4dc
Read
seg000:00A0D4DC dw 0F3Ch 0x0f3C offset to inline hook in wininet
The value 0xF3C + the base address of WinInet is the function prologue for ICSecureSocket::Send_Fsm. Dyre uses this to know the address to place it's hooks.
ICSecureSocket::Send_Fsm(CFsm_SecureSend *) 77200F37 90 NOP 77200F38 90 NOP 77200F39 90 NOP 77200F3A 90 NOP 77200F3B 90 NOP 77200F3C - E9 C7F0398A JMP 015A0008 <- Inline hook 015A0008 68 4077A000 PUSH 0A07740 015A000D C3 RETN 00A07740 55 PUSH EBP 00A07741 8BEC MOV EBP,ESP 00A07743 83EC 08 SUB ESP,8 00A07746 894D FC MOV DWORD PTR SS:[EBP-4],ECX 00A07749 68 2077A000 PUSH 0A07720 00A0774E FF75 08 PUSH DWORD PTR SS:[EBP+8] 00A07751 FF75 FC PUSH DWORD PTR SS:[EBP-4] 00A07754 FF15 94DEA000 CALL DWORD PTR DS:[A0DE94] 00A0775A 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
It will also hooks ICSecureSocket::Receive_Fsm in the same fashion.
Closing
Rather than calling
Hash Analyzed 099c36d73cad5f13ec1a89d5958486060977930b8e4d541e4a2f7d92e104cd21
- http://www.nologin.org/Downloads/Papers/win32-shellcode.pdf
- http://msdn.microsoft.com/en-us/library/ms680313.aspx
No comments:
Post a Comment