PLARGE_UNICODE_STRING LargeStringDuplicate(PLARGE_UNICODE_STRING LargeString, PLARGE_UNICODE_STRING Destination) { union { ANSI_STRING Ansi; UNICODE_STRING Unicode; }; union { ANSI_STRING NewAnsi; UNICODE_STRING NewUnicode; }; if (LargeString->Ansi) return NULL; InitStringFromLargeString(&Unicode, LargeString); if (NT_FAILED(RtlDuplicateUnicodeString(RTL_DUPSTR_ADD_NULL, &Unicode, &NewUnicode))) return NULL; Destination->Ansi = FALSE; Destination->Length = NewUnicode.Length; Destination->MaximumLength = NewUnicode.MaximumLength; Destination->UnicodeBuffer = NewUnicode.Buffer; return Destination; }
static VOID HistoryAddEntry(PCSRSS_CONSOLE Console) { UNICODE_STRING NewEntry; PHISTORY_BUFFER Hist; INT i; NewEntry.Length = NewEntry.MaximumLength = Console->LineSize * sizeof(WCHAR); NewEntry.Buffer = Console->LineBuffer; if (!(Hist = HistoryCurrentBuffer(Console))) return; /* Don't add blank or duplicate entries */ if (NewEntry.Length == 0 || Hist->MaxEntries == 0 || (Hist->NumEntries > 0 && RtlEqualUnicodeString(&Hist->Entries[Hist->NumEntries - 1], &NewEntry, FALSE))) { return; } if (Console->HistoryNoDup) { /* Check if this line has been entered before */ for (i = Hist->NumEntries - 1; i >= 0; i--) { if (RtlEqualUnicodeString(&Hist->Entries[i], &NewEntry, FALSE)) { /* Just rotate the list to bring this entry to the end */ NewEntry = Hist->Entries[i]; memmove(&Hist->Entries[i], &Hist->Entries[i + 1], (Hist->NumEntries - (i + 1)) * sizeof(UNICODE_STRING)); Hist->Entries[Hist->NumEntries - 1] = NewEntry; Hist->Position = Hist->NumEntries - 1; return; } } } if (Hist->NumEntries == Hist->MaxEntries) { /* List is full, remove oldest entry */ RtlFreeUnicodeString(&Hist->Entries[0]); memmove(&Hist->Entries[0], &Hist->Entries[1], --Hist->NumEntries * sizeof(UNICODE_STRING)); } if (NT_SUCCESS(RtlDuplicateUnicodeString(0, &NewEntry, &Hist->Entries[Hist->NumEntries]))) Hist->NumEntries++; Hist->Position = Hist->NumEntries - 1; }
PVOID ProbeInvokeCreateProcessAddress() { PVOID Shell32, Shell32CreateProcessW, CreateProcessW; PLDR_MODULE Shell32Module, MainModule; SHELLEXECUTEINFOW ExecuteInfo; PIMAGE_NT_HEADERS NtHeaders; Shell32 = Ldr::LoadDll(L"Shell32.dll"); Shell32CreateProcessW = PtrAdd(Shell32, IATLookupRoutineRVAByHashNoFix(Shell32, KERNEL32_CreateProcessW)); MainModule = FindLdrModuleByHandle(nullptr); RtlDuplicateUnicodeString(RTL_DUPSTR_ADD_NULL, &MainModule->FullDllName, &ProbeApplicationName); RtlInitUnicodeString(&ProbeCommandLine, L"ML_PROBE_APPLICATION_COMMAMD_LINE"); ZeroMemory(&ExecuteInfo, sizeof(ExecuteInfo)); ExecuteInfo.cbSize = sizeof(ExecuteInfo); ExecuteInfo.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI; ExecuteInfo.lpVerb = L"open"; ExecuteInfo.lpFile = ProbeApplicationName.Buffer; ExecuteInfo.lpParameters = ProbeCommandLine.Buffer; ExecuteInfo.lpDirectory = ProbeApplicationName.Buffer; ExecuteInfo.nShow = SW_SHOW; *(PVOID *)&Shell32CreateProcessWIAT = Shell32CreateProcessW; *(PVOID *)&Shell32CreateProcessWPtr = *(PVOID *)Shell32CreateProcessWIAT; CreateProcessW = ProbeInvokeCreateProcessW; WriteProtectMemory(CurrentProcess, Shell32CreateProcessW, &CreateProcessW, sizeof(CreateProcessW)); ShellExecuteExW(&ExecuteInfo); WriteProtectMemory(CurrentProcess, Shell32CreateProcessW, &Shell32CreateProcessWPtr, sizeof(Shell32CreateProcessWPtr)); RtlFreeUnicodeString(&ProbeApplicationName); NtHeaders = RtlImageNtHeader(Shell32); if (InvokeReturnAddress < Shell32 || InvokeReturnAddress > PtrAdd(Shell32, NtHeaders->OptionalHeader.SizeOfImage)) return nullptr; return InvokeReturnAddress; }
NTSTATUS LeGlobalData::Initialize() { BOOL IsLoader; PLEPEB LePeb; PLDR_MODULE Ntdll; PPEB_BASE Peb; NTSTATUS Status; NLSTABLEINFO NlsTableInfo; UNICODE_STRING SystemDirectory, NlsFileName, OemNlsFileName, LangFileName; PKEY_VALUE_PARTIAL_INFORMATION IndexValue; IsLoader = IsLeLoader(); Wow64 = Ps::IsWow64Process(); Ntdll = GetNtdllLdrModule(); LOOP_ONCE { LePeb = OpenOrCreateLePeb(); if (LePeb == nullptr) { ULONG_PTR DefaultACPLength, DefaultLCIDLength, DefaultOEMCPLength; WCHAR DefaultACP[0x20], DefaultOEMCP[0x20], DefaultLCID[0x20]; PVOID ReloadedNtdll; PUNICODE_STRING FullDllName; LePeb = GetLePeb(); InitDefaultLeb(&LePeb->Leb); FullDllName = &FindLdrModuleByHandle(&__ImageBase)->FullDllName; CopyMemory(LePeb->LeDllFullPath, FullDllName->Buffer, FullDllName->Length + sizeof(WCHAR)); Status = LoadPeImage(Ntdll->FullDllName.Buffer, &ReloadedNtdll, nullptr, LOAD_PE_IGNORE_RELOC); if (NT_SUCCESS(Status)) { PVOID LdrLoadDllAddress; LdrLoadDllAddress = LookupExportTable(ReloadedNtdll, NTDLL_LdrLoadDll); LePeb->LdrLoadDllAddress = PtrAdd(LdrLoadDllAddress, PtrOffset(Ntdll->DllBase, ReloadedNtdll)); CopyMemory(LePeb->LdrLoadDllBackup, LdrLoadDllAddress, LDR_LOAD_DLL_BACKUP_SIZE); LePeb->LdrLoadDllBackupSize = LDR_LOAD_DLL_BACKUP_SIZE; UnloadPeImage(ReloadedNtdll); } DefaultACPLength = (swprintf(DefaultACP, L"%d", LePeb->Leb.AnsiCodePage) + 1) * sizeof(WCHAR); DefaultOEMCPLength = (swprintf(DefaultOEMCP, L"%d", LePeb->Leb.OemCodePage) + 1) * sizeof(WCHAR); DefaultLCIDLength = (swprintf(DefaultLCID, L"%d", LePeb->Leb.LocaleID) + 1) * sizeof(WCHAR); REGISTRY_REDIRECTION_ENTRY64 *Entry, Entries[] = { { { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_ACP), REG_SZ, }, { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_ACP), REG_SZ, DefaultACP, DefaultACPLength }, }, { { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_OEMCP), REG_SZ, }, { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_OEMCP), REG_SZ, DefaultOEMCP, DefaultOEMCPLength }, }, { { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_LANGUAGE), USTR64(REGKEY_DEFAULT_LANGUAGE), REG_SZ, }, { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_LANGUAGE), USTR64(REGKEY_DEFAULT_LANGUAGE), REG_SZ, DefaultLCID, DefaultLCIDLength }, }, }; Status = this->InitRegistryRedirection(Entries, countof(Entries), nullptr); } else { *GetLePeb() = *LePeb; Status = this->InitRegistryRedirection(LePeb->Leb.RegistryReplacement, LePeb->Leb.NumberOfRegistryRedirectionEntries, &LePeb->Leb); NtClose(LePeb->Section); CloseLePeb(LePeb); } if (IsLoader) break; Status = this->TextMetricCache.Initialize(); FAIL_RETURN(Status); PVOID NlsBaseAddress; LCID DefaultLocaleID; LARGE_INTEGER DefaultCasingTableSize; Status = NtInitializeNlsFiles(&NlsBaseAddress, &DefaultLocaleID, &DefaultCasingTableSize); FAIL_RETURN(Status); this->GetLePeb()->OriginalLocaleID = DefaultLocaleID; NtUnmapViewOfSection(CurrentProcess, NlsBaseAddress); WriteLog(L"init leb %s", GetLePeb()->LeDllFullPath); SystemDirectory = Ntdll->FullDllName; SystemDirectory.Length -= Ntdll->BaseDllName.Length; Status = RtlDuplicateUnicodeString(RTL_DUPSTR_ADD_NULL, &SystemDirectory, &this->SystemDirectory); FAIL_RETURN(Status); RtlInitEmptyString(&NlsFileName, nullptr, 0); RtlInitEmptyString(&OemNlsFileName, nullptr, 0); RtlInitEmptyString(&LangFileName, nullptr, 0); SCOPE_EXIT { RtlFreeUnicodeString(&NlsFileName); RtlFreeUnicodeString(&OemNlsFileName); RtlFreeUnicodeString(&LangFileName); } SCOPE_EXIT_END; Status = GetNlsFile(&NlsFileName, GetLeb()->AnsiCodePage, REGPATH_CODEPAGE); FAIL_RETURN(Status); Status = GetNlsFile(&OemNlsFileName, GetLeb()->OemCodePage, REGPATH_CODEPAGE); FAIL_RETURN(Status); Status = GetLangFile(&LangFileName, GetLeb()->LocaleID, REGPATH_LANGUAGE); FAIL_RETURN(Status); NtFileMemory AnsiFile, OemFile, LangFile; Status = ReadFileInSystemDirectory(AnsiFile, &NlsFileName); FAIL_RETURN(Status); Status = ReadFileInSystemDirectory(OemFile, &OemNlsFileName); FAIL_RETURN(Status); Status = ReadFileInSystemDirectory(LangFile, &LangFileName); FAIL_RETURN(Status); AnsiCodePageOffset = 0; OemCodePageOffset = ROUND_UP(AnsiFile.GetSize32(), 16); UnicodeCaseTableOffset = OemCodePageOffset + ROUND_UP(OemFile.GetSize32(), 16); Status = AllocVirtualMemory(&CodePageMapView, UnicodeCaseTableOffset + LangFile.GetSize32(), PAGE_READWRITE, MEM_COMMIT | MEM_TOP_DOWN); FAIL_RETURN(Status); CopyMemory(PtrAdd(CodePageMapView, AnsiCodePageOffset), AnsiFile.GetBuffer(), AnsiFile.GetSize32()); CopyMemory(PtrAdd(CodePageMapView, OemCodePageOffset), OemFile.GetBuffer(), OemFile.GetSize32()); CopyMemory(PtrAdd(CodePageMapView, UnicodeCaseTableOffset), LangFile.GetBuffer(), LangFile.GetSize32()); ProtectVirtualMemory(CodePageMapView, UnicodeCaseTableOffset + LangFile.GetSize32(), PAGE_READONLY); RtlInitNlsTables( (PUSHORT)PtrAdd(CodePageMapView, AnsiCodePageOffset), (PUSHORT)PtrAdd(CodePageMapView, OemCodePageOffset), (PUSHORT)PtrAdd(CodePageMapView, UnicodeCaseTableOffset), &NlsTableInfo ); RtlResetRtlTranslations(&NlsTableInfo); WriteLog(L"reset nls"); Peb = CurrentPeb(); Peb->AnsiCodePageData = (PUSHORT)PtrAdd(CodePageMapView, AnsiCodePageOffset); Peb->OemCodePageData = (PUSHORT)PtrAdd(CodePageMapView, OemCodePageOffset); Peb->UnicodeCaseTableData = (PUSHORT)PtrAdd(CodePageMapView, UnicodeCaseTableOffset); // LdrInitShimEngineDynamic(&__ImageBase); LdrRegisterDllNotification(0, [] (ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context) { return ((PLeGlobalData)Context)->DllNotification(NotificationReason, NotificationData); }, this, &DllNotificationCookie ); } Status = InstallHookPort(); WriteLog(L"inst hp: %08X", Status); FAIL_RETURN(Status); HookNtdllRoutines(Ntdll->DllBase); WriteLog(L"hook ntdll"); if (IsLoader) return Status; PLDR_MODULE Kernel32Ldr; Kernel32Ldr = GetKernel32Ldr(); if (Kernel32Ldr != nullptr) { Kernel32Ldr->EntryPoint = DelayInitDllEntry; // HookKernel32Routines(Kernel32Ldr->DllBase); } WriteLog(L"init %p", Status); return Status; }
NTSTATUS GetRedirectFile(PUNICODE_STRING Redirected, PUNICODE_STRING Original) { ULONG_PTR Length; PWSTR Buffer; UNICODE_STRING FileName; typedef struct { UNICODE_STRING SubPath; ULONG_PTR SuffixLength; PCWSTR NewSubPath; } REDIRECT_ENTRY, *PDB_REDIRECT; PDB_REDIRECT Entry; static REDIRECT_ENTRY RedirectEntries[] = { { RTL_CONSTANT_STRING(L"\\All Users\\QQ\\History.db"), CONST_STRLEN(L"History.db") * sizeof(WCHAR), GlobalHistoryDb }, { RTL_CONSTANT_STRING(L"\\All Users\\QQ\\Registry.db"), CONST_STRLEN(L"Registry.db") * sizeof(WCHAR), GlobalRegistryDb }, //{ RTL_CONSTANT_STRING(L"QQProtect.exe"), CONST_STRLEN(L"QQProtect.exe") * sizeof(WCHAR), NULL }, }; RtlInitEmptyString(Redirected); LOOP_ONCE { if (Original == nullptr) continue; FOR_EACH_ARRAY(Entry, RedirectEntries) { if (Original->Length <= Entry->SubPath.Length) continue; FileName = *Original; FileName.Buffer = PtrSub(PtrAdd(FileName.Buffer, FileName.Length), Entry->SubPath.Length); FileName.Length = Entry->SubPath.Length; if (!RtlEqualUnicodeString(&FileName, &Entry->SubPath, TRUE)) continue; /* if (Entry->NewSubPath == NULL) { ExceptionBox(L"qqprotect"); ++Entry; } */ break; } if (Entry == &RedirectEntries[countof(RedirectEntries)]) break; Length = Original->Length + Entry->SubPath.Length + Entry->SuffixLength + sizeof(Entry->NewSubPath); Buffer = (PWSTR)AllocStack(Length); FileName.MaximumLength = Length; FileName.Buffer = Buffer; Length = StrLengthW(Entry->NewSubPath) * sizeof(WCHAR); RtlCopyUnicodeString(&FileName, Original); CopyMemory(PtrSub(PtrAdd(FileName.Buffer, FileName.Length), Entry->SuffixLength), Entry->NewSubPath, Length + sizeof(WCHAR)); FileName.Length = FileName.Length - Entry->SuffixLength + Length; RtlDuplicateUnicodeString(RTL_DUPSTR_ADD_NULL, &FileName, Redirected); return STATUS_SUCCESS; } return STATUS_NOT_FOUND; }
NTSTATUS LeGlobalData::Initialize() { PLEPEB LePeb; PLDR_MODULE Ntdll; PPEB_BASE Peb; NTSTATUS Status; NLSTABLEINFO NlsTableInfo; UNICODE_STRING SystemDirectory, NlsFileName, OemNlsFileName, LangFileName; PKEY_VALUE_PARTIAL_INFORMATION IndexValue; Wow64 = Ps::IsWow64Process(); Ntdll = GetNtdllLdrModule(); LePeb = OpenOrCreateLePeb(); if (LePeb == nullptr) { PVOID ReloadedNtdll; PUNICODE_STRING FullDllName; LePeb = GetLePeb(); InitDefaultLeb(&LePeb->Leb); FullDllName = &FindLdrModuleByHandle(&__ImageBase)->FullDllName; CopyMemory(LePeb->LeDllFullPath, FullDllName->Buffer, FullDllName->Length + sizeof(WCHAR)); Status = LoadPeImage(Ntdll->FullDllName.Buffer, &ReloadedNtdll, nullptr, LOAD_PE_IGNORE_RELOC); if (NT_SUCCESS(Status)) { PVOID LdrLoadDllAddress; LdrLoadDllAddress = EATLookupRoutineByHashPNoFix(ReloadedNtdll, NTDLL_LdrLoadDll); LePeb->LdrLoadDllAddress = PtrAdd(LdrLoadDllAddress, PtrOffset(Ntdll->DllBase, ReloadedNtdll)); CopyMemory(LePeb->LdrLoadDllBackup, LdrLoadDllAddress, LDR_LOAD_DLL_BACKUP_SIZE); LePeb->LdrLoadDllBackupSize = LDR_LOAD_DLL_BACKUP_SIZE; UnloadPeImage(ReloadedNtdll); } } else { *GetLePeb() = *LePeb; ZwClose(LePeb->Section); CloseLePeb(LePeb); } WriteLog(L"init leb %s", GetLePeb()->LeDllFullPath); SystemDirectory = Ntdll->FullDllName; SystemDirectory.Length -= Ntdll->BaseDllName.Length; Status = RtlDuplicateUnicodeString(RTL_DUPSTR_ADD_NULL, &SystemDirectory, &this->SystemDirectory); FAIL_RETURN(Status); RtlInitEmptyUnicodeString(&NlsFileName, nullptr, 0); RtlInitEmptyUnicodeString(&OemNlsFileName, nullptr, 0); RtlInitEmptyUnicodeString(&LangFileName, nullptr, 0); SCOPE_EXIT { RtlFreeUnicodeString(&NlsFileName); RtlFreeUnicodeString(&OemNlsFileName); RtlFreeUnicodeString(&LangFileName); } SCOPE_EXIT_END; Status = GetNlsFile(&NlsFileName, GetLeb()->AnsiCodePage, REGPATH_CODEPAGE); FAIL_RETURN(Status); Status = GetNlsFile(&OemNlsFileName, GetLeb()->OemCodePage, REGPATH_CODEPAGE); FAIL_RETURN(Status); Status = GetLangFile(&LangFileName, GetLeb()->LocaleID, REGPATH_LANGUAGE); FAIL_RETURN(Status); NtFileMemory AnsiFile, OemFile, LangFile; Status = ReadFileInSystemDirectory(AnsiFile, &NlsFileName); FAIL_RETURN(Status); Status = ReadFileInSystemDirectory(OemFile, &OemNlsFileName); FAIL_RETURN(Status); Status = ReadFileInSystemDirectory(LangFile, &LangFileName); FAIL_RETURN(Status); AnsiCodePageOffset = 0; OemCodePageOffset = ROUND_UP(AnsiFile.GetSize32(), 16); UnicodeCaseTableOffset = OemCodePageOffset + ROUND_UP(OemFile.GetSize32(), 16); Status = AllocVirtualMemory(&CodePageMapView, UnicodeCaseTableOffset + LangFile.GetSize32(), PAGE_READWRITE, MEM_COMMIT | MEM_TOP_DOWN); FAIL_RETURN(Status); CopyMemory(PtrAdd(CodePageMapView, AnsiCodePageOffset), AnsiFile.GetBuffer(), AnsiFile.GetSize32()); CopyMemory(PtrAdd(CodePageMapView, OemCodePageOffset), OemFile.GetBuffer(), OemFile.GetSize32()); CopyMemory(PtrAdd(CodePageMapView, UnicodeCaseTableOffset), LangFile.GetBuffer(), LangFile.GetSize32()); ProtectVirtualMemory(CodePageMapView, UnicodeCaseTableOffset + LangFile.GetSize32(), PAGE_READONLY); RtlInitNlsTables( (PUSHORT)PtrAdd(CodePageMapView, AnsiCodePageOffset), (PUSHORT)PtrAdd(CodePageMapView, OemCodePageOffset), (PUSHORT)PtrAdd(CodePageMapView, UnicodeCaseTableOffset), &NlsTableInfo ); RtlResetRtlTranslations(&NlsTableInfo); WriteLog(L"reset nls"); Peb = CurrentPeb(); Peb->AnsiCodePageData = (PUSHORT)PtrAdd(CodePageMapView, AnsiCodePageOffset); Peb->OemCodePageData = (PUSHORT)PtrAdd(CodePageMapView, OemCodePageOffset); Peb->UnicodeCaseTableData = (PUSHORT)PtrAdd(CodePageMapView, UnicodeCaseTableOffset); // LdrInitShimEngineDynamic(&__ImageBase); LdrRegisterDllNotification(0, [] (ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context) { return ((PLeGlobalData)Context)->DllNotification(NotificationReason, NotificationData); }, this, &DllNotificationCookie ); Status = InstallHookPort(); FAIL_RETURN(Status); WriteLog(L"inst hp"); HookNtdllRoutines(Ntdll->DllBase); WriteLog(L"hook ntdll"); PLDR_MODULE Kernel32Ldr; Kernel32Ldr = GetKernel32Ldr(); if (Kernel32Ldr != nullptr) { Kernel32Ldr->EntryPoint = DelayInitDllEntry; // HookKernel32Routines(Kernel32Ldr->DllBase); } WriteLog(L"init %p", Status); return Status; }