本文最后更新于:2021-08-09 晚上
压缩技术
为了实现windows上的数据压缩和解压缩,最方便的方法就是直接调用win32API函数。windows系统的ntdll专门提供了RtlCompressBuffer和RtlDecompressBuffer函数来负责数据压缩和解压缩操作。
函数介绍
RtlGetCompressionWorkSpaceSize
确定RtlCompressBuffer和RtlDecompressBuffer函数工作空间缓冲区的正确大小。
| NT_RTL_COMPRESS_API NTSTATUS RtlGetCompressionWorkSpaceSize( USHORT CompressionFormatAndEngine, PULONG CompressBufferWorkSpaceSize, PULONG CompressFragmentWorkSpaceSize );
|
CompressionFormatAndEngine:指定压缩格式和引擎类型。该参数必须设置为以下组合之一:
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM
CompressBufferWorkSpaceSize:指向调用者分配的缓冲区指针,用于接受压缩缓冲区所需的大小。此值可确定RtlCompressBuffer的工作空间缓冲区的正确大小。
CompressFragmentWorkSpaceSize:一个指向可调用者分配缓冲区的指针,用于接收将压缩缓冲区解压缩为片段所需的大小。此值用于确定RtlDecompressFragment的工作空间缓冲区的正确大小。
返回值:返回STATUS_SUCCESS成功,否则失败。
RtlCompressBuffer
压缩一个可以由文件系统驱动程序使用的缓冲区,以促进文件压缩的实现。
| NT_RTL_COMPRESS_API NTSTATUS RtlCompressBuffer( USHORT CompressionFormatAndEngine, PUCHAR UncompressedBuffer, ULONG UncompressedBufferSize, PUCHAR CompressedBuffer, ULONG CompressedBufferSize, ULONG UncompressedChunkSize, PULONG FinalCompressedSize, PVOID WorkSpace );
|
CompressionFormatAndEngine:指定压缩格式和引擎类型的位掩码,此参数必须设置为一种格式类型和一种引擎类型的有效按位或组合。相关值得含义如下:
值 |
含义 |
COMPRESSION_FORMAT_LZNT1 |
LZ压缩算法 |
COMPRESSION_FORMAT_XPRESS |
Xpress压缩算法 |
COMPRESSION_FORMAT_XPRESS_HUFF |
Huffman压缩算法 |
COMPRESSION_ENGINE_STANDARD |
标准压缩算法 |
COMPRESSION_ENGINE_MAXIMUM |
最大程序压缩 |
UncompressedBuffer:指向要压缩的数据缓冲区的指针。该参数为必须不可为空。
UncompressedBufferSize:指定UncompressedBuffer缓冲区的大小
CompressedBuffer:指向压缩之后数据缓冲区的指针,用于接收压缩数据。该参数为必须的不可以为空。
CompressedBufferSize:指定CompressedBuffer缓冲区的大小。
UncompressedChunkSize:指定压缩UncompressedBuffer缓冲区时使用块的大小。该参数必须是以下值之一:512、1024、2048或者4096。操作系统使用4096,因此此参数推荐值也是、4096。
FinalCompressedSize
指向调用者分配变量的指针,该变量接收存储在CompressedBuffer中的压缩数据的大小。该参数为必须的,不能为NULL。
WorkSpace:在压缩期间指定由RtlCompressBuffer函数使用的调用者分配的工作空间缓冲区的指针。使用RtlGetCompressionWorkSpaceSize函数可以确定工作缓冲区的正确大小。
返回值:返回STATUS_SUNCCESS表示成功,否则失败。
RtlDecompressBuffer
解压缩整个压缩缓冲区
| NT_RTL_COMPRESS_API NTSTATUS RtlDecompressBuffer( USHORT CompressionFormat, PUCHAR UncompressedBuffer, ULONG UncompressedBufferSize, PUCHAR CompressedBuffer, ULONG CompressedBufferSize, PULONG FinalUncompressedSize );
|
CompressionFormat:指定压缩缓冲区中压缩格式的位掩码。该参数必须设置为COMPRESSION_FORMAT_LZNT1。它和其他相关压缩格式的含义如下:
值 |
含义 |
COMPRESSION_FORMAT_LZNT1 |
LZ压缩算法 |
COMPRESSION_FORMAT_XPRESS |
Xpress压缩算法 |
UncompressedBuffer:指向存储解压缩数据的缓冲区指针,该缓冲区从CompressedBuffer接收解压缩数据。该参数是必须的,不可以为NULL。
UncompressedBufferSize:指定UncompressedBuffer缓冲区的大小。
CompressedBuffer:指向要解压缩的数据缓冲区的指针。该参数是必须的不可以为空。
CompressedBufferSize:指定CompressedBuffer缓冲区的大小。
FinalUncompressedSize:指向解压之后得到的数据大小的指针,该变量接收在UncompressedBuffer中存储的解压缩数据的大小。该参数是必须的,不能为NULL。
返回值:返回STATUS_SUCCESS则表示成功,否则失败。
编码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
| #include <Windows.h> #include <stdio.h>
BOOL CompressData(BYTE* pUnCompressData, DWORD dwUncompressDataLen, BYTE** ppCompressData, DWORD* pdwCompressDataLen); BOOL DeCompressData(BYTE* pCompressData, DWORD dwCompressDataLen, BYTE** ppUnCompressData, DWORD* pdwUncompressDataLen);
typedef NTSTATUS (WINAPI * FN_RtlGetCompressionWorkSpaceSize)( USHORT CompressionFormatAndEngine, PULONG CompressBufferWorkSpaceSize, PULONG CompressFragmentWorkSpaceSize ); typedef NTSTATUS (WINAPI* FN_RtlCompressBuffer)( USHORT CompressionFormatAndEngine, PUCHAR UncompressedBuffer, ULONG UncompressedBufferSize, PUCHAR CompressedBuffer, ULONG CompressedBufferSize, ULONG UncompressedChunkSize, PULONG FinalCompressedSize, PVOID WorkSpace ); typedef NTSTATUS (WINAPI* FN_RtlDecompressBuffer)( USHORT CompressionFormat, PUCHAR UncompressedBuffer, ULONG UncompressedBufferSize, PUCHAR CompressedBuffer, ULONG CompressedBufferSize, PULONG FinalUncompressedSize );
int main() { DWORD i = 0; BOOL flag = FALSE; char buffer[] = "b1ackie"; DWORD dwBufferLen = strlen(buffer); BYTE* pCompressData = NULL; DWORD dwCompreeDataLen = 0; BYTE* pUnCompressData = NULL; DWORD dwUnCompressDataLen = 0; CompressData((BYTE*)buffer, dwBufferLen, &pCompressData, &dwCompreeDataLen);
DeCompressData(pCompressData, dwCompreeDataLen, &pUnCompressData, &dwUnCompressDataLen); printf("原始数据:\n"); for (int i = 0; i < dwBufferLen; i++) { printf("%x ", buffer[i]); } printf("\n加密后数据:\n"); for (int i = 0; i < dwCompreeDataLen; i++) { printf("%x ", pCompressData[i]); } printf("\n解密后数据\n"); for (int i = 0; i < dwUnCompressDataLen; i++) { printf("%x ", pUnCompressData[i]); } if (pUnCompressData) { delete[]pUnCompressData; pUnCompressData = NULL;
} if (pCompressData) { delete[]pCompressData; pCompressData = NULL; } getchar(); return 0; }
BOOL CompressData(BYTE* pUnCompressData, DWORD dwUncompressDataLen, BYTE** ppCompressData, DWORD* pdwCompressDataLen) { BOOL flag = FALSE; NTSTATUS status = 0; DWORD dwWorkSpaceSize = 0; DWORD dwFragmentWorkSpaceSize = 0; BYTE* pWorkSpace = NULL; BYTE* pCompressData = NULL; DWORD dwCompressDataLen = 4096; DWORD dwFinalCompressSize = 0; HMODULE hDll = NULL; do { hDll = LoadLibraryA("ntdll.dll"); if (hDll == NULL) { printf("加载NTDLL失败\n"); break; } FN_RtlGetCompressionWorkSpaceSize RtlGetCompressionWorkSpaceSize = (FN_RtlGetCompressionWorkSpaceSize)GetProcAddress(hDll, "RtlGetCompressionWorkSpaceSize"); if (RtlGetCompressionWorkSpaceSize == NULL) { printf("获取RtlGetCompressionWorkSpaceSize函数地址失败\n"); break; } FN_RtlCompressBuffer RtlCompressBuffer = (FN_RtlCompressBuffer)GetProcAddress(hDll, "RtlCompressBuffer"); if (RtlCompressBuffer == NULL) { printf("获取RtlCompressBuffer地址失败\n"); break; } status = RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD, &dwWorkSpaceSize, &dwFragmentWorkSpaceSize); if (status!=0) { printf("获取workspace大小失败\n"); break; } pWorkSpace = new BYTE[dwWorkSpaceSize]; if (pWorkSpace == NULL) { printf("1申请内存失败\n"); break; } RtlZeroMemory(pWorkSpace, dwWorkSpaceSize); while (TRUE) { pCompressData = new BYTE[dwCompressDataLen]; if (pCompressData == NULL) { printf("2申请内存失败\n"); break; } RtlZeroMemory(pCompressData, dwCompressDataLen); RtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, pUnCompressData, dwUncompressDataLen, pCompressData, dwCompressDataLen, 4096, &dwFinalCompressSize, (PVOID)pWorkSpace);
if (dwCompressDataLen < dwFinalCompressSize) { if (pCompressData) { delete[]pCompressData; pCompressData = NULL; } dwCompressDataLen = dwFinalCompressSize; } else { break; } } *ppCompressData = pCompressData; *pdwCompressDataLen = dwFinalCompressSize; flag = TRUE; }while(FALSE); if(pWorkSpace) { delete[]pWorkSpace; pWorkSpace = NULL; } if (hDll) { FreeLibrary(hDll); } return flag; }
BOOL DeCompressData(BYTE* pCompressData, DWORD dwCompressDataLen, BYTE** ppUnCompressData, DWORD* pdwUncompressDataLen) { BOOL flag = FALSE; HMODULE hDll = NULL; BYTE* pUnCompressData = NULL; DWORD dwUnCompressDataLen = 4096; DWORD dwFinalUnCompressSize = 0; do { hDll = LoadLibraryA("ntdll.dll"); if (hDll == NULL) { printf("加载NTDLL失败\n"); break; } FN_RtlDecompressBuffer RtlDecompressBuffer = (FN_RtlDecompressBuffer)GetProcAddress(hDll, "RtlDecompressBuffer"); if (RtlDecompressBuffer == NULL) { printf("获取RtlDecompressBuffer地址失败\n"); break; } while (TRUE) { pUnCompressData = new BYTE[dwUnCompressDataLen]; if (pUnCompressData == NULL) { printf("3申请内存失败\n"); break; } RtlZeroMemory(pUnCompressData, dwUnCompressDataLen); RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, pUnCompressData, dwUnCompressDataLen, pCompressData, dwCompressDataLen, &dwFinalUnCompressSize); if (dwUnCompressDataLen < dwFinalUnCompressSize) { if (pUnCompressData) { delete[]pUnCompressData; pUnCompressData = NULL; } dwUnCompressDataLen = dwFinalUnCompressSize; } else { break; } } *ppUnCompressData = pUnCompressData; *pdwUncompressDataLen = dwFinalUnCompressSize; flag = TRUE;
} while (FALSE); if (hDll) { FreeLibrary(hDll); }
return flag; }
|
参考
《Windows黑客编程技术详解》