Ilya O. Levin
My Mail Box 887644, Singapore, 917644
eli@literatecode.com
Dec 18, 2006

Undocumented Windows cryptography

Last time we described a set of semi- and undocumented data compression functions in Windows.

Today's subject is cryptographic functions.

There are such functions in Windows that allow you to use few cryptographic primitives easier, without a whole CAPI overhead and hassle.

Here is the C example of how to generate secure random numbers and calculate SHA-1 hash.

First, the header file capix.h:

/* =======================================================================
   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)

Now, the simple demo program:

#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;
}

Here we go. And remember, if you need a warning about not using such undocumented functions in your commercial software then you really should not do any.

© 2003 – 2012  Literatecode