返回首页
EN
H7 / SECURITY RESEARCH NOTES

C++调用ntdll.RtlCompressBuffer压缩收集的数据

代码如下:

#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;
}


int main(int argc, char* argv[])
{
    char* origin_path = argv[1]; // origin file path
    char* new_path = argv[2];  // compressed file path

    DWORD bufferLen, numberBytesRead, compBufferSize, realDecompSize;

    char* data = ReadFileWs(origin_path, bufferLen);
    UCHAR* bufferComprimido = compress_buffer(data, bufferLen, bufferLen + 512, &compBufferSize);
    cout << "Read and Compress file" << endl;

    WriteFileWs(new_path, (char*)bufferComprimido, compBufferSize, numberBytesRead);
    cout << "Write compressed file to specific path" << endl;

    delete[] data;
    delete[] bufferComprimido;

    return 0;
}

复现过程:

  • 通过visual studio 2022编译

  • 使用方法
.\RtlCompressBuffer.exe 文件原路径 目标路径
  • 尝试执行程序压缩文件

  • 如上图执行成功