skrudjmdk
Newbie | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Оставлю здесь для истории. Для тех, кто желает получить русский интерфейс на windows 11, необходимо скачать библиотеку Detours от Microsoft, собрать код как version.dll 64bit и поместить в папку Agnitum\Outpost Firewall Pro , никаких оригинальных файлов патчить не нужно. А если собрать 32-ух битную версию и временно прописать в HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs, то получится запустить инсталлятор. Также, драйвер SandBox64.sys несовместим со встроенным в windows 11 гипервизором и приводит к синему экрану, но его можно отключить, как и удалить из папки Outpost Firewall Pro\plugins_acs всё кроме firewall.* Код: #include <windows.h> #include <detours.h> #pragma comment(lib,"detours.lib") #pragma comment(linker,"/export:GetFileVersionInfoA=C:/Windows/System32/version.GetFileVersionInfoA,@1") #pragma comment(linker,"/export:GetFileVersionInfoByHandle=C:/Windows/System32/version.GetFileVersionInfoByHandle,@2") #pragma comment(linker,"/export:GetFileVersionInfoExA=C:/Windows/System32/version.GetFileVersionInfoExA,@3") #pragma comment(linker,"/export:GetFileVersionInfoExW=C:/Windows/System32/version.GetFileVersionInfoExW,@4") #pragma comment(linker,"/export:GetFileVersionInfoSizeA=C:/Windows/System32/version.GetFileVersionInfoSizeA,@5") #pragma comment(linker,"/export:GetFileVersionInfoSizeExA=C:/Windows/System32/version.GetFileVersionInfoSizeExA,@6") #pragma comment(linker,"/export:GetFileVersionInfoSizeExW=C:/Windows/System32/version.GetFileVersionInfoSizeExW,@7") #pragma comment(linker,"/export:GetFileVersionInfoSizeW=C:/Windows/System32/version.GetFileVersionInfoSizeW,@8") #pragma comment(linker,"/export:GetFileVersionInfoW=C:/Windows/System32/version.GetFileVersionInfoW,@9") #pragma comment(linker,"/export:VerFindFileA=C:/Windows/System32/version.VerFindFileA,@10") #pragma comment(linker,"/export:VerFindFileW=C:/Windows/System32/version.VerFindFileW,@11") #pragma comment(linker,"/export:VerInstallFileA=C:/Windows/System32/version.VerInstallFileA,@12") #pragma comment(linker,"/export:VerInstallFileW=C:/Windows/System32/version.VerInstallFileW,@13") #pragma comment(linker,"/export:VerLanguageNameA=C:/Windows/System32/version.VerLanguageNameA,@14") #pragma comment(linker,"/export:VerLanguageNameW=C:/Windows/System32/version.VerLanguageNameW,@15") #pragma comment(linker,"/export:VerQueryValueA=C:/Windows/System32/version.VerQueryValueA,@16") #pragma comment(linker,"/export:VerQueryValueW=C:/Windows/System32/version.VerQueryValueW,@17") typedef LONG NTSTATUS; #define STATUS_SUCCESS ((NTSTATUS) 0x00000000) typedef struct _LDR_RESOURCE_INFO { ULONG_PTR Type; ULONG_PTR Name; ULONG Language; } LDR_RESOURCE_INFO, * PLDR_RESOURCE_INFO; #define STATUS_RESOURCE_NAME_NOT_FOUND ((NTSTATUS) 0xC000008B) #define STATUS_RESOURCE_DATA_NOT_FOUND ((NTSTATUS) 0xC0000089) #define STATUS_RESOURCE_TYPE_NOT_FOUND ((NTSTATUS) 0xC000008A) #define STATUS_RESOURCE_LANG_NOT_FOUND ((NTSTATUS) 0xC0000204) #define STATUS_MESSAGE_NOT_FOUND ((NTSTATUS) 0xC0000109) PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule) { IMAGE_NT_HEADERS* ret = NULL; IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)hModule; if (dos->e_magic == IMAGE_DOS_SIGNATURE) { ret = (IMAGE_NT_HEADERS*)((char*)dos + dos->e_lfanew); if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL; } return ret; } PIMAGE_SECTION_HEADER WINAPI RtlImageRvaToSection(const IMAGE_NT_HEADERS* nt, HMODULE module, DWORD rva) { int i; const IMAGE_SECTION_HEADER* sec; sec = (const IMAGE_SECTION_HEADER*)((const char*)&nt->OptionalHeader + nt->FileHeader.SizeOfOptionalHeader); for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) { if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva)) return (PIMAGE_SECTION_HEADER)sec; } return NULL; } PVOID WINAPI RtlImageRvaToVa(const IMAGE_NT_HEADERS* nt, HMODULE module, DWORD rva, IMAGE_SECTION_HEADER** section) { IMAGE_SECTION_HEADER* sec; if (section && *section) { sec = *section; if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva)) goto found; } if (!(sec = RtlImageRvaToSection(nt, module, rva))) return NULL; found: if (section) *section = sec; return (char*)module + sec->PointerToRawData + (rva - sec->VirtualAddress); } PVOID WINAPI RtlImageDirectoryEntryToData(HMODULE module, BOOL image, WORD dir, ULONG* size) { const IMAGE_NT_HEADERS* nt; DWORD addr; if ((ULONG_PTR)module & 1) image = FALSE; module = (HMODULE)((ULONG_PTR)module & ~3); if (!(nt = RtlImageNtHeader(module))) return NULL; if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { const IMAGE_NT_HEADERS64* nt64 = (const IMAGE_NT_HEADERS64*)nt; if (dir >= nt64->OptionalHeader.NumberOfRvaAndSizes) return NULL; if (!(addr = nt64->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL; *size = nt64->OptionalHeader.DataDirectory[dir].Size; if (image || addr < nt64->OptionalHeader.SizeOfHeaders) return (char*)module + addr; } else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { const IMAGE_NT_HEADERS32* nt32 = (const IMAGE_NT_HEADERS32*)nt; if (dir >= nt32->OptionalHeader.NumberOfRvaAndSizes) return NULL; if (!(addr = nt32->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL; *size = nt32->OptionalHeader.DataDirectory[dir].Size; if (image || addr < nt32->OptionalHeader.SizeOfHeaders) return (char*)module + addr; } else return NULL; return RtlImageRvaToVa(nt, module, addr, NULL); } static const IMAGE_RESOURCE_DIRECTORY* find_entry_by_id(const IMAGE_RESOURCE_DIRECTORY* dir, WORD id, const void* root, int want_dir) { const IMAGE_RESOURCE_DIRECTORY_ENTRY* entry; int min, max, pos; entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(dir + 1); min = dir->NumberOfNamedEntries; max = min + dir->NumberOfIdEntries - 1; while (min <= max) { pos = (min + max) / 2; if (entry[pos].Id == id) { if (!entry[pos].DataIsDirectory == !want_dir) { return (const IMAGE_RESOURCE_DIRECTORY*)((const char*)root + entry[pos].OffsetToDirectory); } break; } if (entry[pos].Id > id) max = pos - 1; else min = pos + 1; } return NULL; } static const IMAGE_RESOURCE_DIRECTORY* find_entry_by_name(const IMAGE_RESOURCE_DIRECTORY* dir, LPCWSTR name, const void* root, int want_dir) { const IMAGE_RESOURCE_DIRECTORY_ENTRY* entry; const IMAGE_RESOURCE_DIR_STRING_U* str; int min, max, res, pos; if (IS_INTRESOURCE(name)) return find_entry_by_id(dir, LOWORD(name), root, want_dir); entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(dir + 1); auto namelen = wcslen(name); min = 0; max = dir->NumberOfNamedEntries - 1; while (min <= max) { pos = (min + max) / 2; str = (const IMAGE_RESOURCE_DIR_STRING_U*)((const char*)root + entry[pos].NameOffset); res = wcsncmp(name, str->NameString, str->Length); if (!res && namelen == str->Length) { if (!entry[pos].DataIsDirectory == !want_dir) { return (const IMAGE_RESOURCE_DIRECTORY*)((const char*)root + entry[pos].OffsetToDirectory); } break; } if (res < 0) max = pos - 1; else min = pos + 1; } return NULL; } static const IMAGE_RESOURCE_DIRECTORY* find_first_entry(const IMAGE_RESOURCE_DIRECTORY* dir, const void* root, int want_dir) { const IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(dir + 1); int pos; for (pos = 0; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++) { if (!entry[pos].DataIsDirectory == !want_dir) return (const IMAGE_RESOURCE_DIRECTORY*)((const char*)root + entry[pos].OffsetToDirectory); } return NULL; } static inline int push_language(WORD* list, int pos, WORD lang) { int i; for (i = 0; i < pos; i++) if (list[i] == lang) return pos; list[pos++] = lang; return pos; } static LCID user_resource_lcid; static LCID user_resource_neutral_lcid; static LCID system_lcid; void get_resource_lcids(LANGID* user, LANGID* user_neutral, LANGID* system) { *user = LANGIDFROMLCID(user_resource_lcid); *user_neutral = LANGIDFROMLCID(user_resource_neutral_lcid); *system = LANGIDFROMLCID(system_lcid); } typedef struct _CLIENT_ID64 { ULONG64 UniqueProcess; ULONG64 UniqueThread; } CLIENT_ID64; #ifdef _M_X64 typedef struct _TEB { NT_TIB64 Tib; /* 0000 */ ULONG64 EnvironmentPointer; /* 0038 */ CLIENT_ID64 ClientId; /* 0040 */ ULONG64 ActiveRpcHandle; /* 0050 */ ULONG64 ThreadLocalStoragePointer; /* 0058 */ ULONG64 Peb; /* 0060 */ ULONG LastErrorValue; /* 0068 */ ULONG CountOfOwnedCriticalSections; /* 006c */ ULONG64 CsrClientThread; /* 0070 */ ULONG64 Win32ThreadInfo; /* 0078 */ ULONG User32Reserved[26]; /* 0080 */ ULONG UserReserved[5]; /* 00e8 */ ULONG64 WOW32Reserved; /* 0100 */ ULONG CurrentLocale; /* 0108 */ } TEB; #else typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, * PCLIENT_ID; typedef struct _TEB { /* win32/win64 */ NT_TIB Tib; /* 000/0000 */ PVOID EnvironmentPointer; /* 01c/0038 */ CLIENT_ID ClientId; /* 020/0040 */ PVOID ActiveRpcHandle; /* 028/0050 */ PVOID ThreadLocalStoragePointer; /* 02c/0058 */ void* Peb; /* 030/0060 */ ULONG LastErrorValue; /* 034/0068 */ ULONG CountOfOwnedCriticalSections; /* 038/006c */ PVOID CsrClientThread; /* 03c/0070 */ PVOID Win32ThreadInfo; /* 040/0078 */ ULONG User32Reserved[26]; /* 044/0080 */ ULONG UserReserved[5]; /* 0ac/00e8 */ PVOID WOW32Reserved; /* 0c0/0100 */ ULONG CurrentLocale; /* 0c4/0108 */ } TEB, * PTEB; #endif static NTSTATUS find_entry(HMODULE hmod, const LDR_RESOURCE_INFO* info, ULONG level, const void** ret, int want_dir) { ULONG size; const void* root; const IMAGE_RESOURCE_DIRECTORY* resdirptr; WORD list[9]; int i, pos = 0; root = RtlImageDirectoryEntryToData(hmod, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size); if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND; if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND; resdirptr = (IMAGE_RESOURCE_DIRECTORY*)root; if (!level--) goto done; if (!(*ret = find_entry_by_name(resdirptr, (LPCWSTR)info->Type, root, want_dir || level))) return STATUS_RESOURCE_TYPE_NOT_FOUND; if (!level--) return STATUS_SUCCESS; resdirptr = (IMAGE_RESOURCE_DIRECTORY*)(*ret); if (!(*ret = find_entry_by_name(resdirptr, (LPCWSTR)info->Name, root, want_dir || level))) return STATUS_RESOURCE_NAME_NOT_FOUND; if (!level--) return STATUS_SUCCESS; if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */ /* 1. specified language */ pos = push_language(list, pos, info->Language); /* 2. specified language with neutral sublanguage */ pos = push_language(list, pos, MAKELANGID(PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL)); /* 3. neutral language with neutral sublanguage */ pos = push_language(list, pos, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)); /* if no explicitly specified language, try some defaults */ if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL) { LANGID user_lang, user_neutral_lang, system_lang; get_resource_lcids(&user_lang, &user_neutral_lang, &system_lang); /* user defaults, unless SYS_DEFAULT sublanguage specified */ if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT) { /* 4. current thread locale language */ pos = push_language(list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale)); /* 5. user locale language */ pos = push_language(list, pos, user_lang); /* 6. user locale language with neutral sublanguage */ pos = push_language(list, pos, user_neutral_lang); } /* 7. system locale language */ pos = push_language(list, pos, system_lang); /* 8. system locale language with neutral sublanguage */ pos = push_language(list, pos, PRIMARYLANGID(system_lang)); /* 9. English */ pos = push_language(list, pos, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)); } resdirptr = (IMAGE_RESOURCE_DIRECTORY*) *ret; for (i = 0; i < pos; i++) if ((*ret = find_entry_by_id(resdirptr, list[i], root, want_dir))) return STATUS_SUCCESS; /* if no explicitly specified language, return the first entry */ if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL) { if ((*ret = find_first_entry(resdirptr, root, want_dir))) return STATUS_SUCCESS; } return STATUS_RESOURCE_LANG_NOT_FOUND; done: *ret = resdirptr; return STATUS_SUCCESS; } NTSTATUS WINAPI LdrFindResource_U_wine(HMODULE hmod, const LDR_RESOURCE_INFO* info, ULONG level, const IMAGE_RESOURCE_DATA_ENTRY** entry) { const void* res; NTSTATUS status = find_entry(hmod, info, level, &res, FALSE); if (status == STATUS_SUCCESS) *entry = (IMAGE_RESOURCE_DATA_ENTRY*)res; return status; } NTSTATUS(WINAPI* LdrFindResource_U_orig)(PVOID BaseAddress, void* ResourceInfo, ULONG Level, void* ResourceDataEntry) = nullptr; NTSTATUS WINAPI LdrFindResource_U_custom(PVOID BaseAddress, void* ResourceInfo, ULONG Level, void* ResourceDataEntry) { auto result = LdrFindResource_U_orig(BaseAddress, ResourceInfo, Level, ResourceDataEntry); if (result == STATUS_SUCCESS) return result; return LdrFindResource_U_wine((HMODULE)BaseAddress, (const LDR_RESOURCE_INFO*)ResourceInfo, Level, (const IMAGE_RESOURCE_DATA_ENTRY**)ResourceDataEntry); } INT WINAPI LoadStringW_wine(HINSTANCE instance, UINT resource_id, LPWSTR buffer, INT buflen) { HGLOBAL hmem; HRSRC hrsrc; WCHAR* p; int string_num; int i; if (buffer == NULL) return 0; hrsrc = FindResourceW(instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1),(LPWSTR)RT_STRING); if (!hrsrc) return 0; hmem = LoadResource(instance, hrsrc); if (!hmem) return 0; p = (WCHAR*)LockResource(hmem); string_num = resource_id & 0x000f; for (i = 0; i < string_num; i++) p += *p + 1; if (buflen == 0) { *((LPWSTR*)buffer) = p + 1; return *p; } i = min(buflen - 1, *p); if (i > 0) { memcpy(buffer, p + 1, i * sizeof(WCHAR)); buffer[i] = 0; } else { if (buflen > 1) { buffer[0] = 0; return 0; } } return i; } int (WINAPI* LoadStringW_orig)(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int cchBufferMax) = nullptr; int WINAPI LoadStringW_custom(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int cchBufferMax) { auto result = LoadStringW_orig(hInstance, uID, lpBuffer, cchBufferMax); if (result == 0) { return LoadStringW_wine(hInstance, uID, lpBuffer, cchBufferMax); } return result; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { if (fdwReason == DLL_PROCESS_ATTACH) { LdrFindResource_U_orig = (decltype(LdrFindResource_U_orig))GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "LdrFindResource_U"); LoadStringW_orig = (decltype(LoadStringW_orig))GetProcAddress(LoadLibraryW(L"C:\\Windows\\System32\\User32.dll"), "LoadStringW"); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach((PVOID*)(&LdrFindResource_U_orig), (PVOID)LdrFindResource_U_custom); DetourAttach((PVOID*)(&LoadStringW_orig), (PVOID)LoadStringW_custom); DetourTransactionCommit(); } return TRUE; }; | |