-
Notifications
You must be signed in to change notification settings - Fork 0
/
wrsp.py
151 lines (127 loc) · 5.09 KB
/
wrsp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""wrsp.py: A class for automatize WoW (3.3.5) login using sockets and a variation of SRP6.
Thanks to Glusk for the great help
and to karadipola for a draft script
"""
__author__ = "Emanuele Munafò"
__version__ = "0.1"
__email__ = "[email protected]"
__status__ = "Development"
from socket import *
import hashlib
from srp import Srp
from endian import Endian
class Wrsp:
"""A class used to forge and decode SRP-6 like packets.
Internal attributes:
I -- username (capitalized)
P -- password (capitalized)
sck -- socket
"""
def __init__(self, user, password, host, port=3724):
"""Initialize the class."""
self.I = user.upper()
self.p = password.upper()
self.host = host
self.port = port
def login(self):
"""Try to login to host with provided account info.
Return 1 if logged succesfully, 0 otherwise.
"""
try:
# Create socket connection and connect to the server
self.sck = socket(AF_INET, SOCK_STREAM)
self.sck.connect((self.host, self.port))
self.sck.send(self.alchallenge_packet()) # Send Auth Logon Challenge
srp_rcvd = self.decode_packet(self.sck.recv(1024)) # Read SRP for sending Logon Proof
csrp = Srp(srp_rcvd['N'], srp_rcvd['g'], self.I, self.p, srp_rcvd['s'], srp_rcvd['B'])
# Do some math...
A = csrp.gen_A()
u = csrp.gen_u()
S = csrp.gen_S()
K = csrp.gen_K()
M = csrp.gen_M()
# Let's send Auth Logon Proof
self.sck.send(self.alproof_packet(M.blittle(), A.blittle()))
return self.decode_packet(self.sck.recv(1024)).get('login') # 1 if no errors
except ValueError:
return 0
def show_realm(self):
"""Send realm list packet.
Return RAW realm list data.
"""
self.sck.send("\x10\x00\x00\x00\x00") # Send realm list request
return self.sck.recv(1024)
def alchallenge_packet(self):
"""Create an Authorization Logon Packet.
Return a valid Authorization Logon Packet.
"""
packet = "\x00" # Opcode (Auth Logon Challenge)
packet += "\x08" # (Error) da wireshark
packet += chr(30 + len(self.I))
packet += "\x00\x57\x6f\x57\x00" # Game name: <WoW>
packet += "\x03\x03\x05" # Version[1,2,3]: <335>
packet += "\x34\x30" # Build: <12340>
packet += "\x36\x38\x78\x00" # Platform: <x86>
packet += "\x6e\x69\x57\x00" # O.S. : <Win>
packet += "\x53\x55\x6e\x65" # Country: <enUS>
packet += "\x3c\x00\x00\x00" # Timezone bias: <60>
packet += "\xc0\xa8\x01\x02" # IP address: <192.168.1.2>
packet += chr(len(self.I)) # SRP I length
packet += self.I # SRP I value
return packet
@staticmethod
def alproof_packet(M1, A):
"""Create an Authentication Logon Proof packet.
Arguments:
M1 -- Key generated by both client and server used to complete auth.
A -- Public ephemeral value (client generated)
Return an Authentication Logon Proof packet.
"""
packet = "\x01" # Opcode (Auth Logon Proof)
# CRC field (usually) is not checked server side so
# you don't need real value (annoying, sha1 files)
crc = "\xa4\x1f\xd3\xe0\x1f\x72\x40\x46\xa7\xd2\xe7\x44\x9e\x1d\x36\xcf\xaf\x72\xa3\x3a"
null_pad = "\x00\x00"
for i in range(0, 32):
packet += A[i]
for i in range(0, 20):
packet += M1[i]
packet += crc
packet += null_pad
return packet
@staticmethod
def decode_packet(data):
"""Analyze and decode a received SRP packet.
Return a dictionary:
with the keys (error, B, g, N, s, crc) if it was an Auth Logon Challenge
with the key (login = [0|1]) if it was an Auth Logon Proof (1 if no error occurred)
"""
opcodes = [("AUTH_LOGON_CHALLENGE", "\x00"), ("AUTH_LOGON_PROOF", "\x01")]
opcode = data[0] # Opcode of the received packet (First byte)
if opcode == opcodes[0][1]: # Auth Logon challenge
srp_rcvd = {
'error': data[1], # (you should hope that it is always 0)
'B': data[3:35], # Read B and skip 1 field (Length_g)
'g': data[36:37], # Read g and skip 1 field (Length_n)
'N': data[38:70],
's': data[70:102], # Read salt
'crc': data[102:] # (useless for private servers)
}
return srp_rcvd
if opcode == opcodes[1][1]:
# Auth logon proof
if data[1] == "\x00": # Code error: 0
srp_rcvd = {'login': 1}
else:
srp_rcvd = {'login': 0}
return srp_rcvd
'''# Server data
host = "54.213.244.47"
port = 3724
user = "user"
password = "pass"
mypacket = Wrsp(user, password, host)
print mypacket.login()
print mypacket.show_realm()'''