static VOID TH32FreeAllocatedResources(PRTL_DEBUG_INFORMATION HeapDebug, PRTL_DEBUG_INFORMATION ModuleDebug, PVOID ProcThrdInfo, SIZE_T ProcThrdInfoSize) { if(HeapDebug != NULL) { RtlDestroyQueryDebugBuffer(HeapDebug); } if(ModuleDebug != NULL) { RtlDestroyQueryDebugBuffer(ModuleDebug); } if(ProcThrdInfo != NULL) { NtFreeVirtualMemory(NtCurrentProcess(), &ProcThrdInfo, &ProcThrdInfoSize, MEM_RELEASE); } }
BOOL NTAPI BaseDestroyVDMEnvironment(IN PANSI_STRING AnsiEnv, IN PUNICODE_STRING UnicodeEnv) { ULONG Dummy = 0; /* Clear the ASCII buffer since Rtl creates this for us */ if (AnsiEnv->Buffer) RtlFreeAnsiString(AnsiEnv); /* The Unicode buffer is build by hand, though */ if (UnicodeEnv->Buffer) { /* So clear it through the API */ NtFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&UnicodeEnv->Buffer, &Dummy, MEM_RELEASE); } /* All done */ return TRUE; }
/* * SfcIsFileLegit * * Purpose: * * Verify file to be legit ZeroAccess signed binary. * * Verification algorithm (as for current version) * * 1. Open dll file, read it to the allocated buffer, read extended attribute VER, * containing retL packet data regarding file FileName, TimeStamp, FileSize, * Signature (unusued in this verification); * * 2. Import required RSA key (hardcoded in the bot); * * 3. Calc MD5 for FileName+TimeStamp+FileSize values; * * 4. Find resource [1] in dll file, which is embedded signature used to check; * * 5. Remember PE header CRC value, set it to zero in PE file buffer; * * 6. Copy embedded signature [1] to preallocated buffer, zero it in PE file buffer; * * 7. Update MD5 for PE file buffer (excluding PE CRC and signature); * * 8. Use result MD5 as hash value; * * 9. Verify embedded signature. * * If anything from the above fail - file is not legit by ZeroAccess opinion. * * If you copy ZeroAccess downloaded files without copying EA data, it cannot be verified. * */ NTSTATUS SfcIsFileLegit( _In_ LPWSTR lpFileName, _In_ PBYTE BotKey, _In_ DWORD BotKeySize ) { BOOL cond = FALSE; PVOID pBuffer; MD5_CTX context; ZA_FILEHEADER zaHeader; HCRYPTPROV lh_prov = 0; HCRYPTKEY lh_key = 0; HANDLE hFile = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; UNICODE_STRING usFileName; SIZE_T memIO = 0; if ( (lpFileName == NULL) || (BotKey == NULL) || (BotKeySize == 0) ) { return status; } RtlSecureZeroMemory(&usFileName, sizeof(usFileName)); do { if (RtlDosPathNameToNtPathName_U(lpFileName, &usFileName, NULL, NULL) == FALSE) break; InitializeObjectAttributes(&ObjectAttributes, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); status = NtOpenFile(&hFile, FILE_GENERIC_READ, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) break; RtlFreeUnicodeString(&usFileName); RtlSecureZeroMemory(&zaHeader, sizeof(zaHeader)); if (!SfNtfsQueryFileHeaderFromEa(hFile, &zaHeader)) { status = STATUS_EA_LIST_INCONSISTENT; break; } status = STATUS_UNSUCCESSFUL; memIO = zaHeader.Size; pBuffer = NULL; if ( (NT_SUCCESS(NtAllocateVirtualMemory(NtCurrentProcess(), &pBuffer, 0, &memIO, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))) && (pBuffer != NULL) ) { if (NT_SUCCESS(NtReadFile(hFile, NULL, NULL, NULL, &IoStatusBlock, pBuffer, zaHeader.Size, NULL, NULL))) { if (CryptAcquireContext(&lh_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { if (CryptImportKey(lh_prov, (const BYTE *)BotKey, BotKeySize, 0, 0, &lh_key)) { RtlSecureZeroMemory(&context, sizeof(context)); MD5Init(&context); MD5Update(&context, (UCHAR*)&zaHeader, (UINT)3 * sizeof(ULONG)); //note: ZA_FILEHEADER without signature if (SfcVerifyFile(lh_prov, lh_key, &context, pBuffer, zaHeader.Size)) status = STATUS_SUCCESS; CryptDestroyKey(lh_key); } CryptReleaseContext(lh_prov, 0); } } memIO = 0; NtFreeVirtualMemory(NtCurrentProcess(), &pBuffer, &memIO, MEM_RELEASE); } NtClose(hFile); hFile = NULL; } while (cond); if (hFile != NULL) NtClose(hFile); if (usFileName.Buffer != NULL) { RtlFreeUnicodeString(&usFileName); } return status; }
LPVOID engine_HookFunctionInProcess(HANDLE hProcess,LPSTR lpModuleName,LPSTR lpFunctionName,LPVOID lpHookFunctionAddress,PDWORD pdwHookFunctionSize,LPVOID* lpFunctionAddress,INT iRndJmp) { LPVOID lpModule=NULL; LPVOID lpFunction=NULL; MEMORY_BASIC_INFORMATION mbi; CHAR lpTmpFunction[MAX_FUNC_LEN*2]; CHAR lpLocalStub[MAX_FUNC_LEN*3]; CHAR lpLocalFunc[MAX_FUNC_LEN*3]; DWORD dwBytesRead; DWORD dwReadLen=0; DWORD dwExistingJMP=0; DWORD dwStubSize; DWORD dwFree=0; DWORD dwBytesWritten; DWORD dwOldProtect; LPVOID lpRemoteStub=NULL; INT iFuncLen; PBYTE pReadAddress; NTSTATUS ntStatus; // Get module address lpModule=(LPVOID)engine_GetRemoteModuleHandle(hProcess,lpModuleName); if (!lpModule) return NULL; // Get function address lpFunction=engine_GetRemoteProcAddress(hProcess,lpModule,lpFunctionName); if (!lpFunction) return NULL; // Get info about the function address if (!NT_SUCCESS(SafeNtQueryVirtualMemory(hProcess,lpFunction,MemoryBasicInformation,&mbi,sizeof(mbi),NULL))) return NULL; // Flush instruction cache NtFlushInstructionCache(hProcess,mbi.BaseAddress,mbi.RegionSize); // Change the protection for the region if (!NT_SUCCESS(NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,PAGE_EXECUTE_READWRITE,&mbi.Protect))) return NULL; // Fill stub buffer with nops RtlFillMemory(lpLocalStub,MAX_FUNC_LEN*3,NOP); // Read MAX_FUNC_LEN instruction(s) from the function into our function buffer if (!NT_SUCCESS(SafeNtReadVirtualMemory(hProcess,lpFunction,lpTmpFunction,MAX_FUNC_LEN*2,&dwBytesRead))) { NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); return NULL; } pReadAddress=(PBYTE)lpTmpFunction; // check if first opcode in the function is a another jump if (*pReadAddress==LONG_JMP_OPCODE) { // get relative address memcpy(&dwExistingJMP,pReadAddress+1,4); // get absolute address dwExistingJMP=(DWORD)lpFunction+dwExistingJMP; // readlen dwReadLen=jtJmpTable[RELATIVE_JMP].iCodeSize engine_BuildJMPBuffer((CHAR*)lpLocalStub,((DWORD)lpRemoteStub+dwReadLen)-dwExistingJMP,RELATIVE_JMP); NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); return NULL; } // Get the length of the first instruction(s) // This part is done by Z0MBiE's LDE32 v1.05 iFuncLen=disasm_main(pReadAddress); // get first instruction length while (iFuncLen!=-1 && dwReadLen<(DWORD)jtJmpTable[iRndJmp].iCodeSize) { dwReadLen+=iFuncLen; pReadAddress+=iFuncLen; iFuncLen=disasm_main(pReadAddress); // next instruction length } // API code is too short or too long too hook this way (for now ;)) if (dwReadLen<(DWORD)jtJmpTable[iRndJmp].iCodeSize||dwReadLen>MAX_FUNC_LEN*2) { NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); return NULL; } // Read the first instruction(s) from the function into our stub buffer if (!NT_SUCCESS(SafeNtReadVirtualMemory(hProcess,lpFunction,lpLocalStub,dwReadLen,&dwBytesRead))) { NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); return NULL; } // Allocate space with read/write access for our "stub" // note: always use a relative jump for our stub -> RELATIVE_JMP dwStubSize=dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize; if (!NT_SUCCESS(NtAllocateVirtualMemory(hProcess,&lpRemoteStub,0,&dwStubSize,MEM_COMMIT|MEM_TOP_DOWN,PAGE_READWRITE))) { NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); return NULL; } // Check if (dwStubSize<dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize) { NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); // Free allocated buffer NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE); return NULL; } engine_BuildJMPBuffer((CHAR*)lpLocalStub+dwReadLen,jtJmpTable[RELATIVE_JMP].jcStub((DWORD)lpFunction+dwReadLen,(DWORD)lpRemoteStub,dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize),RELATIVE_JMP); // Copy the "stub" buffer to process memory if (!NT_SUCCESS(NtWriteVirtualMemory(hProcess,lpRemoteStub,lpLocalStub,dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize,&dwBytesWritten))) { NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); // Free allocated buffer NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE); return NULL; } // Check if (dwBytesWritten<dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize) { NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); // Free allocated buffer NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE); return NULL; } // change access if (!NT_SUCCESS(NtProtectVirtualMemory(hProcess,&lpRemoteStub,&dwStubSize,PAGE_EXECUTE_READ,&dwOldProtect))) { NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); // Free allocated buffer NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE); return NULL; } // Fill it with NOP RtlFillMemory(lpLocalFunc,MAX_FUNC_LEN*3,NOP); // Prepare jmpcode engine_BuildJMPBuffer((CHAR*)lpLocalFunc,jtJmpTable[iRndJmp].jcFunc((DWORD)lpHookFunctionAddress,(DWORD)lpFunction,(DWORD)jtJmpTable[iRndJmp].iCodeSize),iRndJmp); ntStatus=NtWriteVirtualMemory(hProcess,lpFunction,lpLocalFunc,dwReadLen,&dwBytesWritten); // Check that we really wrote our jmpcode completely if (!NT_SUCCESS(ntStatus) || dwBytesWritten!=dwReadLen) { // Try to fix stuff if (dwBytesWritten) NtWriteVirtualMemory(hProcess,lpFunction,lpRemoteStub,dwBytesWritten,&dwBytesWritten); NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); // Free allocated buffer NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE); return NULL; } // Restore protection NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL); // Save size of read function length if (pdwHookFunctionSize) *pdwHookFunctionSize=dwReadLen; // Save address of function if (lpFunctionAddress) *lpFunctionAddress=lpFunction; return lpRemoteStub; }
static NTSTATUS CopyLoop ( HANDLE FileHandleSource, HANDLE FileHandleDest, LARGE_INTEGER SourceFileSize, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, BOOL *pbCancel, BOOL *KeepDest ) { NTSTATUS errCode; IO_STATUS_BLOCK IoStatusBlock; UCHAR *lpBuffer = NULL; SIZE_T RegionSize = 0x10000; LARGE_INTEGER BytesCopied; DWORD CallbackReason; DWORD ProgressResult; BOOL EndOfFileFound; *KeepDest = FALSE; errCode = NtAllocateVirtualMemory(NtCurrentProcess(), (PVOID *)&lpBuffer, 2, &RegionSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (NT_SUCCESS(errCode)) { BytesCopied.QuadPart = 0; EndOfFileFound = FALSE; CallbackReason = CALLBACK_STREAM_SWITCH; while (! EndOfFileFound && NT_SUCCESS(errCode) && (NULL == pbCancel || ! *pbCancel)) { if (NULL != lpProgressRoutine) { ProgressResult = (*lpProgressRoutine)(SourceFileSize, BytesCopied, SourceFileSize, BytesCopied, 0, CallbackReason, FileHandleSource, FileHandleDest, lpData); switch (ProgressResult) { case PROGRESS_CANCEL: TRACE("Progress callback requested cancel\n"); errCode = STATUS_REQUEST_ABORTED; break; case PROGRESS_STOP: TRACE("Progress callback requested stop\n"); errCode = STATUS_REQUEST_ABORTED; *KeepDest = TRUE; break; case PROGRESS_QUIET: lpProgressRoutine = NULL; break; case PROGRESS_CONTINUE: default: break; } CallbackReason = CALLBACK_CHUNK_FINISHED; } if (NT_SUCCESS(errCode)) { errCode = NtReadFile(FileHandleSource, NULL, NULL, NULL, (PIO_STATUS_BLOCK)&IoStatusBlock, lpBuffer, RegionSize, NULL, NULL); if (NT_SUCCESS(errCode) && (NULL == pbCancel || ! *pbCancel)) { errCode = NtWriteFile(FileHandleDest, NULL, NULL, NULL, (PIO_STATUS_BLOCK)&IoStatusBlock, lpBuffer, IoStatusBlock.Information, NULL, NULL); if (NT_SUCCESS(errCode)) { BytesCopied.QuadPart += IoStatusBlock.Information; } else { WARN("Error 0x%08x reading writing to dest\n", errCode); } } else if (!NT_SUCCESS(errCode)) { if (STATUS_END_OF_FILE == errCode) { EndOfFileFound = TRUE; errCode = STATUS_SUCCESS; } else { WARN("Error 0x%08x reading from source\n", errCode); } } } } if (! EndOfFileFound && (NULL != pbCancel && *pbCancel)) { TRACE("User requested cancel\n"); errCode = STATUS_REQUEST_ABORTED; } NtFreeVirtualMemory(NtCurrentProcess(), (PVOID *)&lpBuffer, &RegionSize, MEM_RELEASE); } else { TRACE("Error 0x%08x allocating buffer of %d bytes\n", errCode, RegionSize); } return errCode; }
void Test_PageFileSection(void) { NTSTATUS Status; HANDLE SectionHandle; LARGE_INTEGER MaximumSize, SectionOffset; PVOID BaseAddress; SIZE_T ViewSize; /* Create a page file backed section */ MaximumSize.QuadPart = 0x20000; Status = NtCreateSection(&SectionHandle, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, NULL); ok(NT_SUCCESS(Status), "NtCreateSection failed with Status %lx\n", Status); if (!NT_SUCCESS(Status)) return; /* Try to map a page at an address that is not 64k aligned */ BaseAddress = (PVOID)0x30001000; SectionOffset.QuadPart = 0; ViewSize = 0x1000; Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewShare, 0, PAGE_READWRITE); ok(Status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned wrong Status %lx\n", Status); /* Try to map a page with execute rights */ BaseAddress = (PVOID)0x30000000; SectionOffset.QuadPart = 0; ViewSize = 0x1000; Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewShare, 0, PAGE_EXECUTE_READWRITE); ok(Status == STATUS_SECTION_PROTECTION, "NtMapViewOfSection returned wrong Status %lx\n", Status); /* Map 2 pages, not comitting them */ BaseAddress = (PVOID)0x30000000; SectionOffset.QuadPart = 0; ViewSize = 0x2000; Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewShare, 0, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status); if (!NT_SUCCESS(Status)) return; /* Commit a page in the section */ BaseAddress = (PVOID)0x30000000; ViewSize = 0x1000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &ViewSize, MEM_COMMIT, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status); Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &ViewSize, MEM_DECOMMIT); ok(Status == STATUS_UNABLE_TO_DELETE_SECTION, "NtFreeVirtualMemory returned wrong Status %lx\n", Status); /* Try to commit a range larger than the section */ BaseAddress = (PVOID)0x30000000; ViewSize = 0x3000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &ViewSize, MEM_COMMIT, PAGE_READWRITE); ok(Status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory failed with wrong Status %lx\n", Status); /* Try to commit a page after the section */ BaseAddress = (PVOID)0x30002000; ViewSize = 0x1000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &ViewSize, MEM_COMMIT, PAGE_READWRITE); ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory Should fail\n"); /* Try to allocate a page after the section */ BaseAddress = (PVOID)0x30002000; ViewSize = 0x1000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &ViewSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory should fail\n"); /* Need to go to next 64k boundary */ BaseAddress = (PVOID)0x30010000; ViewSize = 0x1000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &ViewSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status); if (!NT_SUCCESS(Status)) return; /* Free the allocation */ BaseAddress = (PVOID)0x30010000; ViewSize = 0x1000; Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &ViewSize, MEM_RELEASE); ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed with Status %lx\n", Status); /* Free the section mapping */ BaseAddress = (PVOID)0x30000000; ViewSize = 0x1000; Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &ViewSize, MEM_RELEASE); ok(Status == STATUS_UNABLE_TO_DELETE_SECTION, "NtFreeVirtualMemory failed with wrong Status %lx\n", Status); /* Commit a page in the section */ BaseAddress = (PVOID)0x30001000; ViewSize = 0x1000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &ViewSize, MEM_COMMIT, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status); /* Try to decommit the page */ BaseAddress = (PVOID)0x30001000; ViewSize = 0x1000; Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &ViewSize, MEM_DECOMMIT); ok(Status == STATUS_UNABLE_TO_DELETE_SECTION, "NtFreeVirtualMemory failed with wrong Status %lx\n", Status); BaseAddress = UlongToPtr(0x40000000); SectionOffset.QuadPart = 0; ViewSize = 0x1000; Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewShare, 0, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status); if (!NT_SUCCESS(Status)) return; ok(BaseAddress == UlongToPtr(0x40000000), "Invalid BaseAddress: %p", BaseAddress); BaseAddress = (PVOID)0x40080000; SectionOffset.QuadPart = 0x10000; ViewSize = 0x1000; Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewShare, 0, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status); if (!NT_SUCCESS(Status)) return; ok(BaseAddress == (PVOID)0x40080000, "Invalid BaseAddress: %p", BaseAddress); /* Commit a page in the section */ BaseAddress = (PVOID)0x40000000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &ViewSize, MEM_COMMIT, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status); if (!NT_SUCCESS(Status)) return; }
BOOL NTAPI BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment, IN PANSI_STRING AnsiEnv, IN PUNICODE_STRING UnicodeEnv) { BOOL Result; ULONG RegionSize, EnvironmentSize = 0; PWCHAR p, Environment, NewEnvironment = NULL; NTSTATUS Status; /* Make sure we have both strings */ if (!(AnsiEnv) || !(UnicodeEnv)) { /* Fail */ SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* Check if an environment was passed in */ if (!lpEnvironment) { /* Nope, create one */ Status = RtlCreateEnvironment(TRUE, (PWCHAR*)&Environment); if (!NT_SUCCESS(Status)) goto Quickie; } else { /* Use the one we got */ Environment = lpEnvironment; } /* Do we have something now ? */ if (!Environment) { /* Still not, fail out */ SetLastError(ERROR_BAD_ENVIRONMENT); goto Quickie; } /* Count how much space the whole environment takes */ p = Environment; while ((*p++ != UNICODE_NULL) && (*p != UNICODE_NULL)) EnvironmentSize++; EnvironmentSize += sizeof(UNICODE_NULL); /* Allocate a new copy */ RegionSize = (EnvironmentSize + MAX_PATH) * sizeof(WCHAR); if (!NT_SUCCESS(NtAllocateVirtualMemory(NtCurrentProcess(), (PVOID*)&NewEnvironment, 0, &RegionSize, MEM_COMMIT, PAGE_READWRITE))) { /* We failed, bail out */ SetLastError(ERROR_NOT_ENOUGH_MEMORY); NewEnvironment = NULL; goto Quickie; } /* Begin parsing the new environment */ p = NewEnvironment; /* FIXME: Code here */ /* Terminate it */ *p++ = UNICODE_NULL; /* Initialize the unicode string to hold it */ EnvironmentSize = (p - NewEnvironment) * sizeof(WCHAR); RtlInitEmptyUnicodeString(UnicodeEnv, NewEnvironment, (USHORT)EnvironmentSize); UnicodeEnv->Length = (USHORT)EnvironmentSize; /* Create the ASCII version of it */ Status = RtlUnicodeStringToAnsiString(AnsiEnv, UnicodeEnv, TRUE); if (!NT_SUCCESS(Status)) { /* Set last error if conversion failure */ BaseSetLastNTError(Status); } else { /* Everything went okay, so return success */ Result = TRUE; NewEnvironment = NULL; } Quickie: /* Cleanup path starts here, start by destroying the envrionment copy */ if (!(lpEnvironment) && (Environment)) RtlDestroyEnvironment(Environment); /* See if we are here due to failure */ if (NewEnvironment) { /* Initialize the paths to be empty */ RtlInitEmptyUnicodeString(UnicodeEnv, NULL, 0); RtlInitEmptyAnsiString(AnsiEnv, NULL, 0); /* Free the environment copy */ RegionSize = 0; Status = NtFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&NewEnvironment, &RegionSize, MEM_RELEASE); ASSERT(NT_SUCCESS(Status)); } /* Return the result */ return Result; }
// free buffer ... void misc_FreeBuffer(LPVOID* lpBuffer) { DWORD dwFree=0; NtFreeVirtualMemory(NtCurrentProcess(),lpBuffer,&dwFree,MEM_RELEASE); }
static NTSTATUS TH32CreateSnapshot(DWORD dwFlags, DWORD th32ProcessID, PRTL_DEBUG_INFORMATION *HeapDebug, PRTL_DEBUG_INFORMATION *ModuleDebug, PVOID *ProcThrdInfo, SIZE_T *ProcThrdInfoSize) { NTSTATUS Status = STATUS_SUCCESS; *HeapDebug = NULL; *ModuleDebug = NULL; *ProcThrdInfo = NULL; *ProcThrdInfoSize = 0; /* * Allocate the debug information for a heap snapshot */ if(dwFlags & TH32CS_SNAPHEAPLIST) { *HeapDebug = RtlCreateQueryDebugBuffer(0, FALSE); if(*HeapDebug != NULL) { Status = RtlQueryProcessDebugInformation(th32ProcessID, RTL_DEBUG_QUERY_HEAPS, *HeapDebug); } else Status = STATUS_UNSUCCESSFUL; } /* * Allocate the debug information for a module snapshot */ if(dwFlags & TH32CS_SNAPMODULE && NT_SUCCESS(Status)) { *ModuleDebug = RtlCreateQueryDebugBuffer(0, FALSE); if(*ModuleDebug != NULL) { Status = RtlQueryProcessDebugInformation(th32ProcessID, RTL_DEBUG_QUERY_MODULES, *ModuleDebug); } else Status = STATUS_UNSUCCESSFUL; } /* * Allocate enough memory for the system's process list */ if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD) && NT_SUCCESS(Status)) { for(;;) { (*ProcThrdInfoSize) += 0x10000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), ProcThrdInfo, 0, ProcThrdInfoSize, MEM_COMMIT, PAGE_READWRITE); if(!NT_SUCCESS(Status)) { break; } Status = NtQuerySystemInformation(SystemProcessInformation, *ProcThrdInfo, *ProcThrdInfoSize, NULL); if(Status == STATUS_INFO_LENGTH_MISMATCH) { NtFreeVirtualMemory(NtCurrentProcess(), ProcThrdInfo, ProcThrdInfoSize, MEM_RELEASE); *ProcThrdInfo = NULL; } else { break; } } } /* * Free resources in case of failure! */ if(!NT_SUCCESS(Status)) { TH32FreeAllocatedResources(*HeapDebug, *ModuleDebug, *ProcThrdInfo, *ProcThrdInfoSize); } return Status; }
int Uninstall(int argc, LPWSTR *argv) { DWORD dwPid = wcstoul(argv[1], NULL, 0); DWORD dwTid; HANDLE hProcess; HANDLE hThread; LPVOID lpMemBlock = NULL; static WCHAR wszModFile[32768] = L""; DWORD dwBaseAddress = 0; DWORD dwFunctionOffset = (DWORD) UninstallHandler - (DWORD) GetModuleHandle(L"noexcept.dll"); NTSTATUS status; const WCHAR wczString[] = L"noexcept.dll"; SIZE_T dwStringLength = sizeof wczString; SIZE_T dwRegionSize = dwStringLength; if (argc < 2) { MessageBoxA(NULL, "/u requires a process identifier as parameter.", "Syntax error", MB_ICONEXCLAMATION); return 2; } hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, dwPid); if (hProcess == NULL) { MessageBoxA(NULL, win_errmsgA(win_errno), "Cannot open process", MB_ICONEXCLAMATION); return 1; } status = NtAllocateVirtualMemory(hProcess, &lpMemBlock, 0, &dwRegionSize, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { MessageBoxA(NULL, win_errmsgA(RtlNtStatusToDosError(status)), "Cannot allocate memory in the process", MB_ICONEXCLAMATION); return 1; } if (!WriteProcessMemory(hProcess, lpMemBlock, wczString, dwStringLength, NULL)) { MessageBoxA(NULL, win_errmsgA(win_errno), "Cannot write memory in the process", MB_ICONEXCLAMATION); NtFreeVirtualMemory(hProcess, &lpMemBlock, &dwRegionSize, MEM_RELEASE); return 1; } hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) GetModuleHandleW, lpMemBlock, 4096, &dwTid); if (hThread == NULL) { MessageBoxA(NULL, win_errmsgA(win_errno), "Cannot create thread in the process", MB_ICONEXCLAMATION); dwRegionSize = 0; NtFreeVirtualMemory(hProcess, &lpMemBlock, &dwRegionSize, MEM_RELEASE); return 1; } WaitForSingleObject(hThread, INFINITE); dwRegionSize = 0; NtFreeVirtualMemory(hProcess, &lpMemBlock, &dwRegionSize, MEM_RELEASE); GetExitCodeThread(hThread, &dwBaseAddress); CloseHandle(hThread); if (dwBaseAddress == 0) { MessageBoxA(NULL, "The noexcept.dll module is not loaded into the specified " "process and can therefore not be uninstalled from it.", "Not installed", MB_ICONEXCLAMATION); return 1; } hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) (dwBaseAddress + dwFunctionOffset), (LPVOID) ((argc > 2) ? wcstoul(argv[2], NULL, 0) : 0), 4096, &dwTid); if (hThread == NULL) { MessageBoxA(NULL, win_errmsgA(win_errno), "Cannot create thread in the process", MB_ICONEXCLAMATION); return 1; } WaitForSingleObject(hThread, INFINITE); return 0; }
/* * @implemented */ NTSTATUS NTAPI RtlSetEnvironmentVariable(PWSTR *Environment, PUNICODE_STRING Name, PUNICODE_STRING Value) { MEMORY_BASIC_INFORMATION mbi; UNICODE_STRING var; size_t hole_len, new_len, env_len = 0; WCHAR *new_env = 0, *env_end = 0, *wcs, *env, *val = 0, *tail = 0, *hole = 0; PWSTR head = NULL; SIZE_T size = 0, new_size; LONG f = 1; NTSTATUS Status = STATUS_SUCCESS; DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n", Environment, Name, Value); /* Variable name must not be empty */ if (Name->Length < sizeof(WCHAR)) return STATUS_INVALID_PARAMETER; /* Variable names can't contain a '=' except as a first character. */ for (wcs = Name->Buffer + 1; wcs < Name->Buffer + (Name->Length / sizeof(WCHAR)); wcs++) { if (*wcs == L'=') return STATUS_INVALID_PARAMETER; } if (Environment) { env = *Environment; } else { RtlAcquirePebLock(); env = NtCurrentPeb()->ProcessParameters->Environment; } if (env) { /* get environment length */ wcs = env_end = env; do { env_end += wcslen(env_end) + 1; } while (*env_end); env_end++; env_len = env_end - env; DPRINT("environment length %lu characters\n", env_len); /* find where to insert */ while (*wcs) { var.Buffer = wcs++; wcs = wcschr(wcs, L'='); if (wcs == NULL) { wcs = var.Buffer + wcslen(var.Buffer); } if (*wcs) { var.Length = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR); var.MaximumLength = var.Length; val = ++wcs; wcs += wcslen(wcs); f = RtlCompareUnicodeString(&var, Name, TRUE); if (f >= 0) { if (f) /* Insert before found */ { hole = tail = var.Buffer; } else /* Exact match */ { head = var.Buffer; tail = ++wcs; hole = val; } goto found; } } wcs++; } hole = tail = wcs; /* Append to environment */ } found: if (Value != NULL && Value->Buffer != NULL) { hole_len = tail - hole; /* calculate new environment size */ new_size = Value->Length + sizeof(WCHAR); /* adding new variable */ if (f) new_size += Name->Length + sizeof(WCHAR); new_len = new_size / sizeof(WCHAR); if (hole_len < new_len) { /* enlarge environment size */ /* check the size of available memory */ new_size += (env_len - hole_len) * sizeof(WCHAR); new_size = ROUND_UP(new_size, PAGE_SIZE); mbi.RegionSize = 0; DPRINT("new_size %lu\n", new_size); if (env) { Status = NtQueryVirtualMemory(NtCurrentProcess(), env, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(Status)) { if (Environment == NULL) { RtlReleasePebLock(); } return(Status); } } if (new_size > mbi.RegionSize) { /* reallocate memory area */ Status = NtAllocateVirtualMemory(NtCurrentProcess(), (PVOID)&new_env, 0, &new_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { if (Environment == NULL) { RtlReleasePebLock(); } return(Status); } if (env) { memmove(new_env, env, (hole - env) * sizeof(WCHAR)); hole = new_env + (hole - env); } else { /* absolutely new environment */ tail = hole = new_env; *hole = 0; env_end = hole + 1; } } } /* move tail */ memmove (hole + new_len, tail, (env_end - tail) * sizeof(WCHAR)); if (new_env) { /* we reallocated environment, let's free the old one */ if (Environment) *Environment = new_env; else NtCurrentPeb()->ProcessParameters->Environment = new_env; if (env) { size = 0; NtFreeVirtualMemory(NtCurrentProcess(), (PVOID)&env, &size, MEM_RELEASE); } } /* and now copy given stuff */ if (f) { /* copy variable name and '=' character */ memmove(hole, Name->Buffer, Name->Length); hole += Name->Length / sizeof(WCHAR); *hole++ = L'='; } /* copy value */ memmove(hole, Value->Buffer, Value->Length); hole += Value->Length / sizeof(WCHAR); *hole = 0; } else { /* remove the environment variable */ if (f == 0) { memmove(head, tail, (env_end - tail) * sizeof(WCHAR)); } } if (Environment == NULL) { RtlReleasePebLock(); } return(Status); }
CustomFilterUnicode::~CustomFilterUnicode() { NtFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&map,&size,MEM_RELEASE); map=0; }
int wmain(int argc, LPWSTR *argv) { PROCESS_INFORMATION process_information = { 0 }; HANDLE hThread; DWORD dwTid; LPVOID lpMemBlock = NULL; SIZE_T dwStringLength; SIZE_T dwRegionSize; static WCHAR wszModFile[32768] = L""; DWORD dwBaseAddress = 0; DWORD dwFunctionOffset = (DWORD) InstallHandler - (DWORD) GetModuleHandle(L"noexcept.dll"); NTSTATUS status; DWORD dwMemSize = GetModuleFileName(GetModuleHandle(L"noexcept.dll"), wszModFile, sizeof(wszModFile) / sizeof(*wszModFile)); if (dwMemSize == 0) { MessageBoxA(NULL, win_errmsgA(win_errno), "Cannot attach noexcept.dll", MB_ICONSTOP); return 1; } if (argc < 2) { MessageBoxA(NULL, "Syntax:\r\n" "noexcept <commandline>\r\n" "Starts a new process and attaches noexcept.dll to it with " "special exception handling.\r\n" "\n" "noexcept <pid>\r\n" "Attaches noexcept.dll with special exception handling to a " "running process.\r\n" "\n" "noexcept /u <pid>\r\n" "Detaches noexcept.dll from a running process and restores " "default exception handling in the process.", "noexcept", MB_ICONINFORMATION); return 2; } if (wcsicmp(argv[1], L"/u") == 0) return Uninstall(argc - 1, argv + 1); if (wcstoul(argv[1], NULL, 0) != 0) { process_information.hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, wcstoul(argv[1], NULL, 0)); if (process_information.hProcess == NULL) { MessageBoxA(NULL, win_errmsgA(win_errno), "Cannot open process", MB_ICONEXCLAMATION); return 1; } } else { LPWSTR lpCmdLine = GetCommandLine(); DWORD_PTR dwOffset = argv[1] - argv[0]; STARTUPINFO startupinfo = { 0 }; startupinfo.cb = sizeof startupinfo; if (dwOffset > 1) if (lpCmdLine[dwOffset] == L'"') if (lpCmdLine[dwOffset+1] == L' ') lpCmdLine += dwOffset + 2; else lpCmdLine += dwOffset; else lpCmdLine += dwOffset; else lpCmdLine += dwOffset; while (lpCmdLine[0] == ' ') ++lpCmdLine; if (!CreateProcess(NULL, lpCmdLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupinfo, &process_information)) { MessageBoxA(NULL, mprintfA("Cannot execute command line:%n%1>%2!ws!<", win_errmsgA(win_errno), lpCmdLine), "Cannot create process", MB_ICONEXCLAMATION); return 1; } } dwStringLength = (wcslen(wszModFile) + 1) * sizeof *wszModFile; dwRegionSize = dwStringLength; status = NtAllocateVirtualMemory(process_information.hProcess, &lpMemBlock, 0, &dwRegionSize, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { MessageBoxA(NULL, win_errmsgA(RtlNtStatusToDosError(status)), "Cannot allocate memory in the process", MB_ICONEXCLAMATION); if (process_information.hThread != NULL) TerminateProcess(process_information.hProcess, -1); return 1; } if (!WriteProcessMemory(process_information.hProcess, lpMemBlock, wszModFile, dwStringLength, NULL)) { MessageBoxA(NULL, win_errmsgA(win_errno), "Cannot write memory in the process", MB_ICONEXCLAMATION); NtFreeVirtualMemory(process_information.hProcess, &lpMemBlock, &dwRegionSize, MEM_RELEASE); if (process_information.hThread != NULL) TerminateProcess(process_information.hProcess, -1); return 1; } hThread = CreateRemoteThread(process_information.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) LoadLibraryW, lpMemBlock, 4096, &dwTid); if (hThread == NULL) { MessageBoxA(NULL, win_errmsgA(win_errno), "Cannot create thread in the process", MB_ICONEXCLAMATION); dwRegionSize = 0; NtFreeVirtualMemory(process_information.hProcess, &lpMemBlock, &dwRegionSize, MEM_RELEASE); if (process_information.hThread != NULL) TerminateProcess(process_information.hProcess, -1); return 1; } WaitForSingleObject(hThread, INFINITE); GetExitCodeThread(hThread, &dwBaseAddress); CloseHandle(hThread); dwRegionSize = 0; NtFreeVirtualMemory(process_information.hProcess, &lpMemBlock, &dwRegionSize, MEM_RELEASE); if (dwBaseAddress == 0) { MessageBoxA(NULL, "Cannot load noexcept.dll into the process.", "LoadLibrary() failed in the process", MB_ICONEXCLAMATION); if (process_information.hThread != NULL) TerminateProcess(process_information.hProcess, -1); return 1; } hThread = CreateRemoteThread(process_information.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) (dwBaseAddress + dwFunctionOffset), (LPVOID) (((process_information.hThread == NULL) & (argc > 2)) ? wcstoul(argv[2], NULL, 0) : 0), 4096, &dwTid); if (hThread == NULL) { MessageBoxA(NULL, win_errmsgA(win_errno), "Cannot create thread in the process", MB_ICONEXCLAMATION); if (process_information.hThread != NULL) TerminateProcess(process_information.hProcess, -1); return 1; } WaitForSingleObject(hThread, INFINITE); if (process_information.hThread != NULL) ResumeThread(process_information.hThread); return 0; }
NTSTATUS openProcByName(PHANDLE pProcess, PUNICODE_STRING pProcName, BOOLEAN useDebugPrivilege) { SYSTEM_PROCESS_INFORMATION procInfo; OBJECT_ATTRIBUTES procAttr; OBJECT_BASIC_INFORMATION processHandleInfo; CLIENT_ID cid; BOOLEAN oldValue; HANDLE pid; NTSTATUS status = STATUS_CACHE_PAGE_LOCKED; ULONG procListSize = 0; ULONGLONG memSize = 0; ULONG obQueryLen = 0; PVOID pProcListHead = NULL; PSYSTEM_PROCESS_INFORMATION pProcEntry = NULL; do { if (!pProcName || !pProcess) { status = STATUS_INVALID_PARAMETER; break; } *pProcess = NULL; ///Since we specify a buffer size of 0 the buffer must overflow for sure even if there was running a ///single process only. If we don't receive the dedicated error, something other has gone wrong ///and we cannot rely on the return length. status = NtQuerySystemInformation(SystemProcessInformation, &procInfo, procListSize, &procListSize); if (STATUS_INFO_LENGTH_MISMATCH != status) break; memSize = PAGE_ROUND_UP(procListSize) + PAGE_SIZE; ///We better allocate one page extra ///since between our "test" call and the real call below ///additional processes might be started. (race condition) status = NtAllocateVirtualMemory(INVALID_HANDLE_VALUE, &pProcListHead, 0, &memSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (status) { pProcListHead = NULL; break; } ///By now, we have allocated a buffer large enough for the complete process list, ///even if some new processes have been started in the mean time. ///Hence, the next call is entirely expected to succeed. procListSize = (ULONG)memSize; status = NtQuerySystemInformation(SystemProcessInformation, pProcListHead, procListSize, &procListSize); if (status) break; pid = NULL; pProcEntry = pProcListHead; ///The list of all system processes is a so called singly linked list. while (pProcEntry->NextEntryOffset) { ///If NextEntryOffset member is NULL, we have reached the list end (tail). pProcEntry = (PSYSTEM_PROCESS_INFORMATION)((PUCHAR)pProcEntry + pProcEntry->NextEntryOffset); //DebugPrint2A("PID: %d, %wZ", pProcEntry->UniqueProcessId, pProcEntry->ImageName); if (0 == RtlCompareUnicodeString(pProcName, &pProcEntry->ImageName, TRUE)) { pid = pProcEntry->UniqueProcessId; break; } } if (!pid) { status = STATUS_OBJECT_NAME_NOT_FOUND; break; } if (useDebugPrivilege) { status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &oldValue); if (status){ ///Since we're for some reason supposed to use the SeDebugPrivilege, useDebugPrivilege = FALSE; break; ///we fail deliberately if we can't enable it. } } InitializeObjectAttributes(&procAttr, NULL, 0, NULL, NULL); cid.UniqueThread = (HANDLE)0; cid.UniqueProcess = pid; ///Opening a process for full access might be less suspicious than opening with our real intentions. status = NtOpenProcess(pProcess, PROCESS_ALL_ACCESS, &procAttr, &cid); if (status) { ///Most likely STATUS_ACCESS_DENIED if ///either we didn't specify the useDebugPrivilege flag when opening a cross session process ///or if we tried to open an elevated process while running non-elevated ///or if the process being opened is a so-called "Protected Process". ///In x64 windows, HIPS or AV drivers have the possibility to legally ///receive a notification if a process is about to open a handle to another process. ///In those ObCallback routines they cannot completely deny the opening. ///However, they are able to modify the access masks, so a handle supposed for VM operations still ///will be lacking the PROCESS_VM_XXX rights, for example. If we therefore query the handle rights ///we can still return an appropriate error if wasn't granted the rights we want ///And are not going to fail at first when performing our process operations. *pProcess = NULL; break; } status = NtQueryObject(*pProcess, ObjectBasicInformation, &processHandleInfo, sizeof(OBJECT_BASIC_INFORMATION), &obQueryLen); if (status) ///Not sure if this call ever will fail... break; ///Maybe, HIPS just wanted to deny PROCESS_TERMINATE/PROCESS_SUSPEND right? ///If so, we don't care. We're only interested in VM rights. if (MIN_VM_ACCESS_MASK & ~processHandleInfo.GrantedAccess) { status = STATUS_UNSUCCESSFUL; break; } } while (status); if (status && pProcess) { if (*pProcess) { NtClose(*pProcess); *pProcess = NULL; } } if (pProcListHead) { memSize = 0; NtFreeVirtualMemory(INVALID_HANDLE_VALUE, &pProcListHead, &memSize, MEM_RELEASE); ///We don't need the list anymore. } if (useDebugPrivilege) RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, oldValue, FALSE, &oldValue); ///We don't need the privilege anymore. return status; }
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg) { HANDLE hThread; OBJECT_ATTRIBUTES oaThreadAttrs; CLIENT_ID ciId; CONTEXT cxThreadContext; INITIAL_TEB itInitialTeb; BOOLEAN fSuspended; ULONG nOldPageProtection; NTSTATUS nErrCode; /* initialize generic object attributes */ oaThreadAttrs.Length = sizeof(OBJECT_ATTRIBUTES); oaThreadAttrs.RootDirectory = NULL; oaThreadAttrs.ObjectName = NULL; oaThreadAttrs.Attributes = 0; oaThreadAttrs.SecurityDescriptor = NULL; oaThreadAttrs.SecurityQualityOfService = NULL; /* initialize thread attributes */ fSuspended = FALSE; /* FIXME? really needed? can we hardcode this to FALSE? */ /* stack attributes */ FIXME("stack size defaulted to 0x100000 - thread attributes ignored"); /* stack reserve size */ itInitialTeb.StackReserve = 0x100000; /* stack commit size */ itInitialTeb.StackCommit = itInitialTeb.StackReserve - PAGE_SIZE; /* guard page */ itInitialTeb.StackCommit += PAGE_SIZE; /* reserve stack */ itInitialTeb.StackAllocate = NULL; nErrCode = NtAllocateVirtualMemory ( NtCurrentProcess(), &itInitialTeb.StackAllocate, 0, &itInitialTeb.StackReserve, MEM_RESERVE, PAGE_READWRITE ); if(!NT_SUCCESS(nErrCode)) { return (__status_to_errno(nErrCode)); /* FIXME? TODO? pthread specific error codes? */ } itInitialTeb.StackBase = (PVOID)((ULONG)itInitialTeb.StackAllocate + itInitialTeb.StackReserve); itInitialTeb.StackLimit = (PVOID)((ULONG)itInitialTeb.StackBase - itInitialTeb.StackCommit); /* commit stack */ nErrCode = NtAllocateVirtualMemory ( NtCurrentProcess(), &itInitialTeb.StackLimit, 0, &itInitialTeb.StackCommit, MEM_COMMIT, PAGE_READWRITE ); if(!NT_SUCCESS(nErrCode)) { NtFreeVirtualMemory ( NtCurrentProcess(), itInitialTeb.StackAllocate, &itInitialTeb.StackReserve, MEM_RELEASE ); return (__status_to_errno(nErrCode)); } /* protect guard page */ nErrCode = NtProtectVirtualMemory ( NtCurrentProcess(), itInitialTeb.StackLimit, PAGE_SIZE, PAGE_GUARD | PAGE_READWRITE, &nOldPageProtection ); if(!NT_SUCCESS(nErrCode)) { NtFreeVirtualMemory ( NtCurrentProcess(), itInitialTeb.StackAllocate, &itInitialTeb.StackReserve, MEM_RELEASE ); return (__status_to_errno(nErrCode)); } /* initialize thread registers */ //#ifdef __i386__ memset(&cxThreadContext, 0, sizeof(CONTEXT)); cxThreadContext.Eip = (LONG)__threadentry; cxThreadContext.SegGs = USER_DS; cxThreadContext.SegFs = TEB_SELECTOR; cxThreadContext.SegEs = USER_DS; cxThreadContext.SegDs = USER_DS; cxThreadContext.SegCs = USER_CS; cxThreadContext.SegSs = USER_DS; cxThreadContext.Esp = (ULONG)itInitialTeb.StackBase - 12; cxThreadContext.EFlags = (1<<1) + (1<<9); /* initialize call stack */ *((PULONG)((ULONG)itInitialTeb.StackBase - 4)) = (ULONG)arg; /* thread argument */ *((PULONG)((ULONG)itInitialTeb.StackBase - 8)) = (ULONG)start_routine; /* thread start routine */ *((PULONG)((ULONG)itInitialTeb.StackBase - 12)) = 0xDEADBEEF; /* "shouldn't see me" */ //#else //#error Unsupported architecture //#endif INFO("about to create new thread - start routine at %#x, argument %#x", start_routine, arg); /* create thread */ nErrCode = NtCreateThread ( &hThread, THREAD_ALL_ACCESS, &oaThreadAttrs, NtCurrentProcess(), &ciId, &cxThreadContext, &itInitialTeb, fSuspended ); if(!NT_SUCCESS(nErrCode)) { NtFreeVirtualMemory ( NtCurrentProcess(), itInitialTeb.StackAllocate, &itInitialTeb.StackReserve, MEM_RELEASE ); return (__status_to_errno(nErrCode)); } /* FIXME? should we return the thread handle or the thread id? */ if(thread != 0) *thread = (pthread_t)&ciId.UniqueThread; /* for the moment, we return the id */ return (0); }
_CRTAPI1 main() { LONG i, j; PULONG p4, p3, p2, p1, oldp1, vp1; ULONG Size1, Size2, Size3; NTSTATUS status, alstatus; HANDLE CurrentProcessHandle; HANDLE GiantSection; HANDLE Section2, Section4; MEMORY_BASIC_INFORMATION MemInfo; ULONG OldProtect; STRING Name3; HANDLE Section1; OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES Object1Attributes; ULONG ViewSize; LARGE_INTEGER Offset; LARGE_INTEGER SectionSize; UNICODE_STRING Unicode; CurrentProcessHandle = NtCurrentProcess(); DbgPrint(" Memory Management Tests - AllocVm, FreeVm, ProtectVm, QueryVm\n"); p1 = (PULONG)0x20020000; Size1 = 0xbc0000; alstatus = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(alstatus)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", alstatus, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 1 **************\n"); } status = NtQueryVirtualMemory (CurrentProcessHandle, p1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 2 **************\n"); DbgPrint("FAILURE query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } if ((MemInfo.RegionSize != Size1) || (MemInfo.BaseAddress != p1) || (MemInfo.Protect != PAGE_READWRITE) || (MemInfo.Type != MEM_PRIVATE) || (MemInfo.State != MEM_COMMIT)) { DbgPrint("******** FAILED TEST 3 **************\n"); DbgPrint("FAILURE query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } p2 = (PULONG)NULL; Size2 = 0x100000; alstatus = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 3, &Size2, MEM_TOP_DOWN | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(alstatus)) { DbgPrint("failed first created vm status %lC start %lx size %lx\n", status, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 3a.1 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } // // Touch every other page. // vp1 = p2 + 3000; while (vp1 < (PULONG)((PCHAR)p2 + Size2)) { *vp1 = 938; vp1 += 3000; } // // Decommit pages. // Size3 = Size2 - 5044; vp1 = p2 + 3000; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, &Size3, MEM_DECOMMIT); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 3a.4 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } // // Split the memory block using MEM_RELEASE. // vp1 = p2 + 5000; Size3 = Size2 - 50000; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&vp1, &Size3, MEM_RELEASE); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 3a.b **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } vp1 = p2 + 3000; Size3 = 41; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&vp1, &Size3, MEM_RELEASE); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 3a.5 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } // // free every page, ignore the status. // vp1 = p2; Size3 = 30; while (vp1 < (PULONG)((PCHAR)p2 + Size2)) { status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&vp1, &Size3, MEM_RELEASE); vp1 += 128; } p2 = (PULONG)NULL; Size2 = 0x10000; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 3, &Size2, MEM_TOP_DOWN | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 3.1 **************\n"); } else { if (p2 != (PVOID)0x1fff0000) { DbgPrint("******** FAILED TEST 3.2 **************\n"); DbgPrint("p2 = %lx\n",p2); } status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, &Size2, MEM_RELEASE); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 3.3 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } } if (NT_SUCCESS(alstatus)) { status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, MEM_RELEASE); } if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 4 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } p1 = (PULONG)NULL; Size1 = 16 * 4096; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_RESERVE, PAGE_READWRITE | PAGE_GUARD); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 5 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); } status = NtQueryVirtualMemory (CurrentProcessHandle, p1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 6 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx alloc_protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.AllocationProtect, MemInfo.Type); } if ((MemInfo.RegionSize != Size1) || (MemInfo.BaseAddress != p1) || (MemInfo.AllocationProtect != (PAGE_READWRITE | PAGE_GUARD)) || (MemInfo.Protect != 0) || (MemInfo.Type != MEM_PRIVATE) || (MemInfo.State != MEM_RESERVE)) { DbgPrint("******** FAILED TEST 7 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx alloc_protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.AllocationProtect, MemInfo.Type); } Size2 = 8192; oldp1 = p1; p1 = p1 + 14336; // 64k -8k /4 status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size2, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 8 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); } status = NtQueryVirtualMemory (CurrentProcessHandle, oldp1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 9 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, oldp1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } if ((MemInfo.RegionSize != 56*1024) || (MemInfo.BaseAddress != oldp1) || (MemInfo.AllocationProtect != (PAGE_READWRITE | PAGE_GUARD)) || (MemInfo.Protect != 0) || (MemInfo.Type != MEM_PRIVATE) || (MemInfo.State != MEM_RESERVE)) { DbgPrint("******** FAILED TEST 10 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, oldp1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx alloc_protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.AllocationProtect, MemInfo.Type); } status = NtQueryVirtualMemory (CurrentProcessHandle, p1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 11 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } if ((MemInfo.RegionSize != Size2) || (MemInfo.BaseAddress != p1) || (MemInfo.Protect != PAGE_EXECUTE_READWRITE) || (MemInfo.Type != MEM_PRIVATE) || (MemInfo.State != MEM_COMMIT) || (MemInfo.AllocationBase != oldp1)) { DbgPrint("******** FAILED TEST 12 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, oldp1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } Size1 = Size2; status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, PAGE_READONLY | PAGE_NOCACHE, &OldProtect); if ((!NT_SUCCESS(status)) || (OldProtect != PAGE_EXECUTE_READWRITE)) { DbgPrint("******** FAILED TEST 13 **************\n"); DbgPrint("protected VM status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect); } status = NtQueryVirtualMemory (CurrentProcessHandle, p1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if ((!NT_SUCCESS(status)) || MemInfo.Protect != (PAGE_NOCACHE | PAGE_READONLY)) { DbgPrint("******** FAILED TEST 14 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } i = *p1; status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, PAGE_NOACCESS | PAGE_NOCACHE, &OldProtect); if (status != STATUS_INVALID_PAGE_PROTECTION) { DbgPrint("******** FAILED TEST 15 **************\n"); DbgPrint("protected VM status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect, i); } status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, PAGE_READONLY, &OldProtect); if ((!NT_SUCCESS(status)) || (OldProtect != (PAGE_NOCACHE | PAGE_READONLY))) { DbgPrint("******** FAILED TEST 16 **************\n"); DbgPrint("protected VM status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect); } status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, PAGE_READWRITE, &OldProtect); if ((!NT_SUCCESS(status)) || (OldProtect != (PAGE_READONLY))) { DbgPrint("******** FAILED TEST 17 **************\n"); DbgPrint("protected VM status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect); } for (i = 1; i < 12; i++) { p2 = (PULONG)NULL; Size2 = i * 4096; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 0, &Size2, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 18 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p2, Size2); } if (i==4) { p3 = p2; } if (i == 8) { Size3 = 12000; status = NtFreeVirtualMemory (CurrentProcessHandle,(PVOID *)&p3, &Size3, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 19 **************\n"); DbgPrint("free vm status %X start %lx size %lx\n", status, (ULONG)p3, Size3); } } } p3 = p1 + 8 * 1024; status = NtQueryVirtualMemory (CurrentProcessHandle, p3, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 20 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p3, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } p3 = p1 - 8 * 1024; status = NtQueryVirtualMemory (CurrentProcessHandle, p3, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 21 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p3, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } Size3 = 16 * 4096; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, &Size3, MEM_RELEASE); if (status != STATUS_UNABLE_TO_FREE_VM) { DbgPrint("******** FAILED TEST 22 **************\n"); DbgPrint("free vm status %X start %lx size %lx\n", status, (ULONG)p3, Size3); } Size3 = 1 * 4096; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, &Size3, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 23 **************\n"); DbgPrint("free vm status %X start %lx size %lx\n", status, (ULONG)p3, Size3); } p3 = (PULONG)NULL; Size3 = 300 * 4096; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, 0, &Size3, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 24 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p3, Size3); } p1 = p3; p2 = ((PULONG)((PUCHAR)p3 + Size3)); p4 = p1; j = 0; while (p3 < p2) { j += 1; if (j % 8 == 0) { if (*p4 != (ULONG)p4) { DbgPrint("bad value in xcell %lx value is %lx\n",p4, *p4); } p4 += 1; *p4 = (ULONG)p4; p4 = p4 + 1026; } *p3 = (ULONG)p3; p3 += 1027; } DbgPrint("checking values\n"); status = NtQueryVirtualMemory (CurrentProcessHandle, p3, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 25 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p3, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 1cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 2cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 3cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 4cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 5cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } // // Check physical frame mapping. // // // Check physical frame mapping. // RtlInitAnsiString (&Name3, "\\Device\\PhysicalMemory"); status = RtlAnsiStringToUnicodeString(&Unicode,&Name3,TRUE); if (!NT_SUCCESS(status)) { printf("string conversion failed status %lx\n", status); ExitProcess (status); } InitializeObjectAttributes( &ObjectAttributes, &Unicode, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = NtOpenSection ( &Section1, SECTION_MAP_READ | SECTION_MAP_WRITE, &ObjectAttributes ); RtlFreeUnicodeString(&Unicode); if (status != 0) { DbgPrint("******** FAILED TEST 26 **************\n"); DbgPrint("open physical section failed %lx\n", status); } p1 = NULL; Offset.LowPart = 0x810ff033; Offset.HighPart = 0; ViewSize = 300*4096; status = NtMapViewOfSection (Section1, NtCurrentProcess(), (PVOID *)&p1, 0, ViewSize, &Offset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE ); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 27 **************\n"); DbgPrint ("map physical section %X offset = %lx, base %lx\n",status, Offset.LowPart, p1); } p1 = NULL; Size1 = 8 * 1024 * 1024; alstatus = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(alstatus)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", alstatus, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 28 **************\n"); } RtlZeroMemory (p1, Size1); Size1 -= 20000; (PUCHAR)p1 += 5000; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1 , MEM_DECOMMIT); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 29 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } Size1 -= 20000; (PUCHAR)p1 += 5000; alstatus = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!NT_SUCCESS(alstatus)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", alstatus, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 30 **************\n"); } RtlZeroMemory (p1, Size1); Size1 = 28 * 4096; p1 = NULL; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD); if (!NT_SUCCESS(status)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 31 **************\n"); } try { // // attempt to write the guard page. // *p1 = 973; DbgPrint("************ FAILURE TEST 31.3 guard page exception did not occur\n"); } except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); if (status != STATUS_GUARD_PAGE_VIOLATION) { DbgPrint("******** FAILED TEST 32 ******\n"); } } p2 = NULL; Size2 = 200*1024*1024; //200MB status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 0, &Size2, MEM_COMMIT, PAGE_READWRITE); if (NT_SUCCESS(status)) { status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, &Size2, MEM_RELEASE); } else { if ((status != STATUS_COMMITMENT_LIMIT) && (status != STATUS_PAGEFILE_QUOTA_EXCEEDED)) { DbgPrint("******** FAILED TEST 33 ************** %lx\n",status); } } // // Create a giant section (2gb) // InitializeObjectAttributes( &Object1Attributes, NULL, 0, NULL, NULL ); SectionSize.LowPart = 0x7f000000; SectionSize.HighPart = 0; status = NtCreateSection (&GiantSection, SECTION_MAP_READ | SECTION_MAP_WRITE, &Object1Attributes, &SectionSize, PAGE_READWRITE, SEC_RESERVE, NULL); if (!NT_SUCCESS(status)) { DbgPrint("failed create big section status %X\n", status); DbgPrint("******** FAILED TEST 41 **************\n"); } // // Attempt to map the section (this should fail). // p1 = NULL; ViewSize = 0; status = NtMapViewOfSection (GiantSection, CurrentProcessHandle, (PVOID *)&p1, 0L, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READWRITE ); if (status != STATUS_NO_MEMORY) { DbgPrint("failed map big section status %X\n", status); DbgPrint("******** FAILED TEST 42 **************\n"); } #ifdef i386 // // Test MEM_DOS_LIM support. // InitializeObjectAttributes( &Object1Attributes, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL ); SectionSize.LowPart = 1575757, SectionSize.HighPart = 0; status = NtCreateSection (&Section4, SECTION_MAP_READ | SECTION_MAP_WRITE, &Object1Attributes, &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 42 **************\n"); DbgPrint("t1 create section status %X section handle %lx\n", status, (ULONG)Section4); } p3 = (PVOID)0x9001000; ViewSize = 8000; status = NtMapViewOfSection (Section4, CurrentProcessHandle, (PVOID *)&p3, 0L, 0, 0, &ViewSize, ViewUnmap, MEM_DOS_LIM, PAGE_READWRITE ); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 43 **************\n"); DbgPrint("t1 map section status %X base %lx size %lx\n", status, (ULONG)p3, ViewSize); NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS); } p2 = (PVOID)0x9003000; ViewSize = 8000; status = NtMapViewOfSection (Section4, CurrentProcessHandle, (PVOID *)&p2, 0L, 0, 0, &ViewSize, ViewUnmap, MEM_DOS_LIM, PAGE_READWRITE ); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 44 **************\n"); DbgPrint("t1 map section status %X base %lx size %lx\n", status, (ULONG)p3, ViewSize); NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS); } status = NtQueryVirtualMemory (CurrentProcessHandle, p3, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 44 **************\n"); DbgPrint("FAILURE query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } *p3 = 98; if (*p3 != *p2) { DbgPrint("******** FAILED TEST 45 **************\n"); } Size2 = 8; p1 = (PVOID)((ULONG)p2 - 0x3000); status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size2, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 46 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); } #endif DbgPrint(" End of Memory Management Tests - CreateSection, MapView\n"); DbgPrint("creating too much virtual address space\n"); i = 0; do { p2 = NULL; Size2 = 8*1024*1024 + 9938; i += 1; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 0, &Size2, MEM_RESERVE, PAGE_READWRITE); } while (NT_SUCCESS (status)); if (status != STATUS_NO_MEMORY) { DbgPrint("******** FAILED TEST 46 **************\n"); } DbgPrint("created vm done (successfully) status %X, number of allocs %ld\n", status, i); DbgPrint(" End of Memory Management Tests - AllocVm, FreeVm, ProtectVm, QueryVm\n"); { ULONG size, Size; PVOID BaseAddress; NTSTATUS Status; Size = 50*1024; size = Size - 1; BaseAddress = (PVOID)1; // we pass an address of 1, so mm will round it down to 0. if we // passed 0, it looks like a not present argument // N.B. We have to make two separate calls to allocatevm, because // we want a specific virtual address. If we don't first reserve // the address, the mm fails the commit call. Status = NtAllocateVirtualMemory( NtCurrentProcess(), &BaseAddress, 0L, &size, MEM_RESERVE, PAGE_READWRITE ); if (!NT_SUCCESS(Status)) { DbgPrint("NtReserveVirtualMemory failed !!!! Status = %lx\n", Status); } size = Size - 1; BaseAddress = (PVOID)1; Status = NtAllocateVirtualMemory( NtCurrentProcess(), &BaseAddress, 0L, &size, MEM_COMMIT, PAGE_READWRITE ); if (!NT_SUCCESS(Status)) { DbgPrint("NtCommitVirtualMemory failed !!!! Status = %lx\n", Status); } } ExitProcess (0); }
void test_alloc_free(void) { VOID *address, *a; ULONG size; NTSTATUS r; HANDLE handle = (HANDLE) ~0; /* allocate a page and free it */ address = NULL; size = 0x1000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address != NULL, "NULL allocated\n"); ok(size == 0x1000, "size wrong\n"); r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); /* attempt a double free */ r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_MEMORY_NOT_ALLOCATED, "wrong return code\n"); /* free two halves */ address = NULL; size = 0x2000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address != NULL, "NULL allocated\n"); ok(size == 0x2000, "size wrong\n"); size = 0x1000; a = address; r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(size == 0x1000, "size wrong\n"); ok(address == a, "address changed\n"); size = 0x1000; address += 0x1000; a = address; r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(size == 0x1000, "size wrong\n"); ok(address == a, "address changed\n"); /* alloc and free with a one byte size */ address = NULL; size = 1; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address != NULL, "NULL allocated\n"); ok(size == 0x1000, "size wrong\n"); size = 1; r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(size == 0x1000, "size wrong\n"); /* allocate at an offset address */ a = address++; /* reuse the previously free'd address... no threads! */ size = 1; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address == a, "address changed\n"); ok(size == 0x1000, "size wrong\n"); a = address++; size = 1; r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address == a, "address changed\n"); ok(size == 0x1000, "size wrong\n"); r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_MEMORY_NOT_ALLOCATED, "wrong return code\n"); /* try a double allocate */ address = NULL; size = 0x1000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address != NULL, "NULL allocated\n"); ok(size == 0x1000, "size wrong\n"); a = address; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_CONFLICTING_ADDRESSES, "wrong return code\n"); ok(address == a, "address changed\n"); ok(size == 0x1000, "size wrong\n"); r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); /* test MEM_RESERVE, MEM_COMMIT, MEM_DECOMMIT, MEM_RELEASE */ address = NULL; size = 0x1000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address != NULL, "NULL allocated\n"); ok(size == 0x1000, "size wrong\n"); a = address; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_COMMIT, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address == a, "address changed\n"); ok(size == 0x1000, "size wrong\n"); r = NtFreeVirtualMemory( handle, &address, &size, MEM_DECOMMIT ); ok(r == STATUS_SUCCESS, "wrong return code\n"); r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); /* commit then reserve? */ address = NULL; size = 0x1000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_COMMIT, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address != NULL, "NULL allocated\n"); ok(size == 0x1000, "size wrong\n"); a = address; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_CONFLICTING_ADDRESSES, "wrong return code\n"); ok(address == a, "address changed\n"); ok(size == 0x1000, "size wrong\n"); r = NtFreeVirtualMemory( handle, &address, &size, MEM_DECOMMIT ); ok(r == STATUS_SUCCESS, "wrong return code\n"); r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); /* reserve then decommit? */ address = NULL; size = 0x1000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address != NULL, "NULL allocated\n"); ok(size == 0x1000, "size wrong\n"); r = NtFreeVirtualMemory( handle, &address, &size, MEM_DECOMMIT ); ok(r == STATUS_SUCCESS, "wrong return code\n"); r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); /* reserved with MEM_FREE state? */ address = NULL; size = 0x1000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_FREE, PAGE_NOACCESS ); ok(r == STATUS_INVALID_PARAMETER_5, "wrong return code\n"); ok(address == NULL, "address chagned\n"); ok(size == 0x1000, "size changed\n"); /* reserved with MEM_FREE state? */ address = NULL; size = 0x1000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, 0xffffffff ); ok(r == STATUS_INVALID_PAGE_PROTECTION, "wrong return code\n"); ok(address == NULL, "address chagned\n"); ok(size == 0x1000, "size changed\n"); }
/* * SfExtractDropper * * Purpose: * * Extract Sirefef/ZeroAccess from image resource. * * CNG variant * */ UINT SfExtractDropper( LPWSTR lpCommandLine ) { BOOL cond = FALSE, bSuccess = FALSE; ULONG c, uKey = 0, imagesz; WCHAR szInputFile[MAX_PATH + 1]; WCHAR szOutputFile[MAX_PATH + 1]; WCHAR szKey[MAX_PATH]; PVOID ImageBase = NULL, EncryptedData = NULL, DecryptedData = NULL; IStream *pImageStream = NULL; ULONG_PTR gdiplusToken = 0; GdiplusStartupInput input; GdiplusStartupOutput output; PVOID BitmapPtr = NULL; GdiPlusBitmapData BitmapData; GdiPlusRect rect; SIZE_T sz; PULONG ptr, i_ptr; //input file c = 0; RtlSecureZeroMemory(szInputFile, sizeof(szInputFile)); GetCommandLineParam(lpCommandLine, 1, (LPWSTR)&szInputFile, MAX_PATH, &c); if (c == 0) { SfcuiPrintText(g_ConOut, T_SFEXTRACTUSAGE, g_ConsoleOutput, FALSE); return (UINT)-1; } //output file c = 0; RtlSecureZeroMemory(&szOutputFile, sizeof(szOutputFile)); GetCommandLineParam(lpCommandLine, 2, (LPWSTR)&szOutputFile, MAX_PATH, &c); if (c == 0) { _strcpy(szOutputFile, TEXT("extracted.bin")); } //key c = 0; RtlSecureZeroMemory(&szKey, sizeof(szKey)); GetCommandLineParam(lpCommandLine, 3, (LPWSTR)&szKey, MAX_PATH, &c); if ((c == 0) || (c > 10)) { SfcuiPrintText(g_ConOut, T_SFEXTRACTUSAGE, g_ConsoleOutput, FALSE); return (UINT)-1; } c = 0; if (locase_w(szKey[1]) == 'x') { c = 2; } uKey = hextoul(&szKey[c]); do { ImageBase = SfuCreateFileMappingNoExec(szInputFile); if (ImageBase == NULL) break; c = 0; EncryptedData = SfLdrQueryResourceData(1, ImageBase, &c); if ((EncryptedData == NULL) || (c == 0)) break; pImageStream = SHCreateMemStream((BYTE *)EncryptedData, (UINT)c); if (pImageStream == NULL) break; RtlSecureZeroMemory(&input, sizeof(input)); RtlSecureZeroMemory(&output, sizeof(output)); input.GdiplusVersion = 1; if (GdiplusStartup(&gdiplusToken, &input, &output) != GdiplusOk) break; BitmapPtr = NULL; if (GdipCreateBitmapFromStream(pImageStream, &BitmapPtr) != GdiplusOk) break; RtlSecureZeroMemory(&rect, sizeof(rect)); if ( (GdipGetImageWidth(BitmapPtr, (UINT *)&rect.Width) == GdiplusOk) && (GdipGetImageHeight(BitmapPtr, (UINT *)&rect.Height) == GdiplusOk) ) { RtlSecureZeroMemory(&BitmapData, sizeof(BitmapData)); if (GdipBitmapLockBits(BitmapPtr, &rect, ImageLockModeRead, PixelFormat32bppARGB, &BitmapData) == GdiplusOk) { c = (rect.Width * rect.Height); imagesz = sizeof(ULONG) * c; sz = imagesz; DecryptedData = NULL; NtAllocateVirtualMemory(NtCurrentProcess(), &DecryptedData, 0, &sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (DecryptedData) { i_ptr = (PULONG)BitmapData.Scan0; ptr = DecryptedData; while (c > 0) { *ptr = *i_ptr ^ uKey; ptr++; i_ptr++; c--; } bSuccess = (SfuWriteBufferToFile(szOutputFile, DecryptedData, imagesz, FALSE, FALSE) == imagesz); sz = 0; NtFreeVirtualMemory(NtCurrentProcess(), &DecryptedData, &sz, MEM_RELEASE); } GdipBitmapUnlockBits(BitmapPtr, &BitmapData); } } } while (cond); if (bSuccess == FALSE) { SfcuiPrintText(g_ConOut, T_SFEXTRACTFAIL, g_ConsoleOutput, FALSE); } else { SfcuiPrintText(g_ConOut, szOutputFile, g_ConsoleOutput, TRUE); SfcuiPrintText(g_ConOut, T_SFEXTRACTED, g_ConsoleOutput, TRUE); } if (BitmapPtr != NULL) { GdipDisposeImage(&BitmapPtr); } if (gdiplusToken != 0) { GdiplusShutdown(gdiplusToken); } if (pImageStream != NULL) { pImageStream->lpVtbl->Release(pImageStream); } if (ImageBase != NULL) { NtUnmapViewOfSection(NtCurrentProcess(), ImageBase); } return 0; }
// Figure out what combination of protections and states pages in a single allocation // can have. Can protections be mixed? How about states (COMMIT/RESERVE/FREE)? void test_prot_mem( void ) { VOID *address, *a; ULONG size, old; NTSTATUS r; HANDLE handle = (HANDLE) ~0; // allocate 16 pages address = NULL; size = 0x10000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_RESERVE, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(address != NULL, "address wrong\n"); ok(size == 0x10000, "size wrong\n"); a = address; // try change access immediately size = 0x1000; r = NtProtectVirtualMemory( handle, &address, &size, PAGE_NOACCESS, &old ); ok(r == STATUS_NOT_COMMITTED, "wrong return code (%08lx)\n", r); // commit the page address = a; size = 0x1000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_COMMIT, PAGE_NOACCESS ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(size == 0x1000, "size wrong\n"); // try change access again address = a; size = 0x1000; r = NtProtectVirtualMemory( handle, &address, &size, PAGE_READONLY, &old ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(old == PAGE_NOACCESS, "wrong access\n"); ok(size == 0x1000, "size wrong\n"); // and again address = a; size = 0x1000; r = NtProtectVirtualMemory( handle, &address, &size, PAGE_READWRITE, &old ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(old == PAGE_READONLY, "wrong access\n"); ok(size == 0x1000, "size wrong\n"); // change the second page address = a + 0x1000; size = 0x1000; old = 0; r = NtProtectVirtualMemory( handle, &address, &size, PAGE_READWRITE, &old ); ok(r == STATUS_NOT_COMMITTED, "wrong return code (%08lx)\n", r); ok(size == 0x1000, "size wrong\n"); ok(old == PAGE_READONLY, "wrong access\n"); // commit the second page, overlapping with the first page address = a; size = 0x2000; r = NtAllocateVirtualMemory( handle, &address, 0, &size, MEM_COMMIT, PAGE_EXECUTE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); ok(size == 0x2000, "size wrong\n"); ok(old == PAGE_READONLY, "wrong access\n"); // overlaps the next uncommitted page address = a + 0x1000; size = 0x2000; r = NtProtectVirtualMemory( handle, &address, &size, PAGE_READWRITE, &old ); ok(r == STATUS_NOT_COMMITTED, "wrong return code (%08lx)\n", r); ok(size == 0x2000, "size wrong\n"); #ifdef WIN2K ok(old == PAGE_READONLY, "wrong access\n"); #endif // the page we just committed address = a + 0x1000; size = 0x1000; r = NtProtectVirtualMemory( handle, &address, &size, PAGE_READWRITE, &old ); ok(r == STATUS_SUCCESS, "wrong return code (%08lx)\n", r); ok(size == 0x1000, "size wrong\n"); ok(old == PAGE_EXECUTE, "wrong access\n"); // free all the memory address = a; size = 0x10000; r = NtFreeVirtualMemory( handle, &address, &size, MEM_RELEASE ); ok(r == STATUS_SUCCESS, "wrong return code\n"); }
/*++ * @name SmpMoveFile * * The SmpMoveFile function deletes a specify file. * * @param lpExistingFileName * the name of an existing file which should be removed * * @param lpNewFileName * a new name of an existing file. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL * othwerwise. * * @remarks * This function called from the SmpMoveFilesQueryRoutine function. * * *--*/ NTSTATUS SmpMoveFile( IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName ) { PFILE_RENAME_INFORMATION FileRenameInfo; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; UNICODE_STRING ExistingFileNameU; HANDLE FileHandle; DWORD FileNameSize; BOOLEAN ReplaceIfExists; NTSTATUS Status; if( !lpExistingFileName || !lpNewFileName ) return (STATUS_INVALID_PARAMETER); DPRINT("SmpMoveFile (%S, %S)\n", lpExistingFileName, lpNewFileName); RtlInitUnicodeString(&ExistingFileNameU, lpExistingFileName); InitializeObjectAttributes(&ObjectAttributes, &ExistingFileNameU, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtCreateFile (&FileHandle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS(Status) ) { DPRINT("NtCreateFile() failed (Status %lx)\n", Status); return (Status); } FileNameSize = wcslen(lpNewFileName)*sizeof(*lpNewFileName); FileRenameInfo = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FILE_RENAME_INFORMATION)+FileNameSize); if( !FileRenameInfo ) { DPRINT("RtlAllocateHeap failed\n"); NtClose(FileHandle); return (STATUS_NO_MEMORY); } if( L'!' == *lpNewFileName ) { lpNewFileName++; FileNameSize -= sizeof(*lpNewFileName); ReplaceIfExists = TRUE; } else { ReplaceIfExists = FALSE; } FileRenameInfo->RootDirectory = NULL; FileRenameInfo->ReplaceIfExists = ReplaceIfExists; FileRenameInfo->FileNameLength = FileNameSize; RtlCopyMemory(FileRenameInfo->FileName, lpNewFileName, FileNameSize); Status = NtSetInformationFile( FileHandle, &IoStatusBlock, FileRenameInfo, sizeof(FILE_RENAME_INFORMATION)+FileNameSize, FileRenameInformation ); RtlFreeHeap(RtlGetProcessHeap(), 0, FileRenameInfo); /* FIXME: After the FileRenameInformation parameter will be implemented into the fs driver the following code can be removed */ if( STATUS_NOT_IMPLEMENTED == Status ) { HANDLE FileHandleNew; UNICODE_STRING NewFileNameU; FILE_BASIC_INFORMATION FileBasicInfo; UCHAR *lpBuffer = NULL; SIZE_T RegionSize = 0x10000; LARGE_INTEGER BytesCopied; BOOL EndOfFileFound; Status = NtQueryInformationFile( FileHandle, &IoStatusBlock, &FileBasicInfo, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if( !NT_SUCCESS(Status) ) { DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status); NtClose(FileHandle); return (Status); } RtlInitUnicodeString(&NewFileNameU, lpNewFileName); InitializeObjectAttributes(&ObjectAttributes, &NewFileNameU, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtCreateFile (&FileHandleNew, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, ReplaceIfExists ? FILE_OVERWRITE_IF : FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS(Status) ) { DPRINT("NtCreateFile() failed (Status %lx)\n", Status); NtClose(FileHandle); return (Status); } Status = NtAllocateVirtualMemory( NtCurrentProcess(), (PVOID *)&lpBuffer, 2, &RegionSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if( !NT_SUCCESS(Status) ) { DPRINT("NtAllocateVirtualMemory() failed (Status %lx)\n", Status); NtClose(FileHandle); SmpDeleteFile(lpNewFileName); return (Status); } BytesCopied.QuadPart = 0; EndOfFileFound = FALSE; while( !EndOfFileFound && NT_SUCCESS(Status) ) { Status = NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, lpBuffer, RegionSize, NULL, NULL); if( NT_SUCCESS(Status) ) { Status = NtWriteFile(FileHandleNew, NULL, NULL, NULL, &IoStatusBlock, lpBuffer, IoStatusBlock.Information, NULL, NULL); if( NT_SUCCESS(Status) ) { BytesCopied.QuadPart += IoStatusBlock.Information; } else { DPRINT("NtWriteFile() failed (Status %lx)\n", Status); } } else { if( STATUS_END_OF_FILE == Status ) { EndOfFileFound = TRUE; Status = STATUS_SUCCESS; } else { DPRINT("NtWriteFile() failed (Status %lx)\n", Status); } } } NtFreeVirtualMemory(NtCurrentProcess(), (PVOID *)&lpBuffer, &RegionSize, MEM_RELEASE); Status = NtQueryInformationFile( FileHandleNew, &IoStatusBlock, &FileBasicInfo, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if( !NT_SUCCESS(Status) ) { DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status); } Status = NtSetInformationFile(FileHandleNew, &IoStatusBlock, &FileBasicInfo, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if( !NT_SUCCESS(Status) ) { DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status); } NtClose(FileHandleNew); NtClose(FileHandle); SmpDeleteFile(lpExistingFileName); return (Status); } NtClose(FileHandle); return (Status); }
/****************************************************************************** * RtlDestroyProcessParameters [NTDLL.@] */ void WINAPI RtlDestroyProcessParameters( RTL_USER_PROCESS_PARAMETERS *params ) { void *ptr = params; SIZE_T size = 0; NtFreeVirtualMemory( NtCurrentProcess(), &ptr, &size, MEM_RELEASE ); }
void mymain(void){ ///A valid module name cannot exceed the Windows path part constraints. UCHAR szInternalDllName[MAX_PATH]; PVOID pDllBase = NULL; PVOID pListBuf = NULL; ULONGLONG requiredBufSize = 0; ULONGLONG bufSize = 0; ULONGLONG entryStringLength = 0; NTSTATUS status, fatalStatus = STATUS_HANDLE_NO_LONGER_VALID; for (;;){ pDllBase = NULL; pListBuf = NULL; requiredBufSize = 0; bufSize = 0; entryStringLength = 0; system("CLS"); printf_s("Welcome to .def File Creator V0.1!\n\n"); printf_s("Enter the full DLL or exe name as in the following example:\n"); printf_s("\"ntdll.dll\" (without quotes).\n\n"); printf_s("DLL must reside in \\System32 or in current directory.\n\n"); printf_s("DLL name: "); status = getAndLoadDllByInput(&pDllBase); if (status){ mydie(status, STATUS_SUCCESS); continue; } printf_s("DLL loaded successfully. Address: %p\n", pDllBase); status = obtainImageFileEatEntries(pDllBase, NULL, &requiredBufSize, szInternalDllName, sizeof(szInternalDllName)); if (status != STATUS_BUFFER_TOO_SMALL){ mydie(status, STATUS_SUCCESS); continue; } status = NtAllocateVirtualMemory(INVALID_HANDLE_VALUE, &pListBuf, 0, &requiredBufSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (status){ mydie(status, STATUS_SUCCESS); continue; } bufSize = requiredBufSize; status = obtainImageFileEatEntries(pDllBase, pListBuf, &requiredBufSize, szInternalDllName, sizeof(szInternalDllName)); if (status){ mydie(status, STATUS_SUCCESS); continue; } printf_s("\n%s\n\nlist size: 0x%llX", pListBuf, requiredBufSize); ///We don't want to write zeros into the file. The standard EOF is sufficient. entryStringLength = requiredBufSize - sizeof(WCHAR); status = dumpEatEntriesToDefFile(pListBuf, entryStringLength, szInternalDllName); fatalStatus = NtFreeVirtualMemory(INVALID_HANDLE_VALUE, &pListBuf, &bufSize, MEM_RELEASE); if (status || fatalStatus){ mydie(status, fatalStatus); continue; } printf_s("\nThe image has been successfully scanned and its exports were"); printf_s("\ndumped into \"exports.def\" successfully."); printf_s("\n\nYou can press any key to dump another module or close the window to exit."); fflush(stdin); _getch(); } }
NTSTATUS DoUserLogon ( IN PLOGON_INFO LogonInfo ) /*++ Routine Description: Validates a username/password combination by interfacing to the security subsystem. Arguments: LogonInfo - Pointer to a block containing in/out information about the logon. Return Value: NTSTATUS from the security system. --*/ { NTSTATUS status, subStatus, freeStatus; ULONG actualUserInfoBufferLength; ULONG oldSessionCount; LUID LogonId; ULONG Catts; LARGE_INTEGER Expiry; ULONG BufferOffset; SecBufferDesc InputToken; SecBuffer InputBuffers[2]; SecBufferDesc OutputToken; SecBuffer OutputBuffer; PNTLM_AUTHENTICATE_MESSAGE NtlmInToken = NULL; PAUTHENTICATE_MESSAGE InToken = NULL; PNTLM_ACCEPT_RESPONSE OutToken = NULL; ULONG NtlmInTokenSize; ULONG InTokenSize; ULONG OutTokenSize; ULONG AllocateSize; ULONG profileBufferLength; PAGED_CODE( ); LogonInfo->IsNullSession = FALSE; LogonInfo->IsAdmin = FALSE; #if DBG SrvLogonCount++; #endif // // If this is a null session request, use the cached null session // token, which was created during server startup. // if ( (LogonInfo->UserNameLength == 0) && (LogonInfo->CaseSensitivePasswordLength == 0) && ( (LogonInfo->CaseInsensitivePasswordLength == 0) || ( (LogonInfo->CaseInsensitivePasswordLength == 1) && (*LogonInfo->CaseInsensitivePassword == '\0') ) ) ) { LogonInfo->IsNullSession = TRUE; #if DBG SrvNullLogonCount++; #endif if ( !CONTEXT_NULL(SrvNullSessionToken) ) { LogonInfo->HaveHandle = TRUE; LogonInfo->Token = SrvNullSessionToken; LogonInfo->KickOffTime.QuadPart = 0x7FFFFFFFFFFFFFFF; LogonInfo->LogOffTime.QuadPart = 0x7FFFFFFFFFFFFFFF; LogonInfo->GuestLogon = FALSE; LogonInfo->EncryptedLogon = FALSE; return STATUS_SUCCESS; } } // // This is the main body of the Cairo logon user code // // // First make sure we have a credential handle // if ((SrvHaveCreds & HAVENTLM) == 0) { status = AcquireLMCredentials(); if (!NT_SUCCESS(status)) { goto error_exit; } } // // Figure out how big a buffer we need. We put all the messages // in one buffer for efficiency's sake. // NtlmInTokenSize = sizeof(NTLM_AUTHENTICATE_MESSAGE); NtlmInTokenSize = (NtlmInTokenSize + 3) & 0xfffffffc; InTokenSize = sizeof(AUTHENTICATE_MESSAGE) + LogonInfo->UserNameLength + LogonInfo->WorkstationNameLength + LogonInfo->DomainNameLength + LogonInfo->CaseInsensitivePasswordLength + ROUND_UP_COUNT(LogonInfo->CaseSensitivePasswordLength, sizeof(USHORT)); InTokenSize = (InTokenSize + 3) & 0xfffffffc; OutTokenSize = sizeof(NTLM_ACCEPT_RESPONSE); OutTokenSize = (OutTokenSize + 3) & 0xfffffffc; // // Round this up to 8 byte boundary becaus the out token needs to be // quad word aligned for the LARGE_INTEGER. // AllocateSize = ((NtlmInTokenSize + InTokenSize + 7) & 0xfffffff8) + OutTokenSize; status = NtAllocateVirtualMemory( NtCurrentProcess( ), &InToken, 0L, &AllocateSize, MEM_COMMIT, PAGE_READWRITE ); if ( !NT_SUCCESS(status) ) { INTERNAL_ERROR( ERROR_LEVEL_EXPECTED, "SrvValidateUser: NtAllocateVirtualMemory failed: %X\n.", status, NULL ); SrvLogError( SrvDeviceObject, EVENT_SRV_NO_VIRTUAL_MEMORY, status, &actualUserInfoBufferLength, sizeof(ULONG), NULL, 0 ); status = STATUS_INSUFF_SERVER_RESOURCES; goto error_exit; } // // Zero the input tokens // RtlZeroMemory( InToken, InTokenSize + NtlmInTokenSize ); NtlmInToken = (PNTLM_AUTHENTICATE_MESSAGE) ((PUCHAR) InToken + InTokenSize); OutToken = (PNTLM_ACCEPT_RESPONSE) ((PUCHAR) (((ULONG) NtlmInToken + NtlmInTokenSize + 7) & 0xfffffff8)); // // First set up the NtlmInToken, since it is the easiest. // RtlCopyMemory( NtlmInToken->ChallengeToClient, LogonInfo->EncryptionKey, MSV1_0_CHALLENGE_LENGTH ); NtlmInToken->ParameterControl = 0; // // Okay, now for the tought part - marshalling the AUTHENTICATE_MESSAGE // RtlCopyMemory( InToken->Signature, NTLMSSP_SIGNATURE, sizeof(NTLMSSP_SIGNATURE)); InToken->MessageType = NtLmAuthenticate; BufferOffset = sizeof(AUTHENTICATE_MESSAGE); // // LM password - case insensitive // InToken->LmChallengeResponse.Buffer = (PCHAR) BufferOffset; InToken->LmChallengeResponse.Length = InToken->LmChallengeResponse.MaximumLength = (USHORT) LogonInfo->CaseInsensitivePasswordLength; RtlCopyMemory( BufferOffset + (PCHAR) InToken, LogonInfo->CaseInsensitivePassword, LogonInfo->CaseInsensitivePasswordLength); BufferOffset += ROUND_UP_COUNT(LogonInfo->CaseInsensitivePasswordLength, sizeof(USHORT)); // // NT password - case sensitive // InToken->NtChallengeResponse.Buffer = (PCHAR) BufferOffset; InToken->NtChallengeResponse.Length = InToken->NtChallengeResponse.MaximumLength = (USHORT) LogonInfo->CaseSensitivePasswordLength; RtlCopyMemory( BufferOffset + (PCHAR) InToken, LogonInfo->CaseSensitivePassword, LogonInfo->CaseSensitivePasswordLength); BufferOffset += LogonInfo->CaseSensitivePasswordLength; // // Domain Name // InToken->DomainName.Buffer = (PCHAR) BufferOffset; InToken->DomainName.Length = InToken->DomainName.MaximumLength = (USHORT) LogonInfo->DomainNameLength; RtlCopyMemory( BufferOffset + (PCHAR) InToken, LogonInfo->DomainName, LogonInfo->DomainNameLength); BufferOffset += LogonInfo->DomainNameLength; // // Workstation Name // InToken->Workstation.Buffer = (PCHAR) BufferOffset; InToken->Workstation.Length = InToken->Workstation.MaximumLength = (USHORT) LogonInfo->WorkstationNameLength; RtlCopyMemory( BufferOffset + (PCHAR) InToken, LogonInfo->WorkstationName, LogonInfo->WorkstationNameLength); BufferOffset += LogonInfo->WorkstationNameLength; // // User Name // InToken->UserName.Buffer = (PCHAR) BufferOffset; InToken->UserName.Length = InToken->UserName.MaximumLength = (USHORT) LogonInfo->UserNameLength; RtlCopyMemory( BufferOffset + (PCHAR) InToken, LogonInfo->UserName, LogonInfo->UserNameLength); BufferOffset += LogonInfo->UserNameLength; // // Setup all the buffers properly // InputToken.pBuffers = InputBuffers; InputToken.cBuffers = 2; InputToken.ulVersion = 0; InputBuffers[0].pvBuffer = InToken; InputBuffers[0].cbBuffer = InTokenSize; InputBuffers[0].BufferType = SECBUFFER_TOKEN; InputBuffers[1].pvBuffer = NtlmInToken; InputBuffers[1].cbBuffer = NtlmInTokenSize; InputBuffers[1].BufferType = SECBUFFER_TOKEN; OutputToken.pBuffers = &OutputBuffer; OutputToken.cBuffers = 1; OutputToken.ulVersion = 0; OutputBuffer.pvBuffer = OutToken; OutputBuffer.cbBuffer = OutTokenSize; OutputBuffer.BufferType = SECBUFFER_TOKEN; SrvStatistics.SessionLogonAttempts++; status = AcceptSecurityContext( &SrvLmLsaHandle, NULL, &InputToken, 0, SECURITY_NATIVE_DREP, &LogonInfo->Token, &OutputToken, &Catts, (PTimeStamp) &Expiry ); status = MapSecurityError( status ); if ( !NT_SUCCESS(status) ) { LogonInfo->Token.dwLower = 0; LogonInfo->Token.dwUpper = 0; INTERNAL_ERROR( ERROR_LEVEL_EXPECTED, "SrvValidateUser: LsaLogonUser failed: %X", status, NULL ); freeStatus = NtFreeVirtualMemory( NtCurrentProcess( ), (PVOID *)&InToken, &AllocateSize, MEM_RELEASE ); ASSERT(NT_SUCCESS(freeStatus)); goto error_exit; } LogonInfo->KickOffTime = OutToken->KickoffTime; LogonInfo->LogOffTime = Expiry; LogonInfo->GuestLogon = (BOOLEAN)(OutToken->UserFlags & LOGON_GUEST); LogonInfo->EncryptedLogon = (BOOLEAN)!(OutToken->UserFlags & LOGON_NOENCRYPTION); LogonInfo->LogonId = OutToken->LogonId; LogonInfo->HaveHandle = TRUE; if ( (OutToken->UserFlags & LOGON_USED_LM_PASSWORD) && LogonInfo->NtSmbs ) { ASSERT( MSV1_0_USER_SESSION_KEY_LENGTH >= MSV1_0_LANMAN_SESSION_KEY_LENGTH ); RtlZeroMemory( LogonInfo->NtUserSessionKey, MSV1_0_USER_SESSION_KEY_LENGTH ); RtlCopyMemory( LogonInfo->NtUserSessionKey, OutToken->LanmanSessionKey, MSV1_0_LANMAN_SESSION_KEY_LENGTH ); // // Turn on bit 1 to tell the client that we are using // the lm session key instead of the user session key. // LogonInfo->Action |= SMB_SETUP_USE_LANMAN_KEY; } else { RtlCopyMemory( LogonInfo->NtUserSessionKey, OutToken->UserSessionKey, MSV1_0_USER_SESSION_KEY_LENGTH ); } RtlCopyMemory( LogonInfo->LanManSessionKey, OutToken->LanmanSessionKey, MSV1_0_LANMAN_SESSION_KEY_LENGTH ); freeStatus = NtFreeVirtualMemory( NtCurrentProcess( ), (PVOID *)&InToken, &AllocateSize, MEM_RELEASE ); ASSERT(NT_SUCCESS(freeStatus)); // // Note whether or not this user is an administrator // LogonInfo->IsAdmin = SrvIsAdmin( LogonInfo->Token ); // // One last check: Is our session count being exceeded? // We will let the session be exceeded by 1 iff the client // is an administrator. // if( LogonInfo->IsNullSession == FALSE ) { oldSessionCount = ExInterlockedAddUlong( &SrvStatistics.CurrentNumberOfSessions, 1, &GLOBAL_SPIN_LOCK(Statistics) ); if ( oldSessionCount >= SrvMaxUsers ) { if( oldSessionCount != SrvMaxUsers || !LogonInfo->IsAdmin ) { ExInterlockedAddUlong( &SrvStatistics.CurrentNumberOfSessions, (ULONG)-1, &GLOBAL_SPIN_LOCK(Statistics) ); DeleteSecurityContext( &LogonInfo->Token ); RtlZeroMemory( &LogonInfo->Token, sizeof( LogonInfo->Token ) ); status = STATUS_REQUEST_NOT_ACCEPTED; goto error_exit; } } } return STATUS_SUCCESS; error_exit: return status; } // DoUserLogon
/* * Creates a stack for a thread or fiber */ NTSTATUS WINAPI BaseCreateStack(HANDLE hProcess, SIZE_T StackReserve, SIZE_T StackCommit, PINITIAL_TEB InitialTeb) { NTSTATUS Status; PIMAGE_NT_HEADERS Headers; ULONG_PTR Stack; ULONG PageSize, Dummy, AllocationGranularity; SIZE_T StackReserveHeader, StackCommitHeader, GuardPageSize, GuaranteedStackCommit; DPRINT("BaseCreateStack (hProcess: %p, Max: %lx, Current: %lx)\n", hProcess, StackReserve, StackCommit); /* Read page size */ PageSize = BaseStaticServerData->SysInfo.PageSize; AllocationGranularity = BaseStaticServerData->SysInfo.AllocationGranularity; /* Get the Image Headers */ Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); if (!Headers) return STATUS_INVALID_IMAGE_FORMAT; StackCommitHeader = Headers->OptionalHeader.SizeOfStackCommit; StackReserveHeader = Headers->OptionalHeader.SizeOfStackReserve; if (!StackReserve) StackReserve = StackReserveHeader; if (!StackCommit) { StackCommit = StackCommitHeader; } else if (StackCommit >= StackReserve) { StackReserve = ROUND_UP(StackCommit, 1024 * 1024); } StackCommit = ROUND_UP(StackCommit, PageSize); StackReserve = ROUND_UP(StackReserve, AllocationGranularity); GuaranteedStackCommit = NtCurrentTeb()->GuaranteedStackBytes; if ((GuaranteedStackCommit) && (StackCommit < GuaranteedStackCommit)) { StackCommit = GuaranteedStackCommit; } if (StackCommit >= StackReserve) { StackReserve = ROUND_UP(StackCommit, 1024 * 1024); } StackCommit = ROUND_UP(StackCommit, PageSize); StackReserve = ROUND_UP(StackReserve, AllocationGranularity); /* Reserve memory for the stack */ Stack = 0; Status = NtAllocateVirtualMemory(hProcess, (PVOID*)&Stack, 0, &StackReserve, MEM_RESERVE, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Failure to reserve stack: %lx\n", Status); return Status; } /* Now set up some basic Initial TEB Parameters */ InitialTeb->AllocatedStackBase = (PVOID)Stack; InitialTeb->StackBase = (PVOID)(Stack + StackReserve); InitialTeb->PreviousStackBase = NULL; InitialTeb->PreviousStackLimit = NULL; /* Update the Stack Position */ Stack += StackReserve - StackCommit; /* Allocate memory for the stack */ Status = NtAllocateVirtualMemory(hProcess, (PVOID*)&Stack, 0, &StackCommit, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Failure to allocate stack\n"); GuardPageSize = 0; NtFreeVirtualMemory(hProcess, (PVOID*)&Stack, &GuardPageSize, MEM_RELEASE); return Status; } /* Now set the current Stack Limit */ InitialTeb->StackLimit = (PVOID)Stack; /* Create a guard page */ GuardPageSize = PageSize; Status = NtProtectVirtualMemory(hProcess, (PVOID*)&Stack, &GuardPageSize, PAGE_GUARD | PAGE_READWRITE, &Dummy); if (!NT_SUCCESS(Status)) { DPRINT1("Failure to set guard page\n"); return Status; } /* Update the Stack Limit keeping in mind the Guard Page */ InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit + GuardPageSize); /* We are done! */ return STATUS_SUCCESS; }
NTSTATUS dumpEatEntriesToDefFile(PVOID pEatEntryList, ULONGLONG listBufferSize, PUCHAR pModuleName){ OBJECT_ATTRIBUTES defFileAttr; UNICODE_STRING uDefFileName; IO_STATUS_BLOCK ioSb; NTSTATUS status, fatalStatus = STATUS_CLUSTER_NETINTERFACE_EXISTS; PCHAR pDefPreamble = NULL; ///Keep it simple. We can't allocate less than 4 kB using NtXxx funcs anyway, ///so just allocate 4 kB although we never will need that much. ULONGLONG defPreambleSize = PAGE_SIZE; HANDLE hDefFile = NULL; HANDLE hParentDir = NULL; ///Quite some ugly hacking... char szDefPreamblePart[] = { 0x0D, 0x0A, 0x0D, 0x0A, 'E', 'X', 'P', 'O', 'R', 'T', 'S', 0x0D, 0x0A, 0x0 }; status = NtAllocateVirtualMemory(INVALID_HANDLE_VALUE, &pDefPreamble, 0, &defPreambleSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (status) return status; status = RtlStringCbPrintfA(pDefPreamble, defPreambleSize, "LIBRARY %s%s", pModuleName, szDefPreamblePart); if (status){ fatalStatus = NtFreeVirtualMemory(INVALID_HANDLE_VALUE, &pDefPreamble, &defPreambleSize, MEM_RELEASE); if (fatalStatus) mydie(status, fatalStatus); return status; } status = RtlStringCbLengthA(pDefPreamble, defPreambleSize, &defPreambleSize); if (status){ fatalStatus = NtFreeVirtualMemory(INVALID_HANDLE_VALUE, &pDefPreamble, &defPreambleSize, MEM_RELEASE); if (fatalStatus) mydie(status, fatalStatus); return status; } hParentDir = NtCurrentPeb()->ProcessParameters->CurrentDirectory.Handle; RtlInitUnicodeString(&uDefFileName, L"exports.def"); InitializeObjectAttributes(&defFileAttr, &uDefFileName, OBJ_CASE_INSENSITIVE, hParentDir, NULL); status = NtCreateFile(&hDefFile, FILE_ALL_ACCESS | SYNCHRONIZE, &defFileAttr, &ioSb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_SUPERSEDE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, NULL, 0); if (status){ fatalStatus = NtFreeVirtualMemory(INVALID_HANDLE_VALUE, &pDefPreamble, &defPreambleSize, MEM_RELEASE); if (fatalStatus) mydie(status, fatalStatus); return status; } status = NtWriteFile(hDefFile, NULL, NULL, NULL, &ioSb, pDefPreamble, (ULONG)defPreambleSize, NULL, NULL); if (!status) status = NtWriteFile(hDefFile, NULL, NULL, NULL, &ioSb, pEatEntryList, (ULONG)listBufferSize, NULL, NULL); fatalStatus = NtClose(hDefFile); if (fatalStatus) mydie(status, fatalStatus); fatalStatus = NtFreeVirtualMemory(INVALID_HANDLE_VALUE, &pDefPreamble, &defPreambleSize, MEM_RELEASE); if (fatalStatus) mydie(status, fatalStatus); return status; }
NTSTATUS SrvValidateBlob( IN PSESSION Session, IN PCONNECTION Connection, IN PUNICODE_STRING UserName, IN OUT PCHAR Blob, IN OUT ULONG *BlobLength ) /*++ Routine Description: Validates a Kerberos Blob sent from the client Arguments: Session - A pointer to a session block so that this routine can insert a user token. Connection - A pointer to the connection this user is on. UserName - ASCIIZ string corresponding to the user name to validate. Blob - The Blob to validate and the place to return the output Blob. Note this means that this string space has to be long enough to hold the maximum length Blob. BlobLength - The length of the aforementioned Blob Return Value: NTSTATUS from the security system. --*/ { NTSTATUS Status; ULONG Catts; LARGE_INTEGER Expiry; PUCHAR AllocateMemory = NULL; ULONG AllocateLength = *BlobLength; BOOLEAN virtualMemoryAllocated = FALSE; SecBufferDesc InputToken; SecBuffer InputBuffer; SecBufferDesc OutputToken; SecBuffer OutputBuffer; ULONG oldSessionCount; AllocateLength += 16; Status = NtAllocateVirtualMemory( NtCurrentProcess(), &AllocateMemory, 0, &AllocateLength, MEM_COMMIT, PAGE_READWRITE ); if ( !NT_SUCCESS(Status) ) { INTERNAL_ERROR( ERROR_LEVEL_UNEXPECTED, "Could not allocate Blob Memory %lC\n", Status, NULL); goto get_out; } virtualMemoryAllocated = TRUE; if ( (SrvHaveCreds & HAVEKERBEROS) == 0 ) { // Need to get cred handle first UNICODE_STRING Kerb; Kerb.Length = Kerb.MaximumLength = 16; Kerb.Buffer = (LPWSTR) AllocateMemory; RtlCopyMemory( Kerb.Buffer, MICROSOFT_KERBEROS_NAME, 16); Status = AcquireCredentialsHandle( NULL, // Default principal (PSECURITY_STRING) &Kerb, SECPKG_CRED_INBOUND, // Need to define this NULL, // No LUID NULL, // no AuthData NULL, // no GetKeyFn NULL, // no GetKeyArg &SrvKerberosLsaHandle, (PTimeStamp)&Expiry ); if ( !NT_SUCCESS(Status) ) { Status = MapSecurityError(Status); goto get_out; } SrvHaveCreds |= HAVEKERBEROS; } RtlCopyMemory( AllocateMemory, Blob, *BlobLength ); InputToken.pBuffers = &InputBuffer; InputToken.cBuffers = 1; InputToken.ulVersion = 0; InputBuffer.pvBuffer = AllocateMemory; InputBuffer.cbBuffer = *BlobLength; InputBuffer.BufferType = SECBUFFER_TOKEN; OutputToken.pBuffers = &OutputBuffer; OutputToken.cBuffers = 1; OutputToken.ulVersion = 0; OutputBuffer.pvBuffer = AllocateMemory; OutputBuffer.cbBuffer = *BlobLength; OutputBuffer.BufferType = SECBUFFER_TOKEN; SrvStatistics.SessionLogonAttempts++; Status = AcceptSecurityContext( &SrvKerberosLsaHandle, (PCtxtHandle)NULL, &InputToken, ASC_REQ_EXTENDED_ERROR, // fContextReq SECURITY_NATIVE_DREP, &Session->UserHandle, &OutputToken, &Catts, (PTimeStamp)&Expiry ); Status = MapSecurityError( Status ); if ( NT_SUCCESS(Status) || (Catts & ASC_RET_EXTENDED_ERROR) ) { *BlobLength = OutputBuffer.cbBuffer; RtlCopyMemory( Blob, AllocateMemory, *BlobLength ); // // BUGBUG // All of the following values need to come from someplace // And while we're at it, get the LogonId as well // if(NT_SUCCESS(Status)) { // // Note whether or not this user is an administrator // Session->IsAdmin = SrvIsAdmin( Session->UserHandle ); // // fiddle with the session structures iff the // security context was actually accepted // Session->HaveHandle = TRUE; Session->KickOffTime = Expiry; Session->LogOffTime = Expiry; Session->GuestLogon = FALSE; // No guest logon this way Session->EncryptedLogon = TRUE; // // See if the session count is being exceeded. We'll allow it only // if the new client is an administrator // oldSessionCount = ExInterlockedAddUlong( &SrvStatistics.CurrentNumberOfSessions, 1, &GLOBAL_SPIN_LOCK(Statistics) ); if ( oldSessionCount >= SrvMaxUsers ) { if( oldSessionCount != SrvMaxUsers || !SrvIsAdmin( Session->UserHandle ) ) { ExInterlockedAddUlong( &SrvStatistics.CurrentNumberOfSessions, (ULONG)-1, &GLOBAL_SPIN_LOCK(Statistics) ); DeleteSecurityContext( &Session->UserHandle ); Session->HaveHandle = FALSE; Status = STATUS_REQUEST_NOT_ACCEPTED; goto get_out; } } } } else { *BlobLength = 0; } get_out: if (virtualMemoryAllocated) { (VOID)NtFreeVirtualMemory( NtCurrentProcess(), &AllocateMemory, &AllocateLength, MEM_DECOMMIT ); } return Status; } // SrvValidateBlob
static void Test_NtFreeVirtualMemory(void) { PVOID Buffer = NULL, Buffer2; SIZE_T Length = PAGE_SIZE; NTSTATUS Status; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &Buffer, 0, &Length, MEM_RESERVE, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08lx\n", Status); ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n"); Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer, &Length, MEM_DECOMMIT); ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory failed : 0x%08lx\n", Status); /* Now try to free more than we got */ Length++; Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer, &Length, MEM_DECOMMIT); ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer, &Length, MEM_RELEASE); ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); /* Free out of bounds from the wrong origin */ Length = PAGE_SIZE; Buffer2 = (PVOID)((ULONG_PTR)Buffer+1); Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer2, &Length, MEM_DECOMMIT); ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); Buffer2 = (PVOID)((ULONG_PTR)Buffer+1); Length = PAGE_SIZE; Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer2, &Length, MEM_RELEASE); ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); /* Same but in bounds */ Length = PAGE_SIZE - 1; Buffer2 = (PVOID)((ULONG_PTR)Buffer+1); Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer2, &Length, MEM_DECOMMIT); ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); ok(Buffer2 == Buffer, "NtFreeVirtualMemory set wrong buffer.\n"); ok(Length == PAGE_SIZE, "NtFreeVirtualMemory did not round Length to PAGE_SIZE.\n"); Buffer2 = (PVOID)((ULONG_PTR)Buffer+1); Length = PAGE_SIZE-1; Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer2, &Length, MEM_RELEASE); ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); ok(Buffer2 == Buffer, "NtFreeVirtualMemory set wrong buffer.\n"); ok(Length == PAGE_SIZE, "NtFreeVirtualMemory did not round Length to PAGE_SIZE.\n"); /* Now allocate two pages and try to free them one after the other */ Length = 2*PAGE_SIZE; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &Buffer, 0, &Length, MEM_RESERVE, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08lx\n", Status); ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = Buffer; Length = PAGE_SIZE; Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer2, &Length, MEM_RELEASE); ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == Buffer, "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE); Length = PAGE_SIZE; Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer2, &Length, MEM_RELEASE); ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE), "The buffer is not aligned to PAGE_SIZE.\n"); /* Same, but try to free the second page before the first one */ Length = 2*PAGE_SIZE; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &Buffer, 0, &Length, MEM_RESERVE, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08lx\n", Status); ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE); Length = PAGE_SIZE; Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer2, &Length, MEM_RELEASE); ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE), "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = Buffer; Length = PAGE_SIZE; Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer2, &Length, MEM_RELEASE); ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == Buffer, "The buffer is not aligned to PAGE_SIZE.\n"); /* Now allocate two pages and try to free them in the middle */ Length = 2*PAGE_SIZE; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &Buffer, 0, &Length, MEM_RESERVE, PAGE_READWRITE); ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08lx\n", Status); ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = (PVOID)((ULONG_PTR)Buffer+1); Length = PAGE_SIZE; Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer2, &Length, MEM_RELEASE); ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == Buffer, "The buffer is not aligned to PAGE_SIZE.\n"); }
_CRTAPI1 main() { LONG i, j; PULONG p4, p3, p2, p1, Ro3, Noaccess; ULONG Size1, Size2, Size3, SizeRo3, SizeNoaccess; NTSTATUS status; HANDLE CurrentProcessHandle; ULONG id = 0; ULONG OldProtect; CurrentProcessHandle = NtCurrentProcess(); for(i=0; i<3; i++) { DbgPrint("Hello World...\n\n"); } DbgPrint("allocating virtual memory\n"); p1 = (PULONG)NULL; Size1 = 30 * 4096; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_COMMIT, PAGE_READWRITE); DbgPrint("created vm1 status %X start %lx size %lx\n", status, (ULONG)p1, Size1); p2 = (PULONG)NULL; Size2 = 16 * 4096; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 0, &Size2, MEM_COMMIT, PAGE_READWRITE); DbgPrint("created vm2 status %X start %lx size %lx\n", status, (ULONG)p2, Size2); id = fork () + id; DbgPrint("fork complete id %lx\n",id); p3 = p1 + 8 * 1024; Size3 = 16 * 4096; DbgPrint("deleting va from %lx for %lx bytes\n",p3, Size3); status = NtFreeVirtualMemory (CurrentProcessHandle,(PVOID *)&p3, &Size3, MEM_RELEASE); DbgPrint("free vm status %X start %lx size %lx\n", status, (ULONG)p3, Size3); p3 = (PULONG)NULL; Size3 = 50 * 4096; DbgPrint("allocating 50 pages of vm\n"); status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, 0, &Size3, MEM_COMMIT, PAGE_READWRITE); DbgPrint("created vm3 status %X start %lx size %lx\n", status, (ULONG)p3, Size3); Ro3 = (PULONG)NULL; SizeRo3 = 393933; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&Ro3, 0, &SizeRo3, MEM_COMMIT, PAGE_READONLY); DbgPrint("created vm4 status %X start %lx size %lx\n", status, (ULONG)Ro3, SizeRo3); *p3 = *Ro3; p1 = p3; p2 = ((PULONG)((PUCHAR)p3 + Size3)); p4 = p1; j = 0; while (p3 < p2) { j += 1; if (j % 8 == 0) { if (*p4 != (ULONG)p4) { DbgPrint("bad value in cell %lx value is %lx\n",p4, *p4); } p4 += 1; *p4 = (ULONG)p4; p4 = p4 + 1026; } *p3 = (ULONG)p3; p3 += 1027; } p3 = p1; // // Protect page as no access. // Noaccess = NULL; SizeNoaccess = 200*4096; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&Noaccess, 0, &SizeNoaccess, MEM_COMMIT, PAGE_READWRITE); DbgPrint("created vm5 status %X start %lx size %lx\n", status, (ULONG)Ro3, SizeRo3); // // Touch all the pages. // RtlZeroMemory (Noaccess, SizeNoaccess); *Noaccess = 91; Size1 = 30 * 4097; status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&Noaccess, &Size1, PAGE_NOACCESS, &OldProtect); DbgPrint("protected VM1 status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect); DbgPrint("forking a second time\n"); id = fork () + id; DbgPrint("fork2 complete id %lx\n",id); DbgPrint("changing page protection\n"); Size1 = 9000; OldProtect = *p3; status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, &Size1, PAGE_EXECUTE_READWRITE | PAGE_NOCACHE, &OldProtect); DbgPrint("protected VM2 status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect); status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&Ro3, &Size1, PAGE_READONLY | PAGE_NOCACHE, &OldProtect); DbgPrint("protected VM3 status %X, base %lx, size %lx, old protect %lx\n", status, Ro3, Size1, OldProtect); p1 += 1; while (p3 < p2) { *p1 = (ULONG)p1; if (*p3 != (ULONG)p3) { DbgPrint("bad value in cell %lx value is %lx\n",p3, *p3); } p3 += 1027; p1 += 1027; } DbgPrint("trying noacess test\n"); try { if (*Noaccess != 91) { DbgPrint("*************** FAILED NOACCESS TEST 1 *************\n"); } } except (EXCEPTION_EXECUTE_HANDLER) { if (GetExceptionCode() != STATUS_ACCESS_VIOLATION) { DbgPrint("*************** FAILED NOACCESS TEST 2 *************\n"); } } // // Make no access page accessable. // status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&Noaccess, &Size1, PAGE_READWRITE, &OldProtect); if (*Noaccess != 91) { DbgPrint("*************** FAILED NOACCESS TEST 3 *************\n"); } DbgPrint("that's all process %lx\n",id); NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS); }
/*********************************************************************** * VirtualFreeEx (KERNEL32.@) * * Releases or decommits a region of pages in virtual address space. * * PARAMS * process [I] Handle to process. * addr [I] Address of region to free. * size [I] Size of region. * type [I] Type of operation. * * RETURNS * Success: TRUE. * Failure: FALSE. */ BOOL WINAPI VirtualFreeEx( HANDLE process, LPVOID addr, SIZE_T size, DWORD type ) { NTSTATUS status = NtFreeVirtualMemory( process, &addr, &size, type ); if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; }
static NTSTATUS NTAPI TerminatorM1( _In_ HANDLE ProcessId ) { NTSTATUS status; HANDLE processHandle; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE, ProcessId ))) { PVOID pageOfGarbage; SIZE_T pageSize; PVOID baseAddress; MEMORY_BASIC_INFORMATION basicInfo; pageOfGarbage = NULL; pageSize = PAGE_SIZE; if (!NT_SUCCESS(NtAllocateVirtualMemory( NtCurrentProcess(), &pageOfGarbage, 0, &pageSize, MEM_COMMIT, PAGE_READONLY ))) { NtClose(processHandle); return STATUS_NO_MEMORY; } baseAddress = (PVOID)0; while (NT_SUCCESS(NtQueryVirtualMemory( processHandle, baseAddress, MemoryBasicInformation, &basicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL ))) { ULONG i; // Make sure we don't write to views of mapped files. That // could possibly corrupt files! if (basicInfo.Type == MEM_PRIVATE) { for (i = 0; i < basicInfo.RegionSize; i += PAGE_SIZE) { PhWriteVirtualMemory( processHandle, PTR_ADD_OFFSET(baseAddress, i), pageOfGarbage, PAGE_SIZE, NULL ); } } baseAddress = PTR_ADD_OFFSET(baseAddress, basicInfo.RegionSize); } // Size needs to be zero if we're freeing. pageSize = 0; NtFreeVirtualMemory( NtCurrentProcess(), &pageOfGarbage, &pageSize, MEM_RELEASE ); NtClose(processHandle); } return status; }