Rtlcompressbuffer 压缩与解压

  • Post author:
  • Post category:其他


#include <iostream>
#include <windows.h>
using namespace std;


//typedef unsigned long NTSTATUS;

#define STATUS_SUCCESS                 ((NTSTATUS)0x00000000UL)
#define STATUS_BUFFER_ALL_ZEROS        ((NTSTATUS)0x00000117UL)
#define STATUS_INVALID_PARAMETER       ((NTSTATUS)0xC000000DUL)
#define STATUS_UNSUPPORTED_COMPRESSION ((NTSTATUS)0xC000025FUL)
#define STATUS_NOT_SUPPORTED_ON_SBS    ((NTSTATUS)0xC0000300UL)
#define STATUS_BUFFER_TOO_SMALL        ((NTSTATUS)0xC0000023UL)
#define STATUS_BAD_COMPRESSION_BUFFER  ((NTSTATUS)0xC0000242UL)

HMODULE ntdll = GetModuleHandleA("ntdll.dll");

typedef NTSTATUS(__stdcall* _RtlCompressBuffer)(
    USHORT CompressionFormatAndEngine,
    PUCHAR UncompressedBuffer,
    ULONG UncompressedBufferSize,
    PUCHAR CompressedBuffer,
    ULONG CompressedBufferSize,
    ULONG UncompressedChunkSize,
    PULONG FinalCompressedSize,
    PVOID WorkSpace
    );

typedef NTSTATUS(__stdcall* _RtlDecompressBuffer)(
    USHORT CompressionFormat,
    PUCHAR UncompressedBuffer,
    ULONG UncompressedBufferSize,
    PUCHAR CompressedBuffer,
    ULONG CompressedBufferSize,
    PULONG FinalUncompressedSize
    );

typedef NTSTATUS(__stdcall* _RtlGetCompressionWorkSpaceSize)(
    USHORT CompressionFormatAndEngine,
    PULONG CompressBufferWorkSpaceSize,
    PULONG CompressFragmentWorkSpaceSize
    );

char* ReadFileWs(const char* FilePath, DWORD& bufferLen) {
    HANDLE File = CreateFileA(FilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

    if (File == INVALID_HANDLE_VALUE) {
        return NULL;
    }

    DWORD _size = GetFileSize(File, 0);
    char* Buffer = new char[_size + 1];
    bool result = ReadFile(File, Buffer, _size, &bufferLen, 0);
    CloseHandle(File);

    if (result)return Buffer;
    else return NULL;
}

bool WriteFileWs(const char* FilePath, char* Buffer, DWORD bufferLen, DWORD& numberBytesRead) {
    HANDLE File = CreateFileA(FilePath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);

    if (File == INVALID_HANDLE_VALUE) {
        return false;
    }

    bool result = WriteFile(File, Buffer, bufferLen, &numberBytesRead, NULL);
    CloseHandle(File);

    return result;
}


UCHAR* compress_buffer(const char* buffer, const ULONG bufferLen, ULONG compBufferLen, ULONG* compBufferSize)
{
    _RtlCompressBuffer RtlCompressBuffer = (_RtlCompressBuffer)GetProcAddress(ntdll, "RtlCompressBuffer");
    _RtlGetCompressionWorkSpaceSize RtlGetCompressionWorkSpaceSize = (_RtlGetCompressionWorkSpaceSize)GetProcAddress(ntdll, "RtlGetCompressionWorkSpaceSize");

    ULONG bufWorkspaceSize;  // Workspace Size
    ULONG fragWorkspaceSize; // Fragmented Workspace Size (Unused)
    NTSTATUS ret = RtlGetCompressionWorkSpaceSize(
        COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD, // CompressionFormatAndEngine
        &bufWorkspaceSize,                                     // CompressBufferWorkSpaceSize
        &fragWorkspaceSize                                     // CompressFragmentWorkSpaceSize
    );

    if (ret != STATUS_SUCCESS) return 0;

    VOID* workspace = (VOID*)LocalAlloc(LMEM_FIXED, bufWorkspaceSize);
    if (workspace == NULL) return 0;

    UCHAR* compBuffer = new UCHAR[compBufferLen];
    NTSTATUS result = RtlCompressBuffer(
        COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD, // CompressionFormatAndEngine
        (UCHAR*)buffer,                                         // UncompressedBuffer
        bufferLen,                                              // UncompressedBufferSize
        compBuffer,                                             // CompressedBuffer
        compBufferLen,                                          // CompressedBufferSize
        4096,                                                   // UncompressedChunkSize
        compBufferSize,                                         // FinalCompressedSize
        workspace                                               // WorkSpace
    );

    LocalFree(workspace);
    if (result != STATUS_SUCCESS) {
        return 0;
    }

    return compBuffer;
}

UCHAR* decompress_buffer(const char* buffer, const int bufferLen, const int uncompBufferLen, ULONG* uncompBufferSize)
{
    _RtlDecompressBuffer RtlDecompressBuffer = (_RtlDecompressBuffer)GetProcAddress(ntdll, "RtlDecompressBuffer");

    UCHAR* uncompBuffer = new UCHAR[uncompBufferLen];
    NTSTATUS result = RtlDecompressBuffer(
        COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD, // CompressionFormat
        uncompBuffer,                                           // UncompressedBuffer
        uncompBufferLen,                                        // UncompressedBufferSize
        (UCHAR*)buffer,                                         // CompressedBuffer
        bufferLen,                                              // CompressedBufferSize
        uncompBufferSize                                        // FinalUncompressedSize
    );

    if (result != STATUS_SUCCESS) {
        ;
        return 0;
    }


    return uncompBuffer;
}


int main(void)
{
    char* path = (char*)"D:\\Utest\\TestDll.dll";//源文件
    char* NewPath = (char*)"D:\\Utest\\TestDllYY.dll";                // 压缩后
    char* DecompressPath = (char*)"D:\\Utest\\TestDllJJ.dll";// 解压
    DWORD bufferLen, numberBytesRead, compBufferSize, realDecompSize;

    char* data = ReadFileWs(path, bufferLen); 
    UCHAR* bufferComprimido = compress_buffer(data, bufferLen, bufferLen + 512, &compBufferSize);//necesitara ser liberado
    cout << "读取和压缩文件" << endl;

    WriteFileWs(NewPath, (char*)bufferComprimido, compBufferSize, numberBytesRead);
    cout << "在指定路径写入压缩后的文件" << endl;

    UCHAR* bufferDescomprimido = decompress_buffer((char*)bufferComprimido, bufferLen, compBufferSize * 100, &realDecompSize);
    WriteFileWs(DecompressPath, (char*)bufferDescomprimido, bufferLen, numberBytesRead);
    cout << "在指定路径写入解压后的文件 " << endl;

    delete[] data; 
    delete[] bufferComprimido;
    delete[] bufferDescomprimido;



    cin.get();
    return 0;
}



版权声明:本文为chengriyue原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。