Вывод информации без проверки значения в скомпилированном приложении С++

Тема в разделе "WASM.BEGINNERS", создана пользователем galenkane, 3 мар 2021.

  1. galenkane

    galenkane Active Member

    Публикаций:
    0
    Регистрация:
    13 янв 2017
    Сообщения:
    269
    Не знаю как по другому назвать тему.

    Суть вопроса вот в чем, смотрите:

    должна быть функция, сверяющая данные (текстовые), например qq == qq и возвращающая значение true или false.

    псевдокод для проверки :

    Код (Text):
    1. if(checkFunc ('qq') == 'qq')
    2.   good
    3. else
    4.   bad
    5.  
    Финальный результат желательно получить просто выводом значения Good или Bad после проверки.
    То есть, чтобы функции и не существовало в бинарнике в открытом виде.

    Что подскажете?
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    Чего? Я ничего не понял. Если хочешь, чтобы строки "qq" не было в бинарнике, то бери хещ от строки и сравнивай с ее предопределенным хеш-значением, которое ты вычислишь на этапе компиляции от строки "qq", или просто зашьешь константой, а не со строкой.
    --- Сообщение объединено, 3 мар 2021 ---
    Хеширование строк на этапе компиляции, например, описывалось в моей статье: https://wasm.in/blogs/meta-programmirovanie-s-i-obfuskacija.703/
     
  3. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    988
    Rel, он похоже про другое, как в рантайме собрать из ниоткуда его псевдокод.
    galenkane, напиши код, собери, посмотри в дебагаре опкоды. подумай каким путем из перетасовки мусора ты придешь в эти опкоды, и подумай как ты бросишь указатель на свои опкоды. страница, на которой код, должна быть с правами rwx.
     
  4. galenkane

    galenkane Active Member

    Публикаций:
    0
    Регистрация:
    13 янв 2017
    Сообщения:
    269
    Суть вопроса о том, чтобы не было такой функции после компиляции. То есть значение было if(true) Good к примеру
     
  5. Aiks

    Aiks Member

    Публикаций:
    0
    Регистрация:
    16 апр 2017
    Сообщения:
    109
    Адрес:
    Украина
    Если у тебя на этапе компиляции есть все строки которые нужно сравнить, то зачем писать код который их сравнивает? Сразу пиши "good" или "bad". Или постарайся объяснить задачу более подробно.
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    Мне не понятна ситуация, когда тебе нужно сравнивать две строки на этапе компиляции?
     
  7. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.955
    Нет времени объяснять, просто переходи на фасм. Парадигма, в которой существуют цэшники, не подразумевает того, чтобы код программы генерировался сам исходя из вводных.
     
    M0rg0t нравится это.
  8. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    861
    Ничего не понятно:
    Код (C):
    1.  
    2. #define checkFunc(x) x
    3. if(checkFunc ('qq') == 'qq')
     
  9. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    Это не будет работать на этапе компиляции, надо писать constexpr функцию, которая будет по символу сравнивать. Но надо понять, что это и зачем, тк очень большая вероятность, что ТС пытается чесать левое ухо правой ногой при том, что обе руки у него свободны.
     
    galenkane и Aiks нравится это.
  10. galenkane

    galenkane Active Member

    Публикаций:
    0
    Регистрация:
    13 янв 2017
    Сообщения:
    269
    Для проверки лицензирования программы, чтобы реверсер не ссылался на функцию, где обрабатываются алгоритмы.
    --- Сообщение объединено, 3 мар 2021 ---
    Вот пример.

    Код (C++):
    1. #include <iostream>
    2. #include <string>
    3.  
    4. using namespace std;
    5. int* is_registered = new int;
    6.  
    7. static unsigned int pjw_hash(std::string value)
    8. {
    9.     const auto bits_in_unsigned_int = static_cast<unsigned int>(sizeof(unsigned int) * 8);
    10.     const auto three_quarters = static_cast<unsigned int>(bits_in_unsigned_int * 3 / 4);
    11.     const auto one_eighth = static_cast<unsigned int>(bits_in_unsigned_int / 8);
    12.     const auto high_bits = static_cast<unsigned int>(0xFFFFFFFF) << static_cast<int>(bits_in_unsigned_int - one_eighth);
    13.     unsigned int hash = 0;
    14.     unsigned int test = 0;
    15.     const unsigned int len = value.length();
    16.  
    17.     for (unsigned int i = 0; i < len; i++)
    18.     {
    19.         hash = (hash << static_cast<int>(one_eighth)) + value[i];
    20.  
    21.         if ((test = hash & high_bits) != 0)
    22.         {
    23.             hash = (hash ^ test >> static_cast<int>(three_quarters)) & ~high_bits;
    24.         }
    25.     }
    26.  
    27.     return hash;
    28. }
    29.  
    30.  
    31. void check_registration(const string& reg_number, int* b)
    32. {
    33.     if (pjw_hash(reg_number) == 1921)
    34.     {
    35.         *b = 1;
    36.     }
    37. }
    38.  
    39. int main()
    40. {
    41.     // valid reg_number "qq"
    42.     std::string reg_number;
    43.     cout << "regcode: \r\n";
    44.     cin >> reg_number;
    45.  
    46.     *is_registered = 0;
    47.     check_registration(reg_number, is_registered);
    48.     try
    49.     {
    50.         if (*is_registered)
    51.         {
    52.             cout << "registered\r\n";
    53.         }
    54.         else
    55.         {
    56.             cout << "unregistered\r\n";
    57.         }
    58.     }
    59.     catch (...)
    60.     {
    61.     }
    62.  
    63.     delete is_registered;
    64.     system("pause");
    65. }
     
  11. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    Нууу. Так и что с чем ты там будешь проверять? Регистрационный код же проверяется на этапе исполнения, а не на этапе компиляции, ты не можешь убрать хеширующую функцию из исполняемого файла. Хешируй строку с лицензионным кодом каким-то крипто-стойким алгоритмом на этапе компиляции, вшивай этот хеш в исходный код, в рантайме проверяй этим же алгоритмом хеширования, что хеши совпали. Как собственно я тебе говорил делать в первом ответе.
    --- Сообщение объединено, 3 мар 2021 ---
    Но если у тебя там все равно будет простой джамп для определения того, является ли пользователь легитимным или нет, то такую защиту можно легко сломать, пропатчив джамп.
     
    Последнее редактирование модератором: 3 мар 2021
  12. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    Выделяй RWX память, и там формируй код в виде шеллкода, передавай туда управление; после проверки память освободится и функция "не будет существовать". Но все это полумеры, захотят взломать - взломают, просто чуть больше усилий придется потратить.
     
  13. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.250
    Вообще говоря, лучше не просто освободить, а перед освобождением залить весь буффер нулями или рандомными байтами, тк нет гарантий, когда система выделит эту память после освобождения второй раз, чтобы исходные байты переписались.
     
    M0rg0t нравится это.
  14. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.955
    А на кой черт реверсёру с этим возиться? Он найдет формальный признак зарегистрированности программы и выяснит откуда он берется. Я бы вот даже в сам алгоритм хеширования разбираться не полез, нафиг это не надо. И вообще не понятно тогда что и с чем ты хочешь на этапе компиляции сравнивать.
     
    youneuoy нравится это.
  15. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.087
    фигнёй страдаешь :) для защиты от кряка/реверса в прогу прописывают счётчики в каждом потоке а-ля х++; а затем сравнивают дельты между ними == под виртой/дебагом дельты хорошо искажаются. Второй момент пролегает в видах защиты == есть явная защита, когда юзверу выкидывается мессага, мол-де лицухи нет, окончен срок лицухи, обнаружена нелегальная рега. Есть неявная, когда никаких жалоб юзверу прога не выкидывает == она просто тихо обнаруживает нарушение лицухи, сообщает на сервач при наличие доступа к инету и обрушивается (можно даже в рандомном режиме).
     
  16. Aiks

    Aiks Member

    Публикаций:
    0
    Регистрация:
    16 апр 2017
    Сообщения:
    109
    Адрес:
    Украина
    Например, один поток выполняет больше работы. Соответственно инкремент его переменной будет происходит реже. Да и вообще объем выполняемоей работы потоком может быть динамическим или в определенное время ОС может дать одному потоку меньше времени выполнения. Что тебе даст сравнение "рандомных" значений этих переменных? Или я что-то не понимаю?
     
  17. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.087
    дабы не повторяться..
    https://wasm.in/threads/kuplju-kod-detekta-vm-mashin-bez-crt.33647/#post-416966
    https://wasm.in/threads/kuplju-kod-detekta-vm-mashin-bez-crt.33647/page-2#post-416973
    https://wasm.in/threads/kuplju-kod-detekta-vm-mashin-bez-crt.33647/page-2#post-416976
    про рандомные, я имел ввиду "генерить рандомные ошибки в проге".
     
  18. Aiks

    Aiks Member

    Публикаций:
    0
    Регистрация:
    16 апр 2017
    Сообщения:
    109
    Адрес:
    Украина
    Прочитал. Значит в коде функций выполняемых этими двумя потоками не должно быть ничего лишнего. ОК.

    Я запустил тест от Indy без отладчика 2 раза:
    Код (Text):
    1. 1C86767E
    2. 1267D575
    3.  
    4. 18F1E206
    5. 1234254B
    Так же результаты при запуске под отладчиком:

    Код (Text):
    1. 192C166D
    2. 1166BAFF
    3.  
    4. 19EE7F9C
    5. 127335C1
    Если при запуске под виртуалкой отличия есть, то при отладке нет. Как ты собрался по таким результатам задетектить отладку? :)

    Про рандомное падение приложения я понял. Я имел в виду "рандомные" значения переменных которые ты инкрементишь в двух потоках.
     
    Последнее редактирование: 4 мар 2021
  19. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.087
    а зачем тебе детектить пассивный отладчик? :grin: бряк ставь на треды и вот тута пойдут проблемы :)
    нет, счётчики все с нуля бегают иль с некой -const == короче, что больше нравится.
    --- Сообщение объединено, 4 мар 2021 ---
    на самом деле счётчик может быть весьма витиеватым == я просто указал наиболее простой вариант, дабы юмор с виртами ощущался наиболее ГРОТЕСКНЫМ:crazy::laugh1::laugh2::laugh3::blush2:
     
  20. Aiks

    Aiks Member

    Публикаций:
    0
    Регистрация:
    16 апр 2017
    Сообщения:
    109
    Адрес:
    Украина
    Ты же видишь, что даже без вирты и отладчика разброс между значениями разных потоков ~35%. И это я запускал тест только несколько раз. Как с таким разбросом можно строить детект? Получится генератор ложных срабатываний. На счет брекпоинтов. Если ставить их в коде главного потока(не в коде двух инкрементирующих потоков), то значения получаются меньше, но так же с дельтой в ~35%. Или ты предлагаешь запихнуть вычисление хеша строки в код цикла этих двух потоков и там ставить брекпоинт? Если так, то разница между значениями получится большой. Но это смахивает на какой-то трэш. Ибо значения еще больше будут отличатся )))