NTSTATUS NTAPI QqNtQueryAttributesFile( POBJECT_ATTRIBUTES ObjectAttributes, PFILE_BASIC_INFORMATION FileInformation ) { NTSTATUS Status; OBJECT_ATTRIBUTES LocalObjectAttributes; UNICODE_STRING Redirected; RtlInitEmptyString(&Redirected); LOOP_ONCE { if (ObjectAttributes == nullptr) break; Status = GetRedirectFile(&Redirected, ObjectAttributes->ObjectName); FAIL_BREAK(Status); LocalObjectAttributes = *ObjectAttributes; LocalObjectAttributes.ObjectName = &Redirected; ObjectAttributes = &LocalObjectAttributes; } Status = StubNtQueryAttributesFile(ObjectAttributes, FileInformation); RtlFreeUnicodeString(&Redirected); return Status; }
NTSTATUS NTAPI QqNtCreateFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength ) { NTSTATUS Status; OBJECT_ATTRIBUTES LocalObjectAttributes; UNICODE_STRING Redirected; RtlInitEmptyString(&Redirected); LOOP_ONCE { if (ObjectAttributes == nullptr) break; Status = GetRedirectFile(&Redirected, ObjectAttributes->ObjectName); FAIL_BREAK(Status); LocalObjectAttributes = *ObjectAttributes; LocalObjectAttributes.ObjectName = &Redirected; ObjectAttributes = &LocalObjectAttributes; } Status = StubNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength); RtlFreeUnicodeString(&Redirected); return Status; }
NTSTATUS NTAPI QqNtOpenFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions ) { NTSTATUS Status; OBJECT_ATTRIBUTES LocalObjectAttributes; UNICODE_STRING Redirected; RtlInitEmptyString(&Redirected); LOOP_ONCE { if (ObjectAttributes == nullptr) break; Status = GetRedirectFile(&Redirected, ObjectAttributes->ObjectName); FAIL_BREAK(Status); LocalObjectAttributes = *ObjectAttributes; LocalObjectAttributes.ObjectName = &Redirected; ObjectAttributes = &LocalObjectAttributes; } Status = StubNtOpenFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, ShareAccess, OpenOptions); RtlFreeUnicodeString(&Redirected); return Status; }
VOID AppendPackage() { PLDR_MODULE Self; UNICODE_STRING SelfPath; static WCHAR PythonZip[] = L"python.zip"; ml::MlInitialize(); //Py_IgnoreEnvironmentFlag = TRUE; //Py_NoSiteFlag = TRUE; Py_DontWriteBytecodeFlag = TRUE; //Py_NoUserSiteDirectory = TRUE; Self = FindLdrModuleByHandle(nullptr); SelfPath = Self->FullDllName; SelfPath.Length -= Self->BaseDllName.Length; Py_SetPath(ml::String::Format( L"%wZ;%wZ%s;%wZ%s\\site-packages;%wZlib;%wZDLLs;%wZUserSite", &SelfPath, // exe path &SelfPath, PythonZip, // ./python.zip &SelfPath, PythonZip, // ./python.zip/site-packages &SelfPath, // ./lib &SelfPath, // ./DLLs &SelfPath // ./UserSite )); ml::String PathEnv, UserSite; PWSTR EnvBuffer; ULONG Length; UNICODE_STRING Path; RtlInitEmptyString(&Path); RtlExpandEnvironmentStrings_U(nullptr, &USTR(L"%Path%"), &Path, &Length); EnvBuffer = (PWSTR)AllocStack(Length); RtlInitEmptyString(&Path, EnvBuffer, Length); RtlExpandEnvironmentStrings_U(nullptr, &USTR(L"%Path%"), &Path, nullptr); UserSite = SelfPath; UserSite += L"UserSite"; PathEnv = SelfPath; PathEnv += L"DLLs;"; EnumDirectoryFiles( nullptr, L"*.*", 0, UserSite, nullptr, [] (PVOID Buffer, PWIN32_FIND_DATAW FindData, ULONG_PTR Context) -> LONG { ml::String *PathEnv = (ml::String *)Context; if (FLAG_OFF(FindData->dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) return 0; (*PathEnv) += FindData->cFileName; (*PathEnv) += ';'; return 0; }, (ULONG_PTR)&PathEnv, EDF_PROCDIR | EDF_BEFORE ); PathEnv += Path; PathEnv += ';'; RtlSetEnvironmentVariable(nullptr, &USTR(L"Path"), PathEnv); }
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; }