suricata
util-file-decompression.c
Go to the documentation of this file.
1/* Copyright (C) 2017 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/** \file
19 *
20 * \author Giuseppe Longo <giuseppe@glongo.it>
21 *
22 * \brief Decompress files transferred via HTTP corresponding to file_data
23 * keyword.
24 *
25 */
26
27#include "suricata-common.h"
28#include "suricata.h"
29
30#include "detect-engine.h"
31#include "app-layer-htp.h"
32
35#include "util-misc.h"
36#include "util-print.h"
37
38#define SWF_ZLIB_MIN_VERSION 0x06
39#define SWF_LZMA_MIN_VERSION 0x0D
40
41int FileIsSwfFile(const uint8_t *buffer, uint32_t buffer_len)
42{
43 if (buffer_len >= 3 && buffer[1] == 'W' && buffer[2] == 'S') {
44 if (buffer[0] == 'F')
46 else if (buffer[0] == 'C')
48 else if (buffer[0] == 'Z')
50 else
51 return FILE_IS_NOT_SWF;
52 }
53
54 return FILE_IS_NOT_SWF;
55}
56
57/**
58 * \brief This function decompresses a buffer with zlib/lzma algorithm
59 *
60 * \param buffer compressed buffer
61 * \param buffer_len compressed buffer length
62 * \param decompressed_buffer buffer that store decompressed data
63 * \param decompressed_buffer_len decompressed data length
64 * \param swf_type decompression algorithm to use
65 * \param decompress_depth how much decompressed data we want to store
66 * \param compress_depth how much compressed data we want to decompress
67 *
68 * \retval 1 if decompression works
69 * \retval 0 an error occurred, and event set
70 */
71int FileSwfDecompression(const uint8_t *buffer, uint32_t buffer_len,
72 DetectEngineThreadCtx *det_ctx,
73 InspectionBuffer *out_buffer,
74 int swf_type,
75 uint32_t decompress_depth,
76 uint32_t compress_depth)
77{
78 int r = 0;
79
80 int compression_type = FileIsSwfFile(buffer, buffer_len);
81 if (compression_type == FILE_SWF_NO_COMPRESSION) {
82 return 0;
83 }
84
85 uint32_t offset = 0;
86 if (compression_type == FILE_SWF_ZLIB_COMPRESSION) {
87 /* compressed data start from the 4th bytes */
88 offset = 8;
89 } else if (compression_type == FILE_SWF_LZMA_COMPRESSION) {
90 /* compressed data start from the 17th bytes */
91 offset = 17;
92 }
93
94 if (buffer_len <= offset) {
96 return 0;
97 }
98
99 uint32_t compressed_data_len = 0;
100 if (compress_depth > 0 && compress_depth <= buffer_len - offset) {
101 compressed_data_len = compress_depth;
102 } else {
103 compressed_data_len = buffer_len - offset;
104 }
105
106 /* get swf version */
107 uint8_t swf_version = FileGetSwfVersion(buffer, buffer_len);
108 if (compression_type == FILE_SWF_ZLIB_COMPRESSION &&
109 swf_version < SWF_ZLIB_MIN_VERSION)
110 {
112 return 0;
113 }
114 if (compression_type == FILE_SWF_LZMA_COMPRESSION &&
115 swf_version < SWF_LZMA_MIN_VERSION)
116 {
118 return 0;
119 }
120
121 /* get flash decompressed file length */
122 uint32_t decompressed_swf_len = FileGetSwfDecompressedLen(buffer, buffer_len);
123 if (decompressed_swf_len == 0) {
124 decompressed_swf_len = MIN_SWF_LEN;
125 }
126
127 /* if decompress_depth is 0, keep the flash file length */
128 uint32_t decompressed_data_len = (decompress_depth == 0) ? decompressed_swf_len : decompress_depth;
129 decompressed_data_len += 8;
130
131 /* make sure the inspection buffer has enough space */
132 SCInspectionBufferCheckAndExpand(out_buffer, decompressed_data_len);
133 if (out_buffer->size < decompressed_data_len) {
135 return 0;
136 }
137 out_buffer->len = decompressed_data_len;
138
139 /*
140 * FWS format
141 * | 4 bytes | 4 bytes | n bytes |
142 * | 'FWS' + version | script len | data |
143 */
144 out_buffer->buf[0] = 'F';
145 out_buffer->buf[1] = 'W';
146 out_buffer->buf[2] = 'S';
147 out_buffer->buf[3] = swf_version;
148 memcpy(out_buffer->buf + 4, &decompressed_swf_len, 4);
149 memset(out_buffer->buf + 8, 0, decompressed_data_len - 8);
150
151 if ((swf_type == HTTP_SWF_COMPRESSION_ZLIB || swf_type == HTTP_SWF_COMPRESSION_BOTH) &&
152 compression_type == FILE_SWF_ZLIB_COMPRESSION)
153 {
154 /* the first 8 bytes represents the fws header, see 'FWS format' above.
155 * data will start from 8th bytes
156 */
157 r = FileSwfZlibDecompression(det_ctx,
158 (uint8_t *)buffer + offset, compressed_data_len,
159 out_buffer->buf + 8, out_buffer->len - 8);
160 if (r == 0)
161 goto error;
162
163 } else if ((swf_type == HTTP_SWF_COMPRESSION_LZMA || swf_type == HTTP_SWF_COMPRESSION_BOTH) &&
164 compression_type == FILE_SWF_LZMA_COMPRESSION)
165 {
166 /* we need to setup the lzma header */
167 /*
168 * | 5 bytes | 8 bytes | n bytes |
169 * | LZMA properties | Uncompressed length | Compressed data |
170 */
171 compressed_data_len += 13;
172 uint8_t compressed_data[compressed_data_len];
173 /* put lzma properties */
174 memcpy(compressed_data, buffer + 12, 5);
175 /* put lzma end marker */
176 memset(compressed_data + 5, 0xFF, 8);
177 /* put compressed data */
178 memcpy(compressed_data + 13, buffer + offset, compressed_data_len - 13);
179
180 /* the first 8 bytes represents the fws header, see 'FWS format' above.
181 * data will start from 8th bytes
182 */
183 r = FileSwfLzmaDecompression(det_ctx,
184 compressed_data, compressed_data_len,
185 out_buffer->buf + 8, out_buffer->len - 8);
186 if (r == 0)
187 goto error;
188 } else {
189 goto error;
190 }
191
192 /* all went well so switch the buffer's inspect pointer/size
193 * to use the new data. */
194 out_buffer->inspect = out_buffer->buf;
195 out_buffer->inspect_len = out_buffer->len;
196
197 return 1;
198
199error:
200 return 0;
201}
uint8_t * SCInspectionBufferCheckAndExpand(InspectionBuffer *buffer, uint32_t min_size)
make sure that the buffer has at least 'min_size' bytes Expand the buffer if necessary
void DetectEngineSetEvent(DetectEngineThreadCtx *det_ctx, uint8_t e)
@ FILE_DECODER_EVENT_NO_MEM
Definition detect.h:1470
@ FILE_DECODER_EVENT_INVALID_SWF_VERSION
Definition detect.h:1472
@ FILE_DECODER_EVENT_INVALID_SWF_LENGTH
Definition detect.h:1471
@ HTTP_SWF_COMPRESSION_ZLIB
@ HTTP_SWF_COMPRESSION_LZMA
@ HTTP_SWF_COMPRESSION_BOTH
#define SWF_LZMA_MIN_VERSION
int FileSwfDecompression(const uint8_t *buffer, uint32_t buffer_len, DetectEngineThreadCtx *det_ctx, InspectionBuffer *out_buffer, int swf_type, uint32_t decompress_depth, uint32_t compress_depth)
This function decompresses a buffer with zlib/lzma algorithm.
int FileIsSwfFile(const uint8_t *buffer, uint32_t buffer_len)
#define SWF_ZLIB_MIN_VERSION
@ FILE_SWF_ZLIB_COMPRESSION
@ FILE_SWF_LZMA_COMPRESSION
@ FILE_SWF_NO_COMPRESSION
uint8_t FileGetSwfVersion(const uint8_t *buffer, const uint32_t buffer_len)
uint32_t FileGetSwfDecompressedLen(const uint8_t *buffer, const uint32_t buffer_len)
int FileSwfZlibDecompression(DetectEngineThreadCtx *det_ctx, uint8_t *compressed_data, uint32_t compressed_data_len, uint8_t *decompressed_data, uint32_t decompressed_data_len)
int FileSwfLzmaDecompression(DetectEngineThreadCtx *det_ctx, uint8_t *compressed_data, uint32_t compressed_data_len, uint8_t *decompressed_data, uint32_t decompressed_data_len)
#define MIN_SWF_LEN
uint64_t offset