Skip to content

Commit

Permalink
improved ntfsusn and hiberfile scanner (simsong#99)
Browse files Browse the repository at this point in the history
  • Loading branch information
4n6ist authored and simsong committed Jan 31, 2018
1 parent 90eb5aa commit da1c856
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 145 deletions.
4 changes: 3 additions & 1 deletion src/scan_hiberfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ void scan_hiberfile(const class scanner_params &sp,const recursion_control_block
if(cc[0]==0x81 && cc[1]==0x81 && cc[2]==0x78 && cc[3]==0x70 &&
cc[4]==0x72 && cc[5]==0x65 && cc[6]==0x73 && cc[7]==0x73){

u_int compressed_length = (((cc[9]<<8) + (cc[10] << 16) + (cc[11]<<24)) >> 10) + 1;
//u_int compressed_length = (((cc[9]<<8) + (cc[10] << 16) + (cc[11]<<24)) >> 10) + 1;
u_int compressed_length = ((cc[8] + (cc[9]<<8) + (cc[10] << 16) + (cc[11]<<24)) >> 10) + 1; // ref: Hibr2bin/MemoryBlocks.cpp
compressed_length = (compressed_length + 7) & ~7; // ref: Hibr2bin/MemoryBlocks.cpp
const u_char *compressed_buf = cc+32; // "the header contains 32 bytes"
u_int remaining_size = sbuf.bufsize - (compressed_buf-sbuf.buf); // up to the end of the buffer
size_t compr_size = compressed_length < remaining_size ? compressed_length : remaining_size;
Expand Down
300 changes: 156 additions & 144 deletions src/scan_ntfsusn.cpp
Original file line number Diff line number Diff line change
@@ -1,144 +1,156 @@
/**
* Plugin: scan_ntfsusn
* Purpose: Find all USN_RECORD v2/v4 record into one file
* USN_RECORD_V2 format https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa365722(v=vs.85).aspx
* USN_RECORD_V4 format https://msdn.microsoft.com/ja-jp/library/windows/desktop/mt684964(v=vs.85).aspx
**/
#include "config.h"
#include "be13_api/bulk_extractor_i.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
#include <sstream>
#include <vector>
#include "sbuf_stream.h"

#include "utf8.h"

static uint32_t ntfsusn_carve_mode = feature_recorder::CARVE_ALL;

using namespace std;

#define SECTOR_SIZE 512
#define CLUSTER_SIZE 4096
#define FEATURE_FILE_NAME "ntfsusn_carved"

size_t check_usnrecordv2_signature(size_t offset, const sbuf_t &sbuf) {
size_t record_size;
if (sbuf[offset + 2] == 0x00 && sbuf[offset + 3] == 0x00 && sbuf[offset + 4] == 0x02
&& sbuf[offset + 5] == 0x00 && sbuf[offset + 6] == 0x00 && sbuf[offset + 7] == 0x00
&& sbuf[offset + 58] == 0x3c && sbuf[offset + 59] == 0x00) {
record_size = sbuf.get16i(offset);
if (record_size >= 64 && record_size <= 600)
return record_size;
else
return 0;
}
return 0;
}

size_t check_usnrecordv4_signature(size_t offset, const sbuf_t &sbuf) {
size_t record_size;
if (sbuf[offset + 2] == 0x00 && sbuf[offset + 3] == 0x00 && sbuf[offset + 4] == 0x04
&& sbuf[offset + 5] == 0x00 && sbuf[offset + 6] == 0x00 && sbuf[offset + 7] == 0x00
&& sbuf[offset + 62] == 0x10 && sbuf[offset + 63] == 0x00) {
record_size = sbuf.get16i(offset);
if (record_size >= 64 && record_size <= 600)
return record_size;
else
return 0;
}
return 0;
}

size_t check_usnrecordv2_or_v4_signature(size_t offset, const sbuf_t &sbuf) {
size_t record_size;
record_size = check_usnrecordv2_signature(offset, sbuf);
if (record_size != 0)
return record_size;

record_size = check_usnrecordv4_signature(offset, sbuf);
if (record_size != 0)
return record_size;

return 0;
}

extern "C"

void scan_ntfsusn(const class scanner_params &sp,const recursion_control_block &rcb)
{
assert(sp.sp_version==scanner_params::CURRENT_SP_VERSION);
if(sp.phase==scanner_params::PHASE_STARTUP){
assert(sp.info->si_version==scanner_info::CURRENT_SI_VERSION);
sp.info->name = "ntfsusn";
sp.info->author = "Teru Yamazaki";
sp.info->description = "Scans for USN_RECORD v2/v4 record";
sp.info->scanner_version = "1.0";
sp.info->feature_names.insert(FEATURE_FILE_NAME);
// sp.info->get_config("ntfsusn_carve_mode",&ntfsusn_carve_mode,"0=carve none; 1=carve encoded; 2=carve all");
return;
}
if(sp.phase==scanner_params::PHASE_INIT){
sp.fs.get_name(FEATURE_FILE_NAME)->set_carve_mode(static_cast<feature_recorder::carve_mode_t>(ntfsusn_carve_mode));
}
if(sp.phase==scanner_params::PHASE_SCAN){
const sbuf_t &sbuf = sp.sbuf;
feature_recorder_set &fs = sp.fs;
feature_recorder *ntfsusn_recorder = fs.get_name(FEATURE_FILE_NAME);

size_t offset = 0;
size_t stop = sbuf.pagesize;
size_t record_size=0;
size_t total_record_size=0;

// search for USN_RECORD_V2 Structure in the sbuf
while (offset < stop) {
record_size = check_usnrecordv2_signature(offset,sbuf);
if (record_size == 0) {
offset += 8; // because of USN_RECORD stored at 8 byte boundary
continue;
}
total_record_size = record_size;
if (offset+total_record_size > stop) {
ntfsusn_recorder->carve_records(sbuf,offset,total_record_size,"UsnJrnl-J");
break;
}
// found one record then also checks following valid records and writes all at once
while (true) {
record_size = check_usnrecordv2_or_v4_signature(offset+total_record_size,sbuf);
if (record_size != 0) {
if (offset+total_record_size+record_size < stop) {
total_record_size += record_size;
}
else {
total_record_size = stop-offset;
break;
}
}
else { // consider padding area around sector boundary
if ((offset+total_record_size) % SECTOR_SIZE != 0) {
size_t next_boundary_offset;
next_boundary_offset = offset + total_record_size + SECTOR_SIZE - (total_record_size % SECTOR_SIZE);
record_size = check_usnrecordv2_or_v4_signature(next_boundary_offset,sbuf);
if (record_size != 0) {
total_record_size = next_boundary_offset - offset;
continue;
}
else {
break;
}
}
else {
break;
}
}
}
ntfsusn_recorder->carve_records(sbuf,offset,total_record_size,"UsnJrnl-J");
offset += total_record_size;
}
}
}
/**
* Plugin: scan_ntfsusn
* Purpose: Find all USN_RECORD v2/v4 record into one file
* USN_RECORD_V2 format https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa365722(v=vs.85).aspx
* USN_RECORD_V4 format https://msdn.microsoft.com/ja-jp/library/windows/desktop/mt684964(v=vs.85).aspx
**/
#include "config.h"
#include "be13_api/bulk_extractor_i.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
#include <sstream>
#include <vector>
#include "sbuf_stream.h"

#include "utf8.h"

static uint32_t ntfsusn_carve_mode = feature_recorder::CARVE_ALL;

using namespace std;

#define SECTOR_SIZE 512
#define CLUSTER_SIZE 4096
#define FEATURE_FILE_NAME "ntfsusn_carved"

size_t check_usnrecordv2_signature(size_t offset, const sbuf_t &sbuf) {
size_t record_size;
if (sbuf[offset + 2] == 0x00 && sbuf[offset + 3] == 0x00 && sbuf[offset + 4] == 0x02
&& sbuf[offset + 5] == 0x00 && sbuf[offset + 6] == 0x00 && sbuf[offset + 7] == 0x00
&& sbuf[offset + 58] == 0x3c && sbuf[offset + 59] == 0x00) {
record_size = sbuf.get16i(offset);
if (record_size >= 64 && record_size <= 600)
return record_size;
else
return 0;
}
return 0;
}

size_t check_usnrecordv4_signature(size_t offset, const sbuf_t &sbuf) {
size_t record_size;
if (sbuf[offset + 2] == 0x00 && sbuf[offset + 3] == 0x00 && sbuf[offset + 4] == 0x04
&& sbuf[offset + 5] == 0x00 && sbuf[offset + 6] == 0x00 && sbuf[offset + 7] == 0x00
&& sbuf[offset + 62] == 0x10 && sbuf[offset + 63] == 0x00) {
record_size = sbuf.get16i(offset);
if (record_size >= 64 && record_size <= 600)
return record_size;
else
return 0;
}
return 0;
}

size_t check_usnrecordv2_or_v4_signature(size_t offset, const sbuf_t &sbuf) {
size_t record_size;
record_size = check_usnrecordv2_signature(offset, sbuf);
if (record_size != 0)
return record_size;

record_size = check_usnrecordv4_signature(offset, sbuf);
if (record_size != 0)
return record_size;

return 0;
}

extern "C"

void scan_ntfsusn(const class scanner_params &sp,const recursion_control_block &rcb)
{
assert(sp.sp_version==scanner_params::CURRENT_SP_VERSION);
if(sp.phase==scanner_params::PHASE_STARTUP){
assert(sp.info->si_version==scanner_info::CURRENT_SI_VERSION);
sp.info->name = "ntfsusn";
sp.info->author = "Teru Yamazaki";
sp.info->description = "Scans for USN_RECORD v2/v4 record";
sp.info->scanner_version = "1.0";
sp.info->feature_names.insert(FEATURE_FILE_NAME);
// sp.info->get_config("ntfsusn_carve_mode",&ntfsusn_carve_mode,"0=carve none; 1=carve encoded; 2=carve all");
return;
}
if(sp.phase==scanner_params::PHASE_INIT){
sp.fs.get_name(FEATURE_FILE_NAME)->set_carve_mode(static_cast<feature_recorder::carve_mode_t>(ntfsusn_carve_mode));
}
if(sp.phase==scanner_params::PHASE_SCAN){
const sbuf_t &sbuf = sp.sbuf;
feature_recorder_set &fs = sp.fs;
feature_recorder *ntfsusn_recorder = fs.get_name(FEATURE_FILE_NAME);

size_t offset = 0;
size_t stop = sbuf.pagesize;
size_t record_size=0;
size_t total_record_size=0;

// search for USN_RECORD_V2 Structure in the sbuf
while (offset < stop) {
record_size = check_usnrecordv2_signature(offset,sbuf);
if (record_size == 0) {
offset += 8; // because of USN_RECORD stored at 8 byte boundary
continue;
}
if (record_size % 8 != 0) { // illegal size
uint8_t padding;
padding = 8 - (record_size % 8);
ntfsusn_recorder->carve_records(sbuf,offset,record_size+padding,"UsnJrnl-J_corrupted");
offset += record_size+padding;
continue;
}
total_record_size = record_size;
if (offset+total_record_size > stop) {
if(offset+total_record_size < sbuf.bufsize)
ntfsusn_recorder->carve_records(sbuf,offset,total_record_size,"UsnJrnl-J");
else
ntfsusn_recorder->carve_records(sbuf,offset,total_record_size,"UsnJrnl-J_corrupted");
break;
}
// found one record then also checks following valid records and writes all at once
while (true) {
record_size = check_usnrecordv2_or_v4_signature(offset+total_record_size,sbuf);
if (record_size % 8 != 0) // illegal size and stop process
break;
if (record_size > 0) {
if (offset+total_record_size+record_size < stop) {
total_record_size += record_size;
}
else {
total_record_size = stop-offset;
break;
}
}
else { // consider padding area around sector boundary
if ((offset+total_record_size) % SECTOR_SIZE != 0) {
size_t next_boundary_offset;
next_boundary_offset = offset + total_record_size + SECTOR_SIZE - ((offset+total_record_size) % SECTOR_SIZE);
record_size = check_usnrecordv2_or_v4_signature(next_boundary_offset,sbuf);
if (record_size > 0 && record_size % 8 == 0 && offset+total_record_size+record_size < stop ) {
total_record_size = next_boundary_offset - offset;
continue;
}
else {
break;
}
}
else {
break;
}
}
}
ntfsusn_recorder->carve_records(sbuf,offset,total_record_size,"UsnJrnl-J");
offset += total_record_size;
}
}
}

0 comments on commit da1c856

Please sign in to comment.