// IoEaTest.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include #include typedef struct _FILE_FULL_EA_INFORMATION { ULONG NextEntryOffset; UCHAR Flags; UCHAR EaNameLength; USHORT EaValueLength; CHAR EaName[1]; } FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION; #define ULONG_PTR unsigned char* #define NTSTATUS unsigned int #define STATUS_EA_LIST_INCONSISTENT 0x80000014L #define STATUS_SUCCESS 0x00000000L /* * @implemented */ NTSTATUS NTAPI IoCheckEaBufferValidityROS(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset) { PFILE_FULL_EA_INFORMATION EaBufferEnd; ULONG NextEaBufferOffset; UINT IntEaLength; /* Length of the rest. Initialize it to EaLength */ IntEaLength = EaLength; /* Initialize EaBuffer to EaBuffer */ EaBufferEnd = EaBuffer; /* The rest length of the buffer */ /* 8 = sizeof(ULONG) + sizeof(UCHAR) + sizeof(UCHAR) + sizeof(USHORT) */ while (IntEaLength >= 8) { /* The rest of the buffer must be greater than sizeof(FILE_FULL_EA_INFORMATION) + buffer */ NextEaBufferOffset = EaBufferEnd->EaNameLength+EaBufferEnd->EaValueLength + 9; if (IntEaLength >= NextEaBufferOffset) { /* is the EaBufferName terminated with zero? */ if (EaBufferEnd->EaName[EaBufferEnd->EaNameLength]==0) { /* more EaBuffers ahead */ if (EaBufferEnd->NextEntryOffset == 0) { /* test the rest buffersize */ IntEaLength = IntEaLength - NextEaBufferOffset; if (IntEaLength>=0) { return STATUS_SUCCESS; } } else { /* From MSDN (http://msdn2.microsoft.com/en-us/library/ms795740.aspx). For all entries except the last, the value of NextEntryOffset must be greater than zero and must fall on a ULONG boundary. */ NextEaBufferOffset = ((NextEaBufferOffset + 3) & 0xFFFFFFFC); if ((EaBufferEnd->NextEntryOffset == NextEaBufferOffset) && (EaBufferEnd->NextEntryOffset>0)) { /* The rest of the buffer must be greater than the next offset */ IntEaLength = IntEaLength - EaBufferEnd->NextEntryOffset; if (IntEaLength>=0) { EaBufferEnd = (PFILE_FULL_EA_INFORMATION)((ULONG_PTR)EaBufferEnd + EaBufferEnd->NextEntryOffset); continue; } } } } } break; } if (ErrorOffset != NULL) { /* calculate the error offset. */ *ErrorOffset = (ULONG)((ULONG_PTR)EaBufferEnd - (ULONG_PTR)EaBuffer); } return STATUS_EA_LIST_INCONSISTENT; } void CheckROSAgainstWinAndPrintResult(PFILE_FULL_EA_INFORMATION WinEaBuffer,PFILE_FULL_EA_INFORMATION ROSEaBuffer,NTSTATUS WinStatus,NTSTATUS ROSStatus,ULONG WinErrorOffset,ULONG ROSErrorOffset,int iBufferLength,int iTestCount,ULONG TestEaLength) { printf("Subtest:%i Status:%x EaErrorOffset:%x TestEaLength:%i passed - ",iTestCount,WinStatus,WinErrorOffset,TestEaLength); if (memcmp(WinEaBuffer,ROSEaBuffer,iBufferLength)==0) { if (WinStatus == ROSStatus) { if (WinErrorOffset == ROSErrorOffset) { printf("okay\n"); return; } } } printf("*failed*\n"); } typedef NTSTATUS (*NTAPI pIoCheckEaBufferValidity) (IN PFILE_FULL_EA_INFORMATION EaBuffer,IN ULONG EaLength,OUT PULONG ErrorOffset); typedef PVOID (*NTAPI pMmPageEntireDriver) (IN PVOID AddressWithinSection); #define RANDOM_INIT_ERROR 0xDEADBAD0 #define TEST_BUFFER_LEN 256 int _tmain(int argc, _TCHAR* argv[]) { void *pFunction; pIoCheckEaBufferValidity IoCheckEaBufferValidity; HMODULE hKrnlMod = LoadLibrary(L"ntoskrnl.exe"); if (hKrnlMod) { pFunction = GetProcAddress(hKrnlMod,"IoCheckEaBufferValidity"); IoCheckEaBufferValidity = (pIoCheckEaBufferValidity)pFunction; if (IoCheckEaBufferValidity!=NULL) { /* Check tes Windows Function */ ULONG ulWinError; ULONG ulROSError; NTSTATUS WinStatus; NTSTATUS ROSStatus; PFILE_FULL_EA_INFORMATION WinEaBuffer; PFILE_FULL_EA_INFORMATION ROSEaBuffer; char szTest[100] = "FltMgr"; int iTestCount,i; ULONG TestEaLength; UCHAR TestEaBufferFlags; // Test the flag TestEaBufferFlags = 0; iTestCount = 1; WinEaBuffer = (PFILE_FULL_EA_INFORMATION)malloc(TEST_BUFFER_LEN); ROSEaBuffer = (PFILE_FULL_EA_INFORMATION)malloc(TEST_BUFFER_LEN); printf("1.) Test : *********************\n"); /* Check EaLength calculation */ /* Here all zero : only i>9 pass the test with STATUS_SUCCESS */ for (i=0;iFlags = TestEaBufferFlags; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("2.) Test : *********************\n"); /* Here all zero but EaBuffer::EaName is set : will always end in STATUS_EA_LIST_INCONSISTENT */ /* There must a link to EaBuffer::EaName */ for (i=0;iEaName,"%x",RANDOM_INIT_ERROR); ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); ulROSError = RANDOM_INIT_ERROR; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("3.) Test : *********************\n"); /* Here EaBuffer::EaName is set and EaBuffer::EaNameLength is count up. EaLength is maxbuffer: STATUS_SUCCESS when EaBuffer::EaNameLength>strlen(EaBuffer::EaName) */ TestEaLength = TEST_BUFFER_LEN; for (i=0;iEaName,"%x",RANDOM_INIT_ERROR); WinEaBuffer->EaNameLength = i; ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); ROSEaBuffer->EaNameLength = i; ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("4.) Test : *********************\n"); /* Here EaBuffer::EaName is set and EaBuffer::EaNameLength is strlen(EaBuffer::EaName). EaLength is count: STATUS_SUCCESS when EaLength>=17 (EaBuffer::EaNameLength+9) */ for (i=0;iEaName,"%x",RANDOM_INIT_ERROR); WinEaBuffer->EaNameLength = (UCHAR)strlen(WinEaBuffer->EaName); ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); ROSEaBuffer->EaNameLength = (UCHAR)strlen(ROSEaBuffer->EaName); ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("5.) Test : *********************\n"); /* Here EaBuffer::EaName is set and EaBuffer::EaNameLength is strlen(EaBuffer::EaName) EaBuffer::EaValueLength is strlen(EaBuffer::EaName)+1. EaLength is count: STATUS_SUCCESS when EaLength>=26 (EaBuffer::EaNameLength+EaBuffer::EaValueLength+9) */ for (i=0;iEaName,"%x",RANDOM_INIT_ERROR); WinEaBuffer->EaNameLength = (UCHAR)strlen(WinEaBuffer->EaName); WinEaBuffer->EaValueLength = (UCHAR)strlen(WinEaBuffer->EaName)+1; ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); ROSEaBuffer->EaNameLength = (UCHAR)strlen(ROSEaBuffer->EaName); ROSEaBuffer->EaValueLength = (UCHAR)strlen(ROSEaBuffer->EaName)+1; ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("6.) Test : *********************\n"); /* The same test like 5.) but more data in the buffer*/ /* Here EaBuffer::EaName is set and EaBuffer::EaNameLength is strlen(EaBuffer::EaName) EaBuffer::EaValueLength is strlen(EaBuffer::EaName)+1. EaLength is count: STATUS_SUCCESS when EaLength>=26 (EaBuffer::EaNameLength+EaBuffer::EaValueLength+9) */ for (i=0;iEaName,"%x%x%x",RANDOM_INIT_ERROR,RANDOM_INIT_ERROR,RANDOM_INIT_ERROR); sprintf(WinEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); WinEaBuffer->EaNameLength = (UCHAR)strlen(WinEaBuffer->EaName); WinEaBuffer->EaValueLength = (UCHAR)strlen(WinEaBuffer->EaName)+1; ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x%x%x",RANDOM_INIT_ERROR,RANDOM_INIT_ERROR,RANDOM_INIT_ERROR); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); ROSEaBuffer->EaNameLength = (UCHAR)strlen(ROSEaBuffer->EaName); ROSEaBuffer->EaValueLength = (UCHAR)strlen(ROSEaBuffer->EaName)+1; ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("7.) Test : *********************\n"); /* The same test like 6.) but wrong strlen */ /* Here EaBuffer::EaName is set and EaBuffer::EaNameLength is strlen(EaBuffer::EaName) EaBuffer::EaValueLength is strlen(EaBuffer::EaName)+1. EaLength is count: will always end in STATUS_EA_LIST_INCONSISTENT */ for (i=0;iEaName,"%x%x%x",RANDOM_INIT_ERROR,RANDOM_INIT_ERROR,RANDOM_INIT_ERROR); sprintf(WinEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); WinEaBuffer->EaNameLength = (UCHAR)strlen(WinEaBuffer->EaName)-1; WinEaBuffer->EaValueLength = (UCHAR)strlen(WinEaBuffer->EaName)+2; ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x%x%x",RANDOM_INIT_ERROR,RANDOM_INIT_ERROR,RANDOM_INIT_ERROR); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); ROSEaBuffer->EaNameLength = (UCHAR)strlen(ROSEaBuffer->EaName)-1; ROSEaBuffer->EaValueLength = (UCHAR)strlen(ROSEaBuffer->EaName)+2; ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("8.) Test : *********************\n"); /* Here WinEaBuffer->NextEntryOffset test : STATUS_SUCCESS when NextEntryOffset=0 else STATUS_EA_LIST_INCONSISTENT when NextEntryOffset = 28 = 8+8+9 ((WinEaBuffer->EaNameLength+WinEaBuffer->EaNameLength+9)+3)&0xFFFFFFFC then ErrorOffset 28 */ /* From the MSDN (http://msdn2.microsoft.com/en-us/library/ms795740.aspx). For all entries except the last, the value of NextEntryOffset must be greater than zero and must fall on a ULONG boundary.*/ for (i=0;iEaName,"%x%x%x",RANDOM_INIT_ERROR,RANDOM_INIT_ERROR,RANDOM_INIT_ERROR); sprintf(WinEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); WinEaBuffer->EaNameLength = (UCHAR)strlen(WinEaBuffer->EaName); WinEaBuffer->EaValueLength = (UCHAR)strlen(WinEaBuffer->EaName); ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinEaBuffer->NextEntryOffset = i; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x%x%x",RANDOM_INIT_ERROR,RANDOM_INIT_ERROR,RANDOM_INIT_ERROR); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); ROSEaBuffer->EaNameLength = (UCHAR)strlen(ROSEaBuffer->EaName); ROSEaBuffer->EaValueLength = (UCHAR)strlen(ROSEaBuffer->EaName); ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSEaBuffer->NextEntryOffset = i; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); printf("%i-",ROSEaBuffer->NextEntryOffset); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("9.) Test : *********************\n"); /* Here WinEaBuffer->NextEntryOffset test wrong strlen: STATUS_SUCCESS NextEntryOffset=0 & NextEntryOffset = 28 = 8+8+9 ((WinEaBuffer->EaNameLength+WinEaBuffer->EaNameLength+9)+3)&0xFFFFFFFC */ /* From the MSDN (http://msdn2.microsoft.com/en-us/library/ms795740.aspx). For all entries except the last, the value of NextEntryOffset must be greater than zero and must fall on a ULONG boundary.*/ for (i=0;iEaName,"%x",RANDOM_INIT_ERROR); WinEaBuffer->EaNameLength = (UCHAR)strlen(WinEaBuffer->EaName)-1; WinEaBuffer->EaValueLength = (UCHAR)strlen(WinEaBuffer->EaName); ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinEaBuffer->NextEntryOffset = i; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); ROSEaBuffer->EaNameLength = (UCHAR)strlen(ROSEaBuffer->EaName)-1; ROSEaBuffer->EaValueLength = (UCHAR)strlen(ROSEaBuffer->EaName); ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSEaBuffer->NextEntryOffset = i; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); printf("%i-",ROSEaBuffer->NextEntryOffset); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("10.) Test : *********************\n"); /* Here WinEaBuffer->NextEntryOffset test wrong strlen: STATUS_SUCCESS NextEntryOffset=0 & NextEntryOffset = 28 = 8+8+9 ((WinEaBuffer->EaNameLength+WinEaBuffer->EaNameLength+9)+3)&0xFFFFFFFC */ /* From the MSDN (http://msdn2.microsoft.com/en-us/library/ms795740.aspx). For all entries except the last, the value of NextEntryOffset must be greater than zero and must fall on a ULONG boundary.*/ for (i=0;iEaName,"%x",RANDOM_INIT_ERROR); WinEaBuffer->EaNameLength = (UCHAR)strlen(WinEaBuffer->EaName)+1; WinEaBuffer->EaValueLength = (UCHAR)strlen(WinEaBuffer->EaName)+1; ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinEaBuffer->NextEntryOffset = i; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR); ROSEaBuffer->EaNameLength = (UCHAR)strlen(ROSEaBuffer->EaName)+1; ROSEaBuffer->EaValueLength = (UCHAR)strlen(ROSEaBuffer->EaName)+1; ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSEaBuffer->NextEntryOffset = i; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); printf("%i-",ROSEaBuffer->NextEntryOffset); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } printf("11.) Test : *********************\n"); /* Here WinEaBuffer->NextEntryOffset : */ for (i=0;iEaName,"%x",RANDOM_INIT_ERROR,RANDOM_INIT_ERROR); WinEaBuffer->EaNameLength = (UCHAR)strlen(WinEaBuffer->EaName); WinEaBuffer->EaValueLength = (UCHAR)strlen(WinEaBuffer->EaName); ulWinError = RANDOM_INIT_ERROR; WinEaBuffer->Flags = TestEaBufferFlags; WinEaBuffer->NextEntryOffset = ((WinEaBuffer->EaNameLength+WinEaBuffer->EaNameLength+9)+3)&0xFFFFFFFC; WinStatus = IoCheckEaBufferValidity(WinEaBuffer,TestEaLength,&ulWinError); // ROS memset(ROSEaBuffer,0,TEST_BUFFER_LEN); sprintf(ROSEaBuffer->EaName,"%x",RANDOM_INIT_ERROR,RANDOM_INIT_ERROR); ROSEaBuffer->EaNameLength = (UCHAR)strlen(ROSEaBuffer->EaName); ROSEaBuffer->EaValueLength = (UCHAR)strlen(ROSEaBuffer->EaName); ulROSError = RANDOM_INIT_ERROR; ROSEaBuffer->Flags = TestEaBufferFlags; ROSEaBuffer->NextEntryOffset = ((ROSEaBuffer->EaNameLength+ROSEaBuffer->EaNameLength+9)+3)&0xFFFFFFFC; ROSStatus = IoCheckEaBufferValidityROS(ROSEaBuffer,TestEaLength,&ulROSError); printf("%i-",ROSEaBuffer->NextEntryOffset); CheckROSAgainstWinAndPrintResult(WinEaBuffer,ROSEaBuffer,WinStatus,ROSStatus,ulWinError,ulWinError,TEST_BUFFER_LEN,iTestCount,TestEaLength); iTestCount++; } free(WinEaBuffer); free(ROSEaBuffer); } FreeLibrary(hKrnlMod); } else { DWORD dwLastError = GetLastError(); switch (dwLastError) { case ERROR_MOD_NOT_FOUND: printf("ERROR_MOD_NOT_FOUND\n"); break; case ERROR_BAD_EXE_FORMAT: printf("ERROR_BAD_EXE_FORMAT\n"); break; } } return 0; }