Sha1: 7c0118a02867c5481bbe8b9b228fc9d0f47167b8
Sha256: c89c825c3554d8e1b4bee8096494d8bf08deab3121d104858b5e86ec318ea286
“Trickbot” is not a new malware
but one of the popular banking Trojan that spread through e-mail nowadays. This
malware uses a crypter/packer to hide its code from detection, but upon
manually unpacking it you will see right away a very notable series of jumbled
string (Modified base64) that really give us hint that they are encrypted.
|  | 
| Figure 1. The encoded strings of an unpacked version of Trickbot | 
But
even the encrypted strings are expose on the unpack version of the malware you
cannot directly cross reference the functions that uses the encrypted string, because
Trickbot malware create an index table that contains the VA of each encrypted
string and reference it dynamically using the pointer (DWORD) of each VA
address. Sort of anti-static analysis technique.
|  | 
| Figure 2. There is no xref for the encrypted string | 
The Xref
functions that use the SubDecFunc with some short description:
SubDecFunc – The actual
decryption routine with 2 arguments, the pointer index of encrypted string to
its table that contain the VA’s of the encrypted string and the allocated space
where the decrypted value will be place.
Sub_SetupDecryption – Function That will
call the SubDecFunc. That also has 2 the same arguments.
Sub_DecSetup1, Sub_DecSetup2, Sub_DecSetup3 = Function That can call Sub_SetupDecryption with same number and
arguments values.
And from those 3 Sub_DecSetup*
function there are couple of xref functions that uses it, where the inputting
of the index and the output buffer as arguments of decryption routine take
place. In this type of scenario we need more time to analyze each xref
functions to decrypt all the strings, so it is much better to use scripting
language like python to automate this.
|  | 
| Figure 3. Xref Function using the decryption routine | 
|  | 
| Figure 3.1. decoding flow of this malware | 
Decryption routine:
The structure of the encrypted and the decryption key in the file.
| Figure 4. Encrypted File structure with the decryption routine | 
| Figure 6. Decrpytion Routine | 
A simple explanation of its decryption routine.
1. 
First it will get the
length of the encrypted string.
2. 
The decryption
routine was designed to process 4 encrypted bytes at a time that’s why it needs
to group the string into DWORD. 
3. 
after having a dword
value, it will locate the position of each byte character (index of the byte) on
that DWORD from the decryption key string and that index position will be the
initial key to decrypt the actual value using some shift logical function in
decryption_1.
4. 
If an instance that
the string is not divisible by 4. It will check how many bytes are need to have
a DWORD value during grouping. By using Memset API it will fill the needed
bytes with \x00 or null byte to form DWORD value, then find the index of each
byte and used the decryption_2 to decrypt it.
    limit =
enc_str_len
dec_str = ""
while limit:
if limit >= 4:
dec_bytes = initialized_var(size)
for i in range (0, 4):
index_ptr = locate_index(enc_str[index + i])
dec_bytes[i] = index_ptr
limit -= 4
index = index + i + 1
dec_str = decryption_routine_1(dec_bytes, dec_str)
else:
dec_bytes = initialized_var(size)
for i in range(0, limit):
index_ptr = locate_index(enc_str[index + i])
dec_bytes[i] = index_ptr
limit -= limit
index = index + i + 1
dec_str = decryption_routine_2(dec_bytes, dec_str)
print dec_str
return
dec_str = ""
while limit:
if limit >= 4:
dec_bytes = initialized_var(size)
for i in range (0, 4):
index_ptr = locate_index(enc_str[index + i])
dec_bytes[i] = index_ptr
limit -= 4
index = index + i + 1
dec_str = decryption_routine_1(dec_bytes, dec_str)
else:
dec_bytes = initialized_var(size)
for i in range(0, limit):
index_ptr = locate_index(enc_str[index + i])
dec_bytes[i] = index_ptr
limit -= limit
index = index + i + 1
dec_str = decryption_routine_2(dec_bytes, dec_str)
print dec_str
return
def decryption_routine_1(dec_bytes, dec_str):
al = dec_bytes[1]
cl = dec_bytes[0]
dl = dec_bytes[1]
al = sar(al, 4)
cl = (cl << 2) & 0xFF
al += cl
dec_str += chr(al)
al = dec_bytes[2]
cl = al
cl = sar(cl, 2)
al = (al << 6) & 0xFF
al += dec_bytes[3]
cl &= 0x0f
dl = (dl << 4) & 0xFF
cl ^= dl
dec_str += chr(cl)
dec_str += chr(al)
return dec_str
al = dec_bytes[1]
cl = dec_bytes[0]
dl = dec_bytes[1]
al = sar(al, 4)
cl = (cl << 2) & 0xFF
al += cl
dec_str += chr(al)
al = dec_bytes[2]
cl = al
cl = sar(cl, 2)
al = (al << 6) & 0xFF
al += dec_bytes[3]
cl &= 0x0f
dl = (dl << 4) & 0xFF
cl ^= dl
dec_str += chr(cl)
dec_str += chr(al)
return dec_str
def decryption_routine_2(dec_bytes, dec_str):
al = dec_bytes[1]
cl = dec_bytes[0]
dl = dec_bytes[1]
al = sar(al, 4)
cl = (cl << 2) & 0xFF
al &= 3
al = al + cl
dec_str += chr(al)
al = dec_bytes[2]
cl = al
cl = sar(cl, 2)
cl &= 0x0f
dl = (dl << 4) & 0xff
al = (al << 6) & 0xff
al += dec_bytes[3]
cl ^= dl
dec_str += chr(cl)
dec_str += chr(al)
return dec_str
al = dec_bytes[1]
cl = dec_bytes[0]
dl = dec_bytes[1]
al = sar(al, 4)
cl = (cl << 2) & 0xFF
al &= 3
al = al + cl
dec_str += chr(al)
al = dec_bytes[2]
cl = al
cl = sar(cl, 2)
cl &= 0x0f
dl = (dl << 4) & 0xff
al = (al << 6) & 0xff
al += dec_bytes[3]
cl ^= dl
dec_str += chr(cl)
dec_str += chr(al)
return dec_str
Decrypted string:
Below you can see some notable
decrypted string that may give us some help in analyzing the said malware.
Some of the API/modules
it will parse and use during dynamic execution.
UnloadUserProfile 
LoadUserProfileW  
DestroyEnvironmentBlock 
CreateEnvironmentBlock  
USERENV.dll 
GetAdaptersInfo
IPHLPAPI.dll
NtQueryInformationProcess  
ntdll.dll
PathFindExtensionW
PathRemoveFileSpecW  
PathRemoveBackslashW 
StrStrIW 
PathRenameExtensionW 
PathAddBackslashW 
PathFindFileNameW 
SHLWAPI.dll 
CryptBinaryToStringW 
CryptStringToBinaryW 
CRYPT32.dll 
CoUninitialize 
CoCreateInstance  
ole32.dll
SetSecurityDescriptorDacl  
InitializeSecurityDescriptor  
CopySid  
GetLengthSid
SetEntriesInAclW  
GetSecurityInfo
SetSecurityInfo
SetNamedSecurityInfoW
RegSetValueExW 
RegOpenKeyExW  
RegCloseKey 
RegCreateKeyExW
RevertToSelf
AdjustTokenPrivileges
LookupPrivilegeValueW
CryptGetHashParam 
CryptAcquireContextW 
CryptSetKeyParam  
CryptReleaseContext  
ConvertStringSecurityDescriptorToSecurityDescriptorW  
CryptImportKey 
CryptCreateHash
CryptDecrypt
CryptDestroyHash  
CryptHashData  
CryptDestroyKey
AllocateAndInitializeSid
FreeSid  
OpenProcessToken  
EqualSid 
CreateProcessAsUserW 
DuplicateTokenEx  
LookupAccountSidW 
GetTokenInformation  
GetUserNameW
ADVAPI32.dll
CreateToolhelp32Snapshot
Process32NextW 
Process32FirstW
MultiByteToWideChar  
WideCharToMultiByte  
GetModuleHandleA  
QueryPerformanceCounter 
GetCurrentThreadId
SetUnhandledExceptionFilter
UnhandledExceptionFilter
lstrlenA 
GetCurrentProcessId  
GetSystemTimeAsFileTime 
GetCurrentProcess 
GetVersionExW  
GetVersion  
SetFilePointer 
WriteFile
ReadFile 
CreateFileW 
lstrcmpiW
GetTempFileNameW  
CreateProcessW 
MoveFileExW 
GetTickCount
InitializeCriticalSectionAndSpinCount  
Sleep 
GetFileAttributesW
GetModuleFileNameW
GetStartupInfoW
GetTempPathW
MoveFileW
SetCurrentDirectoryW 
DeleteFileW 
lstrcpyW 
LocalFree
CreateMutexW
ResumeThread
WriteProcessMemory
DuplicateHandle
CreateEventW
GetExitCodeThread 
VirtualAllocEx 
VirtualProtectEx  
TerminateProcess  
ReadProcessMemory 
VirtualFreeEx  
OpenProcess 
CreateRemoteThread
SetEvent 
CreateDirectoryW  
SetFileAttributesW
lstrcmpA 
LoadLibraryA
GetFileTime 
FindNextFileW  
GetSystemInfo  
LockResource
FindClose
GetLastError
lstrcpynW
SetFileTime 
GetModuleHandleW  
LoadResource
FreeLibrary 
FindResourceW  
FindFirstFileW 
GetFullPathNameW  
lstrlenW 
lstrcmpW 
GetComputerNameW  
CreateThread
WTSQueryUserToken 
WTSGetActiveConsoleSessionId  
WTSFreeMemory  
WTSEnumerateSessionsA
wtsapi32 
GetProcAddress 
LoadLibraryW
ExitProcess 
ResetEvent  
CloseHandle 
WaitForSingleObject  
SignalObjectAndWait  
InternetCanonicalizeUrlW
Wininet  
BCryptDestroyKey  
BCryptCloseAlgorithmProvider  
BCryptVerifySignature
BCryptGetProperty 
BCryptImportKeyPair  
BCryptOpenAlgorithmProvider
NCryptFreeObject  
NCryptDeleteKey
NCryptImportKey
NCryptOpenStorageProvider  
Bcrypt.dll  
Ncrypt.dll  
HeapReAlloc 
HeapFree 
GetProcessHeap 
HeapAlloc
kernel32.dll
Some Website
that checks the ip address of the local machine:
ip.anysrc.net  
wtfismyip.com  
myexternalip.com  
icanhazip.com  
api.ipify.org  
ipinfo.io
ipecho.net  
checkip.amazonaws.com
other url
domain:
spam.dnsbl.sorbs.net 
dnsbl-1.uceprotect.net  
b.barracudacentral.org  
cbl.abuseat.org
zen.spamhaus.org  
Registry
entries it used to exclude its drop file from WinDefender anti-virus.
MACHINE\SOFTWARE\Microsoft\Microsoft
Antimalware\Exclusions\Paths 
MACHINE\SOFTWARE\Policies\Microsoft\Windows
Defender\Exclusions\Paths
MACHINE\SOFTWARE\Microsoft\Windows
Defender\Exclusions\Paths
Possible
targeted machine:
x86
x64
Unknown  
Windows 2000
Windows XP  
Windows Server 2003  
Windows Vista  
Windows Server 2008  
Windows 7
Windows Server 2008 R2  
Windows 8
Windows Server 2012  
Windows 8.1 
Windows Server 2012 R2  
Windows 10  
Windows 10 Server
Browser
agent that it may use with its GET and POST traffic:
0.0.0.0  
POST  
GET
Mozilla/5.0 (Windows NT 10.0;
WOW64; rv:59.0) Gecko/20100101 Firefox/59.0
An xml
string that may give us a hint for other stuff it will try to do.
</Command>
</Exec>
</Actions>
</Task>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>false</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>true</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions
Context="Author">
<Exec>
<Command>  
</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByDay>
<DaysInterval>1</DaysInterval>
</ScheduleByDay>
</CalendarTrigger>
</Triggers>
<Principals>
<Principal
id="Author">
<CalendarTrigger>
<Repetition>
<Interval>PT3M</Interval>
<Duration>P1D</Duration>
<StopAtDurationEnd>false</StopAtDurationEnd>
</Repetition>
<StartBoundary>
<?xml version="1.0"
encoding="UTF-16"?>
<Task version="1.2"
xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Version>1.0.1</Version>
<Description>System service
monitor.</Description>
<URI>\Task</URI>
</RegistrationInfo>
<Triggers>
Conclusion:
scripting language is really helpful to automate the analysis and make the Reverse engineering more easier. Analyzing some interesting stuff keeps me improve in Reverse Engineering :) hope you enjoy!!!

 
