May 19, 2014

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'])"

")

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

57 Kudos