Skip to content

Commit

Permalink
Added UISound dumper to dump_stuff; Removed some uncommon options; Up…
Browse files Browse the repository at this point in the history
…date EcaFretni
  • Loading branch information
kennytm committed Mar 16, 2011
1 parent ce82658 commit ea834d2
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 17 deletions.
233 changes: 217 additions & 16 deletions dump_stuff.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,48 @@
import sys
sys.path.append('./EcaFretni/')
import macho.features
macho.features.enable('vmaddr', 'symbol')
macho.features.enable('vmaddr', 'symbol', 'strings')

from argparse import ArgumentParser
from collections import defaultdict

from macho.macho import MachO
from macho.loader import MachOLoader
from macho.utilities import peekStructs
from cpu.arm.thread import Thread
from cpu.pointers import isParameter, Return, Parameter, StackPointer
from cpu.arm.instructions.core import isBLInstruction, CMPInstruction
from sym import SYMTYPE_CFSTRING

def parse_options():
parser = ArgumentParser()
parser.add_argument('--version', action='version', version='dump_stuff 0.1')
parser.add_argument('-y', '--arch', help='the CPU architecture. Default to "armv7".', default="armv7")
parser.add_argument('-u', '--arch', default="armv7",
help='the CPU architecture. Default to "armv7".')
parser.add_argument('-y', '--sdk', default="/",
help='the SDK root. Default to "/"')
parser.add_argument('-c', '--cache',
help='the dyld shared cache file to base on. Provide "-c=" to use the '
'default path.')

subparsers = parser.add_subparsers(help='commands')
ccatom_parser = subparsers.add_parser('caatom', help='Dump CAAtom symbols from QuartzCore')
ccatom_parser.add_argument('-s', '--stringpool', help='the symbol that contains the string pool.', default='_stringpool_contents', metavar='SYM')
ccatom_parser.add_argument('-w', '--wordlist', help='the symbol that contains the word list.', default='_wordlist', metavar='SYM')
ccatom_parser.add_argument('-n', '--count', help='the number of words in the word list. By default, it will continue until hitting the _stringpool_contents symbol.')
ccatom_parser.add_argument('-p', '--format', help='print format. Either "table" (default) or "enum".', default='table', choices=["table", "enum"])

ccatom_parser = subparsers.add_parser('caatom',
help='Dump CAAtom symbols from QuartzCore')
ccatom_parser.add_argument('-p', '--format', default='table', choices=["table", "enum"],
help='print format. Either "table" (default) or "enum".')
ccatom_parser.add_argument('filename', nargs='?', default='QuartzCore',
help='Path to QuartzCore file.')
ccatom_parser.set_defaults(func=caatom_main)

parser.add_argument('filename', help='Path to file to dump')
uisound_parser = subparsers.add_parser('uisound', help='Dump UISound filenames from AudioToolbox')
uisound_parser.add_argument('--testvalue', default=1000, metavar='ID', type=int,
help='first value of Sound ID.')
uisound_parser.add_argument('audioToolbox', nargs='?', default='AudioToolbox',
help='Path to AudioToolbox file.')
uisound_parser.add_argument('coreMedia', nargs='?', default='CoreMedia',
help='Path to CoreMedia file.')
uisound_parser.set_defaults(func=uisound_main)

return parser.parse_args()


Expand All @@ -62,25 +83,205 @@ def caatom_main(opts):

def get_atoms(opts):
inputfn = opts.filename
with MachO(inputfn, opts.arch) as mo:
with MachOLoader(inputfn, arch=opts.arch, sdk=opts.sdk, cache=opts.cache) as (mo,):
if mo is None:
print("Error: {0} is not found.".format(inputfn))
return

try:
spc_sym = mo.symbols.any1('name', opts.stringpool)
wl_sym = mo.symbols.any1('name', opts.wordlist)
spc_sym = mo.symbols.any1('name', '_stringpool_contents')
wl_sym = mo.symbols.any1('name', '_wordlist')
except KeyError as e:
print("Error: Symbol '{0}' not found.".format(e.args[0]))
return

count = opts.count
if count is None:
count = (spc_sym.addr - wl_sym.addr) // 4
count = (spc_sym.addr - wl_sym.addr) // 4
if count <= 0:
print("Error: Word list count '{0}' is invalid. Please rerun with a corrected the --count option.".format(count))
print("Error: Word list count '{0}' is invalid.".format(count))
return

mo.seek(mo.fromVM(wl_sym.addr))
for strindex, atom in peekStructs(mo.file, mo.makeStruct('2H'), count):
if atom:
yield (atom, mo.derefString(strindex + spc_sym.addr))

#--------- UISound -------------------------------------------------------------

class UISoundOnBranchHolder(object):
def __init__(self, mo):
self.msa = mo.symbols.any
self.msa1 = mo.symbols.any1

def __call__(self, prevLoc, instr, thread_):
funcsym = self.msa('addr', thread_.pcRaw)
if funcsym is not None:
fname = funcsym.name
if fname == '_sprintf':
formatPtr = thread_.r[1]
filename = self.msa1('addr', formatPtr).name
thread_.memory.set(thread_.r[0], filename.replace("%s/", ""))
thread_.forceReturn()

class UISoundCoreMediaOnBranch(object):
def __init__(self, mo):
self.msa = mo.symbols.any
self.msall = mo.symbols.all

def __call__(self, prevLoc, instr, thread):
msa = self.msa
funcsym = msa('addr', thread.pcRaw)
if funcsym is not None:
fname = funcsym.name
if fname == '_CFDictionaryCreate':
keysPtr = thread.r[1]
retval = 0
if isinstance(keysPtr, int):
keysSym = msa('addr', keysPtr)
if keysSym is not None and keysSym.name.startswith('_ssids'):
tmg = thread.memory.get
msall = self.msall

valuesPtr = thread.r[2]
count = thread.r[3]

keyValueList = ( (tmg(keysPtr + 4*i), tmg(valuesPtr + 4*i)) for i in range(count))
theDict = {}
for key, valuePtr in keyValueList:
for sym in msall('addr', valuePtr):
if sym.symtype == SYMTYPE_CFSTRING:
theDict[key] = sym.name
break


retval = thread.memory.alloc(theDict)
thread.r[0] = retval

elif fname == '_notify_register_mach_port':
thread.r[0] = 1
elif fname in ('_CelestialCFCreatePropertyList', '_lockdown_connect'):
thread.r[0] = 0

thread.forceReturn()


def uisound_get_name_for_input(mo, thread, startAddr, value, testValues):
mem = thread.memory

retstr = mem.alloc("-")
retbool = mem.alloc(0)

thread.pc = startAddr
thread.r[0] = Parameter("input", value)
thread.r[1] = retstr
thread.r[2] = retbool
thread.lr = Return
thread.sp = StackPointer(0)

while thread.pcRaw != Return:
instr = thread.execute()
if isinstance(instr, CMPInstruction):
(lhs, rhs) = (op.get(thread) for op in instr.operands)
if isParameter(lhs, "input"):
testValues.update((rhs-1, rhs, rhs+1))
elif isParameter(rhs, "input"):
testValues.update((lhs-1, lhs, lhs+1))

filename = mem.get(retstr)
hasSound = mem.get(retbool)

mem.free(retstr)
mem.free(retbool)

return (filename, hasSound)




def uisound_print(fnmaps):
for value, (phoneSound, podSound, category) in sorted(fnmaps.items()):
print("|-\n| {0} || {1} || {2} || {3} || ".format(value, phoneSound, podSound, category))


def uisound_get_filenames(mo, f_sym, iphone_sound_sym, testValue):
testValues = {testValue}
exhaustedValues = set()
startAddr = f_sym.addr

thread = Thread(mo)
thread.instructionSet = f_sym.isThumb
thread.onBranch = UISoundOnBranchHolder(mo)

fnmaps = {}

while True:
valueLeft = testValues - exhaustedValues
if not valueLeft:
break
anyValue = valueLeft.pop()
exhaustedValues.add(anyValue)

thread.memory.set(iphone_sound_sym.addr, 1)
(phoneSound, hasPhoneSound) = uisound_get_name_for_input(mo, thread, startAddr, anyValue, testValues)

if hasPhoneSound:
thread.memory.set(iphone_sound_sym.addr, 0)
podSound = uisound_get_name_for_input(mo, thread, startAddr, anyValue, testValues)[0]
else:
podSound = '-'

if hasPhoneSound:
fnmaps[anyValue] = [phoneSound, podSound, '-']

return fnmaps



def uisound_fill_categories(mo, cat_addr, init_sym):
thread = Thread(mo)
thread.instructionSet = init_sym.isThumb
thread.onBranch = UISoundCoreMediaOnBranch(mo)

msa = mo.symbols.any
mem = thread.memory
tmg = mem.get
tms = mem.set

novol_sym = msa('name', '_gSystemSoundsWithNoVolumeAdjustment')
if novol_sym:
tms(novol_sym.addr, 1)
tms(cat_addr, 0)

thread.pc = init_sym.addr

while thread.pcRaw != Return:
thread.execute()
catdict = tmg(cat_addr)
if catdict:
return tmg(catdict)

return {}


def uisound_main(opts):
with MachOLoader(opts.audioToolbox, opts.coreMedia, arch=opts.arch, sdk=opts.sdk, cache=opts.cache) as (mo, coreMediaMo):
msa1 = mo.symbols.any1
cmsa1 = coreMediaMo.symbols.any1
try:
f_sym = msa1('name', '__Z24GetFileNameForThisActionmPcRb')
iphone_sound_sym = msa1('name', '__ZL12isPhoneSound')
cat_sym = cmsa1('name', '_gSystemSoundIDToCategory')
init_sym = cmsa1('name', '_initializeCMSessionMgr')
except KeyError as e:
print("Error: Symbol '{0}' not found.".format(e.args[0]))
return

fmaps = uisound_get_filenames(mo, f_sym, iphone_sound_sym, opts.testvalue)
catdict = uisound_fill_categories(coreMediaMo, cat_sym.addr, init_sym)
for ssid, cat in catdict.items():
if cat != 'UserAlert':
fmaps[ssid][-1] = cat

uisound_print(fmaps)


#--------- etc -----------------------------------------------------------------
Expand Down

0 comments on commit ea834d2

Please sign in to comment.