Undocumented Windows cryptography
The last time we described semi- and undocumented functions in Windows, these were compression functions. Today’s subject is cryptographic functions. There are such functions in Windows core that allows you to use few cryptographic primitives easier, without whole CAPI overhead and hassle. Here is an example of how to generate secure random numbers and calculate SHA-1 hash.
First, a C header file capix.h which you may use in your own programs right away:
/* =======================================================================
CAPIx
Few cryptographic primitives for direct usage without CAPI overhead.
Based on un(semi)documented Windows XP+ interface
========================================================================= */
#pragma warning (push, 1)
#define WINDOWS_MEAN_AND_LEAN
#include <windows.h>
#pragma warning(pop)
typedef struct {
ULONG SomeJunk[6];
ULONG State[5];
ULONG Count[2];
UCHAR Buffer[64];
} SHA_CONTEXT, *PSHA_CONTEXT;
typedef BOOL (__stdcall *RtlGenRandom_Fn)(OUT PVOID, IN ULONG);
typedef PVOID (__stdcall *SHA_Init_Fn)(IN OUT PSHA_CONTEXT);
typedef PVOID (__stdcall *SHA_Update_Fn)(IN OUT PSHA_CONTEXT, IN PCHAR, IN UINT);
typedef PVOID (__stdcall *SHA_Final_Fn)(IN OUT PSHA_CONTEXT, OUT PVOID);
static HANDLE hAA32DLL = NULL;
static RtlGenRandom_Fn pf_rand = NULL;
static SHA_Init_Fn pf_sha_init = NULL;
static SHA_Update_Fn pf_sha_update = NULL;
static SHA_Final_Fn pf_sha_final = NULL;
BOOL InitCAPIX (void)
{
hAA32DLL = LoadLibrary ("advapi32.dll");
if ( hAA32DLL != NULL )
{
pf_rand = (RtlGenRandom_Fn) GetProcAddress(hAA32DLL, "SystemFunction036");
pf_sha_init = (SHA_Init_Fn) GetProcAddress(hAA32DLL, "A_SHAInit");
pf_sha_update = (SHA_Update_Fn) GetProcAddress(hAA32DLL, "A_SHAUpdate");
pf_sha_final = (SHA_Final_Fn) GetProcAddress(hAA32DLL, "A_SHAFinal");
}
return ( hAA32DLL != NULL );
} /* initcapix */
void _inline ReleaseCAPIX (void)
{
pf_rand = NULL;
pf_sha_init = NULL;
pf_sha_update = NULL;
pf_sha_final = NULL;
while (!FreeLibrary (hAA32DLL) );
hAA32DLL = NULL;
} /* donecapix */
#define random_s(x,y) ((pf_rand != NULL)?(*pf_rand)(x,y):FALSE)
#define sha1_init(x) ((pf_sha_init != NULL)?(*pf_sha_init)(x):NULL)
#define sha1_update(x,y,z) ((pf_sha_update != NULL)?(*pf_sha_update)(x,(PCHAR)y,z):NULL)
#define sha1_final(x,y) ((pf_sha_final != NULL)?(*pf_sha_final)(x,y):NULL)
Next is a C demo program that uses capix.h:
#pragma warning (push, 1)
#include "capix.h"
#include <stdlib.h>
#include <stdio.h>
#pragma warning(pop)
int main (void)
{
BYTE hash[20] = {0}, buf[12] = {0};
SHA_CONTEXT ctx;
PVOID dw;
register BYTE i;
InitCAPIX();
if ( !random_s(buf, sizeof(buf)) ) printf("Failed at generate random\n");
printf("data: ");
for (i = 0; i< sizeof(buf); i++) printf("%02x", buf[i]);
printf("\n");
dw = sha1_init(&ctx);
if ( dw ) dw = sha1_update(&ctx, buf, sizeof(buf));
if ( dw ) dw = sha1_final(&ctx, hash);
if ( dw )
{
printf("hash: ");
for (i = 0; i< sizeof(hash); i++) printf("%02x", hash[i]);
printf("\n");
}
else printf("SHA1 functions failed\n");
ReleaseCAPIX();
return 0;
}
Reddit this / Add to del.icio.us / Digg this!
Subscribe to RSS feed