压缩技术-windows压缩API

本文最后更新于:2021-08-09 晚上

压缩技术

为了实现windows上的数据压缩和解压缩,最方便的方法就是直接调用win32API函数。windows系统的ntdll专门提供了RtlCompressBuffer和RtlDecompressBuffer函数来负责数据压缩和解压缩操作。

函数介绍

RtlGetCompressionWorkSpaceSize

确定RtlCompressBuffer和RtlDecompressBuffer函数工作空间缓冲区的正确大小。

1
2
3
4
5
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

压缩一个可以由文件系统驱动程序使用的缓冲区,以促进文件压缩的实现。

1
2
3
4
5
6
7
8
9
10
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

解压缩整个压缩缓冲区

1
2
3
4
5
6
7
8
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;
}
//获取WORKSPACE的大小
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黑客编程技术详解》