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 
41 int 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  */
71 int 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  InspectionBufferCheckAndExpand(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 
199 error:
200  return 0;
201 }
FILE_SWF_LZMA_COMPRESSION
@ FILE_SWF_LZMA_COMPRESSION
Definition: util-file-decompression.h:34
detect-engine.h
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
FileSwfDecompression
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.
Definition: util-file-decompression.c:71
InspectionBuffer
Definition: detect.h:373
DetectEngineSetEvent
void DetectEngineSetEvent(DetectEngineThreadCtx *det_ctx, uint8_t e)
Definition: detect-engine.c:4973
HTTP_SWF_COMPRESSION_ZLIB
@ HTTP_SWF_COMPRESSION_ZLIB
Definition: app-layer-htp.h:144
SWF_LZMA_MIN_VERSION
#define SWF_LZMA_MIN_VERSION
Definition: util-file-decompression.c:39
InspectionBuffer::size
uint32_t size
Definition: detect.h:384
FileGetSwfVersion
uint8_t FileGetSwfVersion(const uint8_t *buffer, const uint32_t buffer_len)
Definition: util-file-swf-decompression.c:70
FileSwfLzmaDecompression
int FileSwfLzmaDecompression(DetectEngineThreadCtx *det_ctx, uint8_t *compressed_data, uint32_t compressed_data_len, uint8_t *decompressed_data, uint32_t decompressed_data_len)
Definition: util-file-swf-decompression.c:138
app-layer-htp.h
FILE_IS_NOT_SWF
@ FILE_IS_NOT_SWF
Definition: util-file-decompression.h:31
DetectEngineThreadCtx_
Definition: detect.h:1093
SWF_ZLIB_MIN_VERSION
#define SWF_ZLIB_MIN_VERSION
Definition: util-file-decompression.c:38
util-print.h
InspectionBuffer::buf
uint8_t * buf
Definition: detect.h:383
FILE_DECODER_EVENT_INVALID_SWF_LENGTH
@ FILE_DECODER_EVENT_INVALID_SWF_LENGTH
Definition: detect.h:1314
FileIsSwfFile
int FileIsSwfFile(const uint8_t *buffer, uint32_t buffer_len)
Definition: util-file-decompression.c:41
InspectionBufferCheckAndExpand
void * InspectionBufferCheckAndExpand(InspectionBuffer *buffer, uint32_t min_size)
make sure that the buffer has at least 'min_size' bytes Expand the buffer if necessary
Definition: detect-engine.c:1626
FileSwfZlibDecompression
int FileSwfZlibDecompression(DetectEngineThreadCtx *det_ctx, uint8_t *compressed_data, uint32_t compressed_data_len, uint8_t *decompressed_data, uint32_t decompressed_data_len)
Definition: util-file-swf-decompression.c:83
suricata-common.h
FILE_DECODER_EVENT_NO_MEM
@ FILE_DECODER_EVENT_NO_MEM
Definition: detect.h:1313
util-file-swf-decompression.h
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect.h:376
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:374
InspectionBuffer::len
uint32_t len
Definition: detect.h:382
HTTP_SWF_COMPRESSION_BOTH
@ HTTP_SWF_COMPRESSION_BOTH
Definition: app-layer-htp.h:146
util-file-decompression.h
HTTP_SWF_COMPRESSION_LZMA
@ HTTP_SWF_COMPRESSION_LZMA
Definition: app-layer-htp.h:145
suricata.h
FileGetSwfDecompressedLen
uint32_t FileGetSwfDecompressedLen(const uint8_t *buffer, const uint32_t buffer_len)
Definition: util-file-swf-decompression.c:45
FILE_SWF_ZLIB_COMPRESSION
@ FILE_SWF_ZLIB_COMPRESSION
Definition: util-file-decompression.h:33
FILE_DECODER_EVENT_INVALID_SWF_VERSION
@ FILE_DECODER_EVENT_INVALID_SWF_VERSION
Definition: detect.h:1315
util-misc.h
FILE_SWF_NO_COMPRESSION
@ FILE_SWF_NO_COMPRESSION
Definition: util-file-decompression.h:32
MIN_SWF_LEN
#define MIN_SWF_LEN
Definition: util-file-swf-decompression.h:31