def test_packet1(self) -> Node: root = Node.void('test') root.set_attribute('test', 'test string value') # Regular nodes root.add_child(Node.void('void_node')) root.add_child(Node.s8('s8_node', -1)) root.add_child(Node.u8('u8_node', 245)) root.add_child(Node.s16('s16_node', -8000)) root.add_child(Node.u16('u16_node', 65000)) root.add_child(Node.s32('s32_node', -2000000000)) root.add_child(Node.u32('u32_node', 4000000000)) root.add_child(Node.s64('s64_node', -1234567890000)) root.add_child(Node.u64('u64_node', 1234567890000)) root.add_child(Node.binary('bin_node', b'DEADBEEF')) root.add_child(Node.string('str_node', 'this is a string!')) root.add_child(Node.ipv4('ip4_node', '192.168.1.24')) root.add_child(Node.time('time_node', 1234567890)) root.add_child(Node.float('float_node', 2.5)) root.add_child(Node.fouru8('4u8_node', [0x20, 0x21, 0x22, 0x23])) root.add_child(Node.bool('bool_true_node', True)) root.add_child(Node.bool('bool_false_node', False)) # Array nodes root.add_child(Node.s8_array('s8_array_node', [-1, -2, 3, 4, -5])) root.add_child(Node.u8_array('u8_array_node', [245, 2, 0, 255, 1])) root.add_child(Node.s16_array('s16_array_node', [-8000, 8000])) root.add_child(Node.u16_array('u16_array_node', [65000, 1, 2, 65535])) root.add_child(Node.s32_array('s32_array_node', [-2000000000, -1])) root.add_child(Node.u32_array('u32_array_node', [4000000000, 0, 1, 2])) root.add_child( Node.s64_array('s64_array_node', [-1234567890000, -1, 1, 1337])) root.add_child( Node.u64_array('u64_array_node', [1234567890000, 123, 456, 7890])) root.add_child( Node.time_array('time_array_node', [1234567890, 98765432])) root.add_child( Node.float_array('float_array_node', [2.5, 0.0, 5.0, 20.5])) root.add_child( Node.bool_array('bool_array_node', [False, True, True, False])) # XML escaping escape = Node.string( 'escape_test', '\r\n<testing> & \'thing\' "thing" \r\nthing on new line\r\n ') escape.set_attribute('test', '<testing> & \'thing\' "thing" \r\n thing') root.add_child(escape) # Unicode unicode_node = Node.string('unicode', '今日は') unicode_node.set_attribute('unicode_attr', 'わたし') root.add_child(unicode_node) self.assertLoopback(root)
def handle_game_common_request(self, request: Node) -> Node: game = Node.void('game') for flagid in range(512): flag = Node.void('flag') game.add_child(flag) flag.set_attribute('id', str(flagid)) flag.set_attribute('t', '0') flag.set_attribute('s1', '0') flag.set_attribute('s2', '0') flag.set_attribute('area', '51') flag.set_attribute('is_final', '0') # Last month's hit chart hit_chart = self.data.local.music.get_hit_chart( self.game, self.music_version, self.GAME_MAX_SONGS, 30) counts_by_reflink = [0] * self.GAME_MAX_SONGS for (reflink, plays) in hit_chart: if reflink >= 0 and reflink < self.GAME_MAX_SONGS: counts_by_reflink[reflink] = plays game.add_child(Node.u32_array('cnt_music_monthly', counts_by_reflink)) # Last week's hit chart hit_chart = self.data.local.music.get_hit_chart( self.game, self.music_version, self.GAME_MAX_SONGS, 7) counts_by_reflink = [0] * self.GAME_MAX_SONGS for (reflink, plays) in hit_chart: if reflink >= 0 and reflink < self.GAME_MAX_SONGS: counts_by_reflink[reflink] = plays game.add_child(Node.u32_array('cnt_music_weekly', counts_by_reflink)) # Last day's hit chart hit_chart = self.data.local.music.get_hit_chart( self.game, self.music_version, self.GAME_MAX_SONGS, 1) counts_by_reflink = [0] * self.GAME_MAX_SONGS for (reflink, plays) in hit_chart: if reflink >= 0 and reflink < self.GAME_MAX_SONGS: counts_by_reflink[reflink] = plays game.add_child(Node.u32_array('cnt_music_daily', counts_by_reflink)) return game
def handle_game_common_request(self, request: Node) -> Node: game = Node.void('game') for flagid in range(256): flag = Node.void('flag') game.add_child(flag) flag.set_attribute('id', str(flagid)) flag.set_attribute('s2', '0') flag.set_attribute('s1', '0') flag.set_attribute('t', '0') hit_chart = self.data.local.music.get_hit_chart(self.game, self.music_version, self.GAME_MAX_SONGS) counts_by_reflink = [0] * self.GAME_MAX_SONGS for (reflink, plays) in hit_chart: if reflink >= 0 and reflink < self.GAME_MAX_SONGS: counts_by_reflink[reflink] = plays game.add_child(Node.u32_array('cnt_music', counts_by_reflink)) return game
def parse_psmap(data: bytes, offset: str, rootname: str) -> Node: pe = pefile.PE(data=data, fast_load=True) root = Node.void(rootname) base = int(offset, 16) def virtual_to_physical(offset: int) -> int: for section in pe.sections: start = section.VirtualAddress + pe.OPTIONAL_HEADER.ImageBase end = start + section.SizeOfRawData if offset >= start and offset < end: return (offset - start) + section.PointerToRawData raise Exception( f'Couldn\'t find raw offset for virtual offset 0x{offset:08x}') if base >= pe.OPTIONAL_HEADER.ImageBase: # Assume this is virtual base = virtual_to_physical(base) def read_string(offset: int) -> str: # First, translate load offset in memory to disk offset offset = virtual_to_physical(offset) # Now, grab bytes until we're null-terminated bytestring = [] while data[offset] != 0: bytestring.append(data[offset]) offset = offset + 1 # Its shift-jis encoded, so decode it now return bytes(bytestring).decode('shift_jisx0213') # For recursing into nodes saved_root: List[Node] = [] saved_loc: List[int] = [] while True: chunk = data[base:(base + 16)] base = base + 16 (nodetype, mandatory, outoffset, width, nameptr, defaultptr) = struct.unpack('<BBHIII', chunk) if nodetype == 0xFF: # End of nodes, see if we should exit if len(saved_root) == 0: break else: root = saved_root.pop() oldbase = saved_loc.pop() if oldbase is not None: base = oldbase continue # Grab name, get rid of parse numbers name = read_string(nameptr) try: if name.index('#') >= 0: name = name[:name.index('#')] except ValueError: pass if nodetype == 0x00: raise Exception(f'Invalid node type 0x{nodetype:02x}') elif nodetype == 0x01: # This is a void node, so we should handle by recursing node = Node.void(name) root.add_child(node) # Recurse here saved_root.append(root) if defaultptr != 0: saved_loc.append(base) base = virtual_to_physical(defaultptr) else: saved_loc.append(None) root = node continue elif nodetype == 0x02 or nodetype == 0x43: if nodetype < 0x40: elements = int(width / 1) else: elements = width if elements > 1: node = Node.s8_array(name, [-1] * elements) else: node = Node.s8(name, -1) elif nodetype == 0x03 or nodetype == 0x44: if nodetype < 0x40: elements = int(width / 1) else: elements = width if elements > 1: node = Node.u8_array(name, [0] * elements) else: node = Node.u8(name, 0) elif nodetype == 0x04 or nodetype == 0x45: if nodetype < 0x40: elements = int(width / 2) else: elements = width if elements > 1: node = Node.s16_array(name, [-1] * elements) else: node = Node.s16(name, -1) elif nodetype == 0x05 or nodetype == 0x46: if nodetype < 0x40: elements = int(width / 2) else: elements = width if elements > 1: node = Node.u16_array(name, [0] * elements) else: node = Node.u16(name, 0) elif nodetype == 0x06 or nodetype == 0x47: if nodetype < 0x40: elements = int(width / 4) else: elements = width if elements > 1: node = Node.s32_array(name, [-1] * elements) else: node = Node.s32(name, -1) elif nodetype == 0x07 or nodetype == 0x48: if nodetype < 0x40: elements = int(width / 4) else: elements = width if elements > 1: node = Node.u32_array(name, [0] * elements) else: node = Node.u32(name, 0) elif nodetype == 0x08 or nodetype == 0x49: if nodetype < 0x40: elements = int(width / 8) else: elements = width if elements > 1: node = Node.s64_array(name, [-1] * elements) else: node = Node.s64(name, -1) elif nodetype == 0x09 or nodetype == 0x4A: if nodetype < 0x40: elements = int(width / 8) else: elements = width if elements > 1: node = Node.u64_array(name, [0] * elements) else: node = Node.u64(name, 0) elif nodetype == 0x0A: node = Node.string(name, '') elif nodetype == 0x0D: node = Node.float(name, 0.0) elif nodetype == 0x32 or nodetype == 0x6D: if nodetype < 0x40: elements = int(width / 1) else: elements = width if elements > 1: node = Node.bool_array(name, [False] * elements) else: node = Node.bool(name, False) elif nodetype == 0x2F: # Special case, this is an attribute if name[-1] != '@': raise Exception( f'Attribute name {name} expected to end with @') root.set_attribute(name[:-1], '') continue else: raise Exception(f'Unimplemented node type 0x{nodetype:02x}') # Append it root.add_child(node) return root