Stripping Upatre Trojan Downloader
Upatre is a trojan downloader widely used to download banking botnets . It recently started using compression and XOR encoding . Upatre comes with a custom packer . After unpacking real nasty evil code is revealed . Unpacking Upatre is little bit tricky . Following Blog post will show you how to unpack and rebuild Upatre.
This is what Upatre looks like when you open it up in a debugger .
If we skip the decoding routine . We land at OEP which looks something like this.
[]
Calls like CALL DWORD PRT SS :[EBP + 30] are windows API calls. Before jumping to the OEP all the API call addresses are pushed on to the stack . So building a IAT for this type of packer would be a tricky job .
Tracing API calls. #
For tracing the destination of all these indirect API calls made after OEP , we will parse a trace file . One thing to take care of is the installer and downloader . So we have to trace for both the installer and downloader basic blocks . This can be done by patching some jumps in the file .
A jump is where the installation path is checked with the current path , another is when the original file is set up for deletion .
After running the trace on both the patched and non-patched binaries , we will concatenate the result and get the following result ( only CALL’s are filtered out )
We will log the destination address of these Each API calls . For that purpose we will create an immunity debugger’s pycommand script to log the API calls .
Sample pycommands file to hook at CALL [EBP =- X ] functions
import immlib
from immlib import LogBpHook
dbg = immlib.Debugger()
import struct
class Myhook(LogBpHook):
def init(self):
LogBpHook.init(self)
return
def run(self, regs):
imm = immlib.Debugger()
opc = imm.disasm(regs['EIP'])
CallDis = opc.getDisasm()
imm.log("Disasm = %s" % CallDis[CallDis.find("[") + 5: CallDis.find("]") ])
disp = int(CallDis[CallDis.find("[") + 5: CallDis.find("]") ], 16)
addrx = regs['EBP'] + disp
imm.log("Address = %d" % addrx)
addr = imm.readLong(addrx)
fp = open("addrs.txt", "a")
fp.write(imm.getFunction(addr).getName() +","+ str(regs['EIP'])"\n")
fp.close()
return
def main(args):
bplist = []
fp =open("Calls.txt", "r")
for i in fp:
bplist.append(int(i.split()[0], 16))
fp.close()
logbp = Myhook()
for i in bplist:
funcName = dbg.getFunction(i).getName()
logbp.add(funcName,i)
return "done..."
This script will parse the run trace file and will put a log breakpoint on each function to recode the destination and save it in a file .
Later on we can read the file and name the indirect functions again using a
pycommands script.
import immlib
def main(args):
fp = open("addrs.txt", "r")
dbg = immlib.Debugger()
for line in fp:
addr = int(line.split(",")[1],10)
name = line.split(",")[0]
dbg.setComment(addr, name)
return "Done..."
This script will automatically generate names at the indirect call addresses.
Creating a Loader for dump file #
Upatre OEP code is a position independent code , but it depends on address pushed on the stack after dumping the .text section we can place it inside a PE skeleton and place our loader there .
For a skeleton exe we will use this awesome nasm file :(http://www.phreedom.org/research/tinype/) by Alexander Sotirov.
And in the loader stub we will copy all the stack address and push it .
After compiling this nasm file , we will get an exe file as an output with all names and strings visible .
Happy Unpacking
Raashid Bhat
http://twitter.com/raashidbhatt