PDA

Просмотр полной версии : [Python]Логин и вывод списка серверов


GoldFinch
24.02.2010, 23:48
Недавно начал изучать Пайтон, набросал программку которая заходит на логинсервер theabyss.ru (протокол вер. 0x785a - без RSA) и печатает список серверов.
Получилось наверное раз в 4-5 короче чем на С++

Кодес:

import socket
import struct

import blowfish

#-------------- конфиг ---------------------
BLOWFISH_KEY = b'_;5.]94-31==-%xT!^[$\0'
LOGIN_SERVER_ADDR = ("85.112.114.104", 2593)
ACCOUNT = b'аккаунт'
PASSWORD = b'пароль'
#-------------------------------------------

def make_packet(frmt,*data):
"""Возвращает зашифрованный пакет, готовый к отправке"""
align = 7 - (struct.calcsize('<' + frmt) + 7) & 7
packed_data = struct.pack('<' + frmt + 'x' * align, *data)
cr_data = blowfish.Encrypt(packed_data)

dw_struct = struct.Struct('I')
chksum = 0
for i in range(len(packed_data) // 4):
chksum ^= dw_struct.unpack_from(packed_data, i * 4)[0]
cr_chksum = blowfish.Encrypt(dw_struct.pack(chksum))

return struct.pack('h', 2 + len(cr_data) + 8) + cr_data + cr_chksum

def read_packet(socket_):
"""Принимает и расшифровывает пакет, возвращает кортеж (id, данные)"""
size, = struct.unpack('H', socket_.recv(2))
data = blowfish.Decrypt(socket_.recv(size))
return data[0], data[1:]

def calc_abyss_chksum(acc):
"""Дополнительная контрольная сумма для пакета RequestAuthLogin
требуется только для theabyss.ru
"""
acc2 = acc.lower() + b'\0'
chksum = 0xF00D # магическое число
for i in range(len(acc2) // 2):
chksum ^= acc2[i * 2] + (acc2[i * 2 + 1] << 8)
return chksum

#------------------------------------------------

blowfish.SetKey(BLOWFISH_KEY)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
s.connect(LOGIN_SERVER_ADDR)
s.recv(11) # размер Init пакета - 11 байт, и он никак не используется

rqAuthLogin = make_packet('B14s16sH', 0, ACCOUNT, PASSWORD,
calc_abyss_chksum(ACCOUNT))
s.sendall(rqAuthLogin)

id_, data = read_packet(s)
if id_ != 3: # не LoginOk
print('логин неудался, причина:', data[0])
exit(0xBAD)
sessionkey1, = struct.unpack_from('<Q', data, 0)

rqServerList = make_packet('BQB', 5, sessionkey1, 4) # 4 - магическое число
s.sendall(rqServerList)

id_, data = read_packet(s)
srvCount, lastServer = struct.unpack_from('<BB', data, 0)
srv_struct = struct.Struct('<B4sIxxHxxB5x')
for i in range(srvCount):
gsId, ip, port, users, isOn = srv_struct.unpack_from(
data, 2 + i * srv_struct.size)
print('#', gsId, ' ', socket.inet_ntoa(ip), ':', port,
' (оффлайн)' if not isOn else '',
' (последний использованный)' if gsId==lastServer else '', sep='')


Полные сырцы (с модулем blowfish) в аттаче. Писал для Python 3.1, на 2.x наверное не заработает.

GoldFinch
09.03.2010, 00:25
Та же хрень, для Aion'а - эмуля aion-unique

RSA в питоне жжот

auth_data = bytes2number(struct.pack('<64x32s32s', ACCOUNT, PASSWORD))
encrypted_auth_data = pow(auth_data, 3, rsa_key_n)

murc
10.03.2010, 01:32
GoldFinch, ты какой клиент потрашиш если не секрет, они же накрыты в аионе тоже?

GoldFinch
10.03.2010, 17:06
murc, я сорцы aion-unique читал,
но вообще европейский клиент с убитым ГГ нормально дебажится

Developer
12.04.2010, 12:03
В рамках изучения питона, а как бы выглядел этот код, если бы было нужно читать пакеты полученные от сервера, при соединении устанавливаемом клиентом (Gracia Plus / RUOFF)?

GoldFinch
12.04.2010, 20:58
Developer,
а хз какой там протокол, у руоффа

Developer
14.04.2010, 12:00
Developer,
а хз какой там протокол, у руоффа

А вопрос в другом.
Запустить клиент, и выводить в программу все, что получает клиент, даже о дешифрации пока не спрашиваю =)

GoldFinch
15.04.2010, 20:03
Developer, для этого надо инжектить код в клиент.
На питоне можно написать инжект и UI который будет выводить лог.
Теоретически на питоне можно написать длл, и инжектить ее в клиент, но я хз как писать длл на питоне.