This commit is contained in:
rooba 2022-03-17 14:52:04 +00:00
parent 5c818cac5a
commit 1779b47daf
14 changed files with 355 additions and 309 deletions

3
.gitignore vendored

@ -17,3 +17,6 @@ test*.*
.accounts_2 .accounts_2
.names .names
.words .words
.zprofile
.junk

@ -1,3 +1,10 @@
from .character import Character, Traits
from .client import Client
from .client_base import ClientBase, JUNK
from .packet import Packet, iPacket, oPacket
from .packet_helper import Helpers
from .client import NAMES
__all__ = ( __all__ = (
"Character", "Character",
"ClientBase", "ClientBase",
@ -8,18 +15,5 @@ __all__ = (
"oPacket", "oPacket",
"NAMES", "NAMES",
"Traits", "Traits",
"JUNK"
) )
from .character import Character, Traits
from .client_base import ClientBase
from .client import Client
from .packet import Packet, iPacket, oPacket
from .packet_helper import Helpers
NAMES = []
with open("maple_clb/.names", "r") as f:
NAMES.extend([l.rstrip("\n") for l in f.readlines()])
with open("maple_clb/.words", "r") as f:
NAMES.extend([l.rstrip("\n") for l in f.readlines()])

@ -1,6 +1,6 @@
from random import choice, randint from asyncio import Event, sleep
from asyncio import sleep, Event
from ipaddress import IPv4Address from ipaddress import IPv4Address
from random import choice, randint
from rich import print from rich import print
@ -11,11 +11,14 @@ from .packet_helper import Helpers
from .tools import big_fuckin_mac from .tools import big_fuckin_mac
NAMES = []
class Client(ClientBase): class Client(ClientBase):
def __init__( def __init__(
self, self,
loop=None, loop=None,
names=None, # names=None,
username=None, username=None,
password=None, password=None,
proxy=None, proxy=None,
@ -33,7 +36,7 @@ class Client(ClientBase):
self._characters = [] self._characters = []
self._character_id = 0 self._character_id = 0
self._char_selected = None self._char_selected = None
self._NAMES = names self._NAMES = NAMES
self._char_name = "" self._char_name = ""

270
clb/client_base.py Normal file

@ -0,0 +1,270 @@
from asyncio import (Event, Lock, Queue, Task, TimeoutError, create_task,
get_event_loop, sleep)
from datetime import datetime
from socket import AF_INET, IPPROTO_TCP, SOCK_STREAM, TCP_NODELAY, socket
# from socks import socksocket, SOCKS5, create_connection
try:
from python_socks import ProxyConnectionError
from python_socks.async_.asyncio._connect import connect_tcp
from python_socks.async_.asyncio._proxy import Socks5Proxy
except ImportError:
print("python_socks is required to enable proxied connections, all connections made will be unproxied.") # type: ignore
try:
from rich import print
except ImportError:
...
from re import compile
from .crypto import MapleAes, MapleIV, decrypt_transform, encrypt_transform
from .opcodes import RecvOps, SendOps
from .packet import PacketHandler, iPacket
PROXY_RE = compile(r"(?=^(?:([^:]+):([^@]+)@)?([^:]+):([^$]+)$)")
JUNK = set()
LOGIN_PORT = 8485
class ClientBase:
def __init__(self, _loop=None, proxy=None, pproxy=None):
self._loop = _loop or get_event_loop()
self._proxy_url = proxy or ""
match = PROXY_RE.match(self._proxy_url)
if match:
if len(match.groups()) > 2:
self._prox_user, self._prox_pass, self._prox_ip, self._prox_port = match.groups()
self._prox_port = int(self._prox_port)
else:
self._proxy_ip, self._proxy_port = match.groups()
self._proxy_port = int(self._proxy_port)
self._proxy_user = None
self._proxy_pass = None
else:
...
self._tasks = []
self._packet_handlers = []
self._can_login: Event = Event()
self._migrating: Event = Event()
self._migrated: Event = Event()
self._wait_sock_connect = Event()
self._lock: Lock = Lock()
self._action_queue: Queue = Queue()
self._events_task: Task
self._conn_port = 0
self._sock: socket
self._version = None
self._sub_version = None
self._locale = None
self._recv_iv: MapleIV = MapleIV()
self._send_iv: MapleIV = MapleIV()
self._buff = bytearray()
self._prev_buff = bytearray()
self.add_packet_handlers()
async def _connect_sock(self):
# self._sock = socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP)
# self._sock.setblocking(False)
# self._sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1)
# self._sock.setproxy(proxy_type=SOCKS5, addr=self._prox_ip, port=self._prox_port, username=self._prox_user, password=self._prox_pass)
# await self._loop.sock_connect(self._sock, (self._host, self._conn_port))
self._conn = Socks5Proxy(proxy_host=self._prox_ip, proxy_port=self._prox_port, username=self._prox_user, password=self._prox_pass)
try:
self._sock = await self._conn.connect(self._host, self._conn_port)
except ProxyConnectionError:
print(f"{ProxyConnectionError.__name__} | Unable connect to proxy socket")
JUNK.add(self._proxy_url)
del self._events_task
return
except TimeoutError:
print(f"{TimeoutError.__name__} | Unable to connect to proxy")
JUNK.add(self._proxy_url)
del self._events_task
return
except Exception as e:
print(f"Unhandled Exception | {e.__class__.__name__}")
del self._events_task
self._wait_sock_connect.set()
async def start(self):
self._events_task = create_task(self.process_events())
self._host = "51.222.56.169"
self._conn_port = LOGIN_PORT
await self._sock_recv()
async def send_packet(self, opacket, raw=False):
async with self._lock:
opkt = bytearray(opacket.getvalue())
length = len(opkt)
buf = bytearray(length + 4)
buf[0:4] = self._send_iv.get_header(self._version, length)
opkt = bytearray(encrypt_transform(opkt))
MapleAes.transform(opkt, self._send_iv)
buf[4 : length + 4] = opkt
print(f"[{datetime.now().strftime('%d %H:%M:%S.%f')}] [SEND] : {SendOps(opacket.op_code).name} | {opacket.to_string()}")
if not self._sock:
return
await self._loop.sock_sendall(self._sock, buf)
def schedule_action(self, op_code, delay: None | float = 1.0):
async def schd():
if delay:
await sleep(delay)
await self._action_queue.put(op_code)
self._tasks.append(create_task(schd()))
async def _sock_recv(self):
await self._connect_sock()
while self._loop.is_running():
try:
await self._wait_sock_connect.wait()
while self._sock:
await sleep(1)
try:
self._buff.extend(bytearray((await self._loop.sock_recv(self._sock, 8192))))
if self._buff == bytearray(b"\x00\x00\x00\x00\x00\x00"):
self._wait_sock_connect.clear()
self._recv_iv.reset()
self._send_iv.reset()
self._buff = bytearray()
self._prev_buff = bytearray()
break
if not self._send_iv and self._buff:
begin_packet = iPacket(self._buff)
op_code = 0x0E
print(f"[{datetime.now().strftime('%d %H:%M:%S.%f')}] [Client Hello]")
self._version = begin_packet.decode_short()
self._sub_version = int(begin_packet.decode_string())
self._send_iv(begin_packet.decode_int())
self._recv_iv(begin_packet.decode_int())
self._locale = begin_packet.decode_byte()
self._buff = bytearray()
if self._conn_port != LOGIN_PORT and self._migrating.is_set():
self.schedule_action(SendOps.PLAYER_LOGGEDIN, 2.0)
self._migrated.set()
self._migrating.clear()
else:
self.schedule_action(SendOps.LOGIN_PASSWORD, 2.0)
else:
while len(self._buff) > 0:
try:
length = MapleAes.get_length(self._buff[0:4])
buf = bytearray(bytearray(self._buff)[4 : length + 4])
buf = bytearray(MapleAes.transform(buf, self._recv_iv))
buf = decrypt_transform(buf)
packet = iPacket(buf)
await self.handle_packet(packet)
if len(self._buff) - (length + 4) > 0:
self._buff = self._buff[length + 4 :]
else:
self._buff = bytearray()
self._prev_buff = self._buff
except:
...
except ConnectionResetError as e:
self._recv_iv.reset()
self._send_iv.reset()
self._buff = bytearray()
self._prev_buff = bytearray()
self._wait_sock_connect.clear()
await self._connect_sock()
except Exception as e:
print(f"[{datetime.now().strftime('%d %H:%M:%S.%f')}] error in sock_recv: {e}")
else:
print(f"Sock got terminated")
break
except Exception as e:
print(f"Unhandled Exception line 215: {e}")
async def handle_packet(self, packet):
coro = None
for pkt_hndl in self._packet_handlers:
if pkt_hndl.op_code == packet.op_code:
coro = pkt_hndl.callback
break
else:
print(
f"[{datetime.now().strftime('%d %H:%M:%S.%f')}] [RECV] [UNHANDLED] : {RecvOps(packet.op_code).name} | {packet.to_string()}"
)
return
if not coro:
return
# raise AttributeError
print(f"[{datetime.now().strftime('%d %H:%M:%S.%f')}] [RECV] : {RecvOps(packet.op_code).name} | {packet.to_string()}")
if packet.op_code == RecvOps.SERVER_IP:
self._migrating.set()
packet.decode_short()
packet.decode_int()
self._conn_port = packet.decode_short()
self._client_id = packet.decode_int()
self._sock.close()
del self._sock
self._send_iv.reset()
self._recv_iv.reset()
self._buff = bytearray()
self._prev_buff = bytearray()
self._wait_sock_connect.clear()
await self._connect_sock()
return False
# await self._connect_sock()
else:
create_task(coro(self, packet))
def add_packet_handlers(self):
import inspect
members = inspect.getmembers(self)
for _, member in members:
if (
isinstance(member, PacketHandler)
and member not in self._packet_handlers
):
self._packet_handlers.append(member)
async def process_events(self):
raise NotImplementedError

@ -1,7 +1,5 @@
from Crypto.Cipher import AES from Crypto.Cipher import AES
# from struct import unpack, pack
class MapleAes: class MapleAes:
_user_key = bytearray([ _user_key = bytearray([

@ -4,7 +4,7 @@ from random import randint, choice
def big_fuckin_mac() -> str: def big_fuckin_mac() -> str:
hexchars = "ABCDEF0123456789" hexchars = "ABCDEF0123456789"
return f'''{', '.join([ return f'''{', '.join([
choice(["FF-AA-66-66-00-77", "NN-II-GG-GG-EE-RR"]) for _ in range(4) choice(["FF-AA-66-66-00-77", "NN-II-GG-GG-EE-RR"]) for _ in range(40)
])}, {'-'.join([f"{choice(hexchars)}{choice(hexchars)}" for _ in range(6)])}''' ])}, {'-'.join([f"{choice(hexchars)}{choice(hexchars)}" for _ in range(6)])}'''

@ -1,243 +0,0 @@
from asyncio import (
BaseTransport,
Event,
Future,
Lock,
Queue,
Task,
get_event_loop,
sleep,
get_running_loop,
new_event_loop,
create_task
)
from asyncio.trsock import TransportSocket
from socket import AF_INET, IPPROTO_TCP, SOCK_STREAM, TCP_NODELAY, socket
from socks import socksocket, SOCKS5, create_connection
from rich import print
from .crypto import MapleAes, MapleIV, decrypt_transform, encrypt_transform
from .opcodes import RecvOps, SendOps
from .packet import PacketHandler, iPacket
from random import randint
from re import compile
PROXY_RE = compile(r'(?=^([^:]+):([^@]+)@([^:]+):([^$]+)$)')
LOGIN_PORT = 8485
class ClientBase:
def __init__(self, _loop=None, proxy=None, pproxy=None):
self._loop = _loop or get_event_loop()
self._proxy_url = proxy
match = PROXY_RE.match(self._proxy_url)
if match:
self._prox_user, self._prox_pass, self._prox_ip, self._prox_port = match.groups()
self._prox_port = int(self._prox_port)
else:
...
self._tasks = []
self._packet_handlers = []
self._can_login: Event = Event()
self._migrating: Event = Event()
self._migrated: Event = Event()
self._ready: Event = Event()
self._lock: Lock = Lock()
self._action_queue: Queue = Queue()
self._sock: socket | socksocket
self._sock_file_desc: int
self._version = None
self._sub_version = None
self._locale = None
self._recv_iv: MapleIV = MapleIV()
self._send_iv: MapleIV = MapleIV()
self._wait_sock_connect = Event()
self._buff = bytearray()
self._prev_buff = bytearray()
self._conn_port = 0
self.add_packet_handlers()
# def create(
# cls,
# proxy_type: ProxyType,
# host: str,
# port: int,
# username: str = None,
# password: str = None,
# rdns: bool = None,
# **kwargs,
async def _connect_sock(self):
# if hasattr(self, "_proxy_url"):
self._sock = socksocket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP)
self._sock.setproxy(proxy_type=SOCKS5, addr=self._prox_ip, port=self._prox_port, username=self._prox_user, password=self._prox_pass)
# else:
# self._sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
self._sock.setblocking(False)
self._sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1)
# self._sock = TransportSocket(self._sock)
await self._loop.sock_connect(self._sock, (self._host, self._conn_port))
self._wait_sock_connect.set()
async def start(self):
self._tasks.append(create_task(self.process_events()))
self._host = "51.222.56.169"
self._conn_port = LOGIN_PORT
self._ready.set()
self._tasks.append(await self._sock_recv())
async def send_packet(self, opacket, raw=False):
async with self._lock:
opkt = bytearray(opacket.getvalue())
length = len(opkt)
buf = bytearray(length + 4)
buf[0:4] = self._send_iv.get_header(self._version, length)
opkt = bytearray(encrypt_transform(opkt))
MapleAes.transform(opkt, self._send_iv)
buf[4 : length + 4] = opkt
print(f"[SEND] : {SendOps(opacket.op_code).name} | {opacket.to_string()}")
if not self._sock:
return
await self._loop.sock_sendall(self._sock, buf)
def schedule_action(self, op_code, delay: None | float = 1.0):
async def schd():
if delay:
await sleep(delay)
await self._action_queue.put(op_code)
self._tasks.append(create_task(schd()))
async def _sock_recv(self):
await self._connect_sock()
data = bytearray()
while self._loop.is_running():
await self._wait_sock_connect.wait()
print(self._sock)
while self._sock:
await sleep(0.1)
try:
self._buff.extend(bytearray((await self._loop.sock_recv(self._sock, 8192))))
if self._buff == bytearray(b"\x00\x00\x00\x00\x00\x00"):
self._wait_sock_connect.clear()
self._recv_iv.reset()
self._send_iv.reset()
self._buff = bytearray()
self._prev_buff = bytearray()
break
if not self._send_iv and self._buff:
begin_packet = iPacket(self._buff)
op_code = 0x0E
print("[Client Hello]")
self._version = begin_packet.decode_short()
self._sub_version = int(begin_packet.decode_string())
self._send_iv(begin_packet.decode_int())
self._recv_iv(begin_packet.decode_int())
self._locale = begin_packet.decode_byte()
self._buff = bytearray()
if self._conn_port != LOGIN_PORT or self._migrating.is_set():
self.schedule_action(SendOps.PLAYER_LOGGEDIN, 2.0)
self._migrated.set()
self._migrating.clear()
else:
self.schedule_action(SendOps.LOGIN_PASSWORD, 2.0)
else:
while len(self._buff) > 0:
try:
length = MapleAes.get_length(self._buff[0:4])
buf = bytearray(bytearray(self._buff)[4 : length + 4])
buf = bytearray(MapleAes.transform(buf, self._recv_iv))
buf = decrypt_transform(buf)
packet = iPacket(buf)
await self.handle_packet(packet)
if len(self._buff) - (length + 4) > 0:
self._buff = self._buff[length + 4 :]
else:
self._buff = bytearray()
self._prev_buff = self._buff
except:
...
except Exception as e:
print(f"error in sock_recv: {e}")
async def handle_packet(self, packet):
coro = None
for pkt_hndl in self._packet_handlers:
if pkt_hndl.op_code == packet.op_code:
coro = pkt_hndl.callback
break
else:
print(
f"[RECV] [UNHANDLED] : {RecvOps(packet.op_code).name} | {packet.to_string()}"
)
return
if not coro:
raise AttributeError
print(f"[RECV] : {RecvOps(packet.op_code).name} | {packet.to_string()}")
if packet.op_code == RecvOps.SERVER_IP:
self._migrating.set()
packet.decode_short()
packet.decode_int()
self._conn_port = packet.decode_short()
self._client_id = packet.decode_int()
self._sock.close()
del self._sock
self._send_iv.reset()
self._recv_iv.reset()
self._buff = bytearray()
self._prev_buff = bytearray()
self._wait_sock_connect.clear()
await self._connect_sock()
return False
# await self._connect_sock()
else:
create_task(coro(self, packet))
def add_packet_handlers(self):
import inspect
members = inspect.getmembers(self)
for _, member in members:
if (
isinstance(member, PacketHandler)
and member not in self._packet_handlers
):
self._packet_handlers.append(member)
async def process_events(self):
raise NotImplementedError

@ -1,4 +1,5 @@
pycryptodome==3.14.1 pycryptodome==3.14.1
Pygments==2.11.2 attrs==21.4.0
rich==12.0.0 uvloop>=0.16.0
attrs==21.4.0 async_timeout>=4.0.2
python_socks>=2.0.3

62
run.py Normal file

@ -0,0 +1,62 @@
from asyncio import create_task, get_event_loop, new_event_loop, run, sleep
from json import loads
from random import choice
import clb
try:
import uvloop
uvloop.install()
except ImportError:
...
from os.path import dirname
dir_path = dirname(__file__)
ACCOUNTS = []
TASKS = []
PROXIES = []
with open(f"{dir_path}/.names", "r") as f:
clb.NAMES.extend([l.rstrip("\n") for l in f.readlines()])
with open(f"{dir_path}/.words", "r") as f:
clb.NAMES.extend([l.rstrip("\n") for l in f.readlines()])
with open(f"{dir_path}/.proxies", "r") as f:
for line in f.readlines():
PROXIES.append(line.rstrip("\n"))
with open(f"{dir_path}/.accounts_2", "r") as f:
ACCOUNTS = loads(f.read())
print(len(clb.NAMES), len(PROXIES), len(ACCOUNTS))
loop = new_event_loop()
async def create_clients():
loop.set_debug(True)
for account in ACCOUNTS[65:67]:
client = clb.Client(
loop=loop,
# names=NAMES,
username=account["username"],
password=account["password"],
proxy=choice(PROXIES)
)
create_task(client.start())
while loop.is_running():
await sleep(60.0)
loop.run_until_complete(create_clients())
# loop.run_forever()
with open("{dir_path}/.junk", "w+") as f:
for l in clb.JUNK:
f.write(f"{l}""\n")

42
run_.py

@ -1,42 +0,0 @@
from maple_clb import Client, NAMES
from asyncio import run, create_task, new_event_loop, sleep, get_event_loop
from json import loads
try:
import uvloop
uvloop.install()
except:
print("wot")
tasks = []
ACCOUNTS = []
clients = []
with open("maple_clb/.accounts2", "r") as f:
ACCOUNTS = loads(f.read())
loop=new_event_loop()
async def create_clients(accounts):
loop.set_debug(True)
for account in accounts[1700:1730]:
client = Client(
loop=loop,
names=NAMES,
username=account["username"],
password=account["password"],
proxy=account["proxy"]
)
clients.append(create_task(client.start()))
# for client in clients:
# create_task(client.start())
while loop.is_running():
await sleep(5.0)
loop.run_until_complete(create_clients(ACCOUNTS))
loop.run_forever()