Exemple #1
0
NTSTATUS GetExeImageSize(LPWSTR ExeFullPath, PULONG SizeOfImage)
{
    ULONG                   Size;
    NTSTATUS                Status;
    NtFileDisk             file;
    IMAGE_DOS_HEADER        DosHeader;
    IMAGE_NT_HEADERS        NtHeader;
    PIMAGE_OPTIONAL_HEADER  OptionalHeader;
    PIMAGE_SECTION_HEADER   SectionHeader;

    Status = file.Open(ExeFullPath);
    if (!NT_SUCCESS(Status))
        return Status;

    Status = file.Read(&DosHeader, sizeof(DosHeader));
    if (!NT_SUCCESS(Status))
        return Status;

    if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
        return STATUS_INVALID_IMAGE_WIN_32;

    Status = file.Seek(DosHeader.e_lfanew, FILE_BEGIN);
    if (!NT_SUCCESS(Status))
        return Status;

    Status = file.Read(&NtHeader, sizeof(NtHeader) - sizeof(NtHeader.OptionalHeader));
    if (!NT_SUCCESS(Status))
        return Status;

    if (NtHeader.Signature != IMAGE_NT_SIGNATURE)
        return STATUS_INVALID_IMAGE_WIN_32;

    if (NtHeader.FileHeader.SizeOfOptionalHeader > FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, SizeOfImage) + RTL_FIELD_SIZE(IMAGE_OPTIONAL_HEADER, SizeOfImage))
    {
        OptionalHeader = (PIMAGE_OPTIONAL_HEADER)AllocStack(NtHeader.FileHeader.SizeOfOptionalHeader);
        Status = file.Read(OptionalHeader, NtHeader.FileHeader.SizeOfOptionalHeader);
        if (!NT_SUCCESS(Status))
            return Status;

        *SizeOfImage = OptionalHeader->SizeOfImage;
        return STATUS_SUCCESS;
    }

    SectionHeader = (PIMAGE_SECTION_HEADER)AllocStack(NtHeader.FileHeader.NumberOfSections * sizeof(*SectionHeader));
    Status = file.Read(SectionHeader, NtHeader.FileHeader.NumberOfSections * sizeof(*SectionHeader));
    if (!NT_SUCCESS(Status))
        return Status;

    Size = 0;
    for (ULONG NumberOfSections = NtHeader.FileHeader.NumberOfSections; NumberOfSections; --NumberOfSections)
    {
        Size += SectionHeader->Misc.VirtualSize;
        ++SectionHeader;
    }

    Size += ROUND_UP(file.GetCurrentPos(), MEMORY_PAGE_SIZE);
    *SizeOfImage = Size;

    return STATUS_SUCCESS;
}
Exemple #2
0
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;
}
Exemple #3
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;
}