Alexander Yaworsky wrote:
I've found alike functions (may be MD4 or MD5) in w2k advapi.dll by magic numbers but they are used internally. No exports even by ordinals.
XP's cryptdll exports MD5, MD4 and SHA functions but redirects them to advapi32.dll.
There is no decription of SHA and MD4 functions in platform SDK.
In any case the attached source code shows the prototypes of the SHA functions (now with proper legal header I hope :-). I guess the MD4 prototypes are similar to the MD5 ones and can be easily guessed.
- Filip
/* * ADVAPI32 Secure Hash Algorithm Test * Written by Filip Navara navaraf@reactos.com * Based on public domain SHA code by Steve Reid steve@edmweb.com * * THIS SOFTWARE IS NOT COPYRIGHTED * * This source code is offered for use in the public domain. You may * use, modify or distribute it freely. * * This code is distributed in the hope that it will be useful but * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY * DISCLAMED. This includes but is not limited to warrenties of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */
#include <windows.h> #include <stdio.h>
/* SHA Context Structure Declaration ******************************************/
typedef struct { ULONG Unknown[6]; ULONG State[5]; ULONG Count[2]; UCHAR Buffer[64]; } SHA_CTX, *PSHA_CTX;
/* SHA1 Helper Macros *********************************************************/
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* FIXME: This definition of blk0 is little endian specific! */ #define blk0(i) (Block[i] = (rol(Block[i],24)&0xFF00FF00)|(rol(Block[i],8)&0x00FF00FF)) #define blk1(i) (Block[i&15] = rol(Block[(i+13)&15]^Block[(i+8)&15]^Block[(i+2)&15]^Block[i&15],1))
#define f1(x,y,z) (z^(x&(y^z))) #define f2(x,y,z) (x^y^z) #define f3(x,y,z) ((x&y)|(z&(x|y))) #define f4(x,y,z) (x^y^z)
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */ void SHA1Transform(ULONG State[5], CHAR Buffer[64]) { ULONG a, b, c, d, e; ULONG *Block;
Block = (ULONG*)Buffer;
/* Copy Context->State[] to working variables */ a = State[0]; b = State[1]; c = State[2]; d = State[3]; e = State[4];
/* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working variables back into Context->State[] */ State[0] += a; State[1] += b; State[2] += c; State[3] += d; State[4] += e;
/* Wipe variables */ a = b = c = d = e = 0; }
/* SHA Functions **************************************************************/
/* * @implemented */ VOID STDCALL FiN_A_SHAInit(PSHA_CTX Context) { /* SHA1 initialization constants */ Context->State[0] = 0x67452301; Context->State[1] = 0xEFCDAB89; Context->State[2] = 0x98BADCFE; Context->State[3] = 0x10325476; Context->State[4] = 0xC3D2E1F0; Context->Count[0] = Context->Count[1] = 0; }
/* * @implemented */ VOID STDCALL FiN_A_SHAUpdate(PSHA_CTX Context, PCHAR Buffer, UINT BufferSize) { unsigned int i, j; ULONG BufferContentSize;
BufferContentSize = Context->Count[1] & 63; Context->Count[1] += BufferSize; if (Context->Count[1] < BufferSize) Context->Count[0]++; Context->Count[0] += (BufferSize >> 29);
if (BufferContentSize + BufferSize > 63) { RtlCopyMemory(&Context->Buffer[j], Buffer, (i = 64 - j)); SHA1Transform(Context->State, Context->Buffer); for (; i + 63 < BufferSize; i += 64) SHA1Transform(Context->State, &Buffer[i]); j = 0; } else { i = 0; }
if (BufferSize > i) RtlCopyMemory(&Context->Buffer[j], &Buffer[i], BufferSize - i); }
/* * @unimplemented */ VOID STDCALL FiN_A_SHAFinal(PSHA_CTX Context, PULONG Result) { /* FIXME: Do some finalization! */
RtlCopyMemory(Result, Context->State, sizeof(ULONG) * 5); FiN_A_SHAInit(Context); }
/* Test Functions *************************************************************/
typedef VOID (STDCALL *SHAInitFunc)(PSHA_CTX Context); typedef VOID (STDCALL *SHAUpdateFunc)(PSHA_CTX Context, PCHAR Buffer, UINT BufferSize); typedef VOID (STDCALL *SHAFinalFunc)(PSHA_CTX Context, PULONG Result);
VOID FASTCALL PrintSHAContext(PSHA_CTX Context) { printf("State: %x %x %x %x %x\n", Context->State[0], Context->State[1], Context->State[2], Context->State[3], Context->State[4]); printf("Count: %d %d\n", Context->Count[0], Context->Count[1]); }
int main() { SHA_CTX Context, Context2; ULONG ResultBuffer[5]; PCHAR TestBuffer = "In our Life there's If" "In our beliefs there's Lie" "In our business there is Sin" "In our bodies, there is Die"; ULONG TestBufferSize = strlen(TestBuffer);
HMODULE hLibrary; SHAInitFunc A_SHAInit; SHAUpdateFunc A_SHAUpdate; SHAFinalFunc A_SHAFinal;
hLibrary = LoadLibrary("advapi32.dll"); A_SHAInit = (SHAInitFunc)GetProcAddress(hLibrary, "A_SHAInit"); A_SHAUpdate = (SHAUpdateFunc)GetProcAddress(hLibrary, "A_SHAUpdate"); A_SHAFinal = (SHAFinalFunc)GetProcAddress(hLibrary, "A_SHAFinal");
RtlZeroMemory(&Context, sizeof(Context)); RtlZeroMemory(&Context2, sizeof(Context2));
printf("A_SHAInit\n"); A_SHAInit(&Context); PrintSHAContext(&Context);
printf("FiN_A_SHAInit\n"); FiN_A_SHAInit(&Context2); PrintSHAContext(&Context2);
printf("\n");
printf("A_SHAUpdate\n"); A_SHAUpdate(&Context, TestBuffer, TestBufferSize); PrintSHAContext(&Context);
printf("FiN_A_SHAUpdate\n"); FiN_A_SHAUpdate(&Context2, TestBuffer, TestBufferSize); PrintSHAContext(&Context2);
printf("\n");
printf("A_SHAFinal\n"); A_SHAFinal(&Context, ResultBuffer); PrintSHAContext(&Context); printf("Result: %x %x %x %x %x\n", ResultBuffer[0], ResultBuffer[1], ResultBuffer[2], ResultBuffer[3], ResultBuffer[4]);
printf("FiN_A_SHAFinal\n"); FiN_A_SHAFinal(&Context2, ResultBuffer); PrintSHAContext(&Context2); printf("Result: %x %x %x %x %x\n", ResultBuffer[0], ResultBuffer[1], ResultBuffer[2], ResultBuffer[3], ResultBuffer[4]);
FreeLibrary(hLibrary);
return 0; }