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 .

Untitled.jpg

If we skip the decoding routine . We land at OEP which looks something like this.
[Untitled.jpg]

Untitled.jpg

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 .

Untitled.jpg

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 )

Untitled.jpg

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..."

Untitled.jpg

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.

Untitled.jpg

And in the loader stub we will copy all the stack address and push it .

Untitled.jpg

After compiling this nasm file , we will get an exe file as an output with all names and strings visible .
Untitled.jpg

Untitled.jpg

Happy Unpacking

Raashid Bhat

http://twitter.com/raashidbhatt

 
58
Kudos
 
58
Kudos

Now read this

Understanding Neverquest Banking Trojan Polymorphic Engine

Neverquest packer uses polymorphic engine and junk code in its important subroutines. By using polymorphic engine to some extent static signature rules will fail. For example you can see the difference in between two main decoding... Continue →