📄 randlib.c
字号:
&dwBytesThisPass
)) {
return FALSE;
}
dwFilledBytes += dwBytesThisPass;
}
return TRUE;
}
BOOL
RandomFillBuffer(
OUT BYTE *pbBuffer,
IN DWORD *pdwLength
)
{
unsigned int RC4BytesUsed;
unsigned int KeyId;
#ifdef KMODE_RNG
PAGED_CODE();
#endif // KMODE_RNG
//
// update circular hash with user supplied bits.
//
if(!UpdateCircularHash( &g_CircularHashCtx, pbBuffer, *pdwLength ))
return FALSE;
//
// select key.
//
rc4_safe_select( g_RC4SafeCtx, &KeyId, &RC4BytesUsed );
//
// check if re-key required.
//
if ( RC4BytesUsed >= g_dwRC4RekeyParam )
{
PBYTE pbCircularHash;
DWORD cbCircularHash;
BYTE pbRandomKey[ 256 ];
DWORD cbRandomKey = sizeof(pbRandomKey);
RC4BytesUsed = g_dwRC4RekeyParam;
if(!GetCircularHashValue(
&g_CircularHashCtx,
&pbCircularHash,
&cbCircularHash
)) {
return FALSE;
}
if(!GatherRandomKey( pbCircularHash, cbCircularHash, pbRandomKey, &cbRandomKey ))
return FALSE;
//
// Create RC4 key
//
rc4_safe_key(
g_RC4SafeCtx,
KeyId,
cbRandomKey,
pbRandomKey
);
ZeroMemory( pbRandomKey, sizeof(pbRandomKey) );
}
//
// only use RC4_REKEY_PARAM bytes from each RC4 key
//
{
DWORD dwMaxPossibleBytes = g_dwRC4RekeyParam - RC4BytesUsed;
if (*pdwLength > dwMaxPossibleBytes)
*pdwLength = dwMaxPossibleBytes;
}
rc4_safe( g_RC4SafeCtx, KeyId, *pdwLength, pbBuffer );
return TRUE;
}
#ifdef KMODE_RNG
#ifdef USE_HW_RNG
#ifdef _M_IX86
#define NUM_HW_DWORDS_TO_GATHER 4
#define INTEL_DRIVER_NAME L"\\Device\\ISECDRV"
unsigned int
QueryForHWRandomBits(
IN DWORD *pdwRandom,
IN OUT DWORD cdwRandom
)
{
UNICODE_STRING ObjectName;
IO_STATUS_BLOCK StatusBlock;
KEVENT Event;
PIRP pIrp = NULL;
ISD_Capability ISD_Cap; //in/out for GetCapability
ISD_RandomNumber ISD_Random; //in/out for GetRandomNumber
PDEVICE_OBJECT pDeviceObject = NULL;
DWORD i = 0;
unsigned int Status = ERROR_SUCCESS;
PAGED_CODE();
if (1 == g_dwHWDriver)
{
Status = STATUS_ACCESS_DENIED;
goto Ret;
}
ZeroMemory( &ObjectName, sizeof(ObjectName) );
ZeroMemory( &StatusBlock, sizeof(StatusBlock) );
ZeroMemory(&ISD_Cap, sizeof(ISD_Cap));
if (NULL == g_pDeviceObject)
{
ObjectName.Length = sizeof(INTEL_DRIVER_NAME) - sizeof(WCHAR);
ObjectName.MaximumLength = sizeof(INTEL_DRIVER_NAME);
ObjectName.Buffer = INTEL_DRIVER_NAME;
Status = IoGetDeviceObjectPointer(&ObjectName,
FILE_ALL_ACCESS,
&g_pFileObject,
&pDeviceObject);
if ( !NT_SUCCESS(Status) )
{
g_dwHWDriver = 1;
goto Ret;
}
if (NULL == g_pDeviceObject)
{
InterlockedExchangePointer(&g_pDeviceObject, pDeviceObject);
}
}
//
// If this fails then it is because there is no such device
// which signals completion.
//
KeInitializeEvent(&Event, NotificationEvent, FALSE);
ISD_Cap.uiIndex = ISD_RNG_ENABLED; //Set input member
pIrp = IoBuildDeviceIoControlRequest(
IOCTL_ISD_GetCapability,
g_pDeviceObject,
&ISD_Cap,
sizeof(ISD_Cap),
&ISD_Cap,
sizeof(ISD_Cap),
FALSE,
&Event,
&StatusBlock);
if (pIrp == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Ret;
}
Status = IoCallDriver(g_pDeviceObject, pIrp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = StatusBlock.Status;
}
if (ISD_Cap.iStatus != ISD_EOK) {
Status = STATUS_NOT_IMPLEMENTED;
goto Ret;
}
// now get the random bits
for (i = 0; i < cdwRandom; i++) {
ZeroMemory(&ISD_Random, sizeof(ISD_Random));
KeInitializeEvent(&Event, NotificationEvent, FALSE);
pIrp = IoBuildDeviceIoControlRequest(
IOCTL_ISD_GetRandomNumber,
g_pDeviceObject,
&ISD_Random,
sizeof(ISD_Random),
&ISD_Random,
sizeof(ISD_Random),
FALSE,
&Event,
&StatusBlock);
if (pIrp == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Ret;
}
Status = IoCallDriver(g_pDeviceObject, pIrp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = StatusBlock.Status;
}
if (ISD_Random.iStatus != ISD_EOK) {
Status = STATUS_NOT_IMPLEMENTED;
goto Ret;
}
pdwRandom[i] = pdwRandom[i] ^ ISD_Random.uiRandomNum;
}
Ret:
return Status;
}
#endif // _M_IX86
#endif // USE_HW_RNG
#endif // KMODE_RNG
BOOL
GatherRandomKey(
IN BYTE *pbUserSeed,
IN DWORD cbUserSeed,
IN OUT BYTE *pbRandomKey,
IN OUT DWORD *pcbRandomKey
)
{
LPBYTE pbWorkingBuffer = NULL;
DWORD cbWorkingBuffer;
DWORD cbBufferRemaining;
BYTE *pbCurrentBuffer;
DWORD *pdwTmp;
BOOL fRet;
#ifdef KMODE_RNG
PAGED_CODE();
#endif // KMODE_RNG
//
// in NT Usermode, try to re-seed by calling the Kernelmode RNG.
//
#ifndef KMODE_RNG
if( GatherRandomKeyFastUserMode( pbUserSeed, cbUserSeed, pbRandomKey, pcbRandomKey ))
return TRUE;
#endif
//
// verify current working buffer has space for candidate data.
//
#define VERIFY_BUFFER( size ) { \
if( cbBufferRemaining < size ) \
goto finished; \
}
//
// update working buffer and increment to next QWORD aligned boundary.
//
#define UPDATE_BUFFER( size ) { \
DWORD dwSizeRounded; \
dwSizeRounded = (size + sizeof(ULONG64)) & ~(sizeof(ULONG64)-1); \
if(dwSizeRounded > cbBufferRemaining) \
goto finished; \
pbCurrentBuffer += dwSizeRounded; \
cbBufferRemaining -= dwSizeRounded; \
}
cbWorkingBuffer = 3584;
pbWorkingBuffer = (PBYTE)ALLOC( cbWorkingBuffer );
if( pbWorkingBuffer == NULL ) {
return FALSE;
}
cbBufferRemaining = cbWorkingBuffer;
pbCurrentBuffer = pbWorkingBuffer;
//
// pickup user supplied bits.
//
VERIFY_BUFFER( cbUserSeed );
CopyMemory( pbCurrentBuffer, pbUserSeed, cbUserSeed );
UPDATE_BUFFER( cbUserSeed );
//
// ** indicates US DoD's specific recommendations for password generation
//
//
// process id
//
pdwTmp = (PDWORD)pbCurrentBuffer;
#ifndef KMODE_RNG
*pdwTmp = GetCurrentProcessId();
#else
/// *pdwTmp = PsGetCurrentProcessId();
#endif
UPDATE_BUFFER( sizeof(DWORD) );
//
// thread id
//
pdwTmp = (PDWORD)pbCurrentBuffer;
#ifndef KMODE_RNG
*pdwTmp = GetCurrentThreadId();
#else
/// *pdwTmp = PsGetCurrentThreadId();
#endif
UPDATE_BUFFER( sizeof(DWORD) );
//
// ** ticks since boot (system clock)
//
pdwTmp = (PDWORD)pbCurrentBuffer;
#ifndef KMODE_RNG
*pdwTmp = GetTickCount();
#else
/// *pdwTmp = NtGetTickCount();
#endif // !KMODE_RNG
UPDATE_BUFFER( sizeof(DWORD) );
//
// ** system time, in ms, sec, min (date & time)
//
#ifndef KMODE_RNG
{
PSYSTEMTIME psysTime = (PSYSTEMTIME)pbCurrentBuffer;
VERIFY_BUFFER( sizeof( *psysTime ) );
GetLocalTime(psysTime);
UPDATE_BUFFER( sizeof( *psysTime ) );
}
#else
{
PSYSTEM_TIMEOFDAY_INFORMATION pTimeOfDay;
ULONG cbSystemInfo;
pTimeOfDay = (PSYSTEM_TIMEOFDAY_INFORMATION)pbCurrentBuffer;
VERIFY_BUFFER( sizeof(*pTimeOfDay) );
_NtQuerySystemInformation(
SystemTimeOfDayInformation,
pTimeOfDay,
sizeof(*pTimeOfDay),
&cbSystemInfo
);
UPDATE_BUFFER( cbSystemInfo );
}
#endif // !KMODE_RNG
//
// ** hi-res performance counter (system counters)
//
{
LARGE_INTEGER *pliPerfCount = (PLARGE_INTEGER)pbCurrentBuffer;
VERIFY_BUFFER( sizeof(*pliPerfCount) );
#ifndef KMODE_RNG
QueryPerformanceCounter(pliPerfCount);
#else
/// ZwQueryPerformanceCounter(pliPerfCount, &liPerfFreq);
#endif // !KMODE_RNG
UPDATE_BUFFER( sizeof(*pliPerfCount) );
}
#ifndef KMODE_RNG
//
// memory status
//
{
MEMORYSTATUS *pmstMemStat = (MEMORYSTATUS *)pbCurrentBuffer;
VERIFY_BUFFER( sizeof(*pmstMemStat) );
pmstMemStat->dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus( pmstMemStat );
UPDATE_BUFFER( sizeof(*pmstMemStat) );
}
#endif // !KMODE_RNG
//
// free disk clusters
//
#ifndef KMODE_RNG
{
PDWORD pdwDiskInfo = (PDWORD)pbCurrentBuffer;
VERIFY_BUFFER( (sizeof(DWORD) * 4) );
GetDiskFreeSpace(
NULL,
&pdwDiskInfo[0], // sectors per cluster
&pdwDiskInfo[1], // bytes per sector
&pdwDiskInfo[2], // number of free clusters
&pdwDiskInfo[3] // total number of clusters
);
UPDATE_BUFFER( (sizeof(DWORD) * 4) );
}
#endif // !KMODE_RNG
#ifndef KMODE_RNG
{
#if 0
//
// hash the entire user environment block.
// we do this instead of GetUserName & GetComputerName,
// as the environment block contains these values, plus additional
// values.
//
static BOOL fHashedEnv;
static BYTE HashEnv[ MD4_LEN ];
if( !fHashedEnv ) {
LPVOID lpEnvBlock;
BOOL fAnsi = FALSE;
//
// try the Unicode version first, as, on WinNT, this returns us
// a pointer to the existing Unicode environment block, rather
// than an allocated copy. Fallback to ANSI if this fails (eg: Win9x)
//
lpEnvBlock = GetEnvironmentStringsW();
if( lpEnvBlock == NULL )
{
lpEnvBlock = GetEnvironmentStringsA();
fAnsi = TRUE;
}
if( lpEnvBlock != NULL ) {
ULONG cbEntry;
PBYTE pbEntry;
MD4_CTX MD4Ctx;
MD4Init( &MD4Ctx );
pbEntry = (PBYTE)lpEnvBlock;
cbEntry = 0;
do {
if( !fAnsi ) {
pbEntry += (cbEntry + sizeof(WCHAR));
cbEntry = lstrlenW( (LPWSTR)pbEntry ) * sizeof(WCHAR);
} else {
pbEntry += (cbEntry + sizeof(CHAR));
cbEntry = lstrlenA( (LPSTR)pbEntry ) * sizeof(CHAR);
}
MD4Update(
&MD4Ctx,
(unsigned char *)pbEntry,
(unsigned int)cbEntry
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -