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.
#!/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 )

Open in new window

LiberationSoftAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

LiberationSoftAuthor Commented:
Anybody?  I'm attempting to muddle my way through the python but this is literally the first time I've looked at python...  and it's kickin my butt.   :)
0
Jorge PaulinoIT Pro/DeveloperCommented:
That's not a easy job and also not the propose of this page (like others on web).
If you use VS2010 you can take a look into dynamic support and use python on VB.NET (Ironpython). That way you can maybe use that code (maybe!).
It's better to create a new topic asking what you want to do and someone could provide you a solution, not a complete conversion.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
LiberationSoftAuthor Commented:
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.   :)
0
LiberationSoftAuthor Commented:
Not what I was hoping for but...  It'll do.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.