Esempio n. 1
0
BOOL InitializeUin()
{
    ULONG_PTR Length;
    WCHAR ch;
    PWSTR CommandLine, QQUIN;

    CommandLine = CurrentPeb()->ProcessParameters->CommandLine.Buffer;

    QQUIN = wcsstr(CommandLine, L"QQUIN:");
    if (QQUIN == nullptr)
        return FALSE;

    QQUIN += CONST_STRLEN(L"QQUIN:");

    CommandLine = QQUIN;
    while (*CommandLine != ' ' && *CommandLine != '\t' && *CommandLine != 0)
        ++CommandLine;

    Length = PtrOffset(CommandLine, QQUIN);
    if (Length >= sizeof(GlobalRegistryDb) - sizeof(L".db"))
        return FALSE;

    Length /= sizeof(WCHAR);

    swprintf(GlobalRegistryDb, L"Registry_%.*s.db", Length, QQUIN);
    swprintf(GlobalHistoryDb, L"History_%.*s.db", Length, QQUIN);

    return TRUE;
}
Esempio n. 2
0
NTSTATUS GenerateXlAccCommandLine(PWSTR* XlAccCmdLine, PWSTR Entry, PCWSTR ApplicationName, PCWSTR CommandLine)
{
    PWSTR           Buffer;
    ULONG_PTR       Length;
    PLDR_MODULE     Module;
    UNICODE_STRING  AccPath;

    ApplicationName = ApplicationName == NULL ? L"" : ApplicationName;
    CommandLine = CommandLine == NULL ? L"" : CommandLine;

    Module = FindLdrModuleByHandle(&__ImageBase);
    Length = (lstrlenW(ApplicationName) + lstrlenW(CommandLine) + MAX_NTPATH) * sizeof(WCHAR) + Module->FullDllName.Length;
    Buffer = (PWSTR)malloc(Length);
    if (Buffer == NULL)
        return STATUS_NO_MEMORY;

    *XlAccCmdLine = Buffer;

    AccPath = Module->FullDllName;
    AccPath.Length = (USHORT)PtrOffset(PathFindFileNameW(Module->FullDllName.Buffer), Module->FullDllName.Buffer);

    swprintf(
        Buffer,
        L"\"%wZXLacc.exe\" -hookstart game:\"%s\" path:\"%s\" param:%s",
        &AccPath,
        Entry, ApplicationName, CommandLine
    );

    return STATUS_SUCCESS;
}
Esempio n. 3
0
ULONG
NitroPlus::
HashBuffer(
    PVOID Buffer,
    ULONG Length
)
{
    PBYTE Buf;
    ULONG Hash;

    Hash = 0x20101118;
    Buf  = (PBYTE)Buffer;
    for (; Length; --Length)
    {
        Hash -= *Buf++;
    }

    return Hash * PtrOffset(Buf, Buffer);
}
Esempio n. 4
0
ULONG FASTCALL GetStringOffset(PSCRIPT_OBJECT Script, ULONG OpIndex, PCSTR StringBuffer)
{
    ULONG                   Offset, Hash;
    PTEXT_NODE*             TextNode;
    TextNodeList*           NodeList;
    PML_HANDLE_TABLE_ENTRY  NodeListHandle;

    Offset = Script->OpBuffer[OpIndex];
    if (Script->ScriptName == NULL)
        return Offset;

    Hash = HashAPILower(Script->ScriptName);
    //AllocConsole();PrintConsoleW(L"%08X, %S\n", Hash, Script->ScriptName);

    LOOP_ONCE
    {
        NodeListHandle = g_TextTable->Lookup(Hash);
        if (NodeListHandle == NULL)
            break;

        NodeList = (TextNodeList *)NodeListHandle->Handle;
        if (NodeList == NULL)
            break;

        TextNode = BinarySearch(NodeList->GetData(), NodeList->GetData() + NodeList->GetSize(), Offset,
                        [] (PTEXT_NODE* ValuePtr, ULONG Value, ULONG Context)
                        {
                            return (*ValuePtr)->Offset == Value ? 0 : (*ValuePtr)->Offset < Value ? -1 : 1;
                        },
                        0
                    );

        if (TextNode == NULL)
            break;

        Offset = PtrOffset((*TextNode)->Text, StringBuffer);
    }

    return Offset;
}
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;
}
Esempio n. 6
0
NTSTATUS CheckIsExplorer()
{
    NTSTATUS                    Status;
    PLDR_MODULE                 Module;
    PWSTR                       FullPath, BackSlash;
    ULONG                       ReturnLength;
    ULONG_PTR                   Length;
    MEMORY_BASIC_INFORMATION    MemoryBasic;

    PPROCESS_IMAGE_FILE_NAME            ExeFileName;
    PMEMORY_MAPPED_FILENAME_INFORMATION NtdllFileName;
    MEMORY_MAPPED_FILENAME_INFORMATION  LocalMapped;

    static WCHAR ExplorerName[] = L"explorer.exe";

    Status = NtQueryVirtualMemory(CurrentProcess, NtClose, MemoryMappedFilenameInformation, &LocalMapped, sizeof(LocalMapped), &Length);
    if (Status != STATUS_INFO_LENGTH_MISMATCH && Status != STATUS_BUFFER_OVERFLOW)
        return Status;

    NtdllFileName = (PMEMORY_MAPPED_FILENAME_INFORMATION)AllocStack(Length);
    Status = NtQueryVirtualMemory(CurrentProcess, NtClose, MemoryMappedFilenameInformation, NtdllFileName, Length, &Length);
    FAIL_RETURN(Status);

    Status = NtQueryInformationProcess(CurrentProcess, ProcessImageFileName, nullptr, 0, &ReturnLength);
    if (Status != STATUS_INFO_LENGTH_MISMATCH)
        return Status;

    ExeFileName = (PPROCESS_IMAGE_FILE_NAME)AllocStack(ReturnLength);
    Status = NtQueryInformationProcess(CurrentProcess, ProcessImageFileName, ExeFileName, ReturnLength, &ReturnLength);
    FAIL_RETURN(Status);

    BackSlash = nullptr;
    Length = NtdllFileName->Name.Length / sizeof(WCHAR) - 1;
    for (; Length != 0; --Length)
    {
        if (NtdllFileName->Name.Buffer[Length] != '\\')
            continue;

        if (BackSlash != nullptr)
        {
            BackSlash = &NtdllFileName->Name.Buffer[Length];
            break;
        }

        BackSlash = &NtdllFileName->Name.Buffer[Length];
    }

    if (BackSlash == nullptr)
        return STATUS_NO_MATCH;

    ++BackSlash;

    if (PtrOffset(BackSlash, NtdllFileName->Name.Buffer) + sizeof(ExplorerName) > NtdllFileName->Name.MaximumLength)
        return STATUS_NO_MATCH;

    CopyStruct(BackSlash, ExplorerName, sizeof(ExplorerName));

    NtdllFileName->Name.Length = PtrOffset(BackSlash + CONST_STRLEN(ExplorerName), NtdllFileName->Name.Buffer);

    Status = RtlEqualUnicodeString(&NtdllFileName->Name, &ExeFileName->ImageFileName, TRUE) ? STATUS_SUCCESS : STATUS_NO_MATCH;

    return Status;
}
Esempio n. 7
0
UPK_STATUS
NitroPlus::
Pack(
    PCWSTR          InputPath,
    PCWSTR          OutputFile  /* = NULL */,
    PLARGE_INTEGER  PackedFiles /* = NULL */,
    ULONG           Flags       /* = 0 */
)
{
    UNREFERENCED_PARAMETER(OutputFile);
    UNREFERENCED_PARAMETER(Flags);

    ULONG                   PathLength, Length, Hash, Offset;
    ULONG                   Size, CompressedSize, FileBufferSize, CompresseBufferSize;
    WCHAR                   FilePath[MAX_NTPATH];
    PVOID                   NpaEntryBase, FileBuffer, CompresseBuffer;
    PBYTE                   NpaEntryBuffer;
    PWSTR                   FileName;
    NTSTATUS                Status;
    LARGE_INTEGER           FileCount, PackedFileCount;
    NITRO_PLUS_ENTRY       *BaseEntry, *Entry;
    NITRO_PLUS_NPA_HEADER   Header;
    NITRO_PLUS_NPA_ETNRY   *Info;
    NtFileDisk              File;

    if (PackedFiles == NULL)
        PackedFiles = &PackedFileCount;

    PackedFiles->QuadPart = 0;

    if (!EnumDirectoryFiles(
            (PVOID *)&BaseEntry,
            L"*.*",
            sizeof(*BaseEntry),
            InputPath,
            &FileCount,
            (EnumDirectoryFilesCallBackRoutine)QueryFileList,
            0,
            EDF_SUBDIR)
       )
    {
        return STATUS_UNSUCCESSFUL;
    }

    FileBufferSize      = 0;
    CompresseBufferSize = 0;
    FileBuffer          = NULL;
    CompresseBuffer     = NULL;

    *(PULONG)&Header.Signature  = NPA_HEADER_MAGIC;
    Header.Version              = NPA_GCLX_VERSION;
    Header.EntryCount           = FileCount.LowPart;
    Header.FileCount            = FileCount.LowPart;
    Header.DirectoryCount       = 0;
    Header.IsCompressed         = TRUE;
    Header.IsEncrypted          = TRUE;

    RtlRandom(&Header.Hash[0]);
    RtlRandom(&Header.Hash[1]);

    PathLength = StrLengthW(InputPath);

    if (OutputFile != NULL)
    {
        Status = m_File.Create(OutputFile);
    }
    else
    {
        FileName = FilePath + PathLength;
        CopyMemory(FilePath, InputPath, PathLength * sizeof(*FilePath));
        if (FileName[-1] == '\\')
            --FileName;

        *(PULONG64)FileName = TAG4W('.npa');
        FileName[4] = 0;

        Status = m_File.Create(FilePath);
    }

    if (!NT_SUCCESS(Status))
        goto RETURN_POINT;

    PathLength += InputPath[PathLength - 1] != '\\';

    NpaEntryBase = AllocateMemory(sizeof(*BaseEntry) * FileCount.LowPart);
    if (NpaEntryBase == NULL)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto RETURN_POINT;
    }

    NpaEntryBuffer  = (PBYTE)NpaEntryBase;
    Entry           = BaseEntry;

    for (ULONG Index = 0, Count = FileCount.LowPart; Count; ++Index, --Count)
    {
        Length = StrLengthW(Entry->FileName) - PathLength;

        Length = WideCharToMultiByte(
                    CP_SHIFTJIS,
                    0,
                    Entry->FileName + PathLength,
                    Length,
                    (PSTR)NpaEntryBuffer + 4,
                    INT_MAX,
                    NULL,
                    NULL
                 );
//        Nt_UnicodeToAnsi((PSTR)NpaEntryBuffer + 4, INT_MAX, Entry->FileName + PathLength, Length, &Length);
        *(PULONG)NpaEntryBuffer = Length;

        NpaEntryBuffer += 4;

        Entry->DecryptLength    = Length;
        Entry->Seed             = HashBuffer(NpaEntryBuffer, Length);

        EncryptName(NpaEntryBuffer, Length, Index, &Header);

        NpaEntryBuffer += Length;
        NpaEntryBuffer += sizeof(*Info);

        ++Entry;
    }

    Header.EntrySize = PtrOffset(NpaEntryBuffer, NpaEntryBase);

    Hash            = Header.Hash[0] * Header.Hash[1];
    NpaEntryBuffer  = (PBYTE)NpaEntryBase;
    Entry           = BaseEntry;
    Offset          = 0;

    m_File.Seek(Header.EntrySize + sizeof(Header), FILE_BEGIN);

    for (ULONG Index = 0, Count = FileCount.LowPart; Count; ++Index, --Count)
    {
        Status = File.Open(Entry->FileName);
        if (!NT_SUCCESS(Status))
            break;

        Size = File.GetSize32();
        if (FileBufferSize < Size)
        {
            FileBufferSize = Size;
            FileBuffer = ReAllocateMemory(FileBuffer, FileBufferSize);
            if (FileBuffer == NULL)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }
        }

        Status = File.Read(FileBuffer, Size);
        if (!NT_SUCCESS(Status))
            break;

        CompressedSize = Size * 4;
        if (CompresseBufferSize < CompressedSize)
        {
            CompresseBufferSize = CompressedSize;
            CompresseBuffer = ReAllocateMemory(CompresseBuffer, CompresseBufferSize);
            if (CompresseBuffer == NULL)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }
        }

        CompressedSize = CompresseBufferSize;
        Status = compress2(CompresseBuffer, &CompressedSize, FileBuffer, Size, Z_BEST_COMPRESSION);
        if (Status != Z_OK)
        {
            Status = STATUS_UNSUCCESSFUL;
            break;
        }

        EncryptData(
            CompresseBuffer,
            MY_MIN(CompressedSize, Entry->DecryptLength + 0x1000),
            (Hash + Entry->Seed) * Size
        );

        NpaEntryBuffer += *(PULONG)NpaEntryBuffer + 4;
        Info            = (NITRO_PLUS_NPA_ETNRY *)NpaEntryBuffer;
        NpaEntryBuffer += sizeof(*Info);

        Info->FileType          = NP_FILE_TYPE_FILE;
        Info->CompressedSize    = CompressedSize;
        Info->Offset            = Offset;
        Info->OriginalSize      = Size;
        Info->DirectoryIndex    = 0;

        Status = m_File.Write(CompresseBuffer, CompressedSize);
        if (!NT_SUCCESS(Status))
            break;

        Offset += CompressedSize;
        ++Entry;
    }

    if (!NT_SUCCESS(Status))
        goto RETURN_POINT;

    m_File.Seek(0, FILE_BEGIN);
    Status = m_File.Write(&Header, sizeof(Header));
    if (!NT_SUCCESS(Status))
        goto RETURN_POINT;

    Status = m_File.Write(NpaEntryBase, Header.EntrySize);
    if (!NT_SUCCESS(Status))
        goto RETURN_POINT;

    PackedFiles->QuadPart = FileCount.QuadPart;

RETURN_POINT:

    FreeMemory(FileBuffer);
    EnumDirectoryFilesFree(BaseEntry);

    return Status;
}
Esempio n. 8
0
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;
}