LiberationSoft
asked on
Python to VB.NET
Having a bit of a problem converting some python to vb.net. One other person requested a single function be converted from the same python program but I actually have that one converted. It's the support functions and main program I am having difficulty with.
Basically, the python program encrypts a packet to send to a server. It receives a packet back with the same encryption and is decrypted and displayed.
My problem I believe is the actual encryption of the packet. What I do understand of python tells me that it's using little endian int32's... which I think is what vb.net uses if I just use bitconverter.getbytes()... But for some reason I just can't get the server to talk to me (it won't throw errors at all, and only tosses a blank string or null if your packet is malformed).
I don't think I need any network code... just something to actually create a packet (array of bytes I would imagine).
The following is the packet format from the docs, what little of them there are...
Packet format
int32 32-bit unsigned integer
1 byte bits 7..0 of value
1 byte bits 15..8 of value
1 byte bits 23..16 of value
1 byte bits 31..24 of value
Word
int32 Size Number of bytes in word, excluding trailing null
byte char[] Content Word contents -- must not contain any null bytes char
Terminator Trailing null byte
Packet
int32 Sequence Bit 31: 0 = The command in this command/response pair originated on the server 1 = The command in this command/response pair originated on the client
Bit 30: 0 = Request, 1 = Response
Bits 29..0: Sequence number (this is used to match requests/responses in a full duplex transmission)
int32 Size Total size of packet, in bytes
int32 NumWords Number of words following the packet header
Word[N] Words N words
A packet cannot be more than 4096 bytes in size.
Any help would be greatly appreciated... I wouldn't even need the python code converted if I could just get something that can create said packet. :)
Thanks much.
Basically, the python program encrypts a packet to send to a server. It receives a packet back with the same encryption and is decrypted and displayed.
My problem I believe is the actual encryption of the packet. What I do understand of python tells me that it's using little endian int32's... which I think is what vb.net uses if I just use bitconverter.getbytes()...
I don't think I need any network code... just something to actually create a packet (array of bytes I would imagine).
The following is the packet format from the docs, what little of them there are...
Packet format
int32 32-bit unsigned integer
1 byte bits 7..0 of value
1 byte bits 15..8 of value
1 byte bits 23..16 of value
1 byte bits 31..24 of value
Word
int32 Size Number of bytes in word, excluding trailing null
byte char[] Content Word contents -- must not contain any null bytes char
Terminator Trailing null byte
Packet
int32 Sequence Bit 31: 0 = The command in this command/response pair originated on the server 1 = The command in this command/response pair originated on the client
Bit 30: 0 = Request, 1 = Response
Bits 29..0: Sequence number (this is used to match requests/responses in a full duplex transmission)
int32 Size Total size of packet, in bytes
int32 NumWords Number of words following the packet header
Word[N] Words N words
A packet cannot be more than 4096 bytes in size.
Any help would be greatly appreciated... I wouldn't even need the python code converted if I could just get something that can create said packet. :)
Thanks much.
#!/usr/local/bin/python
from struct import *
import binascii
import socket
import sys
import shlex
import string
import threading
import md5
import os
def EncodeHeader(isFromServer, isResponse, sequence):
header = sequence & 0x3fffffff
if isFromServer:
header += 0x80000000
if isResponse:
header += 0x40000000
return pack('<I', header)
def DecodeHeader(data):
[header] = unpack('<I', data[0 : 4])
return [header & 0x80000000, header & 0x40000000, header & 0x3fffffff]
def EncodeInt32(size):
return pack('<I', size)
def DecodeInt32(data):
return unpack('<I', data[0 : 4])[0]
def EncodeWords(words):
size = 0
encodedWords = ''
for word in words:
strWord = str(word)
encodedWords += EncodeInt32(len(strWord))
encodedWords += strWord
encodedWords += '\x00'
size += len(strWord) + 5
return size, encodedWords
def DecodeWords(size, data):
numWords = DecodeInt32(data[0:])
words = []
offset = 0
while offset < size:
wordLen = DecodeInt32(data[offset : offset + 4])
word = data[offset + 4 : offset + 4 + wordLen]
words.append(word)
offset += wordLen + 5
return words
def EncodePacket(isFromServer, isResponse, sequence, words):
encodedHeader = EncodeHeader(isFromServer, isResponse, sequence)
encodedNumWords = EncodeInt32(len(words))
[wordsSize, encodedWords] = EncodeWords(words)
encodedSize = EncodeInt32(wordsSize + 12)
return encodedHeader + encodedSize + encodedNumWords + encodedWords
# Decode a request or response packet
# Return format is:
# [isFromServer, isResponse, sequence, words]
# where
# isFromServer = the command in this command/response packet pair originated on the server
# isResponse = True if this is a response, False otherwise
# sequence = sequence number
# words = list of words
def DecodePacket(data):
[isFromServer, isResponse, sequence] = DecodeHeader(data)
wordsSize = DecodeInt32(data[4:8]) - 12
words = DecodeWords(wordsSize, data[12:])
return [isFromServer, isResponse, sequence, words]
###############################################################################
clientSequenceNr = 0
# Encode a request packet
def EncodeClientRequest(words):
global clientSequenceNr
packet = EncodePacket(False, False, clientSequenceNr, words)
clientSequenceNr = (clientSequenceNr + 1) & 0x3fffffff
return packet
# Encode a response packet
def EncodeClientResponse(sequence, words):
return EncodePacket(False, True, sequence, words)
###################################################################################
# Display contents of packet in user-friendly format, useful for debugging purposes
def printPacket(packet):
if (packet[0]):
print "IsFromServer, ",
else:
print "IsFromClient, ",
if (packet[1]):
print "Response, ",
else:
print "Request, ",
print "Sequence: " + str(packet[2]),
if packet[3]:
print " Words:",
for word in packet[3]:
print "\"" + word + "\"",
print ""
###################################################################################
def generatePasswordHash(salt, password):
m = md5.new()
m.update(salt)
m.update(password)
return m.digest()
###################################################################################
# Example program
if __name__ == '__main__':
from getopt import getopt
import sys
global running
print "Remote administration console for BFBC2"
# history_file = os.path.join( os.environ["HOME"], ".bfbc2_rcon_history" )
host = raw_input('Enter game server host IP/name: ')
port = int(raw_input('Enter host port: '))
pw = raw_input('Enter password: ')
serverSocket = None
running = True
opts, args = getopt(sys.argv[1:], 'h:p:a:')
for k, v in opts:
if k == '-h':
host = v
elif k == '-p':
port = int(v)
elif k == '-a':
pw = v
try:
try:
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Connecting to port: %s:%d...' % ( host, port )
serverSocket.connect( ( host, port ) )
serverSocket.setblocking(1)
if pw is not None:
print 'Logging in - 1: retrieving salt...'
# Retrieve this connection's 'salt' (magic value used when encoding password) from server
getPasswordSaltRequest = EncodeClientRequest( [ "login.hashed" ] )
serverSocket.send(getPasswordSaltRequest)
getPasswordSaltResponse = serverSocket.recv(4096)
printPacket(DecodePacket(getPasswordSaltResponse))
[isFromServer, isResponse, sequence, words] = DecodePacket(getPasswordSaltResponse)
# if the server doesn't understand "login.hashed" command, abort
if words[0] != "OK":
sys.exit(0);
print 'Received salt: ' + words[1]
# Given the salt and the password, combine them and compute hash value
salt = words[1].decode("hex")
passwordHash = generatePasswordHash(salt, pw)
passwordHashHexString = string.upper(passwordHash.encode("hex"))
print 'Computed password hash: ' + passwordHashHexString
# Send password hash to server
print 'Logging in - 2: sending hash...'
loginRequest = EncodeClientRequest( [ "login.hashed", passwordHashHexString ] )
serverSocket.send(loginRequest)
loginResponse = serverSocket.recv(4096)
printPacket(DecodePacket(loginResponse))
[isFromServer, isResponse, sequence, words] = DecodePacket(loginResponse)
# if the server didn't like our password, abort
if words[0] != "OK":
sys.exit(0);
while running:
command = raw_input( "> " )
words = shlex.split(command)
if len(words) >= 1:
if "quit" == words[0]:
running = False
# Send request to server on command channel
request = EncodeClientRequest(words)
serverSocket.send(request)
# Wait for response from server
packet = serverSocket.recv(4096)
[isFromServer, isResponse, sequence, words] = DecodePacket(packet)
# The packet from the server should
# For now, we always respond with an "OK"
if not isResponse:
print 'Received an unexpected request packet from server, ignored:'
printPacket(DecodePacket(packet))
except socket.error, detail:
print 'Network error:', detail[1]
except EOFError, KeyboardInterrupt:
pass
except:
raise
finally:
try:
if serverSocket is not None:
serverSocket.close()
print "Done"
except:
raise
sys.exit( 0 )
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks. I've managed, I think, to muddle my way through it. I'll know when I send my first packet and get a valid response. Or not. :)
ASKER
Not what I was hoping for but... It'll do.
ASKER