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 #include "util-validate.h"
38 
39 #define SWF_ZLIB_MIN_VERSION 0x06
40 #define SWF_LZMA_MIN_VERSION 0x0D
41 
42 int FileIsSwfFile(const uint8_t *buffer, uint32_t buffer_len)
43 {
44  if (buffer_len >= 3 && buffer[1] == 'W' && buffer[2] == 'S') {
45  if (buffer[0] == 'F')
47  else if (buffer[0] == 'C')
49  else if (buffer[0] == 'Z')
51  else
52  return FILE_IS_NOT_SWF;
53  }
54 
55  return FILE_IS_NOT_SWF;
56 }
57 
58 /**
59  * \brief This function decompresses a buffer with zlib/lzma algorithm
60  *
61  * \param buffer compressed buffer
62  * \param buffer_len compressed buffer length
63  * \param out_buffer inspection buffer that stores decompressed data
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  if (decompress_depth > MAX_SWF_DECOMPRESS_DEPTH || compress_depth > MAX_SWF_COMPRESS_DEPTH) {
81  return 0;
82  }
83 
84  int compression_type = FileIsSwfFile(buffer, buffer_len);
85  if (compression_type == FILE_SWF_NO_COMPRESSION) {
86  return 0;
87  }
88 
89  uint32_t offset = 0;
90  if (compression_type == FILE_SWF_ZLIB_COMPRESSION) {
91  /* compressed data start from the 4th bytes */
92  offset = 8;
93  } else if (compression_type == FILE_SWF_LZMA_COMPRESSION) {
94  /* compressed data start from the 17th bytes */
95  offset = 17;
96  }
97 
98  if (buffer_len <= offset) {
100  return 0;
101  }
102 
103  uint32_t compressed_data_len = 0;
104  if (compress_depth > 0 && compress_depth <= buffer_len - offset) {
105  compressed_data_len = compress_depth;
106  } else {
107  compressed_data_len = buffer_len - offset;
108  }
109 
110  /* get swf version */
111  uint8_t swf_version = FileGetSwfVersion(buffer, buffer_len);
112  if (compression_type == FILE_SWF_ZLIB_COMPRESSION &&
113  swf_version < SWF_ZLIB_MIN_VERSION)
114  {
116  return 0;
117  }
118  if (compression_type == FILE_SWF_LZMA_COMPRESSION &&
119  swf_version < SWF_LZMA_MIN_VERSION)
120  {
122  return 0;
123  }
124 
125  uint32_t decompressed_data_limit =
126  (decompress_depth == 0) ? MAX_SWF_DECOMPRESSED_LEN : decompress_depth;
127 
128  uint32_t initial_buffer_len =
129  MIN(SWF_DECOMPRESS_INITIAL_BUFFER_LEN, decompressed_data_limit + SWF_HEADER_LEN);
130  if (SCInspectionBufferCheckAndExpand(out_buffer, initial_buffer_len) == NULL) {
132  return 0;
133  }
134 
135  /*
136  * FWS format
137  * | 4 bytes | 4 bytes | n bytes |
138  * | 'FWS' + version | script len | data |
139  */
140  out_buffer->buf[0] = 'F';
141  out_buffer->buf[1] = 'W';
142  out_buffer->buf[2] = 'S';
143  out_buffer->buf[3] = swf_version;
144  memcpy(out_buffer->buf + 4, buffer + 4, 4);
145 
146  uint32_t decompressed_data_produced = 0;
147 
148  if ((swf_type == HTTP_SWF_COMPRESSION_ZLIB || swf_type == HTTP_SWF_COMPRESSION_BOTH) &&
149  compression_type == FILE_SWF_ZLIB_COMPRESSION)
150  {
151  /* the first 8 bytes represents the fws header, see 'FWS format' above.
152  * data will start from 8th bytes
153  */
154  r = FileSwfZlibDecompression(det_ctx, buffer + offset, compressed_data_len, out_buffer,
155  decompressed_data_limit, &decompressed_data_produced);
156  if (r == 0)
157  goto error;
158 
159  } else if ((swf_type == HTTP_SWF_COMPRESSION_LZMA || swf_type == HTTP_SWF_COMPRESSION_BOTH) &&
160  compression_type == FILE_SWF_LZMA_COMPRESSION)
161  {
162  /* we need to setup the lzma header */
163  /*
164  * | 5 bytes | 8 bytes | n bytes |
165  * | LZMA properties | Uncompressed length | Compressed data |
166  */
167  compressed_data_len += SWF_LZMA_HEADER_LEN;
168  uint8_t *compressed_data = SCCalloc(1, compressed_data_len);
169  if (compressed_data == NULL) {
171  goto error;
172  }
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 + SWF_LZMA_HEADER_LEN, buffer + offset,
179  compressed_data_len - SWF_LZMA_HEADER_LEN);
180 
181  /* the first 8 bytes represents the fws header, see 'FWS format' above.
182  * data will start from 8th bytes
183  */
184  r = FileSwfLzmaDecompression(det_ctx, compressed_data, compressed_data_len, out_buffer,
185  decompressed_data_limit, &decompressed_data_produced);
186  SCFree(compressed_data);
187  if (r == 0)
188  goto error;
189  } else {
190  goto error;
191  }
192 
193  DEBUG_VALIDATE_BUG_ON(decompressed_data_produced > decompressed_data_limit);
194  out_buffer->len = SWF_HEADER_LEN + decompressed_data_produced;
195 
196  /* all went well so switch the buffer's inspect pointer/size
197  * to use the new data. */
198  out_buffer->inspect = out_buffer->buf;
199  out_buffer->inspect_len = out_buffer->len;
200 
201  return 1;
202 
203 error:
204  return 0;
205 }
detect-engine.h
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SWF_DECOMPRESS_INITIAL_BUFFER_LEN
#define SWF_DECOMPRESS_INITIAL_BUFFER_LEN
Definition: util-file-swf-decompression.h:35
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
FILE_DECODER_EVENT_INVALID_SWF_VERSION
@ FILE_DECODER_EVENT_INVALID_SWF_VERSION
Definition: detect.h:1537
InspectionBuffer
Definition: detect-engine-inspect-buffer.h:34
DetectEngineSetEvent
void DetectEngineSetEvent(DetectEngineThreadCtx *det_ctx, uint8_t e)
Definition: detect-engine.c:5293
MIN
#define MIN(x, y)
Definition: suricata-common.h:416
HTTP_SWF_COMPRESSION_ZLIB
@ HTTP_SWF_COMPRESSION_ZLIB
Definition: app-layer-htp.h:90
SWF_LZMA_MIN_VERSION
#define SWF_LZMA_MIN_VERSION
Definition: util-file-decompression.c:40
MAX_SWF_DECOMPRESS_DEPTH
#define MAX_SWF_DECOMPRESS_DEPTH
Definition: util-file-decompression.h:33
FileGetSwfVersion
uint8_t FileGetSwfVersion(const uint8_t *buffer, const uint32_t buffer_len)
Definition: util-file-swf-decompression.c:40
app-layer-htp.h
SWF_HEADER_LEN
#define SWF_HEADER_LEN
Definition: util-file-decompression.h:30
DetectEngineThreadCtx_
Definition: detect.h:1306
SWF_ZLIB_MIN_VERSION
#define SWF_ZLIB_MIN_VERSION
Definition: util-file-decompression.c:39
FILE_SWF_ZLIB_COMPRESSION
@ FILE_SWF_ZLIB_COMPRESSION
Definition: util-file-decompression.h:39
FILE_SWF_NO_COMPRESSION
@ FILE_SWF_NO_COMPRESSION
Definition: util-file-decompression.h:38
util-print.h
InspectionBuffer::buf
uint8_t * buf
Definition: detect-engine-inspect-buffer.h:44
FILE_SWF_LZMA_COMPRESSION
@ FILE_SWF_LZMA_COMPRESSION
Definition: util-file-decompression.h:40
FILE_IS_NOT_SWF
@ FILE_IS_NOT_SWF
Definition: util-file-decompression.h:37
FileIsSwfFile
int FileIsSwfFile(const uint8_t *buffer, uint32_t buffer_len)
Definition: util-file-decompression.c:42
SWF_LZMA_HEADER_LEN
#define SWF_LZMA_HEADER_LEN
Definition: util-file-decompression.h:31
suricata-common.h
FILE_DECODER_EVENT_NO_MEM
@ FILE_DECODER_EVENT_NO_MEM
Definition: detect.h:1535
util-validate.h
util-file-swf-decompression.h
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect-engine-inspect-buffer.h:37
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect-engine-inspect-buffer.h:35
InspectionBuffer::len
uint32_t len
Definition: detect-engine-inspect-buffer.h:43
SCFree
#define SCFree(p)
Definition: util-mem.h:61
HTTP_SWF_COMPRESSION_BOTH
@ HTTP_SWF_COMPRESSION_BOTH
Definition: app-layer-htp.h:92
util-file-decompression.h
HTTP_SWF_COMPRESSION_LZMA
@ HTTP_SWF_COMPRESSION_LZMA
Definition: app-layer-htp.h:91
suricata.h
SCInspectionBufferCheckAndExpand
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
Definition: detect-engine-inspect-buffer.c:217
MAX_SWF_COMPRESS_DEPTH
#define MAX_SWF_COMPRESS_DEPTH
Definition: util-file-decompression.h:34
MAX_SWF_DECOMPRESSED_LEN
#define MAX_SWF_DECOMPRESSED_LEN
Definition: util-file-swf-decompression.h:33
util-misc.h
FileSwfZlibDecompression
int FileSwfZlibDecompression(DetectEngineThreadCtx *det_ctx, const uint8_t *compressed_data, uint32_t compressed_data_len, InspectionBuffer *out_buffer, uint32_t decompressed_data_limit, uint32_t *decompressed_data_produced)
Definition: util-file-swf-decompression.c:85
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
FILE_DECODER_EVENT_INVALID_SWF_LENGTH
@ FILE_DECODER_EVENT_INVALID_SWF_LENGTH
Definition: detect.h:1536
FileSwfLzmaDecompression
int FileSwfLzmaDecompression(DetectEngineThreadCtx *det_ctx, const uint8_t *compressed_data, uint32_t compressed_data_len, InspectionBuffer *out_buffer, uint32_t decompressed_data_limit, uint32_t *decompressed_data_produced)
Definition: util-file-swf-decompression.c:159