import struct import array lua_opcode_types = [ "ABC", "ABx", "ABC", "ABC", "ABC", "ABx", "ABC", "ABx", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "AsBx", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "ABC", "AsBx", "AsBx", "ABC", "ABC", "ABC", "ABx", "ABC" ] lua_opcode_names = [ "MOVE", "LOADK", "LOADBOOL", "LOADNIL", "GETUPVAL", "GETGLOBAL", "GETTABLE", "SETGLOBAL", "SETUPVAL", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL", "DIV", "MOD", "POW", "UNM", "NOT", "LEN", "CONCAT", "JMP", "EQ", "LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL", "RETURN", "FORLOOP", "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG" ] # at [p]osition to k def get_bits(num, p, k): # convert number into binary first binary = bin(num) # remove first two characters binary = binary[2:] # fill in missing bits for i in range(32 - len(binary)): binary = '0' + binary end = len(binary) - p + 1 start = len(binary) - k + 1 # extract k bit sub-string kBitSubStr = binary[start : end] # convert extracted sub-string into decimal again return (int(kBitSubStr,2)) class LuaUndump: def __init__(self): self.chunks = [] self.chunk = {} self.index = 0 @staticmethod def dis_chunk(chunk): print("==== [[" + str(chunk['NAME']) + "]] ====\n") for z in chunk['PROTOTYPES']: print("** decoding proto\n") LuaUndump.dis_chunk(chunk['PROTOTYPES'][z]) print("\n==== [[" + str(chunk['NAME']) + "'s constants]] ====\n") for z in chunk['CONSTANTS']: i = chunk['CONSTANTS'][z] print(str(z) + ": " + str(i['DATA'])) print("\n==== [[" + str(chunk['NAME']) + "'s dissassembly]] ====\n") for z in chunk['INSTRUCTIONS']: i = chunk['INSTRUCTIONS'][z] if (i['TYPE'] == "ABC"): print(lua_opcode_names[i['OPCODE']], i['A'], i['B'], i['C']) elif (i['TYPE'] == "ABx"): if (i['OPCODE'] == 1 or i['OPCODE'] == 5): print(lua_opcode_names[i['OPCODE']], i['A'], -i['Bx']-1, chunk['CONSTANTS'][i['Bx']]['DATA']) else: print(lua_opcode_names[i['OPCODE']], i['A'], -i['Bx']-1) elif (i['TYPE'] == "AsBx"): print("AsBx", lua_opcode_names[i['OPCODE']], i['A'], i['sBx']) def loadBlock(self, sz): temp = bytearray(self.bytecode[self.index:self.index+sz]) self.index = self.index + sz return temp def get_byte(self): return self.loadBlock(1)[0] def get_int32(self): if (self.big_endian): return int.from_bytes(self.loadBlock(4), byteorder='big', signed=False) else: return int.from_bytes(self.loadBlock(4), byteorder='little', signed=False) def get_int(self): if (self.big_endian): return int.from_bytes(self.loadBlock(self.int_size), byteorder='big', signed=False) else: return int.from_bytes(self.loadBlock(self.int_size), byteorder='little', signed=False) def get_size_t(self): if (self.big_endian): return int.from_bytes(self.loadBlock(self.size_t), byteorder='big', signed=False) else: return int.from_bytes(self.loadBlock(self.size_t), byteorder='little', signed=False) def get_double(self): if self.big_endian: return struct.unpack('>d', self.loadBlock(8))[0] else: return struct.unpack('