def parse_b(self, b): #Set article scripts if len(self.Hashes) > 0: self.ArticleScripts.append( Article(Hash40(hex(self.CurrentArticle)), self.Hashes)) self.RemoveArticle(self.CurrentArticle) self.Hashes = []
def loadHashes(kind): with open('scriptNames.txt', 'r') as f: HashList.append(NameHash40(kind, Hash40.CreateFromString( kind.lower()))) #Share animation for s in f: if (s != "\n"): s = (kind + s).strip() HashList.append( NameHash40(s, Hash40.CreateFromString(s.lower()))) if 'Special' in s or 'Final' in s: HashList.append( NameHash40( s.replace('Special', 'SpecialAir').replace( 'Final', 'FinalAir').strip(), Hash40.CreateFromString( s.replace('Special', 'SpecialAir').replace( 'Final', 'FinalAir').lower().strip())))
def parse_add(self, add): p = add.split(',')[0].strip() p2 = add.split(',')[1].strip() try: v = int(add.split(',')[2], 16) register = next((x for x in self.Registers if x.register == p), None) if register: register.value += v else: self.Registers.append(Register(p, v)) except: try: f = add.split(':')[2].replace('_phx', '').replace('_lib', '').replace( '_void', '') find = next((x for x in self.Sections if '::' in x.demname and x.demname.split(':')[2].split('(')[0] == f), None) if find: v = find.ordinal register = next( (x for x in self.Registers if x.register == p), None) if register: register.value += v else: self.Registers.append(Register(p, v)) else: px2 = next( (x for x in self.Registers if x.register == "x2"), None) if px2: self.Issues.append( Issue(Hash40(hex(px2.value)), add.split(',')[2])) self.hasIssue = True except: px2 = next((x for x in self.Registers if x.register == "x2"), None) if px2: self.Issues.append( Issue(Hash40(hex(px2.value)), add.split(',')[2])) self.hasIssue = True
def __init__(self, r2, af, sectionList=[]): global methodInfo self.r2 = r2 self.Registers = [] self.Articles = [] self.Hashes = [] self.CurrentArticle = None self.ArticleScripts = [] self.hasIssue = False self.Issues = [] self.Subscript = None self.Sections = sectionList self.ops = af.ops for op in self.ops: if self.Subscript: self.Hashes.extend(self.Subscript.Hashes) self.Subscript = None find = next((x for x in self.Articles if x.branch == op.offset), None) if find: self.CurrentArticle = find.article t = op.opcode.split(' ') instr = t[0] val = ''.join(t[1:]) if instr == 'movz': self.parse_movz(val) elif instr == 'movk': self.parse_movk(val) elif instr == 'cmp': self.parse_cmp(val) elif instr == 'adrp': self.parse_adrp(val) elif instr == 'add': self.parse_add(val) elif instr == 'bl': addr = int(val, 0) m = methodInfo.get(addr, addr) self.parse_bl(m) elif instr == 'b.le': self.parse_b_le(val) elif instr == 'b.gt': self.parse_b_gt(val) elif instr == 'b.eq': self.parse_b_eq(val) elif instr == 'b.ne': self.parse_b_ne(val) elif instr == 'b': self.parse_b(val) #Check if list has hashes and CurrentArticle has a value, this happens when there is a Code XREF on Radare output #Since branch doesn't close data needs to be set here if not it won't be dumped if len(self.Hashes) > 0 and self.CurrentArticle is not None: self.ArticleScripts.append( Article(Hash40(hex(self.CurrentArticle)), self.Hashes))
def openFile(path): global hashes tag = None f = open(path, "r") for x in f: if(x != "\n"): if x[0] == '-': tag = x[1:].strip() else: hashes.append(Hash40(x.lower().strip(), tag))
def parse_bl(self, bl): if type(bl) is int: text = self.r2.cmdJ("s {0};af;pdfj".format(bl)) self.Subscript = ParseAnimcmdList(self.r2, text, self.Sections) elif "::Hash40" in bl.demname: if not self.hasIssue: px1 = next((x for x in self.Registers if x.register == "x1"), None) px2 = next((x for x in self.Registers if x.register == "x2"), None) if px1 and px2: self.Hashes.append( ScriptHash(Hash40(hex(px2.value)), px1.value)) else: self.hasIssue = False
def __init__(self, r2, text, sectionList=[]): self.r2 = r2 self.Registers = [] self.Articles = [] self.Hashes = [] self.CurrentArticle = None self.ArticleScripts = [] self.hasIssue = False self.Issues = [] self.Sections = [] self.Subscript = None ignoreLine = True self.Sections = sectionList self.lines = [] self.address = [] for l in text.split('\r'): if len(l) > 0: if l[0] == '|': if ignoreLine: ignoreLine = False else: a = l.split(';')[0].strip().split(" ") line = a[len(a) - 1][1:] self.lines.append(line) address = re.search("0x[0-9a-f]{8}", l) if address: address = address.group() self.address.append(address) for line, address in zip(self.lines, self.address): #print(line) if self.Subscript: self.Hashes.extend(self.Subscript.Hashes) self.Subscript = None find = next( (x for x in self.Articles if address is not None and x.branch == int(address, 16)), None) if find: self.CurrentArticle = find.article t = line.split(' ') op = t[0] val = ''.join(t[1:]) if op == 'movz': self.parse_movz(val) elif op == 'movk': self.parse_movk(val) elif op == 'cmp': self.parse_cmp(val) elif op == 'adrp': self.parse_adrp(val) elif op == 'add': self.parse_add(val) elif op == 'bl': self.parse_bl(val) elif op == 'b.le': self.parse_b_le(val) elif op == 'b.gt': self.parse_b_gt(val) elif op == 'b.eq': self.parse_b_eq(val) elif op == 'b.ne': self.parse_b_ne(val) elif op == 'b': self.parse_b(val) #Check if list has hashes and CurrentArticle has a value, this happens when there is a Code XREF on Radare output #Since branch doesn't close data needs to be set here if not it won't be dumped if len(self.Hashes) > 0 and self.CurrentArticle is not None: self.ArticleScripts.append( Article(Hash40(hex(self.CurrentArticle)), self.Hashes))
def parse_bl(self, bl): if '0x' in bl or 'fcn.' in bl: #Add subscript if 'fcn.' in bl: bl = bl.replace('fcn.', '0x') if self.r2: script = adjustr2Output( self.r2.cmd('s {0};aF;pdf'.format(hex(int(bl, 16))))) self.SubScript = SubScript(self.r2, script, self.Sections) elif bl == 'method.lib::L2CValue.L2CValue_int': if isinstance(self.CurrentValue, Value): self.CurrentValue = self.CurrentValue.value if self.isConstant: self.Values.append(Value(self.CurrentValue, 'intC')) self.CurrentValue = 0 self.isConstant = False else: self.Values.append(Value(self.CurrentValue, 'int')) self.CurrentValue = 0 elif bl == 'method.lib::L2CValue.L2CValue_float': if isinstance(self.CurrentValue, Value): self.CurrentValue = self.CurrentValue.value self.Values.append(Value(self.CurrentValue, 'float')) self.CurrentValue = 0 elif bl == 'method.lib::L2CValue.L2CValue_bool': if isinstance(self.CurrentValue, Value): self.CurrentValue = self.CurrentValue.value self.Values.append(Value(self.CurrentValue, 'bool')) self.CurrentValue = 0 elif bl == 'method.lib::L2CValue.L2CValue_phx::Hash40': register = next((x for x in self.Registers if x.register == "x1"), None) self.Values.append(Value(Hash40(hex(register.value)), 'hash40')) elif bl == 'method.app::sv_animcmd.is_excute_lua_State': self.Values.append( Value('method.app::sv_animcmd.is_excute_lua_State', 'function')) elif bl == 'method.lib::L2CValue.operatorbool__const': if self.CurrentBlock: if self.CurrentBlock.ElseBlock: self.CurrentBlock.ElseBlock.Functions.append( Function(bl, self.Values, self.CurrentAddress)) else: self.CurrentBlock.Functions.append( Function(bl, self.Values, self.CurrentAddress)) else: self.Functions.append( Function(bl, self.Values, self.CurrentAddress)) self.Values = [] self.CurrentValue = 0 elif bl == 'method.app::lua_bind.WorkModule__is_flag_impl_app::BattleObjectModuleAccessor__int': l = self.Values self.Values = [] self.Values.append( Value(Function(bl, l, self.CurrentAddress), 'function')) elif bl == 'method.lib::L2CValue.L2CValue_long': self.CurrentValue = 0 elif bl == 'method.app::lua_bind.WorkModule__get_int64_impl_app::BattleObjectModuleAccessor__int': self.CurrentValue = 0 elif bl == 'method.lib::L2CAgent.pop_lua_stack_int': #self.Values.append(Value(self.CurrentValue, 'int')) #self.CurrentValue = 0 None elif bl == 'method.lib::L2CAgent.clear_lua_stack': self.PrevStack = self.Values self.Values = [] elif bl == 'method.lib::L2CValue.as_integer__const': self.CurrentValue = Value(self.CurrentValue, 'int') elif bl == 'method.lib::L2CValue.as_number__const': self.CurrentValue = Value(self.CurrentValue, 'float') elif bl == 'method.lib::L2CValue.as_bool__const': self.CurrentValue = Value(self.CurrentValue, 'bool') elif bl == 'method.lib::L2CValue.L2CValue_long' or bl == 'method.lib::L2CValue.L2CValue_long': #self.CurrentValue = Value(self.CurrentValue, 'long') None elif bl == 'method.lib::L2CValue._L2CValue' or bl == 'method.lib::L2CAgent.push_lua_stack_lib::L2CValueconst': #Ignore None #elif bl == 'method.app::sv_animcmd.frame_lua_State__float' or bl == 'method.app::sv_animcmd.wait_lua_State__float': # if self.CurrentBlock: # self.CurrentBlock.Functions.append(Function(bl, self.PrevStack, self.CurrentAddress)) # else: # self.Functions.append(Function(bl, self.PrevStack, self.CurrentAddress)) # self.PrevStack = [] else: if len(self.Values) > 0: if self.CurrentBlock: if self.CurrentBlock.ElseBlock: self.CurrentBlock.ElseBlock.Functions.append( Function(bl, self.Values, self.CurrentAddress)) else: self.CurrentBlock.Functions.append( Function(bl, self.Values, self.CurrentAddress)) else: self.Functions.append( Function(bl, self.Values, self.CurrentAddress)) self.Values = [] else: if self.CurrentBlock: if self.CurrentBlock.ElseBlock: self.CurrentBlock.ElseBlock.Functions.append( Function(bl, self.PrevStack, self.CurrentAddress)) else: self.CurrentBlock.Functions.append( Function(bl, self.PrevStack, self.CurrentAddress)) else: self.Functions.append( Function(bl, self.PrevStack, self.CurrentAddress)) self.PrevStack = []
if 'Special' in s or 'Final' in s: HashList.append( NameHash40( s.replace('Special', 'SpecialAir').replace( 'Final', 'FinalAir').strip(), Hash40.CreateFromString( s.replace('Special', 'SpecialAir').replace( 'Final', 'FinalAir').lower().strip()))) articlesFile = open('articles.txt', 'r') for s in articlesFile: if (s != "\n"): s = s.replace("WEAPON_KIND_", "").strip() ArticleList.append( NameHash40(s.lower(), Hash40.CreateFromString(s.lower()))) class Article: # Character / Weapon def __init__(self, article, hashes=[]): self.article = article self.scriptsHash = hashes def addScriptHash(self, hash, address): self.scriptsHash.append(ScriptHash(hash, address)) def findHashValue(self): find = next((x for x in ArticleList if self.article.hash == x.hash40.hash and self.article.length == x.hash40.length), None) if find:
def parse_bl(self, bl): if type(bl) is int: if self.r2: script = self.r2.cmdJ('s {0};af;pdfj'.format(bl)) self.SubScript = SubScript(self.r2, script, self.Sections) elif bl.demname == 'lib::L2CValue::L2CValue(int)': if isinstance(self.CurrentValue, Value): self.CurrentValue = self.CurrentValue.value if self.isConstant: self.Values.append(Value(self.CurrentValue, 'intC')) self.CurrentValue = 0 self.isConstant = False else: self.Values.append(Value(self.CurrentValue, 'int')) self.CurrentValue = 0 elif bl.demname == 'lib::L2CValue::L2CValue(float)': if isinstance(self.CurrentValue, Value): self.CurrentValue = self.CurrentValue.value self.Values.append(Value(self.CurrentValue, 'float')) self.CurrentValue = 0 elif bl.demname == 'lib::L2CValue::L2CValue(bool)': if isinstance(self.CurrentValue, Value): self.CurrentValue = self.CurrentValue.value self.Values.append(Value(self.CurrentValue, 'bool')) self.CurrentValue = 0 elif bl.demname == 'lib::L2CValue::L2CValue(phx::Hash40)': register = next((x for x in self.Registers if x.register == "x1"), None) self.Values.append(Value(Hash40(hex(register.value)), 'hash40')) elif bl.demname == 'app::sv_animcmd::is_excute(lua_State*)': self.Values.append( Value('app::sv_animcmd::is_excute(lua_State*)', 'function')) elif bl.demname == 'lib::L2CValue::operator bool() const': if self.CurrentBlock: if self.CurrentBlock.ElseBlock: self.CurrentBlock.ElseBlock.Functions.append( Function(bl.name, self.Values, self.CurrentAddress)) else: self.CurrentBlock.Functions.append( Function(bl.name, self.Values, self.CurrentAddress)) else: self.Functions.append( Function(bl.name, self.Values, self.CurrentAddress)) self.Values = [] self.CurrentValue = 0 elif bl.demname == 'app::lua_bind::WorkModule__is_flag_impl(app::BattleObjectModuleAccessor*,int)': l = self.Values self.Values = [] self.Values.append( Value(Function(bl, l, self.CurrentAddress), 'function')) elif bl.demname == 'lib::L2CValue::L2CValue(long)': self.CurrentValue = 0 elif bl.demname == 'app::lua_bind::WorkModule__get_int64_impl(app::BattleObjectModuleAccessor*,int)': self.CurrentValue = 0 elif bl.demname == 'lib::L2CAgent::pop_lua_stack(int)': #self.Values.append(Value(self.CurrentValue, 'int')) #self.CurrentValue = 0 None elif bl.demname == 'lib::L2CAgent::clear_lua_stack()': self.PrevStack = self.Values self.Values = [] elif bl.demname == 'lib::L2CValue::as_integer() const': self.CurrentValue = Value(self.CurrentValue, 'int') elif bl.demname == 'lib::L2CValue::as_number() const': self.CurrentValue = Value(self.CurrentValue, 'float') elif bl.demname == 'lib::L2CValue::as_bool() const': self.CurrentValue = Value(self.CurrentValue, 'bool') elif bl.demname == 'lib::L2CValue::L2CValue(long)': #self.CurrentValue = Value(self.CurrentValue, 'long') None elif bl.demname == 'lib::L2CValue::~L2CValue()' or bl.demname == 'lib::L2CAgent::push_lua_stack(lib::L2CValue const&)': #Ignore None #elif bl.demname == 'app::sv_animcmd::frame(lua_State*,float)' or bl.demname == 'app::sv_animcmd::wait(lua_State*,float)': # if self.CurrentBlock: # self.CurrentBlock.Functions.append(Function(bl, self.PrevStack, self.CurrentAddress)) # else: # self.Functions.append(Function(bl, self.PrevStack, self.CurrentAddress)) # self.PrevStack = [] else: if len(self.Values) > 0: if self.CurrentBlock: if self.CurrentBlock.ElseBlock: self.CurrentBlock.ElseBlock.Functions.append( Function(bl.name, self.Values, self.CurrentAddress)) else: self.CurrentBlock.Functions.append( Function(bl.name, self.Values, self.CurrentAddress)) else: self.Functions.append( Function(bl.name, self.Values, self.CurrentAddress)) self.Values = [] else: if self.CurrentBlock: if self.CurrentBlock.ElseBlock: self.CurrentBlock.ElseBlock.Functions.append( Function(bl.name, self.PrevStack, self.CurrentAddress)) else: self.CurrentBlock.Functions.append( Function(bl.name, self.PrevStack, self.CurrentAddress)) else: self.Functions.append( Function(bl.name, self.PrevStack, self.CurrentAddress)) self.PrevStack = []
class NameHash40: def __init__(self, name, hash40): self.name = name self.hash40 = hash40 HashList = [] ArticleList = [] namesFile = open('scriptNames.txt', 'r') #Game HashList.append( NameHash40("game_".strip(), Hash40.CreateFromString("game_".lower().strip()))) HashList.append( NameHash40("sound_".strip(), Hash40.CreateFromString("sound_".lower().strip()))) HashList.append( NameHash40("effect_".strip(), Hash40.CreateFromString("effect_".lower().strip()))) HashList.append( NameHash40("expression_".strip(), Hash40.CreateFromString("expression_".lower().strip()))) for s in namesFile: if (s != "\n"): sc = s s = "game_" + s HashList.append( NameHash40(s.strip(), Hash40.CreateFromString(s.lower().strip())))