LONG STDCALL QueryFileList(NITRO_PLUS_ENTRY *Entry, PWIN32_FIND_DATAW FindData, ULONG_PTR Context) { UNREFERENCED_PARAMETER(Context); Entry->Size.LowPart = FindData->nFileSizeLow; Entry->Size.HighPart = FindData->nFileSizeHigh; StrCopyW(Entry->FileName, FindData->cFileName); return 1; }
VOID WINAPI GetDir(LPWSTR Path, ULONG Size, WCHAR EnvVar) { if (__argc == 1) { StrCopyW(Path, L"G:\\x"); Nt_SetCurrentDirectory(Path); } else { Nt_GetCurrentDirectory(Size, Path); } }
NTSTATUS ModifySelfSizeOfImage(LPWSTR ExeFullPath, LPWSTR CommandLine, ULONG SizeOfImage) { BOOL Result; ULONG Length; PVOID FakeCPInfoBuffer; WCHAR CmdFullPath[MAX_NTPATH]; PWCHAR CmdLineBuffer; NTSTATUS Status; PLDR_MODULE LdrModule; PIMAGE_DOS_HEADER DosHeader; PIMAGE_NT_HEADERS NtHeader; PIMAGE_SECTION_HEADER SectionHeader; FAKE_CREATE_PROCESS_INFO *fcpi; PROCESS_INFORMATION ProcessInformation; CONTEXT Context; NtFileDisk file; UNICODE_STRING ExeNtPath, *ProcessCommandLine; UNREFERENCED_PARAMETER(CommandLine); LdrModule = Nt_FindLdrModuleByName(NULL); DosHeader = (PIMAGE_DOS_HEADER)&__ImageBase; NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew); fcpi = (FAKE_CREATE_PROCESS_INFO *)AllocStack(0x2000); fcpi->PeHeaderSize = (ULONG_PTR)(IMAGE_FIRST_SECTION(NtHeader) + NtHeader->FileHeader.NumberOfSections) - (ULONG_PTR)DosHeader; Status = file.Open(LdrModule->FullDllName.Buffer); if (!NT_SUCCESS(Status)) return Status; Status = file.Read(fcpi->PeHeader, fcpi->PeHeaderSize); if (!NT_SUCCESS(Status)) return Status; CmdLineBuffer = (PWCHAR)((ULONG_PTR)fcpi->PeHeader + fcpi->PeHeaderSize); fcpi->CommandLine.Buffer = CmdLineBuffer; fcpi->CommandLine.Length = (USHORT)(StrLengthW(ExeFullPath) * sizeof(WCHAR)); ProcessCommandLine = &Nt_CurrentPeb()->ProcessParameters->CommandLine; CopyMemory(CmdLineBuffer, ProcessCommandLine->Buffer, ProcessCommandLine->Length); *(PULONG_PTR)&CmdLineBuffer += ProcessCommandLine->Length; CmdLineBuffer[0] = 0; fcpi->CommandLine.Length = ProcessCommandLine->Length; fcpi->CommandLine.MaximumLength = fcpi->CommandLine.Length + sizeof(WCHAR); ++CmdLineBuffer; CmdLineBuffer = (PWCHAR)ROUND_UP((ULONG_PTR)CmdLineBuffer, 16); RtlDosPathNameToNtPathName_U(LdrModule->FullDllName.Buffer, &ExeNtPath, NULL, NULL); fcpi->ExeNtPath.Buffer = CmdLineBuffer; CopyMemory(CmdLineBuffer, ExeNtPath.Buffer, ExeNtPath.Length); *(PULONG_PTR)&CmdLineBuffer += ExeNtPath.Length; CmdLineBuffer[0] = 0; fcpi->ExeNtPath.Length = ExeNtPath.Length; fcpi->ExeNtPath.MaximumLength = fcpi->ExeNtPath.Length + sizeof(WCHAR); *CmdLineBuffer++ = 0; RtlFreeUnicodeString(&ExeNtPath); DosHeader = (PIMAGE_DOS_HEADER)fcpi->PeHeader; NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew); SectionHeader = IMAGE_FIRST_SECTION(NtHeader); SectionHeader += NtHeader->FileHeader.NumberOfSections - 1; SizeOfImage -= LdrModule->SizeOfImage; SizeOfImage = ROUND_UP(SizeOfImage, MEMORY_PAGE_SIZE); SectionHeader->Misc.VirtualSize = ROUND_UP(SectionHeader->Misc.VirtualSize, MEMORY_PAGE_SIZE) + SizeOfImage; if (NtHeader->FileHeader.SizeOfOptionalHeader > FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, SizeOfImage) + RTL_FIELD_SIZE(IMAGE_OPTIONAL_HEADER, SizeOfImage)) NtHeader->OptionalHeader.SizeOfImage += SizeOfImage; Length = Nt_GetSystemDirectory(CmdFullPath, countof(CmdFullPath)); StrCopyW(CmdFullPath + Length, L"cmd.exe"); ProcessInformation.hProcess = NtCurrentProcess(); ProcessInformation.hThread = NtCurrentThread(); #if 1 Result = Nt_CreateProcess(NULL, CmdFullPath, NULL, CREATE_SUSPENDED, NULL, &ProcessInformation); if (!Result) return STATUS_UNSUCCESSFUL; #endif FakeCPInfoBuffer = NULL; LOOP_ONCE { ULONG_PTR Offset; Status = NtDuplicateObject( NtCurrentProcess(), NtCurrentProcess(), ProcessInformation.hProcess, &fcpi->ProcessHandle, 0, 0, DUPLICATE_SAME_ACCESS ); if (!NT_SUCCESS(Status)) break; /* Status = NtDuplicateObject( NtCurrentProcess(), file, ProcessInformation.hProcess, &fcpi->FileHandle, 0, 0, DUPLICATE_SAME_ACCESS ); if (!NT_SUCCESS(Status)) break; */ Status = Nt_AllocateMemory(ProcessInformation.hProcess, &FakeCPInfoBuffer, MEMORY_PAGE_SIZE); if (!NT_SUCCESS(Status)) break; fcpi->CreateProcessInternalW = CreateProcessInternalW; fcpi->NtTerminateProcess = NtTerminateProcess; fcpi->LdrShutdownProcess = LdrShutdownProcess; fcpi->NtCreateFile = NtCreateFile; fcpi->NtWriteFile = NtWriteFile; fcpi->NtClose = NtClose; fcpi->NtWaitForSingleObject = NtWaitForSingleObject; fcpi->InitialDirectory.Buffer = NULL; Offset = (ULONG_PTR)FakeCPInfoBuffer - (ULONG_PTR)fcpi; *(PULONG_PTR)&fcpi->CommandLine.Buffer += Offset; *(PULONG_PTR)&fcpi->ExeNtPath.Buffer += Offset; Status = Nt_WriteMemory( ProcessInformation.hProcess, FakeCPInfoBuffer, fcpi, (ULONG_PTR)CmdLineBuffer - (ULONG_PTR)fcpi, &Length ); if (!NT_SUCCESS(Status)) break; Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; Status = NtGetContextThread(ProcessInformation.hThread, &Context); if (!NT_SUCCESS(Status)) break; Context.Eip = (ULONG_PTR)FakeCPInfoBuffer + Length; Context.Eip = ROUND_UP(Context.Eip, 16); Context.Ecx = (ULONG_PTR)FakeCPInfoBuffer; Status = Nt_WriteMemory( ProcessInformation.hProcess, (PVOID)Context.Eip, ModifySizeOfImage, (ULONG_PTR)ModifySizeOfImageEnd - (ULONG_PTR)ModifySizeOfImage, &Length ); if (!NT_SUCCESS(Status)) break; #if 1 Status = NtSetContextThread(ProcessInformation.hThread, &Context); if (!NT_SUCCESS(Status)) break; Status = NtResumeThread(ProcessInformation.hThread, NULL); #else INLINE_ASM jmp Context.Eip; #endif } if (!NT_SUCCESS(Status)) { if (FakeCPInfoBuffer != NULL) Nt_FreeMemory(ProcessInformation.hProcess, FakeCPInfoBuffer); NtTerminateProcess(ProcessInformation.hProcess, 0); } NtClose(ProcessInformation.hProcess); NtClose(ProcessInformation.hThread); return Status; }
PWSTR GetFileName( PWSTR HookedPath, ULONG HookedPathCount, PWSTR OriginalPath, ULONG OriginalCount, LPCSTR InputFileName, BOOL IsInputUnicode = FALSE ) { ULONG_PTR Length, AppPathLength; PWSTR FileName; static WCHAR szDataPath[] = L"data\\"; static WCHAR szPatch[] = L"patch\\\\"; static WCHAR szPatch2[] = L"patch2\\"; if (IsInputUnicode) { StrCopyW(OriginalPath, (PWSTR)InputFileName); } else { AnsiToUnicode(OriginalPath, OriginalCount, (PSTR)InputFileName, -1); } PLDR_MODULE Module; Module = FindLdrModuleByHandle(NULL); AppPathLength = (Module->FullDllName.Length - Module->BaseDllName.Length) / sizeof(WCHAR); Length = RtlGetFullPathName_U(OriginalPath, HookedPathCount * sizeof(WCHAR), HookedPath, NULL); Length = Length / sizeof(WCHAR) + 1; FileName = HookedPath + AppPathLength; LOOP_ONCE { if (StrNICompareW(FileName, szDataPath, countof(szDataPath) - 1) || StrNICompareW(Module->FullDllName.Buffer, HookedPath, AppPathLength)) { FileName = OriginalPath; break; } FileName += countof(szDataPath) - 2; RtlMoveMemory( FileName + countof(szPatch) - countof(szDataPath), FileName, (Length - (FileName - HookedPath)) * sizeof(*FileName) ); FileName -= countof(szDataPath) - 2; CopyStruct(FileName, szPatch, sizeof(szPatch) - sizeof(*szPatch)); WriteLog(L"pass1: %s", HookedPath); if (IsPathExists(HookedPath)) { FileName = HookedPath; break; } CopyStruct(FileName, szPatch2, sizeof(szPatch2) - sizeof(*szPatch2)); FileName = IsPathExists(HookedPath) ? HookedPath : OriginalPath; WriteLog(L"pass2: %s", HookedPath); } WriteLog(L"%d, %s -> %s", FileName == HookedPath, OriginalPath, HookedPath); return FileName; }
BOOL Initialize(PVOID BaseAddress) { PVOID hModule; SizeT Length, Length2; LPWSTR lpCmdLineW, pCmdLine; WChar end, szCmdLine[MAX_PATH + 40]; static WChar AddCmdLineHeadW[] = L" --user-data-dir=\""; static WChar AddCmdLineTailW[] = L"UserData\" --purge-memory-button"; LdrDisableThreadCalloutsForDll(BaseAddress); Length = Nt_GetSystemDirectory(szCmdLine, countof(szCmdLine)); CopyStruct(szCmdLine + Length, L"wtsapi32.dll", sizeof(L"wtsapi32.dll")); hModule = Ldr::LoadDll(szCmdLine); *(PVOID *)&StubWTSFreeMemory = GetRoutineAddress(hModule, "WTSFreeMemory"); *(PVOID *)&StubWTSQuerySessionInformationW = GetRoutineAddress(hModule, "WTSQuerySessionInformationW"); *(PVOID *)&StubWTSUnRegisterSessionNotification = GetRoutineAddress(hModule, "WTSUnRegisterSessionNotification"); *(PVOID *)&StubWTSRegisterSessionNotification = GetRoutineAddress(hModule, "WTSRegisterSessionNotification"); *(PVOID *)&StubWTSQueryUserToken = GetRoutineAddress(hModule, "WTSQueryUserToken"); lpCmdLineW = Ps::GetCommandLine(); Length = StrLengthW(lpCmdLineW); pCmdLine = szCmdLine; StrCopyW(pCmdLine, AddCmdLineHeadW); pCmdLine += countof(AddCmdLineHeadW) - 1; pCmdLine += Nt_GetExeDirectory(pCmdLine, countof(szCmdLine) - (pCmdLine - szCmdLine)); StrCopyW(pCmdLine, AddCmdLineTailW); pCmdLine += countof(AddCmdLineTailW); Length2 = pCmdLine - szCmdLine; g_pCmdLineW = (PWChar)AllocateMemory(Length * 2 + Length2 * 2 + 2); pCmdLine = lpCmdLineW; end = *pCmdLine++ == '\"' ? '\"' : ' '; while (*pCmdLine && *pCmdLine != end) ++pCmdLine; ++pCmdLine; /* if (*++pCmdLine) { while (*pCmdLine == ' ' || *pCmdLine == '\t') ++pCmdLine; } */ end = *pCmdLine; *pCmdLine = 0; StrCopyW(g_pCmdLineW, lpCmdLineW); *pCmdLine = end; lpCmdLineW = g_pCmdLineW + (pCmdLine - lpCmdLineW); StrCopyW(lpCmdLineW, szCmdLine); lpCmdLineW += Length2 - 1; StrCopyW(lpCmdLineW, pCmdLine); Length = StrLengthW(g_pCmdLineW); g_pCmdLineA = (PChar)AllocateMemory(Length * 2); // WideCharToMultiByte(CP_ACP, 0, g_pCmdLineW, -1, g_pCmdLineA, Length * 2, NULL, NULL); UnicodeToAnsi(g_pCmdLineA, Length * 2, g_pCmdLineW, -1); hModule = Nt_GetModuleHandle(L"chrome.dll"); MEMORY_FUNCTION_PATCH f[] = { INLINE_HOOK_JUMP_NULL(::GetCommandLineW, MyGetCommandLineW), INLINE_HOOK_JUMP_NULL(::GetCommandLineA, MyGetCommandLineA), INLINE_HOOK_JUMP(LoadAcceleratorsW, MyLoadAcceleratorsW, StubLoadAcceleratorsW), }; Nt_PatchMemory(0, 0, f, countof(f), 0); return TRUE; }
NTSTATUS InjectSelfToRemoteProcess(HANDLE hProcess, HANDLE hThread) { NTSTATUS Status; PVOID pvBuffer; DWORD Length; WCHAR szSelfPath[MAX_PATH]; CONTEXT ThreadContext; LARGE_INTEGER TimeOut; INJECT_DLL_CURRENT_THREAD inj; ThreadContext.ContextFlags = CONTEXT_CONTROL; Status = NtGetContextThread(hThread, &ThreadContext); if (!NT_SUCCESS(Status)) { // BaseSetLastNTError(Status); // PrintError(RtlGetLastWin32Error()); return Status; } // PrintConsoleW(L"Eip = %08X\n", ThreadContext.Eip); // getch(); Length = Nt_GetExeDirectory(szSelfPath, countof(szSelfPath)); if (Length == NULL) return STATUS_UNSUCCESSFUL; static WCHAR szDll[] = L"LocaleEmulator.dll"; StrCopyW(szSelfPath + Length, szDll); Length += CONST_STRLEN(szDll); pvBuffer = NULL; Status = Nt_AllocateMemory(hProcess, &pvBuffer, MEMORY_PAGE_SIZE); if (!NT_SUCCESS(Status)) { // BaseSetLastNTError(Status); // PrintError(RtlGetLastWin32Error()); return Status; } Length *= sizeof(WCHAR); inj.pfLdrLoadDll = LdrLoadDll; inj.ReturnAddr = ThreadContext.Eip; inj.ModuleFileName.Length = Length; inj.ModuleFileName.MaximumLength = Length + sizeof(WCHAR); inj.ModuleFileName.Buffer = (LPWSTR)((ULONG_PTR)pvBuffer + sizeof(inj)); Status = STATUS_UNSUCCESSFUL; LOOP_ONCE { Status = Nt_WriteMemory(hProcess, pvBuffer, &inj, sizeof(inj)); if (!NT_SUCCESS(Status)) break; Length += sizeof(WCHAR); Status = Nt_WriteMemory(hProcess, (PVOID)((ULONG_PTR)pvBuffer + sizeof(inj)), szSelfPath, Length); if (!NT_SUCCESS(Status)) break; ThreadContext.Eip = (DWORD)(PBYTE)pvBuffer + sizeof(inj) + Length; Status = Nt_WriteMemory( hProcess, (PVOID)ThreadContext.Eip, LoadExternDll, (ULONG_PTR)_LoadExternDllEnd - (ULONG_PTR)LoadExternDll ); if (!NT_SUCCESS(Status)) break; Status = NtSetContextThread(hThread, &ThreadContext); if (!NT_SUCCESS(Status)) break; Status = NtResumeThread(hThread, NULL); if (!NT_SUCCESS(Status)) break; BaseFormatTimeOut(&TimeOut, 500); for (DWORD TryTimes = 30; TryTimes; --TryTimes) { DWORD Val; Status = Nt_ReadMemory(hProcess, pvBuffer, &Val, sizeof(Val)); if (!NT_SUCCESS(Status)) break; if (Val != 0) { NtDelayExecution(FALSE, &TimeOut); continue; } break; } if (!NT_SUCCESS(Status)) break; NtDelayExecution(FALSE, &TimeOut); Status = NtGetContextThread(hThread, &ThreadContext); if (!NT_SUCCESS(Status)) break; if ((ULONG_PTR)ThreadContext.Eip < (ULONG_PTR)pvBuffer || (ULONG_PTR)ThreadContext.Eip > (ULONG_PTR)pvBuffer + MEMORY_PAGE_SIZE) { Status = STATUS_SUCCESS; } else { Status = STATUS_UNSUCCESSFUL; } } // BaseSetLastNTError(Status); // PrintError(RtlGetLastWin32Error()); // Nt_FreeMemory(hProcess, pvBuffer); return Status; }