def prioritySend(self, msg): self.activePriority = True _startTime = time.time() while self.sending: _diffTime = time.time() - _startTime if _diffTime > 5: # In case two threads start at the same time break continue msg = DDFunc.toBytes(msg) # Figure out what function needed to use backupKey = self.key[::] funcIndex ,self.sigbytes = DDFunc.functionSelection(self.key, self.sigbytes) # print '[>] [', self.sigbytes, funcIndex, ']' # Encrypt message encryptedMsg = DDFunc.messageEncryption(funcIndex, self.key, msg) self.key = backupKey[::] encryptedMsg = ''.join(DDFunc.toHex(encryptedMsg)) msgLength = len(encryptedMsg.decode('hex')) # Log about data being sent # print '[.] Sending ', msgLength, ' bytes' # print '[.] Encrypted Data: ', encryptedMsg # Send data try: self.socket.sendall(encryptedMsg.decode('hex')) except: # Something went wrong, return False print '[.] Errors occured, message has not been sent' self.activePriority = False return False # Successfully sent the message, return True # print '[.] Message has been sent' self.activePriority = False return True
def prioritySend(self, msg): self.activePriority = True _startTime = time.time() while self.sending: _diffTime = time.time() - _startTime if _diffTime > 5: # In case two threads start at the same time break continue msg = DDFunc.toBytes(msg) # Figure out what function needed to use backupKey = self.key[::] funcIndex, self.sigbytes = DDFunc.functionSelection( self.key, self.sigbytes) # print '[>] [', self.sigbytes, funcIndex, ']' # Encrypt message encryptedMsg = DDFunc.messageEncryption(funcIndex, self.key, msg) self.key = backupKey[::] encryptedMsg = ''.join(DDFunc.toHex(encryptedMsg)) msgLength = len(encryptedMsg.decode('hex')) # Log about data being sent # print '[.] Sending ', msgLength, ' bytes' # print '[.] Encrypted Data: ', encryptedMsg # Send data try: self.socket.sendall(encryptedMsg.decode('hex')) except: # Something went wrong, return False print '[.] Errors occured, message has not been sent' self.activePriority = False return False # Successfully sent the message, return True # print '[.] Message has been sent' self.activePriority = False return True
def run(self): global CortexMemory while True: if CortexMemory.empty(): continue data = CortexMemory.get() # Sort out signals backupData = data[::] # 4010 = Character Packet # print '[>] ' + ''.join(DDFunc.toHex(DDFunc.toBytes(backupData))) if data[:2:] == '\x40\x10': Character['aspd'] = struct.unpack('<h', data[12:14:])[0] if data[2:4:] == '\x00\x00': data = data[33::] else: # UID of character if data[2:4:] == '\x00\x20': Character['uid'] = struct.unpack('<i', data[18:22:])[0] Character['money'] = struct.unpack('<i', data[14:18:])[0] # Playing safe with regex _next = re.search(r'' + data[2:10:], data[10::], flags=re.DOTALL) if isinstance(_next, types.NoneType): continue _next = _next.start() + 10 data = data[_next+15::] # Assign latest attributes of character Character['maxhp'] = struct.unpack('<h', data[1:3:])[0] Character['maxsp'] = struct.unpack('<h', data[3:5:])[0] Character['hp'] = struct.unpack('<h', data[5:7:])[0] Character['sp'] = struct.unpack('<h', data[7:9:])[0] Character['pos'] = (struct.unpack('<h', data[9:11:])[0], struct.unpack('<h', data[11:13:])[0]) # It seems like this robot is death? if Character['hp'] <= 0: print 'Error packet: ' + ''.join(DDFunc.toHex(DDFunc.toBytes(backupData))) """print 'HP:', Character['maxhp'], '/', Character['hp']
def getKey(self): # Request key from server print '[.] Requesting encryption key from server' self.socket.sendall('0f08005100646273637068'.decode('hex')) print '[.] Sending packet...' keyPacket = DDFunc.toBytes(self.socket.recv(65535)[4::]) # Split to key and 2 significant bytes self.sigbytes = int('0x' + ''.join(['{0:x}'.format(x) for x in keyPacket[16:18][::-1]]),0) self.key = keyPacket[0:16] print '[.] Got an encryption key, [', ''.join(DDFunc.toHex(self.key)), self.sigbytes, ']'
def getKey(self): # Request key from server print '[.] Requesting encryption key from server' self.socket.sendall('0f08005100646273637068'.decode('hex')) print '[.] Sending packet...' keyPacket = DDFunc.toBytes(self.socket.recv(65535)[4::]) # Split to key and 2 significant bytes self.sigbytes = int( '0x' + ''.join(['{0:x}'.format(x) for x in keyPacket[16:18][::-1]]), 0) self.key = keyPacket[0:16] print '[.] Got an encryption key, [', ''.join(DDFunc.toHex( self.key)), self.sigbytes, ']'
def read(self): # Get message length try: recvLength = self.socket.recv(3) except: # Got nothing, return false return False # Something was sent to us recvLength = DDFunc.toHex(DDFunc.toBytes(recvLength)) try: recvLength = int(recvLength[2] + recvLength[1], 16) except: recvLength = 0 # Receive remaining data if recvLength == 0: # Still nothing? return False recvMsg = self.socket.recv(recvLength) return recvMsg
def read(self): # Get message length try: recvLength = self.socket.recv(3) except: # Got nothing, return false return False # Something was sent to us recvLength = DDFunc.toHex(DDFunc.toBytes(recvLength)) try: recvLength = int( recvLength[2] + recvLength[1], 16 ) except: recvLength = 0 # Receive remaining data if recvLength == 0: # Still nothing? return False recvMsg = self.socket.recv(recvLength) return recvMsg
def run(self): lastResponse = '' overflow = False while True: if self.stopFlag: continue if not overflow: response = self.connection.read() else: response = lastResponse overflow = False if not response: continue signal = response[1:3:] if signal == '4110'.decode('hex'): # re-read to get the rest packet. while True: _response = self.connection.read() if not _response: continue if _response[0] == '\x0a': lastResponse = _response overflow = True break else: response += _response responseLength = len(response) # Transmission signal if signal == '4110'.decode('hex'): VisionMemory.put(response[1::]) elif signal == '4010'.decode('hex'): _next = 0 if response[3] == '\x00' and response[4] == '\x00': _next = re.search(r'.{2}\x00\x00.{2}\x00\x00', response[50::], flags=re.DOTALL) if isinstance(_next, types.NoneType): if response[51::][:5:] == '\x00\x00\x00\x00\x00': _next = 52 else: if DEBUG: _f = open('logs/relay-log.txt', 'a+') _f.write('-'*20) _f.write('- Error -\n' + ''.join(DDFunc.toHex(DDFunc.toBytes(response))) + '\n') _f.close() else: _next = _next.start() + 50 else: __next = re.search(r'' + response[3:5:], response[11::], flags=re.DOTALL) if isinstance(__next, types.NoneType): __next = -32 _f = open('logs/relay-log.txt', 'a+') _f.write('-'*20) _f.write('- Error -\n' + ''.join(DDFunc.toHex(DDFunc.toBytes(response))) + '\n') _f.close() else: __next = __next.start() + 11 _next = re.search(r'.{2}\x00\x00.{2}\x00\x00', response[__next + 32::], flags=re.DOTALL) if isinstance(_next, types.NoneType): if response[__next + 32::][:5:] == '\x00\x00\x00\x00\x00': _next = __next + 33 else: if DEBUG: _f = open('logs/relay-log.txt', 'a+') _f.write('-'*20) _f.write('- Error -\n' + ''.join(DDFunc.toHex(DDFunc.toBytes(response))) + '\n') _f.close() else: _next = _next.start() + __next + 32 if not isinstance(_next, types.NoneType): CortexMemory.put(response[1:_next-1:]) VisionMemory.put('\x40\x10' + response[_next-1::]) if DEBUG: _f = open('logs/relay-log.txt', 'a+') _f.write('-'*20) _f.write('- Cortex -\n' + ''.join(DDFunc.toHex(DDFunc.toBytes(response[1:_next-1:]))) + '\n') _f.write('- Vision -\n' + ''.join(DDFunc.toHex(DDFunc.toBytes(response[_next-1::]))) + '\n') _f.close() elif signal == '4210'.decode('hex'): VisionMemory.put(response[1::]) elif signal == '2540'.decode('hex'): VisionMemory.put(response[1::]) # Log if DEBUG: self.logging('Length: ' + str(responseLength)) self.logging('Message: ' + response) response = ''.join(DDFunc.toHex(DDFunc.toBytes(response))) self.logging(response, 1)
def run(self): global VisionMemory, PlayerMemory, ItemMemory, MonsterMemory, Inventory, MonsterMemoryLatestUpdate while True: if VisionMemory.empty(): continue data = VisionMemory.get() # Sort out signal # --- 4110 --- Players (START) if data[:2:] == '\x41\x10': _num = ord(data[2]) data = data[3::] backupData = data[::] __num = _num #_num = 0 while _num: #print '*'*10 #print 'Backup: ' + ''.join(DDFunc.toHex(DDFunc.toBytes(backupData))) backupData = data[::] #print '-'*10 #print 'Raw: ' + ''.join(DDFunc.toHex(DDFunc.toBytes(data))) if len(data) == 0: # print '[>] Not complete analysis' break #handling error if len(data) <= 4: #print '[>] Stuck at Loop 1' data = backupData[1::] continue id = str(struct.unpack('<i', data[1:5:])[0]) notmet = 1 if not id in PlayerMemory else 0 #print 'notmet', notmet if not notmet: # double check if len(re.findall(PlayerMemory[id]['name'], data)): notmet = 1 if notmet: # handling error if len(data) <= 18: #print '[>] Stuck at Loop 2' data = backupData[1::] continue level = ord(data[13]) job = data[14:16:] _namelen = ord(data[16]) # handling error if _namelen <= 0: data = backupData[1::] continue name = data[17:17+_namelen:] try: tmp = name.decode('utf-8') except: data = backupData[1::] continue data = data[17+_namelen::] # handling error if len(data) == 0: #print '[>] Stuck at Loop 3' data = backupData[1::] continue cursor = 0 # wearing hat? if data[0] == '\xff': cursor += 1 else: cursor += 3 # holding weapon? # handling error if cursor >= len(data): #print '[>] Stuck at Loop 4' data = backupData[1::] continue if data[cursor] == '\xff': cursor += 1 else: cursor += 4 # have a guild? if cursor >= len(data): #print '[>] Stuck at Loop 5' data = backupData[1::] continue if data[cursor] == '\x00': cursor += 8 else: cursor += 2 + ord(data[cursor]) + 8 data = data[cursor::] else: if data[13] == '\xff': data = data[20::] else: if data[14] == '\x00': data = data[24::] else: data = data[25::] # handling error if len(data) <= 12: #print '[>] Stuck at Loop 6' data = backupData[1::] continue # get player current status direction = data[0] hp = (struct.unpack('<h', data[1:3:])[0], struct.unpack('<h', data[5:7:])[0]) sp = (struct.unpack('<h', data[3:5:])[0], struct.unpack('<h', data[7:9:])[0]) pos = (struct.unpack('<h', data[9:11:])[0], struct.unpack('<h', data[11:13:])[0]) distance = ((pos[0] - Character['pos'][0])**2 + (pos[1] - Character['pos'][1])**2)**0.5 #print 'Distance:', distance if distance >= 50000: #print '[>] Stuck at Distance' data = backupData[1::] continue if (hp[0] <= 0) or (sp[0] <= 0) or (hp[1] > hp[0]) or (sp[1] > sp[0]): #print '[>] Stuck at Loop 7' data = backupData[1::] continue if (pos[0] < 0) or (pos[1] < 0): #print '[>] Stuck at Loop 8' data = backupData[1::] continue if (notmet == 1) and (level <= 0 or level > 75) : #print '[>] Stuck at Loop 9' data = backupData[1::] continue data = data[13::] data = data[4::] if notmet: PlayerMemory[id] = {} PlayerMemory[id]['name'] = name PlayerMemory[id]['level'] = level PlayerMemory[id]['job'] = job PlayerMemory[id]['direction'] = direction PlayerMemory[id]['hp'] = hp PlayerMemory[id]['sp'] = sp PlayerMemory[id]['pos'] = pos """try: print '[.] Just meet "' + PlayerMemory[id]['name'] + '"' except: print '[.] Cannot print'""" else: PlayerMemory[id]['direction'] = direction PlayerMemory[id]['hp'] = hp PlayerMemory[id]['sp'] = sp PlayerMemory[id]['pos'] = pos """ print '[.] Updating "' + PlayerMemory[id]['name'] + '"' # shout it out loud print ' [.] Level: ' + str(PlayerMemory[id]['level']) print ' [.] HP:', hp print ' [.] SP:', sp print ' [.] Pos:', pos""" _num -= 1 # Log each processed packet if DEBUG: f = open('logs/player-memory.txt', 'a+') for object in PlayerMemory.iteritems(): f.write(object[0]) f.write('\n') f.write('[.] ' + object[1]['name'] + ' Lv.' + str(object[1]['level'])) f.write('\n') f.write('*'*20) f.close() # --- 4110 --- Players (END) # --- 4010 --- Monsters (START) elif data[:2:] == '\x40\x10': _num = ord(data[2]) data = data[3::] backupData = data[::] if len(data) < 25*_num: continue #_num = 0 _start = time.time() if DEBUG: _f = open('logs/monster-log.txt', 'a+') _f.write('\n' + '-'*10 + '\n') _f.write('monsterLarge: ' + ''.join(DDFunc.toHex(DDFunc.toBytes(data))) + '\n' + '*'*10 + '\n') _f.close() fullData = backupData[::] while _num: if time.time() - _start > 30: print '[.] Program is trapped' continue backupData = data[::] if len(data) < 4: data = '' _f = open('Character-Emergency.txt', 'a+') _f.write( ''.join(DDFunc.toHex(DDFunc.toBytes(fullData))) + '\n' ) _f.close() Character['emergency'] = True break uid = struct.unpack('<i', data[:4:])[0] if uid <= 0: data = backupData[1::] continue notmet = 1 if not str(uid) in MonsterMemory else 0 if notmet: dataLength = len(data) if dataLength < 33: data = backupData[1::] continue id = struct.unpack('<h', data[12:14:])[0] level = ord(data[18]) if data[16:18:] != '\x00\x00': level = -1 hp = (struct.unpack('<h', data[14:16:])[0], struct.unpack('<h', data[20:22:])[0]) pos = (struct.unpack('<h', data[24:26:])[0], struct.unpack('<h', data[26:28:])[0]) target = 0 if data[29:33:] == '\xff\xff\xff\xff' or data[31:33:] == '\x00\x00' else struct.unpack('<i', data[29:33:])[0] distance = ((pos[0] - Character['pos'][0])**2 + (pos[1] - Character['pos'][1])**2)**0.5 if str(id) in MonsterList: if MonsterList[str(id)]['level'] != level: data = backupData[1::] continue else: data = backupData[1::] continue if hp[0] < hp[1]: data = backupData[1::] continue if DEBUG: _f = open('logs/monster-log.txt', 'a+') _f.write('notmet:' + str(notmet) + '\n') _f.write('num:' + str(_num) + '\n') _f.write('monster: ' + ''.join(DDFunc.toHex(DDFunc.toBytes(data))) + '\n' + '*'*10 + '\n') _f.close() data = data[33::] if _num > 1: _next = re.search(r'.{2}\x00\x00.{2}\x00\x00', data, flags=re.DOTALL) if isinstance(_next, types.NoneType): data = backupData[1::] continue else: _next = _next.start() data = data[_next::] MonsterMemory[str(uid)] = {} MonsterMemory[str(uid)]['uid'] = uid MonsterMemory[str(uid)]['id'] = id MonsterMemory[str(uid)]['level'] = level MonsterMemory[str(uid)]['hp'] = hp MonsterMemory[str(uid)]['pos'] = pos MonsterMemory[str(uid)]['target'] = target MonsterMemory[str(uid)]['name'] = MonsterList[str(id)]['name'] MonsterMemory[str(uid)]['distance'] = distance else: hp = (MonsterMemory[str(uid)]['hp'][0], struct.unpack('<h', data[12:14:])[0]) pos = (struct.unpack('<h', data[16:18:])[0], struct.unpack('<h', data[18:20:])[0]) target = 0 if data[21:25:] == '\xff\xff\xff\xff' or data[23:25:] == '\x00\x00' else struct.unpack('<i', data[21:25:])[0] distance = ((pos[0] - Character['pos'][0])**2 + (pos[1] - Character['pos'][1])**2)**0.5 if DEBUG: _f = open('logs/monster-log.txt', 'a+') _f.write('notmet:' + str(notmet) + '\n') _f.write('num:' + str(_num) + '\n') _f.write('monster: ' + ''.join(DDFunc.toHex(DDFunc.toBytes(data))) + '\n' + '*'*10 + '\n') _f.close() if hp[0] < hp[1]: data = backupData[1::] continue data = data[25::] if _num > 1: _next = re.search(r'.{2}\x00\x00.{2}\x00\x00', data, flags=re.DOTALL) if isinstance(_next, types.NoneType): data = backupData[1::] continue else: _next = _next.start() data = data[_next::] MonsterMemory[str(uid)]['hp'] = hp MonsterMemory[str(uid)]['pos'] = pos MonsterMemory[str(uid)]['target'] = target MonsterMemory[str(uid)]['distance'] = distance """print str(uid) print MonsterMemory[str(uid)]['hp'] print MonsterMemory[str(uid)]['pos'] print MonsterMemory[str(uid)]['distance']""" _num -= 1 MonsterMemoryLatestUpdate = time.time() _next = re.search(r'.{5}\x10\x00\x00\x00\x00\x00', data, flags=re.DOTALL) _next = 12 if isinstance(_next, types.NoneType) else _next.start() if _next >= 12: _next = re.search(r'.{5}\x00\x00\x00\x00\x00\x00', data, flags=re.DOTALL) if isinstance(_next, types.NoneType): continue else: _next = _next.start() data = data[_next::] """if len(data) < 14: continue data = data[:len(data)-3:] + '\x12\x13\x14\x15\x16\x17\x00\x00\x00\x00\x00\x00\x0a' _next = re.search(r'.{5}[\x00]{6}[^\x00]', data, flags=re.DOTALL) if isinstance(_next, types.NoneType): continue else: _next = _next.start() if str(struct.unpack('<i', data[_next-2::][:4:])[0]) in ItemMemory: data = data[_next-3::] else: data = data[_next-2::]""" if DEBUG: _f = open('logs/item-log.txt', 'a+') _f.write('item: ' + ''.join(DDFunc.toHex(DDFunc.toBytes(data))) + '\n') _f.close() _inum = ord(data[0]) if _inum: data = data[1::] while _inum: dataLength = len(data) uid = struct.unpack('<i', data[0:4:])[0] # notmet = 1 if not str(uid) in ItemMemory else 0 notmet = 1 if data[4] == '\x10' else 0 if notmet: type = ord(data[12]) id = struct.unpack('<h', data[13:15:])[0] pos = (struct.unpack('<h', data[15:17:])[0], struct.unpack('<h', data[17:19:])[0]) owner = struct.unpack('<i', data[19:23:])[0] if _num > 1: data = data[25::] ItemMemory[str(uid)] = {} ItemMemory[str(uid)]['type'] = type ItemMemory[str(uid)]['id'] = id ItemMemory[str(uid)]['pos'] = pos ItemMemory[str(uid)]['owner'] = owner ItemMemory[str(uid)]['uid'] = uid else: if _num > 1: data = data[12::] _inum -= 1 # --- 4010 --- Monsters (END) # --- 4210 --- Monsters out of sight (START) elif data[:2:] == '\x42\x10': _num = ord(data[2]) data = data[3::] while _num: uid = struct.unpack('<i', data[1:5:])[0] if str(uid) in MonsterMemory: MonsterMemory.pop(str(uid), None) elif str(uid) in ItemMemory: ItemMemory.pop(str(uid), None) data = data[4::] _num -= 1 # --- 4210 --- Monsters out of sight (END) # --- 2540 --- Inventory (START) elif data[:2:] == '\x25\x40': _num = ord(data[6]) data = data[7::] print _num if DEBUG: _f = open('logs/inventory-log.txt', 'a+') _f.write('inventory: ' + ''.join(DDFunc.toHex(DDFunc.toBytes(data))) + '\n') _f.close() while _num: #print ''.join(DDFunc.toHex(DDFunc.toBytes(data))) #print '-'*10 if len(data) == 0: break slot = ord(data[0]) type = ord(data[1]) id = struct.unpack('<h', data[2:4:])[0] num = ord(data[7]) if not type in [12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24]: num = 1 Inventory[str(slot)] = {} Inventory[str(slot)]['slot'] = slot Inventory[str(slot)]['type'] = type Inventory[str(slot)]['id'] = id Inventory[str(slot)]['num'] = num if data[8] == '\x00' or data[8] == '\x01': data = data[9::] else: data = data[10::] _num -= 1 Inventory['latestUpdated'] = time.time()
def warp(self, ch, mapCode, mapKey): global PlayerMemory, MonsterMemory, ItemMemory, CortexMemory, VisionMemory # Stop reading packet from relay station self.relaystation.stop() self.busyFlag = True print '[.] Pause RelayStation' time.sleep(3.0) print 'Monster: ', MonsterMemory print 'Vision', VisionMemory # Wipe out all memories PlayerMemory = {} MonsterMemory = {} ItemMemory = {} CortexMemory.queue.clear() VisionMemory.queue.clear() print '[.] Waiting other threads to shutdown' print 'Monster: ', MonsterMemory print 'Vision', VisionMemory time.sleep(3.0) # Declare sending packets print '[.] Request travelling to', mapCode # Switch channel, or change map? if Character['map'].lower() != mapCode.lower(): mapPacket = '0a901001'.decode('hex') + mapCode mapPacket2 = '0a007001' + '0' + str(ch) else: mapPacket = '0a901003'.decode('hex') + mapCode mapPacket2 = '0a007003' + '0' + str(ch) mapPacket2 = mapPacket2.decode('hex') + mapCode # Send packets self.connection.send(mapPacket) self.connection.send(mapPacket2) # If a map server is changed, try make connection with new one print '[.] Getting map server' while True: _response = self.connection.read() if _response == False: gameServer = [ self.connection.dest, self.connection.port ] break if _response[1:3:] == '\x10\x70': gameServer = [ _response[15:15+ord(_response[14]):], struct.unpack('<h', _response[15+ord(_response[14]):17+ord(_response[14]):])[0] ] break self.connection.send('\x02') while True: _response = self.connection.read() if not _response: break self.connection.close() self.connection.dest = gameServer[0] self.connection.port = gameServer[1] self.connection.connect() self.connection.getKey() self.connection.send(mapKey) while True: _response = self.connection.read() print DDFunc.toHex(DDFunc.toBytes(_response)) if _response[:3:] == '\x01\xe9\x03': break self.connection.mapKey = self.connection.mapKey[:2:] + _response[::-1][:4:][::-1] + self.connection.mapKey[6::] self.connection.multipleSend(['\x0a\x81\x10', '\x0a\x95\x10', '\x0a\x50\x30', '\x0a\x40\x62', '\x0a\x18\x10']) print '[.] Waking up...' self.relaystation.restart() self.timer = time.time() print '[.] Opening both eyes...' time.sleep(3.0) self.busyFlag = False
def pack(msg): return ''.join(DDFunc.toHex(DDFunc.toBytes(msg)))