Author Topic: pspos - sniff PS position data  (Read 311 times)

thob

  • Traveller
  • *
  • Posts: 23
    • View Profile
pspos - sniff PS position data
« on: November 08, 2011, 03:27:55 pm »
Heya,

made this just for fun.. maybe it is useful for those still using these mapmaker-tools.
Asks questions.. use it or not.

Code: (python) [Select]
#!/usr/bin/python2
# License: WTFPL <http://sam.zoy.org/wtfpl>
#  >You just DO WHAT THE FUCK YOU WANT TO.<
import pcap
import struct


class Packet(object):
    def __init__(self, data):
        self.pos = (0, 0, 0)
        self.rotation = 0
        self.sector = ''
        self.is_valid = False
        self.data = data
        self.strip_header()
        if self.data: self.unpack()

    def __str__(self):
        return str((self.pos, self.rotation, self.sector))

    def __repr__(self):
        return str((self.pos, self.rotation, self.sector))

    def strip_header(self):
        #  Strip UDP header / extract data
        if self.data and self.data[12:14] == '\x08\x00':
            header_len = ord(self.data[14]) & 0x0f
            self.data = self.data[22 + (4 * header_len):]
        else: self.data = b''

        # Strip PS header:
        # 4 bytes id / 4 bytes offset / 4 bytes size
        # 2 bytes size / 1 byte priority / 2 bytes size
        # 1 byte msg_type = 15 bytes
        if len(self.data) > 15:  # Acks are smaller
            (msg_type, ) = struct.unpack('<B', self.data[15])
            # DeadReckoningPacket
            if msg_type == 16: self.data = self.data[18:]
            else: self.data = b''
        else: self.data = b''

    def struct_unpack(self, pattern):
        size = struct.calcsize(pattern)
        (data,) = struct.unpack(pattern, self.data[:size])
        self.data = self.data[size:]
        return data

    def unpack(self):
        eid = self.struct_unpack('<L')
        counter = self.struct_unpack('<B')
        flags = self.struct_unpack('<B')

        if flags & 1: mode = self.struct_unpack('<B')
        if flags & 2: ang_vel = self.struct_unpack('<f')
        if flags & 4: vel = (self.struct_unpack('<f'), 0, 0)
        if flags & 8: vel = (0, self.struct_unpack('<f'), 0)
        if flags & 16: vel = (0, 0, self.struct_unpack('<f'))
        if flags & 32: world_vel = (self.struct_unpack('<f'), 0, 0)
        if flags & 64: world_vel = (0, self.struct_unpack('<f'), 0)
        if flags & 128: world_vel = (0, 0, self.struct_unpack('<f'))

        self.pos = (self.struct_unpack('<f'),
               self.struct_unpack('<f'),
               self.struct_unpack('<f'))
        rotation = self.struct_unpack('<B')
        # quantized to 0 - 256: radian = (2pi * quan) / 256
        self.rotation = (2 * 3.14159 * rotation) / 256

        if self.struct_unpack('<L') == 4294967295:
            self.sector = self.data[:-1].decode('utf-8')
        else: self.sector = ''
        self.is_valid = True


class Sniffer(pcap.pcapObject):
    def __init__(self, dst, port=7777, device=None):
        pcap.pcapObject.__init__(self)
        if device is None: device = pcap.lookupdev()
        self.open_live(device, 65535, 0, 100)
        self.setfilter('dst {} and port {} and udp'.format(dst, port), 0, 0)

    def get_callback(self, callback):
        def process_packet(pktlen, data, timestamp):
            packet = Packet(data)
            if packet.is_valid: callback(timestamp, packet)
        return process_packet

    def loop(self, count, callback):
        pcap.pcapObject.loop(self, count, self.get_callback(callback))

    def dispatch(self, count, callback):
        pcap.pcapObject.dispatch(self, count, self.get_callback(callback))

    def next(self, *args):
        ret = pcap.pcapObject.next(self)
        if not ret in None:
            (pktlen, data, timestamp) = ret
            packet = Packet(data)
            if packet.is_valid: return (timestamp, packet)
        return None


def main():
    def print_it(*args): print args
    sniffer = Sniffer('62.173.168.9')
    try: sniffer.loop(0, print_it)
    except KeyboardInterrupt: pass

if __name__ == '__main__': main()
https://gist.github.com/1349063

You need to run it as root or find a way to access the buffer as user.
If you make something cool using this code, please inform me :).

o/ Thob

EDIT:
Cause Nanos asked:
That thing observes the network traffic between the PlaneShift client and the server. Its picks the packets from the sever and unpacks fthem if they contain position data.
It then calls a callback (here it prints the information). Just install pcap, run it as root and move your char ingame.
« Last Edit: November 08, 2011, 04:11:24 pm by thob »
Thob Ciscon, Crafter and Merchant for crafted Weapons.
Proud member of The Woiperdinger and the Merchantile Order of Commerce!

derula

  • Hydlaa Citizen
  • *
  • Posts: 405
  • My main: Jamona Shikon
    • View Profile
    • Ugly Horst Tld.
Re: pspos - sniff PS position data
« Reply #1 on: November 09, 2011, 11:50:59 am »
Code: (python) [Select]
# License: WTFPL <http://sam.zoy.org/wtfpl>

High five! o/