1323 lines
45 KiB
Python
1323 lines
45 KiB
Python
# Simple attempt emulate suspicious functions in widewine (4.10.2209.0). Adjust to taste (starting point, logs, etc) and run while project is open.
|
|
#@author Satsuoni
|
|
#@category Deobfuscation
|
|
#@keybinding
|
|
#@menupath
|
|
#@toolbar
|
|
|
|
from binascii import hexlify
|
|
import logging
|
|
from ghidra.app.emulator import EmulatorHelper
|
|
#from ghidra.program.model.symbol import SymbolUtilities
|
|
from ghidra.util.task import ConsoleTaskMonitor
|
|
from ghidra.program.model.pcode import PcodeOp
|
|
from ghidra.program.model.symbol import *
|
|
from ghidra.program.model.pcode import JumpTable
|
|
from java.util import LinkedList, Arrays, ArrayList
|
|
from ghidra.app.cmd.function import CreateFunctionCmd
|
|
from ghidra.app.cmd.disassemble import DisassembleCommand
|
|
from ghidra.program.model.lang import Register
|
|
from ghidra.program.model.lang import OperandType
|
|
from ghidra.program.model.lang import RegisterManager
|
|
import array
|
|
import sys
|
|
logger = logging.getLogger("")
|
|
logger.setLevel(logging.DEBUG)
|
|
handler1=logging.StreamHandler(sys.stdout)
|
|
class WarnFormatter(logging.Formatter):
|
|
err_fmt = "ERROR: %(msg)s"
|
|
warn_fmt = "Warning: %(msg)s"
|
|
dbg_fmt = "DBG: %(module)s: %(lineno)d: %(msg)s"
|
|
info_fmt = "%(msg)s"
|
|
def __init__(self, fmt="%(levelno)s: %(msg)s"):
|
|
logging.Formatter.__init__(self, fmt)
|
|
|
|
def format(self, record):
|
|
# Save the original format configured by the user
|
|
# when the logger formatter was instantiated
|
|
format_orig = self._fmt
|
|
# Replace the original format with one customized by logging level
|
|
if record.levelno == logging.DEBUG:
|
|
self._fmt = WarnFormatter.dbg_fmt
|
|
elif record.levelno == logging.INFO:
|
|
self._fmt = WarnFormatter.info_fmt
|
|
elif record.levelno == logging.ERROR:
|
|
self._fmt = WarnFormatter.err_fmt
|
|
elif record.levelno == logging.WARNING:
|
|
self._fmt = WarnFormatter.warn_fmt
|
|
# Call the original formatter class to do the grunt work
|
|
result = logging.Formatter.format(self, record)
|
|
# Restore the original format configured by the user
|
|
self._fmt = format_orig
|
|
return result
|
|
|
|
formatter = WarnFormatter('%(message)s')
|
|
handler1.setFormatter(formatter)
|
|
handler2=logging.FileHandler("trunlog.log", mode='w', encoding="utf-8")
|
|
handler2.setFormatter(formatter)
|
|
logger.addHandler(handler1)
|
|
logger.addHandler(handler2)
|
|
|
|
def getAddress(offset):
|
|
return currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(offset)
|
|
|
|
def getProgramRegisterList(currentProgram):
|
|
pc = currentProgram.getProgramContext()
|
|
return pc.registers
|
|
def step(emu,monitor):
|
|
success = emu.step(monitor)
|
|
if (success == False):
|
|
lastError = emu.getLastError()
|
|
logger.error("Emulation Error: '{}'".format(lastError))
|
|
return success
|
|
def isCallInstruction(instr):
|
|
if instr is None:
|
|
return False
|
|
flowType = instr.getFlowType()
|
|
if flowType.isCall():
|
|
return True
|
|
return False
|
|
|
|
# 009bc60e heap alloc. No free available or necessary
|
|
class FakeMemory(object):
|
|
def __init__(self,startpoint):
|
|
self.start=startpoint
|
|
self.curpoint=self.start
|
|
def allocate(self,ln):
|
|
rpoint=self.curpoint
|
|
self.curpoint+=ln
|
|
return rpoint
|
|
mem=FakeMemory( 0x000000F02FFF0000)
|
|
|
|
def EmuRet(emu,offs=0):
|
|
pos=emu.readStackValue(0,8,False)
|
|
emu.writeRegister(emu.getPCRegister(), pos)
|
|
stack=emu.readRegister("RSP")
|
|
emu.writeRegister("RSP",stack+8+offs)
|
|
|
|
def OperatorNew(emu):
|
|
bytes=emu.readRegister("RCX")
|
|
ptr=mem.allocate(bytes)
|
|
logger.info("Allocating (new) {} bytes to {:x}".format(bytes,ptr))
|
|
emu.writeRegister("RAX",ptr)
|
|
EmuRet(emu)
|
|
|
|
def HeapAlloc(emu):
|
|
bytes=emu.readRegister("R8")
|
|
logger.info("Allocating {} bytes".format(bytes))
|
|
ptr=mem.allocate(bytes)
|
|
emu.writeRegister("RAX",ptr)
|
|
EmuRet(emu)
|
|
def MFree(emu):
|
|
bt2=emu.readRegister("R8")
|
|
logger.info("Freed something at {:x}".format(bt2))
|
|
emu.writeRegister("RAX",bt2)
|
|
EmuRet(emu)
|
|
|
|
def EnterCriticalSection(emu):
|
|
EmuRet(emu)
|
|
|
|
def TryAcquireSRWLockExclusive(emu):
|
|
emu.writeRegister("RAX",1)
|
|
EmuRet(emu)
|
|
|
|
tlsval=1
|
|
tlsstorage={}
|
|
def TlsAlloc(emu):
|
|
global tlsval
|
|
emu.writeRegister("RAX",tlsval)
|
|
tlsval+=1
|
|
EmuRet(emu)
|
|
def TlsSetValue(emu):
|
|
global tlsval,tlsstorage
|
|
index=emu.readRegister("RCX")
|
|
value=emu.readRegister("RDX")
|
|
tlsstorage[index]=value
|
|
emu.writeRegister("RAX",1)
|
|
EmuRet(emu)
|
|
|
|
def TlsGetValue(emu):
|
|
global tlsval,tlsstorage
|
|
index=emu.readRegister("RCX")
|
|
if index in tlsstorage:
|
|
emu.writeRegister("RAX",tlsstorage[index])
|
|
else:
|
|
emu.writeRegister("RAX",0)
|
|
EmuRet(emu)
|
|
def QueryPerformanceFrequency(emu):
|
|
offs=emu.readRegister("RCX")
|
|
emu.writeMemoryValue(getAddress(offs),8,1000)
|
|
emu.writeRegister("RAX",1)
|
|
EmuRet(emu)
|
|
|
|
def Ret0(emu):
|
|
emu.writeRegister("RAX",0)
|
|
EmuRet(emu)
|
|
def Ret1(emu):
|
|
emu.writeRegister("RAX",1)
|
|
EmuRet(emu)
|
|
def Ret1st(emu):
|
|
emu.writeRegister("RAX",emu.readRegister("RCX"))
|
|
EmuRet(emu)
|
|
time_cnt=0
|
|
def timeGetTime(emu):
|
|
global time_cnt
|
|
emu.writeRegister("RAX",time_cnt)
|
|
time_cnt+=1
|
|
EmuRet(emu)
|
|
|
|
last_error=-20
|
|
def LoadLibrary(emu):
|
|
global last_error
|
|
offs=emu.readRegister("RCX")
|
|
lname=emu.readMemory(getAddress(offs),200)
|
|
logger.info("Load library: {}".format(lname))
|
|
emu.writeRegister("RAX",0)
|
|
last_error=-21
|
|
EmuRet(emu)
|
|
def GetLastError(emu):
|
|
global last_error
|
|
emu.writeRegister("RAX",last_error)
|
|
EmuRet(emu)
|
|
def SetLastError(emu):
|
|
global last_error
|
|
last_error=emu.readRegister("RCX")
|
|
EmuRet(emu)
|
|
|
|
def getptd_noexit(emu):
|
|
global mem
|
|
tiddata=mem.allocate(256) # _tiddata
|
|
emu.writeRegister("RAX",tiddata)
|
|
EmuRet(emu)
|
|
|
|
def findwindowA(emu):
|
|
lpclass=emu.readRegister("RCX")
|
|
lpname=emu.readRegister("RDX")
|
|
logger.info(emu.readNullTerminatedString(getAddress(lpclass),200))
|
|
logger.info(emu.readNullTerminatedString(getAddress(lpname),200))
|
|
emu.writeRegister("RAX",0)
|
|
EmuRet(emu)
|
|
def InitThreadHeader(emu):
|
|
mm=emu.readRegister("RCX")
|
|
logger.info("Init Thread header?")
|
|
emu.writeMemoryValue(getAddress(mm),4,-1)
|
|
EmuRet(emu)
|
|
def InitThreadFooter(emu):
|
|
mm=emu.readRegister("RCX")
|
|
logger.info("Init Thread footer?")
|
|
emu.writeMemoryValue(getAddress(mm),4,-1)
|
|
EmuRet(emu)
|
|
def GetRandom(emu):
|
|
ptr=emu.readRegister("RCX")
|
|
len=emu.readRegister("RDX")
|
|
logger.info("Random... kinda")
|
|
for a in range(len):
|
|
emu.writeMemoryValue(getAddress(ptr),1,0xaf)
|
|
ptr+=1
|
|
emu.writeRegister("RAX",1)
|
|
EmuRet(emu)
|
|
|
|
dict={}
|
|
dict[getAddress(0x009bc60e )]=HeapAlloc
|
|
dict[getAddress(0x009bc1ec )]=EnterCriticalSection
|
|
dict[getAddress(0x009bc61a )]=MFree
|
|
dict[getAddress(0x009bcae2 )]=TlsAlloc
|
|
dict[getAddress(0x009bcb06 )]=TlsSetValue
|
|
dict[getAddress(0x009bcaf8 )]=TlsGetValue
|
|
dict[getAddress(0x009bcb14 )]=TryAcquireSRWLockExclusive
|
|
dict[getAddress(0x009bc8d6 )]=EnterCriticalSection #void
|
|
dict[getAddress(0x009bc874 )]=QueryPerformanceFrequency
|
|
dict[getAddress(0x009bccb6 )]=timeGetTime
|
|
dict[getAddress(0x009bc7f6 )]=LoadLibrary
|
|
dict[getAddress(0x009bc422 )]=GetLastError
|
|
dict[getAddress(0x18052d44c)]=EnterCriticalSection #FlsSetValue
|
|
dict[getAddress(0x009bc7ba )]=EnterCriticalSection #LeaveCriticalSection
|
|
dict[getAddress(0x009bcce8 )]=findwindowA
|
|
dict[getAddress(0x009bc4ae )]=Ret0 #GetModuleHandle
|
|
dict[getAddress(0x009bc4e4 )]=Ret0 #GetProcAddress
|
|
dict[getAddress(0x009bcc80 )]=GetRandom #SystemFunction036
|
|
dict[getAddress(0x009bc81c )]=EnterCriticalSection #OutputDebugString - void
|
|
dict[getAddress(0x009bc392 )]=Ret1 #GetCurrentThreadId
|
|
dict[getAddress(0x009bc100 )]=Ret0 #AcquireSRWLockExclusive
|
|
|
|
dict[getAddress(0x18052cc50)]=getptd_noexit
|
|
dict[getAddress(0x009bca2a )]=SetLastError
|
|
|
|
dict[getAddress(0x180256270)]=Ret0 #GetCurrentDir??
|
|
|
|
dict[getAddress(0x18050f1c0)]=OperatorNew
|
|
|
|
#dict[getAddress(0x180111f45)]=Ret1 #probably a table generator. Very slow, but nothing works after without it
|
|
|
|
dict[getAddress(0x18050f330)]=InitThreadHeader
|
|
dict[getAddress(0x18050f3c8)]=InitThreadFooter
|
|
dict[getAddress(0x180256d10)]=Ret1st
|
|
dict[getAddress(0x18050f580)]=EnterCriticalSection
|
|
|
|
def allocLargeStdstring(emu,len):
|
|
ptr=mem.allocate(24)
|
|
emu.writeMemoryValue(getAddress(ptr+8),8,len)
|
|
emu.writeMemoryValue(getAddress(ptr+16),8,len)
|
|
buf=mem.allocate(len)
|
|
emu.writeMemoryValue(getAddress(ptr),8,buf)
|
|
return ptr
|
|
|
|
|
|
|
|
def HostAllocate(emu):
|
|
bytes=emu.readRegister("RDX")
|
|
logger.info("HostAllocate: {} bytes".format(bytes))
|
|
ptr=mem.allocate(bytes)
|
|
emu.writeRegister("RAX",ptr)
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa01)]=HostAllocate
|
|
|
|
def HostSetTimer(emu):
|
|
delay=emu.readRegister("RDX")
|
|
logger.info("HostSetTimer: {} msec".format(delay))
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa02)]=HostSetTimer
|
|
|
|
def HostGetCurrentWallTime(emu):
|
|
logger.info("HostGetCurrentWallTime")
|
|
emu.writeRegister("XMM0",0)
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa03)]=HostGetCurrentWallTime
|
|
|
|
def HostOnInitialized(emu):
|
|
success=emu.readRegister("EDX")
|
|
logger.info("OnInitialized : maybe?: {}".format(success))
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa04)]=HostOnInitialized
|
|
|
|
|
|
def HostOnResolveKeyStatusPromise(emu):
|
|
prid=emu.readRegister("EDX")
|
|
logger.info("HostOnResolveKeyStatusPromise : {}".format(prid))
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa05)]=HostOnResolveKeyStatusPromise
|
|
|
|
|
|
def HostOnResolveNewSessionPromise(emu):
|
|
prid=emu.readRegister("EDX")
|
|
sesid=emu.readRegister("R8")
|
|
logger.info("OnResolveNewSessionPromise : {} {}".format(prid,sesid))
|
|
EmuRet(emu)
|
|
|
|
dict[getAddress(0x0aa06)]=HostOnResolveNewSessionPromise
|
|
|
|
def HostOnResolvePromise(emu):
|
|
prid=emu.readRegister("EDX")
|
|
logger.info("HostOnResolvePromise : {}".format(prid))
|
|
EmuRet(emu)
|
|
|
|
dict[getAddress(0x0aa07)]=HostOnResolvePromise
|
|
|
|
|
|
def HostOnRejectPromise(emu):
|
|
prid=emu.readRegister("EDX")
|
|
ex=emu.readRegister("R8")
|
|
sc=emu.readRegister("R9")
|
|
logger.info("HostOnRejectPromise : {} Exc: {} sc: {}".format(prid,ex,sc ))
|
|
EmuRet(emu,8)
|
|
|
|
dict[getAddress(0x0aa08)]=HostOnRejectPromise
|
|
|
|
def HostOnSessionMessage(emu):
|
|
saveSnapshot(emu,"OnSessionMessage.gz")
|
|
messSize=emu.readStackValue(0x30,8,False)
|
|
print(messSize)
|
|
messPtr=emu.readStackValue(0x28,8,False)
|
|
mtype=emu.readRegister("R9")
|
|
logger.info("message_type")
|
|
logger.info(mtype)
|
|
mm=emu.readMemory(getAddress(messPtr),int(messSize))
|
|
logger.info("OnSessionMessage {} {} ".format( mtype, mm))
|
|
rmsg=""
|
|
for a in mm:
|
|
if a<0: a=256+a
|
|
rmsg+="{:02X}".format(a)
|
|
logger.info(rmsg)
|
|
raise 999
|
|
EmuRet(emu,8)
|
|
|
|
dict[getAddress(0x0aa09)]=HostOnSessionMessage
|
|
|
|
def HostOnSessionKeysChange(emu):
|
|
logger.info("HostOnSessionKeysChange")
|
|
EmuRet(emu,8)
|
|
|
|
dict[getAddress(0x0aa0a)]=HostOnSessionKeysChange
|
|
|
|
def HostOnExpirationChange(emu):
|
|
logger.info("HostOnExpirationChange")
|
|
EmuRet(emu)
|
|
|
|
dict[getAddress(0x0aa0b)]=HostOnExpirationChange
|
|
|
|
def HostOnSessionClosed(emu):
|
|
logger.info("HostOnSessionClosed")
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa0c)]=HostOnExpirationChange
|
|
|
|
def HostSendPlatformChallenge(emu):
|
|
logger.info("HostSendPlatformChallenge")
|
|
EmuRet(emu)
|
|
|
|
dict[getAddress(0x0aa0d)]=HostSendPlatformChallenge
|
|
|
|
def HostEnableOutputProtection(emu):
|
|
logger.info("HostEnableOutputProtection")
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa0e)]=HostEnableOutputProtection
|
|
|
|
def HostQueryOutputProtectionStatus(emu):
|
|
logger.info("HostQueryOutputProtectionStatus")
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa0f)]=HostQueryOutputProtectionStatus
|
|
def HostOnDeferredInitializationDone(emu):
|
|
logger.info("HostOnDeferredInitializationDone")
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa10)]=HostOnDeferredInitializationDone
|
|
|
|
def HostCreateFileIO(emu):
|
|
logger.info("HostCreateFileIO")
|
|
emu.writeRegister("RAX",0)
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa11)]=HostCreateFileIO
|
|
|
|
def HostRequestStorageId(emu):
|
|
logger.info("HostRequestStorageId")
|
|
EmuRet(emu)
|
|
dict[getAddress(0x0aa12)]=HostRequestStorageId
|
|
|
|
|
|
# create Host structure+vtable
|
|
def allocHost(emu):
|
|
vt_ptr=mem.allocate(8*16)
|
|
ptr=vt_ptr
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa01)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa02)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa03)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa04)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa05)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa06)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa07)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa08)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa09)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa0a)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa0b)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa0c)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa0d)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa0e)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa0f)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa10)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa11)
|
|
ptr+=8
|
|
emu.writeMemoryValue(getAddress(ptr),8,0x0aa12)
|
|
cls=mem.allocate(8)
|
|
emu.writeMemoryValue(getAddress(cls),8,vt_ptr)
|
|
return cls
|
|
def makeHost(emu):
|
|
logger.info("Getting host")
|
|
ptr=allocHost(emu)
|
|
emu.writeRegister("RAX",ptr)
|
|
EmuRet(emu)
|
|
|
|
def isCallOther(instr):
|
|
if instr is None:
|
|
return False
|
|
raw_pcode = instr.getPcode()
|
|
for code in raw_pcode:
|
|
if code.getOpcode()==PcodeOp.CALLOTHER:
|
|
return True
|
|
return False
|
|
def getCallOtherName(instr):
|
|
if instr is None:
|
|
return None
|
|
raw_pcode = instr.getPcode()
|
|
for code in raw_pcode:
|
|
if code.getOpcode()==PcodeOp.CALLOTHER:
|
|
return currentProgram.getLanguage().getUserDefinedOpName(code.getInput(0).getOffset())
|
|
return None
|
|
|
|
|
|
def skip(emu):
|
|
executionAddress = emu.getExecutionAddress()
|
|
instr=getInstructionAt(executionAddress)
|
|
nextInstr=instr.getNext()
|
|
lval = int("0x{}".format(nextInstr.getAddress()), 16)
|
|
emu.writeRegister(emu.getPCRegister(), lval)
|
|
|
|
dict[getAddress(0xf0000)]=makeHost
|
|
initCdm=getAddress(0x180001040)
|
|
|
|
monitor=ConsoleTaskMonitor()
|
|
rspStart=0x000000002FFF0000
|
|
emu=EmulatorHelper(currentProgram)
|
|
startaddr=initCdm#getAddress(0x18017e3b0)
|
|
cur_fun=getFunctionContaining(startaddr)
|
|
mainFunctionEntryLong = int("0x{}".format(cur_fun.getEntryPoint()), 16)
|
|
emu.writeRegister(emu.getPCRegister(), mainFunctionEntryLong)
|
|
emu.writeRegister("RSP", rspStart)
|
|
emu.writeRegister("RBP", 0x000000002FFF0000)
|
|
datstring=allocLargeStdstring(emu,256)
|
|
emu.writeRegister("RDX",datstring)
|
|
|
|
#clearkeys = "org.w3.clearkey"
|
|
import struct
|
|
def readULL(emu,addr):
|
|
dat=emu.readMemory(addr,8)
|
|
cdv=struct.unpack("<Q",dat)[0]
|
|
return cdv
|
|
def get_cptr(emu,string):
|
|
ptr=mem.allocate(len(string)+1)
|
|
emu.writeMemory(getAddress(ptr),string.encode("utf-8"))
|
|
emu.writeMemory(getAddress(ptr+len(string)),b'\0')
|
|
return ptr
|
|
|
|
def listToMem(emu,lst):
|
|
ptr=mem.allocate(len(lst)+1)
|
|
emu.writeMemory(getAddress(ptr),array.array('B',lst).tostring())
|
|
emu.writeMemory(getAddress(ptr+len(lst)),b'\0')
|
|
logger.info("Written memory is: {}".format(emu.readMemory(getAddress(ptr),len(lst))))
|
|
logger.info("Lst is is: {}".format(array.array('B',lst)))
|
|
return ptr
|
|
def EmuPush(emu,val):
|
|
stack=emu.readRegister("RSP")
|
|
stack=stack-8
|
|
emu.writeRegister("RSP",stack)
|
|
emu.writeMemoryValue(getAddress(stack), 8,val)
|
|
def EmuPull(emu,offs):
|
|
stack=emu.readRegister("RSP")
|
|
stack=stack+offs
|
|
emu.writeRegister("RSP",stack)
|
|
# +x30 +x20
|
|
def EmuPush4(emu,val):
|
|
stack=emu.readRegister("RSP")
|
|
stack=stack-4
|
|
emu.writeRegister("RSP",stack)
|
|
emu.writeMemoryValue(getAddress(stack), 4,val)
|
|
def isReturn(instr):
|
|
if instr is None:
|
|
return False
|
|
raw_pcode = instr.getPcode()
|
|
for code in raw_pcode:
|
|
if code.getOpcode()==PcodeOp.RETURN:
|
|
return True
|
|
return False
|
|
|
|
#fill process information blocks with varying garbage
|
|
emu.writeRegister("GS_OFFSET",0x3f000)
|
|
threadinfo=mem.allocate(1024)
|
|
pptr=threadinfo
|
|
#fill with the same struct 128 times
|
|
threaddata=mem.allocate(1024)
|
|
|
|
for a in range(128):
|
|
emu.writeMemoryValue(getAddress(pptr),8,threaddata)
|
|
pptr+=8
|
|
|
|
for a in range(1024):
|
|
emu.writeMemoryValue(getAddress(threaddata+a),1,0xff)
|
|
|
|
|
|
emu.writeMemoryValue(getAddress(0x3f058),8,threadinfo)
|
|
|
|
logger.info("GS: {:x}".format(emu.readRegister("GS_OFFSET")))
|
|
trace=False
|
|
class Operand(object):
|
|
def getVal(self,emu):
|
|
if self.type=="const":
|
|
return self.value
|
|
elif self.type=="register":
|
|
return emu.readRegister(self.value)
|
|
elif self.type=="stackvar":
|
|
return emu.readStackValue(int(self.value,0),self.length,False)
|
|
elif self.type=="memconst":
|
|
return 0 #need implementation?
|
|
def __hash__(self):
|
|
return hash((self.type, self.value))
|
|
def __eq__(self, other):
|
|
return (self.type, self.value) == (other.type, other.value)
|
|
def __ne__(self, other):
|
|
return not(self == other)
|
|
def __init__(self,instr,num):
|
|
self.type="unknown"
|
|
if instr is None:
|
|
return
|
|
if num>=instr.getNumOperands():
|
|
return
|
|
tp=instr.getOperandType(num)
|
|
objlist=instr.getOpObjects(num)
|
|
ln=len(objlist)
|
|
if ln==0:
|
|
return
|
|
if tp&OperandType.SCALAR: #const
|
|
self.type="const"
|
|
self.value=int(str(objlist[0]),16)
|
|
return
|
|
if tp&OperandType.REGISTER and len(objlist)==1: #pure register
|
|
self.type="register"
|
|
self.value=str(objlist[0])
|
|
return
|
|
if len(objlist)==2 and str(objlist[0])=="RSP":
|
|
self.type="stackvar"
|
|
self.value="0x{:x}".format(int(str(objlist[1]),0))
|
|
self.offset=int(str(objlist[1]),0)
|
|
self.len=1
|
|
oprep=instr.getDefaultOperandRepresentation(num)
|
|
if "xword" in oprep:
|
|
self.length=16
|
|
elif "qword" in oprep:
|
|
self.length=8
|
|
elif "dword" in oprep:
|
|
self.length=4
|
|
elif "word ptr" in oprep:
|
|
self.length=2
|
|
elif "byte ptr" in oprep:
|
|
self.length=1
|
|
return
|
|
if len(objlist)==2 and tp&OperandType.DYNAMIC and tp&OperandType.ADDRESS : #dword ptr [RCX + -0x4]
|
|
self.type="memconst"
|
|
self.value=str(objlist[1])
|
|
self.olist=objlist
|
|
return
|
|
if len(objlist)==2 and str(objlist[0])=="GS":
|
|
self.type="debugho"
|
|
self.value="__0x{:x}".format(int(str(objlist[1]),0))
|
|
return
|
|
if len(objlist)==3 and isinstance(objlist[0],Register): #not quite correct, but. uff
|
|
self.type="register"
|
|
self.value=str(objlist[0])
|
|
return
|
|
logger.warning("{} {:x} {} needs operand implementation {}".format(instr,tp,num,objlist))
|
|
|
|
#not sure why only these are missing.
|
|
def pshuflw(emu,instr):
|
|
if instr is None: return
|
|
if instr.getNumOperands()!=3: return
|
|
reg_into=Operand(instr,0)
|
|
reg_from=Operand(instr,1)
|
|
shuf=Operand(instr,2)
|
|
if reg_into.type!="register" or reg_from.type!="register" or shuf.type!="const" :
|
|
raise 33
|
|
fr=emu.readRegister(reg_from.value)
|
|
imm=shuf.value
|
|
to=(fr&0xffffffffffffffff0000000000000000)
|
|
to+=(fr>> (imm&4)*16 )&0xffff
|
|
to+=((fr>> ( (imm>>2) & 4)*16 )&0xffff)<<16
|
|
to+=((fr>> ( (imm>>4) & 4)*16 )&0xffff)<<32
|
|
to+=((fr>> ( (imm>>8) & 4)*16 )&0xffff)<<48
|
|
emu.writeRegister(reg_into.value,to)
|
|
skip(emu)
|
|
def pmovmskb(emu,instr):
|
|
if instr is None: return
|
|
if instr.getNumOperands()!=2: return
|
|
reg_into=Operand(instr,0)
|
|
reg_from=Operand(instr,1)
|
|
if reg_into.type!="register" or reg_from.type!="register":
|
|
raise 34
|
|
fr=emu.readRegister(reg_from.value)
|
|
cnt=1
|
|
val=0
|
|
for bt in range(16):
|
|
idir=int((fr&(1<<(8*cnt-1)))!=0)
|
|
val |= (idir<<bt)
|
|
cnt+=1
|
|
emu.writeRegister(reg_into.value,val)
|
|
skip(emu)
|
|
|
|
def dumpParameters(emu,num):
|
|
pars=[emu.readRegister("RCX"),emu.readRegister("RDX"),emu.readRegister("R8"),emu.readRegister("R9")]
|
|
if num>4:
|
|
co=0x28
|
|
esp=emu.readRegister("ESP")
|
|
for a in range(num-4):
|
|
pars.append(readULL(emu,getAddress(esp+co)))
|
|
co+=8
|
|
for a in range (num):
|
|
logger.info("Param_{}: {:x}".format(a+1,pars[a]))
|
|
|
|
def writeRegister(emu,reg,fl):
|
|
nm=reg.getName()
|
|
ln=reg.getMinimumByteSize()
|
|
if ln >8:
|
|
ln=16
|
|
elif ln>4:
|
|
ln=8
|
|
elif ln >2:
|
|
ln=4
|
|
else:
|
|
ln=2
|
|
fl.write(struct.pack("<H", len(nm)))
|
|
fl.write(nm.encode("ascii"))
|
|
fl.write(struct.pack("<H", ln))
|
|
val=emu.readRegister(nm)
|
|
if ln==16:
|
|
fl.write(struct.pack("<Q", (val>>64)&0xffffffffffffffff ))
|
|
fl.write(struct.pack("<Q", val&0xffffffffffffffff))
|
|
elif ln==8:
|
|
fl.write(struct.pack("<Q", val&0xffffffffffffffff))
|
|
elif ln==4:
|
|
fl.write(struct.pack("<I", val&0xffffffff))
|
|
else:
|
|
fl.write(struct.pack("<H", val&0xffff))
|
|
|
|
def writeMemoryChunk(emu,start,ln,fl):
|
|
fl.write(struct.pack("<Q",start))
|
|
fl.write(struct.pack("<Q",ln))
|
|
if ln>0:
|
|
mbuf=emu.readMemory(getAddress(start),ln)
|
|
fl.write(mbuf)
|
|
|
|
def writeSnapshot(emu,fl):
|
|
global mem, rspStart, currentProgram
|
|
excl=set(["contextreg"])
|
|
br=set([e.getBaseRegister() for e in getProgramRegisterList(currentProgram) if e.getBaseRegister().getName() not in excl])
|
|
rsp=emu.readRegister("RSP")
|
|
fl.write(struct.pack("<I",len(br)))
|
|
for reg in br:
|
|
writeRegister(emu,reg,fl)
|
|
writeMemoryChunk(emu,mem.start,mem.curpoint-mem.start,fl)
|
|
if rsp<=rspStart:
|
|
writeMemoryChunk(emu,rsp,rspStart-rsp+8,fl)
|
|
for blk in currentProgram.getMemory().getBlocks():
|
|
writeMemoryChunk(emu,blk.getStart().getOffset(),blk.getSize(),fl)
|
|
|
|
def readRegister(emu,fl):
|
|
dt=fl.read(2)
|
|
if len(dt)<2: return False
|
|
nmlen=struct.unpack("<H",dt)[0]
|
|
nml=fl.read(nmlen)
|
|
if len(nml)<nmlen: return False
|
|
nm=nml.decode("ascii")
|
|
dt=fl.read(2)
|
|
if len(dt)<2: return False
|
|
ln=struct.unpack("<H",dt)[0]
|
|
if ln==16:
|
|
dt=fl.read(16)
|
|
if len(dt)<16: return False
|
|
vals=struct.unpack("<QQ",dt)
|
|
val=(vals[0]<<64)+vals[1]
|
|
elif ln==8:
|
|
dt=fl.read(8)
|
|
if len(dt)<8: return False
|
|
val=struct.unpack("<Q",dt)[0]
|
|
elif ln==4:
|
|
dt=fl.read(4)
|
|
if len(dt)<4: return False
|
|
val=struct.unpack("<I",dt)[0]
|
|
else:
|
|
dt=fl.read(2)
|
|
if len(dt)<2: return False
|
|
val=struct.unpack("<H",dt)[0]
|
|
if nm!= "contextreg":
|
|
emu.writeRegister(nm,val)
|
|
return True
|
|
def readMemoryChunk(emu,fl,setmem=False):
|
|
#start,ln,
|
|
global mem
|
|
dt=fl.read(8)
|
|
if len(dt)<8: return False
|
|
start=struct.unpack("<Q",dt)[0]
|
|
dt=fl.read(8)
|
|
if len(dt)<8: return False
|
|
ln=struct.unpack("<Q",dt)[0]
|
|
if ln>0:
|
|
dat=fl.read(ln)
|
|
if len(dat)<ln: return False
|
|
emu.writeMemory(getAddress(start),dat)
|
|
if setmem:
|
|
mem.start=start
|
|
mem.curpoint=start+ln
|
|
return True
|
|
def readSnapshot(emu,fl):
|
|
global mem, rspStart
|
|
numreg=struct.unpack("<I",fl.read(4))[0]
|
|
for i in range(numreg):
|
|
if not readRegister(emu,fl):
|
|
logger.warning("Corrupt snapshot: not enough registers")
|
|
return
|
|
mset=True
|
|
while readMemoryChunk(emu,fl,mset):
|
|
mset=False
|
|
|
|
import gzip
|
|
import os
|
|
basedir="./"
|
|
def saveSnapshot(emu,name):
|
|
global basedir
|
|
fname=os.path.join(basedir,name)
|
|
with gzip.open(fname, 'wb',compresslevel=8) as f:
|
|
writeSnapshot(emu,f)
|
|
|
|
def loadSnapshot(emu,name):
|
|
global basedir
|
|
fname=os.path.join(basedir,name)
|
|
with gzip.open(fname, 'rb') as f:
|
|
readSnapshot(emu,f)
|
|
class Permutator(object): #for 256-byte objects...
|
|
def __init__(self, grabAddr,tableReg,ptrReg,name=None,cntd=31):
|
|
self.grabAddr=grabAddr
|
|
self.table=None
|
|
self.tableReg=tableReg
|
|
self.ptrReg=ptrReg
|
|
self.countdown=0
|
|
self.name=name
|
|
self.cntd=cntd
|
|
def grab(self, emu,addr):
|
|
if addr==self.grabAddr:
|
|
if self.table is None:
|
|
print("Getting table from {}".format(self.tableReg))
|
|
if isinstance(self.tableReg, (int,long)):
|
|
rg=self.tableReg
|
|
else:
|
|
rg=emu.readRegister(self.tableReg)
|
|
self.table=[]
|
|
for a in range(32):
|
|
self.table.append(emu.readMemoryByte(getAddress(rg+a)))
|
|
if self.countdown>0:
|
|
self.countdown-=1
|
|
else:
|
|
#print("Grabbing at {}".format(addr))
|
|
if isinstance(self.ptrReg,list):
|
|
if len(self.ptrReg)==2:
|
|
dataAddr=emu.readRegister(self.ptrReg[0])+self.ptrReg[1]
|
|
else:
|
|
indirAddr=emu.readRegister(self.ptrReg[0])+self.ptrReg[1]
|
|
dataAddr=readULL(emu,getAddress(indirAddr))
|
|
elif isinstance(self.ptrReg,(int,long)):
|
|
dataAddr=self.ptrReg
|
|
else:
|
|
dataAddr=emu.readRegister(self.ptrReg)
|
|
val=0
|
|
for a in range(32):
|
|
dlt=readULL(emu,getAddress(dataAddr+8*self.table[a]))
|
|
val=val+dlt*(1<<(64*a))
|
|
self.countdown=self.cntd
|
|
if self.name is None:
|
|
logger.info("Grabbed at {}: {:x}".format(self.grabAddr,val))
|
|
else:
|
|
logger.info("Grabbed {} at {}: {:x}".format(self.name,self.grabAddr,val))
|
|
class BCollector(object):
|
|
def __init__(self,name,startAddr,collectAddr,collectA,collectB,endAddr,paraCol=False):
|
|
self.name=name
|
|
self.startAddr=getAddress(startAddr)
|
|
self.endAddr=getAddress(endAddr)
|
|
self.collectAddr=getAddress(collectAddr)
|
|
self.isCollecting=False
|
|
self.collectA=collectA
|
|
self.a=0
|
|
self.collectB=collectB
|
|
self.b=0
|
|
self.cnt=0
|
|
self.cntb=0
|
|
self.paracol=paraCol
|
|
def emget(self,emu, coll):
|
|
lc=len(coll)
|
|
if lc ==1:
|
|
if isinstance(coll[0],int):
|
|
return readULL(emu,getAddress(coll[0]))
|
|
else:
|
|
return emu.readRegister(coll[0])
|
|
elif lc==2: #[reg+const]
|
|
addr=emu.readRegister(coll[0])+coll[1]
|
|
return readULL(emu,getAddress(addr))
|
|
elif lc==3: #[reg+reg*const]
|
|
addr=emu.readRegister(coll[0])+emu.readRegister(coll[1])*coll[2]
|
|
#logger.info("Cll: {:x} {:x} {:x}".format(emu.readRegister(coll[0]),emu.readRegister(coll[1]),addr))
|
|
return readULL(emu,getAddress(addr))
|
|
elif lc==4: #[reg+reg*const+c2]
|
|
addr=emu.readRegister(coll[0])+emu.readRegister(coll[1])*coll[2]+coll[3]
|
|
return readULL(emu,getAddress(addr))
|
|
elif lc==5: # ["RSP",40,"RAX",8,"indir"]
|
|
addr=emu.readRegister(coll[0])+coll[1]
|
|
addr2=readULL(emu,getAddress(addr))+emu.readRegister(coll[2])*coll[3]
|
|
return readULL(emu,getAddress(addr2))
|
|
def collect(self,emu,addr):
|
|
if addr==self.startAddr:
|
|
self.a=0
|
|
self.b=0
|
|
self.cntb=0
|
|
self.cnt=0
|
|
self.isCollecting=True
|
|
elif addr==self.endAddr:
|
|
logger.info("Collected as {} ,a : {:x}".format(self.name,self.a))
|
|
logger.info("Collected as {} ,b : {:x}".format(self.name,self.b))
|
|
logger.info("Collection rounds as {} , {}".format(self.name,self.cnt))
|
|
self.a=0
|
|
self.b=0
|
|
self.cnt=0
|
|
self.isCollecting=False
|
|
elif addr==self.collectAddr and self.isCollecting:
|
|
da=self.emget(emu,self.collectA)
|
|
if not self.paracol:
|
|
db=self.emget(emu,self.collectB)
|
|
ml=(1<<(64*self.cnt))
|
|
self.a+=ml*da
|
|
if not self.paracol:
|
|
self.b+=ml*db
|
|
self.cnt+=1
|
|
elif self.isCollecting and self.paracol and self.cntb<32 and addr>self.startAddr and addr<self.endAddr:
|
|
instr=getInstructionAt(addr)
|
|
if instr.getMnemonicString()=="MUL":
|
|
db=self.emget(emu,self.collectB)
|
|
ml=(1<<(64*self.cntb))
|
|
self.b+=ml*db
|
|
self.cntb+=1
|
|
snc=528
|
|
def dumpBuffer(emu,offs_addr,ln):
|
|
dl=emu.readMemory(getAddress(offs_addr),ln)
|
|
dst=""
|
|
for a in dl:
|
|
if a<0: a+=256
|
|
dst+="{:02X}".format(a)
|
|
logger.info("{}".format(dst))
|
|
def runModule(start,lSnapshot=None):
|
|
global trace, basedir, snc
|
|
cur_fun=getFunctionContaining(start)
|
|
mainFunctionEntryLong = int("0x{}".format(cur_fun.getEntryPoint()), 16)
|
|
emu.writeRegister(emu.getPCRegister(), mainFunctionEntryLong)
|
|
#for nl in range(nnl):
|
|
subN=False
|
|
nnn=0
|
|
fff=0
|
|
ncnt=0
|
|
cnt=0
|
|
#stack=emu.readRegister("RSP")
|
|
fname=None
|
|
if lSnapshot is not None:
|
|
if os.path.isfile(lSnapshot):
|
|
fname=lSnapshot
|
|
elif os.path.isfile(os.path.join(basedir,lSnapshot)):
|
|
fname=os.path.join(basedir,lSnapshot)
|
|
else:
|
|
logger.warning("{} is not correct file name".format(lSnapshot))
|
|
if fname is None:
|
|
EmuPush(emu,0xfafadeadbeef)
|
|
else:
|
|
loadSnapshot(emu,fname)
|
|
snapcnt=0
|
|
#precoll= BCollector("MbSubtr",0x18017b07c,0x18017b0eb,["R14"],["RCX","RAX",8],0x18017b13f)
|
|
#ncoll=BCollector("SubN",0x18017b140,0x18017b1e5,["RDI"],["RAX"],0x18017b24b)
|
|
#vcoll=BCollector("VC",0x18016dc81,0x18016dcb5,["RCX"],["RCX"],0x18016dcdb)
|
|
#pcoll=BCollector("Plus",0x18017b367,0x18017b397,["R14","RAX",8],["R15","RAX",8],0x18017b3ff)
|
|
#ucoll=BCollector("Upper",0x18017c4d2,0x18017c52a,["RAX"],["R12","RCX",8],0x18017d326,False)
|
|
#yacoll=BCollector("YetAnother",0x18017b513,0x18017b578,["RAX"],["R14","RCX",8],0x18017c2f5,False)
|
|
#hm1coll=BCollector("HasMulAdd",0x18016dd26,0x18016dd87,["RAX"],["R13","RCX",8],0x18016ebb4,False)
|
|
#hm2coll=BCollector("HasMulAdd2",0x18016ec3f,0x18016eca5,["RAX"],["R12","RCX",8],0x18016fab9,False)
|
|
#mnscoll=BCollector("Subtractor",0x18017d4ac,0x18017d54a,["R12"],["RAX"],0x18017d598)
|
|
# add permutators to track Bignum manipulation. Each one slows down execution, so use with care?
|
|
prms=[Permutator(getAddress(0x18017c373),"RSI","R14"),
|
|
Permutator(getAddress(0x18017c505),"RBX","R12"),
|
|
Permutator(getAddress(0x18017b0c7),"RDI","R15"),
|
|
#MaybeImportantSubtraction
|
|
Permutator(getAddress(0x18017b0eb),0x180bb7258,"R15","SubtractionA"), #maybesubtraction
|
|
Permutator(getAddress(0x18017b0eb),0x180bb7258,["RSP", 32,"rd"],"SubtractionB"), #maybesubtraction
|
|
#SubN - moved to next function that actually finalized modN operation, it seems.
|
|
Permutator(getAddress(0x18017b33d),0x180bb7258,["RSP", 32,"rd"],"ModN",0),
|
|
#VC - maybe first op?
|
|
Permutator(getAddress(0x18016dce0),0x180bb7258,["RSP", 0xae20],"VC"), #VC
|
|
#LooksSum: only args?
|
|
Permutator(getAddress(0x18017b367),0x180bb7258,"R15","SumA",0),#sum?
|
|
Permutator(getAddress(0x18017b367),0x180bb7258,"R14","SumB",0),#sum?
|
|
#Plum - only result
|
|
Permutator(getAddress(0x18017b4ba),0x180bb7258,"R13","PostSum",0),#dealing with overflow?
|
|
#"Upper" multiply. Looks like square, honestly
|
|
Permutator(getAddress(0x18017d313),0x180bb7258,["RSP", 48,"rd"],"Upper",0),
|
|
#YetAnother: get args:
|
|
Permutator(getAddress(0x18017b513),0x180bb7258,["RSP", 0x60,"rd"],"MulA",0),#mul?
|
|
Permutator(getAddress(0x18017b513),0x180bb7258,["RSP", 56,"rd"],"MulB",0),#mul?
|
|
#Main(?) func has several multiplies separate
|
|
Permutator(getAddress(0x18016dd26),0x180bb7258,["RSP", 0xab20],"Main1A",0),
|
|
Permutator(getAddress(0x18016dd26),0x180bb7258,0x180650ef0,"Main1B",0),
|
|
|
|
Permutator(getAddress(0x18016ec3f),0x180bb7258,["RSP", 0xaa20],"Main2A",0),
|
|
Permutator(getAddress(0x18016ec3f),0x180bb7258,0x180651450,"Main2B",0),
|
|
#CopyLnum
|
|
Permutator(getAddress(0x18017c39f),0x180bb7258,"R15","Copy",0),
|
|
# Second func (decrypt?)
|
|
Permutator(getAddress(0x180148eea),0x180bb70d4,"R15","S_SubtractionA"), #maybesubtraction
|
|
Permutator(getAddress(0x180148eea),0x180bb70d4,["RSP", 32,"rd"],"S_SubtractionB"), #maybesubtraction
|
|
#main
|
|
Permutator(getAddress(0x180144477),0x180bb70d4,["RSP", 0xb000],"S_Main1A",0),
|
|
Permutator(getAddress(0x180144477),0x180bb70d4,0x18064e750,"S_Main1B",0),
|
|
#nmodulo
|
|
Permutator(getAddress(0x1801491ab),0x180bb70d4,["RSP", 32,"rd"],"S_ModN",0),
|
|
#sum
|
|
Permutator(getAddress(0x1801491e5),0x180bb70d4,"R15","S_SumA",0),#sum?
|
|
Permutator(getAddress(0x1801491e5),0x180bb70d4,"R14","S_SumB",0),#sum?
|
|
#sumres
|
|
Permutator(getAddress(0x180149328),0x180bb70d4,"R13","PostSum",0),#dealing with overflow?
|
|
|
|
|
|
Permutator(getAddress(0x18017d50a),"RSI","RCX"),
|
|
#Permutator(getAddress(0x18017d535),"RDI","RCX"), is xored??
|
|
#AdcUser??
|
|
Permutator(getAddress(0x18014b378),"RSI","RCX"),
|
|
#SumAdc??
|
|
Permutator(getAddress(0x180149205),"RDI","R15"),
|
|
Permutator(getAddress(0x180149228),"RDI","R14"),
|
|
#Another minusN?
|
|
Permutator(getAddress(0x180149013),"RBX","RCX"),
|
|
#Mul is suspect
|
|
Permutator(getAddress(0x1801444a6),"R13",["RSP", 0xb000]),
|
|
]
|
|
#prms=[]
|
|
|
|
coutp=None
|
|
|
|
cclen=None
|
|
#very detailed trace, good for spotting small discrepancies but slow and verbose
|
|
superTrace=False
|
|
while True:
|
|
executionAddress = emu.getExecutionAddress()
|
|
if executionAddress==getAddress(0xfafadeadbeef):
|
|
logger.info("Probably return ")
|
|
break
|
|
if executionAddress==getAddress(0x18016dc81):
|
|
rsp=emu.readRegister("RSP")+0xb120
|
|
logger.info("Preload")
|
|
dumpBuffer(emu,rsp,0x402)
|
|
if executionAddress==getAddress(0x18016d323):
|
|
rsi=emu.readRegister("RSI")
|
|
logger.info("Param4")
|
|
dumpBuffer(emu,rsi,0x40e)
|
|
|
|
#if executionAddress==getAddress(0x18016d42d):
|
|
#rsi=emu.readRegister("RSP")+0x1120
|
|
#logger.info("Altering local4")
|
|
#for i in range(4):
|
|
# emu.writeMemoryValue(getAddress(rsi+i),1,0)
|
|
|
|
#if executionAddress==getAddress(0x18016d328):
|
|
#rsi=emu.readRegister("RDI")
|
|
#logger.info("Parpost")
|
|
#dumpBuffer(emu,rsi,0x40e)
|
|
|
|
|
|
if executionAddress==getAddress(0x18016db2a):
|
|
rsp=emu.readRegister("RSP")+0xab20
|
|
logger.info("collector")
|
|
dumpBuffer(emu,rsp,0x10)
|
|
|
|
if executionAddress==getAddress(0x18016b07e): #ConstUser
|
|
cnst=emu.readRegister("RCX")
|
|
inp1=emu.readRegister("RDX")
|
|
inp2=emu.readRegister("R8")
|
|
output=emu.readRegister("R9")
|
|
coutp=output
|
|
offset = (cnst & 0x3fffff)
|
|
ln=(cnst >> 0x24) & 0x3fff
|
|
ln2=cnst >> 0x32
|
|
flen=ln+ln2
|
|
cclen=flen
|
|
if ln>0:
|
|
logger.info("Constant of offset {:x} len {} len2 {}".format(offset,ln,ln2))
|
|
logger.info("Constant input 1: ")
|
|
dumpBuffer(emu,inp1,flen)
|
|
logger.info("Constant input 2: ")
|
|
dumpBuffer(emu,inp2,flen)
|
|
|
|
if executionAddress==getAddress(0x18016b147):
|
|
if coutp is not None and cclen>0:
|
|
logger.info("Constant output: ")
|
|
dumpBuffer(emu,coutp,cclen)
|
|
coutp=None
|
|
cclen=0
|
|
|
|
if executionAddress==getAddress(0x1801722bb):
|
|
esp=emu.readRegister("RSP")+0x50e20
|
|
logger.info("Austack ");
|
|
dumpBuffer(emu,esp,0x5d0)
|
|
if executionAddress==getAddress(0x180172624):
|
|
esp=emu.readRegister("RSP")+0x4faf0
|
|
logger.info("Austack 2");
|
|
dumpBuffer(emu,esp,0x5d0)
|
|
|
|
if executionAddress==getAddress(0x18017df74):
|
|
logger.info("Much bollockry reached")
|
|
dumpParameters(emu,5)
|
|
saveSnapshot(emu,"bollockrySnap.gz")
|
|
|
|
for prm in prms:
|
|
prm.grab(emu,executionAddress)
|
|
|
|
if executionAddress==getAddress(0x1801f539b):
|
|
saveSnapshot(emu,"snap1801f539b_{}.gz".format(snc))
|
|
snc+=1
|
|
if executionAddress==getAddress(0x18016dbc1):
|
|
print(emu.readRegister("ECX"))
|
|
#print(CALLED)
|
|
if executionAddress==getAddress(0x1800779a0):
|
|
saveSnapshot(emu,"Walltimeindir1801f539b_{}.gz".format(snc))
|
|
snc+=1
|
|
logger.info("Walltimeindir saved")
|
|
if executionAddress==getAddress(0x180072a58):
|
|
saveSnapshot(emu,"Irrel180072a58_{}.gz".format(snc))
|
|
snc+=1
|
|
logger.info("Irrel entry saved")
|
|
if executionAddress==getAddress(0x18016d24d):
|
|
saveSnapshot(emu,"Hasmulret18016d24d_2_{}.gz".format(snc))
|
|
snc+=1
|
|
logger.info("Mulret entry saved")
|
|
|
|
if executionAddress==getAddress(0x180057514):
|
|
logger.info("Sussery reached")
|
|
dumpParameters(emu,2)
|
|
saveSnapshot(emu,"susserySnap.gz")
|
|
#trace=True
|
|
|
|
if executionAddress==getAddress(0x1801a3556):
|
|
saveSnapshot(emu,"paramBuggery.gz")
|
|
|
|
if executionAddress==getAddress(0x180291490): #RSA encrypt?
|
|
rcx=emu.readRegister("RCX")
|
|
nptr=readULL(emu,getAddress(rcx))
|
|
eptr=readULL(emu,getAddress(rcx+8))
|
|
dptr=readULL(emu,getAddress(rcx+16))
|
|
logger.info("At RSA encrypt: {:x} {:x} {:x}".format(nptr,eptr,dptr))
|
|
saveSnapshot(emu,"rsaSnap.gz")
|
|
|
|
if executionAddress==getAddress(0x1801d6780):
|
|
rax=emu.readRegister("ESI")
|
|
rsp=emu.readRegister("RSP")
|
|
logger.info("Should be esi: {:x} at {:x}+".format(rax,rsp+0xc8))
|
|
if executionAddress==getAddress(0x18017e3b0):
|
|
saveSnapshot(emu,"Longstringproc_{}.gz".format(snc))
|
|
snc+=1
|
|
if executionAddress==getAddress(0x1801720e0):
|
|
saveSnapshot(emu,"ManyMults1801720e0_{}.gz".format(snc))
|
|
snc+=1
|
|
|
|
if executionAddress==getAddress(0x1801722bb):
|
|
dat=emu.readMemory(getAddress(emu.readRegister("RSP")+0x70),0x5a0)
|
|
dst=""
|
|
for a in dat:
|
|
if a<0: a+=256
|
|
dst+="{:02X}".format(a)
|
|
#print("{:x}".format(eadr))
|
|
logger.info("Buffer: {}".format(dst))
|
|
dat=emu.readMemory(getAddress(emu.readRegister("RSP")+0x50e20),0x5a0)
|
|
dst=""
|
|
for a in dat:
|
|
if a<0: a+=256
|
|
dst+="{:02X}".format(a)
|
|
logger.info("Buffer2: {}".format(dst))
|
|
|
|
if executionAddress==getAddress(0x1801a35d0):
|
|
rsp=emu.readRegister("RSP")+0x33a0
|
|
logger.info("Bollocks3:")
|
|
dumpBuffer(emu,rsp,0x5a*4)
|
|
if executionAddress==getAddress(0x18017a771):
|
|
superTrace=True
|
|
if superTrace:
|
|
ein=getInstructionAt(executionAddress)
|
|
xmm0=emu.readRegister("XMM0")
|
|
xmm1=emu.readRegister("XMM1")
|
|
xmm2=emu.readRegister("XMM2")
|
|
xmm3=emu.readRegister("XMM3")
|
|
xmm4=emu.readRegister("XMM4")
|
|
xmm5=emu.readRegister("XMM5")
|
|
xmm6=emu.readRegister("XMM6")
|
|
xmm7=emu.readRegister("XMM7")
|
|
xmm8=emu.readRegister("XMM8")
|
|
xmm9=emu.readRegister("XMM9")
|
|
xmm10=emu.readRegister("XMM10")
|
|
logger.info("###############")
|
|
logger.info("Address: 0x{} ({})".format(executionAddress, ein))
|
|
logger.info("Xmm0 ={:x} Xmm1 ={:x} Xmm2 ={:x} Xmm3 ={:x} ".format(xmm0,xmm1,xmm2,xmm3))
|
|
logger.info("Xmm4 ={:x} Xmm5 ={:x} Xmm6 ={:x} Xmm7 ={:x} ".format(xmm4,xmm5,xmm6,xmm7))
|
|
logger.info("Xmm8 ={:x} Xmm9 ={:x} Xmm10={:x}".format(xmm8,xmm9,xmm10))
|
|
regs=["RAX","RBX","RCX","RDX","R8","R9","R10","R11","R12","R13","R14","R15","RBP","RSI","RDI"]
|
|
rt=""
|
|
for r in regs:
|
|
val=emu.readRegister(r)
|
|
rt=rt+"{}: {:x} ".format(r,val)
|
|
logger.info("Registers: {}".format(rt))
|
|
|
|
if executionAddress==getAddress(0x18017e440):
|
|
saveSnapshot(emu,"Longstring_nearsha_{}.gz".format(snc))
|
|
snc+=1
|
|
addr=emu.readRegister("R8")
|
|
dat=emu.readMemory(getAddress(addr),0x1c8)
|
|
dst=""
|
|
for a in dat:
|
|
if a<0: a+=256
|
|
dst+="{:02X}".format(a)
|
|
logger.info("Buffer before: {}".format(dst))
|
|
if executionAddress==getAddress(0x18017e454):
|
|
saveSnapshot(emu,"Longstring_postsha_{}.gz".format(snc))
|
|
snc+=1
|
|
addr=emu.readRegister("RBP")
|
|
dat=emu.readMemory(getAddress(addr),0x1c8)
|
|
dst=""
|
|
for a in dat:
|
|
if a<0: a+=256
|
|
dst+="{:02X}".format(a)
|
|
logger.info("Buffer After: {}".format(dst))
|
|
if executionAddress==getAddress(0x18017e473):
|
|
saveSnapshot(emu,"Longstring_postfun_{}.gz".format(snc))
|
|
snc+=1
|
|
addr=emu.readRegister("RDI")
|
|
dat=emu.readMemory(getAddress(addr),0x200)
|
|
dst=""
|
|
for a in dat:
|
|
if a<0: a+=256
|
|
dst+="{:02X}".format(a)
|
|
logger.info("Buffer other: {}".format(dst))
|
|
|
|
#if executionAddress==getAddress(0x1802c8d56):
|
|
# rax=emu.readRegister("RAX")
|
|
# logger.info("Index: {:x}".format(rax))
|
|
#if executionAddress==getAddress(0x18017b4cb):
|
|
# rcx=emu.readRegister("RCX")
|
|
# dat=emu.readMemory(getAddress(rcx),256)
|
|
# logger.info("First array: {}".format(dat))
|
|
if executionAddress==getAddress(0x1801d67e4):
|
|
rsp=emu.readRegister("RSP")
|
|
strng=readULL(emu,getAddress(rsp+0xc0))
|
|
dat=emu.readMemory(getAddress(strng),91)
|
|
logger.info("Shouldreallybestring: {:x} dat :{}".format(strng,dat))
|
|
if executionAddress==getAddress(0x1802ca455):
|
|
rax=emu.readRegister("RAX")
|
|
ptr=readULL(emu,getAddress(rax))
|
|
sz=readULL(emu,getAddress(rax+8))
|
|
cap=readULL(emu,getAddress(rax+16))
|
|
logger.info("Shouldbestring: {:x} sz: {} cap : {:x}".format(ptr,sz,cap))
|
|
stdat=emu.readMemory(getAddress(ptr),90)
|
|
logger.info("Shouldbestringdata: {}".format(stdat))
|
|
if executionAddress==getAddress(0x1802c8af8) or executionAddress==getAddress(0x1802cbf37):
|
|
rcx=emu.readRegister("RCX")
|
|
rdx=emu.readRegister("RDX")
|
|
r8=emu.readRegister("R8")
|
|
r9=emu.readRegister("R9")
|
|
logger.info("Thishere: {} {} {} {}".format(rcx,rdx,r8,r9))
|
|
|
|
if executionAddress in dict:
|
|
logger.info("Substituting {}".format(executionAddress))
|
|
dict[executionAddress](emu)
|
|
else:
|
|
ein=getInstructionAt(executionAddress)
|
|
cnt+=1
|
|
snapcnt+=1
|
|
if cnt>100000:
|
|
cnt=0
|
|
logger.info("Address: 0x{} ({})".format(executionAddress, ein))
|
|
logger.info("RAX: {:x} RCX: {:x} RBP: {:x}".format(emu.readRegister("RAX"),emu.readRegister("RCX"),emu.readRegister("RBP")))
|
|
if snapcnt>1000000:
|
|
saveSnapshot(emu,"Periodic2_{}.gz".format(snc))
|
|
snc+=1
|
|
snapcnt=0
|
|
logger.info("Periodic snapshot {} saved".format(snc-1))
|
|
con=getCallOtherName(ein)
|
|
if con is not None:
|
|
if con == "pshuflw":
|
|
pshuflw(emu,ein)
|
|
elif con == "pmovmskb":
|
|
pmovmskb(emu,ein)
|
|
else:
|
|
logger.info("Skipping: {}".format(ein))
|
|
skip(emu)
|
|
continue
|
|
if trace:
|
|
logger.info("Address: 0x{} ({})".format(executionAddress, ein))
|
|
elog=False
|
|
if elog:
|
|
if isCallInstruction(ein):
|
|
logger.info("CAddress: 0x{} ({})".format(executionAddress, ein))
|
|
logger.info("RAX: {:x} RCX: {:x} RBP: {:x}".format(emu.readRegister("RAX"),emu.readRegister("RCX"),emu.readRegister("RBP")))
|
|
logger.info("RDX: {:x} RDI: {:x} RBX: {:x}".format(emu.readRegister("RDX"),emu.readRegister("RDI"),emu.readRegister("RBX")))
|
|
logger.info("R8 : {:x} R9 : {:x} R15: {:x}".format(emu.readRegister("R8"),emu.readRegister("R9"),emu.readRegister("R15")))
|
|
if isReturn(ein):
|
|
logger.info("Returning: 0x{} {:x}".format(executionAddress, emu.readRegister("RAX")))
|
|
|
|
sn4file=os.path.join(basedir,"Longstringproc_620.gz") #from 250...586 Periodic2_1230.gz Hasmulret18016d24d_602.gz ManyMults1801720e0_1206.gz
|
|
if os.path.isfile(sn4file):
|
|
snc=1359
|
|
#trace=True
|
|
runModule(initCdm,sn4file)
|
|
else:
|
|
runModule(initCdm)
|
|
createCdmInstance=getAddress(0x1800010a0)
|
|
emu.writeRegister("RCX",10)
|
|
keys = "com.widevine.alpha"#"com.widevine.alpha"
|
|
keyptr=get_cptr(emu,keys)
|
|
emu.writeRegister("RDX",keyptr)
|
|
emu.writeRegister("R8",len(keys))
|
|
emu.writeRegister("R9",0xf0000)
|
|
EmuPush(emu,0)
|
|
logger.info("Running CreateInstance")
|
|
runModule(createCdmInstance)
|
|
saveSnapshot(emu,"snapshot1.gz")
|
|
cdmInst=emu.readRegister("RAX")
|
|
logger.info("Instance: {:x}".format(cdmInst))
|
|
#vtable[0]=Initialize(true, false, false);
|
|
#cdmVtableP=readULL(emu,getAddress(cdmInst))
|
|
cdmVtable=readULL(emu,getAddress(cdmInst))
|
|
logger.info("Vtable: {:x}".format(cdmVtable))
|
|
cdmInitialize=readULL(emu,getAddress(cdmVtable))
|
|
logger.info("cdmInitialize: {:x}".format(cdmInitialize))
|
|
emu.writeRegister("RCX",cdmInst)
|
|
logger.info("Running Initialize")
|
|
#trace=True
|
|
emu.writeRegister("RDX",1)
|
|
emu.writeRegister("R8",0)
|
|
emu.writeRegister("R9",0)
|
|
runModule(getAddress(cdmInitialize))
|
|
saveSnapshot(emu,"snapshot2.gz")
|
|
#ContentDecryptionModule_10* cdm =(ContentDecryptionModule_10 *) create(10, keys.c_str(), keys.length(),
|
|
#GetDummyHost, (void*) msg);
|
|
#logger.info("First compare: {}".format(readULL(emu,getAddress(cdmInst+0x92))))
|
|
creses=readULL(emu,getAddress(cdmVtable+3*8))#CreateSessionAndGenerateRequest
|
|
logger.info("CreateSessionAndGenerateRequest: {:x}".format(creses))
|
|
logger.info("Running CreateSession")
|
|
emu.writeRegister("RCX",cdmInst)
|
|
emu.writeRegister("RDX",11)
|
|
emu.writeRegister("R8",0)
|
|
emu.writeRegister("R9",0)
|
|
idata= [0, 0, 0, 91, 112, 115, 115, 104,
|
|
0, 0, 0, 0,
|
|
237, 239, 139, 169, 121, 214, 74,206,
|
|
163, 200, 39, 220, 213, 29, 33, 237,
|
|
0, 0, 0, 59,
|
|
8, 1, 18, 16, 235, 103, 106, 187, 203, 52,
|
|
94, 150, 187, 207, 97, 102, 48, 241, 163, 218, 26, 13,
|
|
119, 105, 100, 101, 118, 105, 110, 101, 95, 116, 101,
|
|
115, 116, 34, 16, 102, 107,106, 51, 108, 106, 97, 83,
|
|
100, 102, 97, 108, 107, 114, 51, 106, 42, 2, 72, 68,50, 0]
|
|
initdata=listToMem(emu,idata)
|
|
EmuPush4(emu, 0)
|
|
EmuPush4(emu, 91)
|
|
rsp=emu.readRegister("RSP")
|
|
logger.info("Pushed len to {:x}".format(rsp))
|
|
|
|
EmuPush(emu, initdata)
|
|
rsp=emu.readRegister("RSP")
|
|
logger.info("Pushed data to {:x}".format(rsp))
|
|
|
|
EmuPush(emu, 0)
|
|
EmuPush(emu, 0)
|
|
EmuPush(emu, 0)
|
|
EmuPush(emu, 0)
|
|
runModule(getAddress(creses))
|
|
|
|
|
|
|