forked from Cisco-Talos/TeslaDecrypt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Log.cpp
424 lines (366 loc) · 12 KB
/
Log.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
/*
* Copyright (C) 2016 Cisco Talos Security Intelligence and Research Group
*
* Authors: Andrea Allievi
*
* This program is free software; you can redistribute it and/or modify
* it 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* Filename: Log.cpp
* Log engine implementation file
* Last revision: 05/30/2016
*
*/
#include "stdafx.h"
#include "log.h"
//#include <crtdbg.h>
#pragma comment (lib, "version.lib")
CLog staticLog;
// Static function to write data to an uninitialized log
// Default behaviour: if Application Communication instance is not NULL, use that, else use Dbg Output
void WriteToLog(LPTSTR dbgStr, LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4) {
//CLog log;
staticLog.WriteLine(dbgStr, arg1, arg2, arg3, arg4);
}
// Default Class Constructor
CLog::CLog():
g_hLogFile(NULL),
g_strLogTitle(NULL),
g_bIsAutoDeleteLog(true),
g_bAtLeastOneWrite(false),
g_bImCopy(false),
g_strLogFile(NULL)
{
g_strLogFile = new TCHAR[MAX_PATH];
RtlZeroMemory(g_strLogFile, MAX_PATH * sizeof(TCHAR));
}
// Specialized Class Constructor
CLog::CLog(LPTSTR logFile, LPTSTR logTitle) {
g_bIsAutoDeleteLog = true;
g_bAtLeastOneWrite = false;
g_bImCopy = false;
g_hLogFile = NULL;
g_strLogFile = new TCHAR[MAX_PATH];
g_strLogTitle = NULL;
RtlZeroMemory(g_strLogFile, MAX_PATH * sizeof(TCHAR));
if (logTitle) this->SetLogTitle(logTitle);
if (!this->Open(logFile))
DbgBreak();
}
// Copy constructor
CLog::CLog(CLog &log) {
g_bAtLeastOneWrite = log.g_bAtLeastOneWrite;
g_bIsAutoDeleteLog = log.g_bIsAutoDeleteLog;
g_hLogFile = log.g_hLogFile;
if (log.g_hLogFile) {
HANDLE hProc = GetCurrentProcess();
DuplicateHandle(hProc, log.g_hLogFile, hProc, &g_hLogFile, 0, FALSE, DUPLICATE_SAME_ACCESS);
}
if (log.g_strLogFile) {
g_strLogFile = new TCHAR[MAX_PATH];
RtlCopyMemory(g_strLogFile, log.g_strLogFile, MAX_PATH * sizeof(TCHAR));
}
if (log.g_strLogTitle) {
int titleLen = (int)wcslen(log.g_strLogTitle);
g_strLogTitle = new TCHAR[titleLen+1];
RtlZeroMemory(g_strLogTitle, (titleLen+1) * sizeof(TCHAR));
RtlCopyMemory(g_strLogTitle, log.g_strLogTitle, (titleLen+1) * sizeof(TCHAR));
}
g_bImCopy = true;
log.g_bAtLeastOneWrite = true;
}
// Destructor
CLog::~CLog() {
this->Close();
if (g_strLogTitle) delete[] g_strLogTitle;
if (g_strLogFile) delete[] g_strLogFile;
}
// Set log Title
void CLog::SetLogTitle(LPTSTR strTitle) {
if (!strTitle) return;
int titleLen = (int)wcslen(strTitle);
if (this->g_strLogTitle) {
delete g_strLogTitle;
g_strLogTitle = NULL;
}
g_strLogTitle = new TCHAR[titleLen+1];
wcscpy_s(g_strLogTitle, titleLen+1, strTitle);
}
// Create or open a log file
bool CLog::Open(LPTSTR fileName, bool overwrite) {
BOOL retVal = FALSE;
HANDLE hFile = NULL;
SYSTEMTIME time = {0};
CHAR logStr[255] = {0};
DWORD bytesToWrite = 0;
DWORD bytesWritten = 0;
DWORD lastErr = 0;
if (this->g_hLogFile != NULL) {
// Log File already opened, close it
if (wcscmp(fileName, this->g_strLogFile) != 0) this->Close();
else
// File already opened
return true;
}
hFile = CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, (overwrite ? CREATE_ALWAYS : OPEN_ALWAYS),
FILE_ATTRIBUTE_NORMAL, NULL);
lastErr = GetLastError();
if (hFile == INVALID_HANDLE_VALUE)
return false;
if (lastErr == ERROR_ALREADY_EXISTS && overwrite == false) {
retVal = SetFilePointer(hFile, 0, 0, FILE_END);
if (retVal > 0)
// Don't autodelete log that already contains data
g_bIsAutoDeleteLog = false;
}
// Mi memorizzo il nome del file
if (!g_strLogFile)
g_strLogFile = new TCHAR[MAX_PATH];
wcscpy_s(g_strLogFile, MAX_PATH, fileName);
GetLocalTime(&time);
LPTSTR logTitle = this->g_strLogTitle;
if (!logTitle) {
// 20/02/2012 If there isn't a log title use CVersionInfo
#ifdef LOGTITLE
logTitle = LOGTITLE;
#else
LPTSTR prodName = NULL, companyName = NULL, verStr = NULL;
logTitle = new TCHAR[0x100];
CVersionInfo fileInfo;
prodName = fileInfo.GetProductName();
companyName = fileInfo.GetCompanyName();
verStr = fileInfo.GetFileVersionString();
wsprintf(logTitle, L"%s %s %s Log File", companyName, prodName, verStr);
this->g_strLogTitle = logTitle;
#endif
}
bytesToWrite = sprintf_s(logStr, 255, "%S\r\nExecution time: %02i/%02i/%02i - %02i:%02i\r\n", logTitle,
time.wDay, time.wMonth, time.wYear, time.wHour, time.wMinute) + 1;
retVal = WriteFile(hFile, logStr, bytesToWrite - 1, &bytesWritten, NULL);
this->g_bAtLeastOneWrite = false;
if (retVal) {
this->g_hLogFile = hFile;
return true;
} else {
RtlZeroMemory(g_strLogFile, MAX_PATH * sizeof(TCHAR));
return false;
}
}
// Close this log file
void CLog::Close(bool WriteEnd) {
if (!this->g_hLogFile || g_hLogFile == INVALID_HANDLE_VALUE)
return;
bool deleteMe = false;
if (!g_bAtLeastOneWrite && g_bIsAutoDeleteLog && !g_bImCopy)
// Auto delete this log if there aren't any write
deleteMe = true;
if (WriteEnd && !g_bImCopy) WriteLine(L"Execution Ended!\r\n\r\n");
CloseHandle(g_hLogFile); g_hLogFile = NULL;
if (deleteMe) DeleteFile(g_strLogFile);
if (g_strLogFile)
RtlZeroMemory(g_strLogFile, MAX_PATH * sizeof(TCHAR));
}
// Write a log line (NO parameters)
void CLog::WriteLine(LPTSTR dbgStr) {
if (g_hLogFile) WriteCurTime();
Write(dbgStr);
Write(L"\r\n");
}
// Write a log line (4 parameters max)
void CLog::WriteLine(LPTSTR dbgStr, LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4) {
if (g_hLogFile) WriteCurTime();
Write(dbgStr, arg1, arg2, arg3, arg4);
Write(L"\r\n");
}
// Write current time to log
void CLog::WriteCurTime() {
TCHAR timeStr[20] = {0};
SYSTEMTIME curTime = {0};
GetLocalTime(&curTime);
swprintf_s(timeStr, 20, L"%02i:%02i:%02i - ", curTime.wHour, curTime.wMinute, curTime.wSecond);
Write(timeStr);
}
// Write a Unicode log string (NO parameters)
void CLog::Write(LPWSTR dbgStr) {
DWORD bytesToWrite = 0;
DWORD bytesWritten = 0;
CHAR * logStr = NULL; // String to write in file
if (!g_hLogFile || g_hLogFile == INVALID_HANDLE_VALUE) { // If I don't have opened a log file
OutputDebugString(dbgStr); // write to debug output
} else {
bytesToWrite = (DWORD)wcslen(dbgStr) + 1;
logStr = new CHAR[bytesToWrite];
sprintf_s(logStr, bytesToWrite, "%S", dbgStr);
WriteFile(g_hLogFile, logStr, bytesToWrite - 1, &bytesWritten, NULL); //BOOL retVal =
delete[] logStr;
}
g_bAtLeastOneWrite = true;
}
// Write a log string (4 parameters max)
void CLog::Write(LPTSTR dbgStr, LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4) {
LPTSTR resStr = NULL; // Formatted string
// Format unicode original string
resStr = new TCHAR[2048];
swprintf_s(resStr, 2048, dbgStr, arg1, arg2, arg3, arg4);
Write(resStr);
if (resStr != dbgStr) delete[] resStr;
}
// Write an ANSI log string (NO parameters)
void CLog::Write(LPSTR dbgStr) {
DWORD bytesToWrite = 0;
DWORD bytesWritten = 0;
if (!this->g_hLogFile || g_hLogFile == INVALID_HANDLE_VALUE) { // If I don't have opened a log file
OutputDebugStringA(dbgStr); // write to debug output
} else {
bytesToWrite = (DWORD)strlen(dbgStr);
WriteFile(g_hLogFile, dbgStr, bytesToWrite, &bytesWritten, NULL);
}
g_bAtLeastOneWrite = true;
}
// Write an ANSI log string (4 parameters max)
void CLog::Write(LPSTR dbgStr, LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4) {
LPSTR resStr = NULL; // Formatted string
// Format ansi original string
resStr = new CHAR[2048];
sprintf_s(resStr, 2048, dbgStr, arg1, arg2, arg3, arg4);
Write(resStr);
delete[] resStr;
}
// Flush file to perform actual disk write
void CLog::Flush() {
if (!this->g_hLogFile) return;
FlushFileBuffers(g_hLogFile);
}
#pragma region Version Information Class functions
// Default constructor
CVersionInfo::CVersionInfo():
g_bVerInfoBuff(NULL),
iLangTableLen(0),
pLangTable(NULL),
g_LangStr(NULL),
g_fVerStr(NULL)
{
GetModuleVersionInfo();
}
// Constructor that accept a module name
CVersionInfo::CVersionInfo(LPTSTR modName) {
g_LangStr = NULL;
g_fVerStr = NULL;
GetModuleVersionInfo(modName);
}
// Constructor that accept a module handle
CVersionInfo::CVersionInfo(HMODULE hModule) {
g_LangStr = NULL;
g_fVerStr = NULL;
GetModuleVersionInfo(hModule);
}
// Destructor
CVersionInfo::~CVersionInfo() {
if (g_bVerInfoBuff) delete[] g_bVerInfoBuff;
g_bVerInfoBuff = NULL;
if (g_LangStr) delete[] g_LangStr;
if (g_fVerStr) delete[] g_fVerStr;
}
// Get fixed Version Information
VS_FIXEDFILEINFO CVersionInfo::GetFixedVersion() {
VS_FIXEDFILEINFO * pVerInfo = NULL;
UINT verSize = 0;
BOOL retVal = FALSE;
if (!g_bVerInfoBuff) return VS_FIXEDFILEINFO();
retVal = VerQueryValue((LPCVOID)g_bVerInfoBuff, L"\\", (LPVOID*)&pVerInfo, (PUINT)&verSize);
if (retVal) return *pVerInfo;
else return VS_FIXEDFILEINFO();
}
LPTSTR CVersionInfo::GetFileVersionString() {
VS_FIXEDFILEINFO fixedVer = {0};
if (!g_bVerInfoBuff) return NULL;
fixedVer = GetFixedVersion();
if (!g_fVerStr) g_fVerStr = new TCHAR[0x30];
wsprintf(g_fVerStr, L"%i.%i",
(WORD)(fixedVer.dwFileVersionMS >> 16),
(WORD)(fixedVer.dwFileVersionMS));
return g_fVerStr;
}
// Helper function that Get a Language Code Page Version Value
LPTSTR CVersionInfo::VerQueryLangCpValue(LPTSTR value) {
if (!g_bVerInfoBuff || !g_LangStr) return NULL;
LPTSTR verValue = NULL;
LPTSTR verLangStr = new TCHAR[0x40];
UINT dwChars = 0;
BOOL retVal = FALSE;
wcscpy_s(verLangStr, 0x40, g_LangStr);
wcscat_s(verLangStr, 0x40, value);
// Retrieve file description for language and code page "i".
retVal = VerQueryValue((LPCVOID)g_bVerInfoBuff, verLangStr, (LPVOID*)&verValue, &dwChars);
delete[] verLangStr;
if (retVal)
return verValue;
else
return NULL;
}
LPTSTR CVersionInfo::GetProductName() {
return VerQueryLangCpValue(L"ProductName");
}
LPTSTR CVersionInfo::GetCompanyName() {
return VerQueryLangCpValue(L"CompanyName");
}
// Helper function that receive versione information of a specific module (NULL = this executable)
bool CVersionInfo::GetModuleVersionInfo(HMODULE hMod) {
LPTSTR modFileName = NULL; // Filename of module used to retrieve version information
BOOL retVal = FALSE;
modFileName = new TCHAR[MAX_PATH];
retVal = GetModuleFileName(hMod, modFileName, MAX_PATH);
if (!retVal) {
delete modFileName;
::WriteToLog(L"CLog::GetModuleVersion - Error while getting module filename...");
return false;
}
retVal = GetModuleVersionInfo(modFileName);
delete modFileName;
return (retVal == TRUE);
}
bool CVersionInfo::GetModuleVersionInfo(LPTSTR modName = NULL) {
DWORD dummy = 0; // Dummy DWORD variable for GetFileVersionInfoSize
DWORD verSize = 0; // Version info size
LPBYTE buff = NULL; // Buffer
BOOL retVal = FALSE;
LPTSTR langStr = NULL; // Lang and code page Version string
if (!modName) return false;
verSize = GetFileVersionInfoSize(modName, &dummy);
if (!verSize)
return false;
buff = new BYTE[verSize];
retVal = GetFileVersionInfo(modName, dummy, verSize, (LPVOID)buff);
if (retVal) {
iLangTableLen = 0;
pLangTable = NULL;
if (g_LangStr) {delete g_LangStr; g_LangStr = NULL; }
// Read the list of languages and code pages.
retVal = VerQueryValue(buff, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&pLangTable, &iLangTableLen);
langStr = new TCHAR[0x40];
// Read the file description for each language and code page.
for(int i = 0; i < (int)(iLangTableLen / sizeof(struct LANGANDCODEPAGE)); i++)
wsprintf(langStr, TEXT("\\StringFileInfo\\%04x%04x\\"), pLangTable[i].wLanguage, pLangTable[i].wCodePage);
g_LangStr = langStr;
}
if (retVal)
this->g_bVerInfoBuff = buff;
else
if (buff) delete buff;
return (retVal == TRUE);
}
#pragma endregion
// ....
// One Log to rule them all!
// ....