Página 1 de 1

[Funcion] RtlCompressBuffer c++

Publicado: 07 Sep 2015, 04:45
por crack81
Buscando en mis codigos encontre este ejemplo de como usar la RtlCompressBuffer tanto como para comprimir como para descomprimir en un principio la funcion estaba diseñada funcion en el C clasico por eso por el uso excesivo de punteros despues termine complementadolo con c++ asi que quedo como un revoltijo c y c++ XD
Pero se puede retocar facilmente y si no le gusta el uso de *Char pueden usar string por comodidad
#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 = GetModuleHandle("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_MAXIMUM, // 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_MAXIMUM, // 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_MAXIMUM, // 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*)"C:\\bcb6kg.exe";//archivo original a ser comprimido y descomprimido
  char *NewPath=(char*)"C:\\Nuevo.exe";//la nueva ruta del comprimido
  char *DecompressPath=(char*)"C:\\descomprimido.exe";//la nueva ruta del comprimido
  DWORD bufferLen,numberBytesRead,compBufferSize,realDecompSize;

  char *data=ReadFileWs(path,bufferLen);//necesitara ser liberado
  UCHAR *bufferComprimido=compress_buffer(data,bufferLen,bufferLen+512,&compBufferSize);//necesitara ser liberado
  cout<<"Archivo Leido y comprimido"<<endl;

  WriteFileWs(NewPath,(char*)bufferComprimido,compBufferSize,numberBytesRead);
  cout<<"Archivo comprimido escrito en la ruta indicada"<<endl;

  UCHAR *bufferDescomprimido=decompress_buffer((char*)bufferComprimido,bufferLen,compBufferSize*100,&realDecompSize);
  WriteFileWs(DecompressPath,(char*)bufferDescomprimido,bufferLen,numberBytesRead);
  cout<<"Archivo descomprimido y escrito en la ruta indicada "<<endl;

  delete[] data;//liberamos
  delete[] bufferComprimido;
  delete[] bufferDescomprimido;



  cin.get();
  return 0;
}
Saludos..

Re: [Funcion] RtlCompressBuffer c++

Publicado: 07 Sep 2015, 05:44
por Blau
¿Cuál es el resultado?, ¿cuánta es la diferencia de peso entre archivos? No tengo ganas de comprobarlo

Re: [Funcion] RtlCompressBuffer c++

Publicado: 07 Sep 2015, 16:25
por Pink
Excelete bro gracias por compartirlo.

Saludos