You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/util-file-swf-decompression.c

184 lines
5.4 KiB
C

/* Copyright (C) 2017 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/** \file
*
* \author Giuseppe Longo <giuseppe@glongo.it>
*
*/
#include "suricata.h"
#include "suricata-common.h"
#include "app-layer-htp.h"
#include "util-file-decompression.h"
#include "util-file-swf-decompression.h"
#include "util-misc.h"
#include "util-print.h"
#include "util-validate.h"
#include "rust.h"
#include <zlib.h>
#define MAX_SWF_DECOMPRESSED_LEN 50000000
/*
* Return uncompressed file length
* in little-endian order
*/
uint32_t FileGetSwfDecompressedLen(const uint8_t *buffer,
const uint32_t buffer_len)
{
if (buffer_len < 8) {
return 0;
}
uint32_t a = buffer[4];
uint32_t b = buffer[5];
uint32_t c = buffer[6];
uint32_t d = buffer[7];
uint32_t value = (((a & 0xff) << 24UL) |
((b & 0xff) << 16UL) |
((c & 0xff) << 8UL) |
(d & 0xff));
uint32_t len = (((value >> 24) & 0x000000FFUL) |
((value >> 8) & 0x0000FF00UL) |
((value << 8) & 0x00FF0000UL) |
((value << 24) & 0xFF000000UL));
return MIN(MAX_SWF_DECOMPRESSED_LEN, len);
}
uint8_t FileGetSwfVersion(const uint8_t *buffer, const uint32_t buffer_len)
{
if (buffer_len > 3)
return buffer[3];
return 0;
}
/* CWS format */
/*
* | 4 bytes | 4 bytes | n bytes |
* | 'CWS' + version | script len | compressed data |
*/
int FileSwfZlibDecompression(DetectEngineThreadCtx *det_ctx,
uint8_t *compressed_data, uint32_t compressed_data_len,
uint8_t *decompressed_data, uint32_t decompressed_data_len)
{
int ret = 1;
z_stream infstream;
memset(&infstream, 0, sizeof(infstream));
infstream.zalloc = Z_NULL;
infstream.zfree = Z_NULL;
infstream.opaque = Z_NULL;
infstream.avail_in = (uInt)compressed_data_len;
infstream.next_in = (Bytef *)compressed_data;
infstream.avail_out = (uInt)decompressed_data_len;
infstream.next_out = (Bytef *)decompressed_data;
int result = inflateInit(&infstream);
if (result != Z_OK) {
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_Z_UNKNOWN_ERROR);
return 0;
}
result = inflate(&infstream, Z_NO_FLUSH);
switch(result) {
case Z_STREAM_END:
break;
case Z_OK:
break;
case Z_DATA_ERROR:
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_Z_DATA_ERROR);
ret = 0;
break;
case Z_STREAM_ERROR:
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_Z_STREAM_ERROR);
ret = 0;
break;
case Z_BUF_ERROR:
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_Z_BUF_ERROR);
ret = 0;
break;
default:
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_Z_UNKNOWN_ERROR);
ret = 0;
break;
}
inflateEnd(&infstream);
return ret;
}
/* ZWS format */
/*
* | 4 bytes | 4 bytes | 4 bytes | 5 bytes | n bytes | 6 bytes |
* | 'ZWS' + version | script len | compressed len | LZMA props | LZMA data | LZMA end marker |
*/
int FileSwfLzmaDecompression(DetectEngineThreadCtx *det_ctx,
uint8_t *compressed_data, uint32_t compressed_data_len,
uint8_t *decompressed_data, uint32_t decompressed_data_len)
{
int ret = 0;
size_t inprocessed = compressed_data_len;
size_t outprocessed = decompressed_data_len;
ret = lzma_decompress(compressed_data, &inprocessed, decompressed_data, &outprocessed,
MAX_SWF_DECOMPRESSED_LEN);
switch(ret) {
case LzmaOk:
ret = 1;
break;
case LzmaIoError:
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_IO_ERROR);
ret = 0;
break;
case LzmaHeaderTooShortError:
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_HEADER_TOO_SHORT_ERROR);
ret = 0;
break;
case LzmaError:
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_DECODER_ERROR);
ret = 0;
break;
case LzmaMemoryError:
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_MEMLIMIT_ERROR);
ret = 0;
break;
case LzmaXzError:
/* We should not see XZ compressed SWF files */
DEBUG_VALIDATE_BUG_ON(ret == LzmaXzError);
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_XZ_ERROR);
ret = 0;
break;
default:
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_LZMA_UNKNOWN_ERROR);
ret = 0;
break;
}
return ret;
}