Literatecode

Undocumented Windows cryptography

Dec 18, 2006

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 an entire CAPI overhead and hassle.

Here is the C example of how to generate secure random numbers and calculate the 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.


Contact Us

E-mail

hello@literatecode.com

Phone

+1 202 470 0042

Regular Mail

Literatecode
22 Sin Ming Lane #06-76
Midview City
Singapore 573969