-
Notifications
You must be signed in to change notification settings - Fork 68
/
xPacketTool.py
248 lines (218 loc) · 7.97 KB
/
xPacketTool.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
from phBot import *
import QtBind
import json
import os
pName = 'xPackeTool'
pVersion = '1.2.0'
pUrl = 'https://raw.githubusercontent.com/JellyBitz/phBot-xPlugins/master/xPackeTool.py'
# ______________________________ Initializing ______________________________ #
# Graphic user interface
gui = QtBind.init(__name__,pName)
lblInject = QtBind.createLabel(gui,'Inject Packets to Client/Server through bot, or analyze the packets you need.',6,10)
# Injection
_x=6
_y=50
lblOpcode = QtBind.createLabel(gui,'Opcode:',_x,_y)
txtOpcode = QtBind.createLineEdit(gui,"",_x+45,_y-3,32,20)
lblData = QtBind.createLabel(gui,'Data:',_x+45+32+6,_y)
txtData = QtBind.createLineEdit(gui,"",_x+45+32+6+32,_y-3,385,20)
cbxEncrypted = QtBind.createCheckBox(gui, 'cbxEnc_clicked','Encrypted',_x+432,_y-20)
_y+=25
btnInjectClient = QtBind.createButton(gui,'btnInjectClient_clicked'," Inject To Client ",_x+308,_y)
btnInjectServer = QtBind.createButton(gui,'btnInjectServer_clicked'," Inject To Server ",_x+404,_y)
# Filter
_x=720-176
_y=12
QtBind.createLineEdit(gui,"",_x-26,_y,1,265) # Separator line
cbxSro = QtBind.createCheckBox(gui, 'cbxShowClient_checked','Show Client packets [C->S]',_x+10,_y)
cbxShowClient = False
_y+=20
cbxJmx = QtBind.createCheckBox(gui, 'cbxShowServer_checked','Show Server packets [S->C]',_x+10,_y)
cbxShowServer = False
_y+=40
cbxDontShow = QtBind.createCheckBox(gui, 'cbxDontShow_clicked',"Don't show",_x+5,_y)
cbxOnlyShow = QtBind.createCheckBox(gui, 'cbxOnlyShow_clicked',"Only Show",_x+100,_y)
QtBind.setChecked(gui,cbxDontShow,True) # using two checkbox like radiobutton
cbxDontShow_checked = True
_y+=20
lblOpcodes = QtBind.createLabel(gui,"The following list of opcodes ( Filter )",_x,_y)
_y+=18
tbxOpcodes = QtBind.createLineEdit(gui,"",_x,_y,100,20)
btnAddOpcode = QtBind.createButton(gui,'btnAddOpcode_clicked'," Add ",_x+100+2,_y-2)
_y+=20
lstOpcodes = QtBind.createList(gui,_x,_y,176,120)
lstOpcodesData = []
btnRemOpcode = QtBind.createButton(gui,'btnRemOpcode_clicked'," Remove ",_x+88-32,_y-1+120)
# ______________________________ Methods ______________________________ #
# Return plugin configs path (JSON)
def getConfig():
return get_config_dir()+pName+".json"
# Load default configs
def loadDefaultConfig():
# Clear data
global lstOpcodesData
lstOpcodesData = []
QtBind.clear(gui,lstOpcodes)
# Load the list of opcodes with the config file
def loadConfigs():
loadDefaultConfig()
if os.path.exists(getConfig()):
data = {}
with open(getConfig(),"r") as f:
data = json.load(f)
# load the opcodes list
if "FilteredOpcodes" in data:
global lstOpcodesData
lstOpcodesData = data["FilteredOpcodes"]
for opcode in lstOpcodesData:
QtBind.append(gui,lstOpcodes,'0x{:02X}'.format(opcode))
# config radiobutton if is saved
if "DontShow" in data:
global cbxDontShow_checked
cbxDontShow_checked = data["DontShow"]
QtBind.setChecked(gui,cbxDontShow,data["DontShow"])
QtBind.setChecked(gui,cbxOnlyShow,not data["DontShow"])
# Save all config
def saveConfigs():
# Save all data
data = {}
data['DontShow'] = cbxDontShow_checked
data['FilteredOpcodes'] = lstOpcodesData
# Overrides
with open(getConfig(),"w") as f:
f.write(json.dumps(data, indent=4, sort_keys=True))
# Checkbox "Show Client Packets" checked
def cbxShowClient_checked(checked):
global cbxShowClient
cbxShowClient = checked
# Checkbox "Show Server Packets" checked
def cbxShowServer_checked(checked):
global cbxShowServer
cbxShowServer = checked
# Inject packet on button clicked
def btnInjectServer_clicked():
btnInjectPacket(inject_joymax)
# Inject packet on button clicked
def btnInjectClient_clicked():
btnInjectPacket(inject_silkroad)
# Inject packet to the direction specified
def btnInjectPacket(IProxySend):
strOpcode = QtBind.text(gui,txtOpcode)
strData = QtBind.text(gui,txtData)
# Opcode or Data is not empty
if strOpcode and strData:
data = bytearray()
opcode = int(strOpcode,16)
strData = strData.replace(' ','')
strDataLen = len(strData)
# Make sure is raw of bytes
if not strDataLen % 2 == 0:
log("Plugin: Error, data needs to be a raw of bytes")
return
# Add bytes as pairs
for i in range(0,int(strDataLen),2):
data.append(int(strData[i:i+2],16))
# Check encryption
encrypted = QtBind.isChecked(gui,cbxEncrypted)
# Show injection log
log("Plugin: Injecting packet"+(' (Encrypted)' if encrypted else '')+" :")
log("(Opcode) 0x" + '{:02X}'.format(opcode) + " (Data) "+ ("None" if not data else ' '.join('{:02X}'.format(x) for x in data)))
IProxySend(opcode,data,encrypted)
# Checkbox "Don't show" checked
def cbxDontShow_clicked(checked):
cbxDontShow_editConfig(checked)
QtBind.setChecked(gui,cbxOnlyShow,not checked)
# Checkbox "Only Show" checked
def cbxOnlyShow_clicked(checked):
cbxDontShow_editConfig(not checked)
QtBind.setChecked(gui,cbxDontShow,not checked)
# Edit Key "DontShow" into the config file
def cbxDontShow_editConfig(checked):
global cbxDontShow_checked
cbxDontShow_checked = checked
saveConfigs()
# Button "Add" clicked
def btnAddOpcode_clicked():
# Avoid empty data
opcode = QtBind.text(gui,tbxOpcodes)
if not opcode:
return
# Try to normalize it
try:
opcode = int(opcode,16)
except Exception as ex:
log("Plugin: Error ["+str(ex)+"]")
return
# Check if is already added
global lstOpcodesData
if not opcode in lstOpcodesData:
lstOpcodesData.append(opcode)
strOpcode = '0x{:02X}'.format(opcode)
QtBind.append(gui,lstOpcodes,strOpcode)
saveConfigs()
# saved successfully
QtBind.setText(gui, tbxOpcodes,"")
log("Plugin: Added opcode ["+strOpcode+"]")
# Button "Remove" clicked
def btnRemOpcode_clicked():
selectedIndex = QtBind.currentIndex(gui,lstOpcodes)
if selectedIndex >= 0:
strOpcode = '0x{:02X}'.format(lstOpcodesData[selectedIndex])
del lstOpcodesData[selectedIndex]
QtBind.removeAt(gui,lstOpcodes,selectedIndex)
# saved successfully
saveConfigs()
log("Plugin: Removed opcode ["+strOpcode+"]")
# return True if can log/show the packet
def CanShowPacket(opcode):
if opcode in lstOpcodesData:
if not cbxDontShow_checked:
return True
elif cbxDontShow_checked:
return True
return False
# ______________________________ Events ______________________________ #
# Inject packet through Script. All his data is separated by comma, encrypted will be false if it's not specified.
# Example 1: "inject,Opcode,ItsEncrypted?,Data?,Data?,Data?,..."
# Example 2: "inject,3091,False,0" or "inject,3091,0" (which means greet action)
def inject(args):
argCount = len(args)
if argCount < 2:
log("Plugin: Incorrect structure to inject packet")
return 0
# Check packet structure
opcode = int(args[1],16)
data = bytearray()
encrypted = False
dataIndex = 2
if argCount >= 3:
enc = args[2].lower()
if enc == 'true' or enc == 'false':
encrypted = enc == "true"
dataIndex +=1
# Create packet data and inject it
for i in range(dataIndex, argCount):
data.append(int(args[i],16))
# Show injection log
log("Plugin: Injecting packet"+(' (Encrypted)' if encrypted else '')+" :")
log("(Opcode) 0x" + '{:02X}'.format(opcode) + " (Data) "+ ("None" if not data else ' '.join('{:02X}'.format(x) for x in data)))
# inject it
inject_joymax(opcode,data,encrypted)
return 0
# All packets received from Silkroad will be passed to this function
# Returning True will keep the packet and False will not forward it to the game server
def handle_silkroad(opcode, data):
if cbxShowClient:
if CanShowPacket(opcode):
log("Client: (Opcode) 0x" + '{:02X}'.format(opcode) + " (Data) "+ ("None" if not data else ' '.join('{:02X}'.format(x) for x in data)))
return True
# All packets received from game server will be passed to this function
# Returning True will keep the packet and False will not forward it to the game client
def handle_joymax(opcode, data):
if cbxShowServer:
if CanShowPacket(opcode):
log("Server: (Opcode) 0x" + '{:02X}'.format(opcode) + " (Data) "+ ("None" if not data else ' '.join('{:02X}'.format(x) for x in data)))
return True
# Plugin loaded
log('Plugin: '+pName+' v'+pVersion+' succesfully loaded')
loadConfigs()