ctf-writeup/2020/flare-on/6_-_codeit/wincrypto/native.py
2021-02-05 23:42:57 +07:00

132 lines
4.0 KiB
Python

from ctypes import FormatError
from ctypes import windll, c_void_p, byref, create_string_buffer, c_int
import struct
from wincrypto.constants import HP_ALGID, HP_HASHSIZE, KP_KEYLEN, KP_ALGID, CRYPT_EXPORTABLE
PROV_RSA_FULL = 1
PROV_RSA_AES = 24
def assert_success(success):
if not success:
raise AssertionError(FormatError())
def CryptAcquireContext():
hprov = c_void_p()
success = windll.advapi32.CryptAcquireContextA(byref(hprov), 0, 0, PROV_RSA_AES, 0)
assert_success(success)
return hprov
def CryptReleaseContext(hprov):
success = windll.advapi32.CryptReleaseContext(hprov, 0)
assert_success(success)
def CryptImportKey(hprov, keyblob, hPubKey=0):
hkey = c_void_p()
success = windll.advapi32.CryptImportKey(hprov, keyblob, len(keyblob), hPubKey, 0, byref(hkey))
assert_success(success)
return hkey
def CryptExportKey(hkey, hexpkey, blobType):
# determine output buffer length
bdatalen = c_int(0)
success = windll.advapi32.CryptExportKey(hkey, hexpkey, blobType, 0, 0, byref(bdatalen))
assert_success(success)
# export key
bdata = create_string_buffer(b'', bdatalen.value)
success = windll.advapi32.CryptExportKey(hkey, hexpkey, blobType, 0, bdata, byref(bdatalen))
assert_success(success)
return bdata.raw[:bdatalen.value]
def CryptDestroyKey(hkey):
success = windll.advapi32.CryptDestroyKey(hkey)
assert_success(success)
def CryptDecrypt(hkey, encrypted_data):
bdata = create_string_buffer(encrypted_data)
bdatalen = c_int(len(encrypted_data))
success = windll.advapi32.CryptDecrypt(hkey, 0, 1, 0, bdata, byref(bdatalen))
assert_success(success)
return bdata.raw[:bdatalen.value]
def CryptEncrypt(hkey, plain_data):
# determine output buffer length
bdatalen_test = c_int(len(plain_data))
success = windll.advapi32.CryptEncrypt(hkey, 0, 1, 0, 0, byref(bdatalen_test), len(plain_data))
assert_success(success)
out_buf_len = bdatalen_test.value
# encrypt data
bdata = create_string_buffer(plain_data, out_buf_len)
bdatalen = c_int(len(plain_data))
success = windll.advapi32.CryptEncrypt(hkey, 0, 1, 0, bdata, byref(bdatalen), out_buf_len)
assert_success(success)
return bdata.raw[:bdatalen.value]
def CryptGetKeyParam(hkey, dwparam):
# determine output buffer length
bdatalen = c_int(0)
success = windll.advapi32.CryptGetKeyParam(hkey, dwparam, 0, byref(bdatalen), 0)
assert_success(success)
# get hash param
bdata = create_string_buffer(b'', bdatalen.value)
success = windll.advapi32.CryptGetKeyParam(hkey, dwparam, bdata, byref(bdatalen), 0)
assert_success(success)
result = bdata.raw[:bdatalen.value]
if dwparam in [KP_KEYLEN, KP_ALGID]:
result = struct.unpack('I', result)[0]
return result
def CryptCreateHash(hProv, Algid):
hCryptHash = c_void_p()
success = windll.advapi32.CryptCreateHash(hProv, Algid, 0, 0, byref(hCryptHash))
assert_success(success)
return hCryptHash
def CryptHashData(hHash, data):
bdata = create_string_buffer(data)
dwdatalen = c_int(len(data))
success = windll.advapi32.CryptHashData(hHash, bdata, dwdatalen, 0)
assert_success(success)
def CryptGetHashParam(hHash, dwParam):
# determine output buffer length
bdatalen = c_int(0)
success = windll.advapi32.CryptGetHashParam(hHash, dwParam, 0, byref(bdatalen), 0)
assert_success(success)
# get hash param
bdata = create_string_buffer(b'', bdatalen.value)
success = windll.advapi32.CryptGetHashParam(hHash, dwParam, bdata, byref(bdatalen), 0)
assert_success(success)
result = bdata.raw[:bdatalen.value]
if dwParam in [HP_ALGID, HP_HASHSIZE]:
result = struct.unpack('I', result)[0]
return result
def CryptDestroyHash(hCryptHash):
success = windll.advapi32.CryptDestroyHash(hCryptHash)
assert_success(success)
def CryptDeriveKey(hProv, Algid, hBaseData):
hkey = c_void_p()
success = windll.advapi32.CryptDeriveKey(hProv, Algid, hBaseData, CRYPT_EXPORTABLE, byref(hkey))
assert_success(success)
return hkey