Valhalla Legends Forums Archive | Battle.net Bot Development | [Python] Using BNCSUtil with Python

AuthorMessageTime
Topaz
Used ctypes to access functions in BNCSUtil, [s]just finished the ones used for checkrevision[/s]. More will be ported as I complete them (watch this post).

[code]from ctypes import *
from struct import *

platformDict = { 'NIX':0x01, 'WIN32':0x01, 'PMAC':0x02, 'XMAC':0x03 }

bncsutil = windll.LoadLibrary('./bncsutil.dll')

#checkrevision functions

def extractMPQNumber(mpqName):
    return bncsutil.extractMPQNumber(mpqName)

def checkRevision(formula, hashFiles, mpqNumber):
    #Make sure hashFiles is a list - if it isn't, fail.
    if len(hashFiles) <> 3: return 0

    checkSum = create_string_buffer('\000' * 10) #mutable memory block
       
    if (bncsutil.checkRevisionFlat(formula, hashFiles[0], hashFiles[1],
                        hashFiles[2], mpqNumber, checkSum) == True):
        #unpack the checksum, return first value of tuple
        return unpack('L', checkSum.value)[0]
    else:
        #failed
        return 0
       
def getExeInfo(exe):
    size = 256
    infoString = create_string_buffer(256)
    version = create_string_buffer('\000' * 10)
       
    result = bncsutil.getExeInfo(exe, infoString, size, version, platformDict['WIN32'])

    while result > size:
        if size > 1024:
            return 0
        else:
            size = size + 256
            infoString = create_string_buffer(size)
           
            result = bncsutil.getExeInfo(exe, infoString, size, version, platformDict['WIN32'])

    version = unpack('L', version.value)[0] #unpack version
       
    return [version, infoString.value] #return version and info as a list

#ols functions

def doubleHashPassword( password, cToken, sToken):
    dHash = create_string_buffer(20)
    bncsutil.doubleHashPassword(password, cToken, sToken, dHash)

    return dHash.value

def hashPassword(password):
    pHash = create_string_buffer(20)
    bncsutil.hashPassword(password, pHash)

    return pHash.value

#sha1 function

def calcHashBuf(data):
        dataLen = len(data)
        dHash = create_string_buffer(20)

        bncsutil.calcHashBuf(data, dataLen, dHash)

        return dHash.value

#key decoding

def decodeCDKey(cdkey):
    bncsutil.kd_create(cdkey, len(cdkey))
       
    return decoder

def quickDecode(cdkey, cToken, sToken):
    pdtValue = create_string_buffer('\000' * 10)
    pvtValue = create_string_buffer('\000' * 10)
    keyHash = create_string_buffer(20)

    if (bncsutil.kd_quick(cdkey, cToken, sToken,
                          pdtValue, pvtValue, keyHash, 20)) == 0:
        return 0 #failed to decode cdkey
    else:
        #returns the product value, private value,
        # and hashed cdkey in a list
        return [pdtValue, pvtValue, keyHash]
       
def calcKeyHash(decoder, cToken, sToken):
    keyhash = bncsutil.kd_calculateHash(decoder, cToken, sToken)

    return unpack('L', decoder.value)[0]

def getKeyHash(decoder, hashLength, keyHash):
    keyHash = create_string_buffer(hashLength)
       
    bncsutil.kd_getHash(decoder, keyHash)

    return unpack('L', keyHash.value)[0]

def getValues(decoder):
    #product and private values
    pdtValue = unpack('L', bncsutil.kd_product(decoder).value)
    pvtValue = unpack('L', bncsutil.kd_val1(decoder).value)

    return (pdtValue, pvtValue)[/code]
July 11, 2006, 12:41 AM
Topaz
I decided to remove the use of classes to seperate the different functions - it cleaned up the code and made it easier to access the functions without needing to initialize anything.

[s]However, the keydecoding functions don't work[/s] - for some odd reason, the DLL attempts to read/write something it shouldn't be.

In case shadypalm88 looks at this:

[code]
traceback:

Traceback (most recent call last):
  File "C:\Projects\bot-python\bncsutil.py", line 98, in -toplevel-
    decoder = decodeCDKey('-------------')
  File "C:\Projects\bot-python\bncsutil.py", line 74, in decodeCDKey
    bncsutil.kd_create(cdkey, len(cdkey))
WindowsError: exception: access violation writing 0x00000010

code:

def decodeCDKey(cdkey):
    decoder = bncsutil.kd_create(cdkey, len(cdkey))
       
    return decoder[/code]

Post if you find out why its doing that or if you can fix it.

Edit: In the meantime, I wrote a function (quickdecode) that utilizes kd_quick().

[size=1]MyndFyre edit: removed your CD key[/size]
July 12, 2006, 9:28 AM
St0rm.iD
http://starship.python.net/crew/theller/ctypes/tutorial.html

I believe you need to pass a pointer (byref) to a byte array.
July 13, 2006, 3:00 AM
St0rm.iD
That is, I think you probably have to pass the result of create_string_buffer rather than an actual string. In addition, you might have to wrap it in ctypes.byref(), though I'm not sure. Give it a shot, see if it works.
July 13, 2006, 6:14 PM
Topaz
[quote author=Banana fanna fo fanna link=topic=15374.msg155668#msg155668 date=1152814476]
That is, I think you probably have to pass the result of create_string_buffer rather than an actual string. In addition, you might have to wrap it in ctypes.byref(), though I'm not sure. Give it a shot, see if it works.
[/quote]

Doesn't help, I tried:

[code]def decodeCDKey(cdkey):
    cdkey = create_string_buffer(cdkey)
    decoder = bncsutil.kd_create(cdkey, 13)
       
    return decoder[/code]

I'm not allowed to use Byref(), since it requires an integer and the cdkey is thirteen digits in length.
July 13, 2006, 11:47 PM
Topaz
I've come to think kd_create() is broken - in the VB6 example, shadypalm88 uses kd_quick(), but uses kd_create() in the previous version-/example.
July 14, 2006, 7:57 AM

Search