• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

C++ Fake login to benchmark

Shaykie2

New Member
Joined
Dec 21, 2018
Messages
17
Reaction score
0
Is there a tool that simulates server login? I need it to do a load test with many players....

If it exists for versions 8.22 and 8.60, that would be great.
Does anyone know of a tool like this?
 
I would like to log in and connect a character, simulate someone entering the username and password, selecting the character and entering the game.
I would like a tool to connect to my server to do a load test.
 
It's quite simple to do that, here is an example with python:

Python:
import asyncio
import socket
import time
import random
import uuid


character_login = <hex bytes (capture yours with wireshark)>
north = bytes.fromhex('0c0042032711b5ec00c8060821a9')
east = bytes.fromhex('0c00f8030912707a939926bcf10e')
south = bytes.fromhex('0c00ce02c70b774a1860399822a1')
west = bytes.fromhex('0c007103701057d9803a324ceb1d')
pong = bytes.fromhex('0c00e803011495dc0cefca223d52')
logout = bytes.fromhex('0c0008050f1ae4a4f6c83ff94f3a')
attack = bytes.fromhex('0c000e058717f0697183fbb5d040')


response = bytearray()

async def tcp_client(host: str, port: int):
    reader, writer = await asyncio.open_connection(host, port)

    sock = writer.get_extra_info('socket')
    if sock is not None:
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

    print(f'Connected to {host}:{port}')
    try :
        pkt_length = await reader.read(2)
        packet_length = int.from_bytes(pkt_length, 'little')
        chunk = await reader.read(packet_length)
        print(packet_length, chunk[:20])

        data = bytes.fromhex(character_login)
        writer.write(data)
        await writer.drain()
        print('Data sent')

        start = time.time()
        last_ping = time.time()

        count = 0
        count_attack = 0
        previous_val = 0
        global response
        response = bytearray()
        response.extend(pkt_length + chunk)
        while True:
            pkt_length = await reader.read(2)
            packet_length = int.from_bytes(pkt_length, 'little')
            chunk = await reader.read(packet_length)
            chunk = pkt_length + chunk
            if not chunk:
                break

            if time.time() - last_ping >= 5:
                last_ping = time.time()
                writer.write(pong)
                print('sending pong')
                await writer.drain()
                await asyncio.sleep(0.1)
                count_attack += 1

            #print(time.time() - start, packet_length, chunk[:20])
#            if count_attack == 4:
#                writer.write(attack)
#                await writer.drain()
            if random.random() > 0.75:
                val = (count + random.randrange(4)) % 4
            else:
                val = previous_val
            previous_val = val
            match val:
                case 0:
                    writer.write(east)
                    await writer.drain()
                case 1:
                    writer.write(south)
                    await writer.drain()
                case 2:
                    writer.write(west)
                    await writer.drain()
                case 3:
                    writer.write(north)
                    await writer.drain()
            await asyncio.sleep(0.1)
            count += 1
            response.extend(chunk)
    except asyncio.CancelledError as e:
        print('exception', e)

    writer.write(logout)
    await writer.drain()

    end = time.time()
    print(f'took {end-start}')

    writer.close()
    await writer.wait_closed()
    print('Connection closed')
    with open(f'{time.time()}_{uuid.uuid4().hex}', 'wb') as f:
        f.write(response)

if __name__ == "__main__":
    client = tcp_client('192.168.1.8', 7172)
    asyncio.run(client)

Just copy the tibia packet part from wireshark.
That script will login to the character and start a random walk around the map.
You can also modify to send the account login by changing the packet and removing the walking part.
It is quite light, each python process consume only around 20mb of ram and it is not CPU heavy.
Remember to copy the encrypted packet.


download.gif
 
Last edited:
Wow, fantastic!!!!, this is going to help me a lot, thank you very much for taking the time to help me!!!!

One question, is it possible for me to adapt this script so that it only passes the login and password and simulates the full path? Without having to capture the packet?

I ask because both things are already tested, the login server and the server.

Anyway, thanks again!
 
Back
Top