Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Уничтожить функцию в runtime


Автор: fridkaratel 27.1.2009, 17:07
В-общем, хочется убрать всякую возможность определить ссылку на функцию, т.е. вызов функции...
Приблизительно так - если функция не нужна, то затереть ее или частично испортить...

Также интересует вопрос, как можно из неправильной ссылки на функцию сделать правильный...
Т.е. сделать void + int, например....

Это необходимо, т.к. приложение распространяется в двух версиях - демо и полной, т.е. через директиву #define вырезать функции из полной, превратив в демо не получится - надо как-то "портить" функции в рантайме...

Автор: Alexeis 27.1.2009, 17:45
Цитата(fridkaratel @  27.1.2009,  16:07 Найти цитируемый пост)
Это необходимо, т.к. приложение распространяется в двух версиях - демо и полной, т.е. через директиву #define вырезать функции из полной, превратив в демо не получится - надо как-то "портить" функции в рантайме... 

  Вот это самое место где портить или не портить легко исправляется. ИМХО если речь идет о динамической загрузке, то лучше иметь 2е Dll зашифрованные разными ключами. В зависимости от типа ключа демо или нет распаковывать разные версии одной Dll. Не имея ключа взломщик не сможет извлечь полную Dll. Останется только вариант купить одну копию и ее распространять.

Автор: fridkaratel 29.1.2009, 15:39
Идея интересная - я к этому и склонялся... Но хотело бы без dll - поэтому и спросил про указатели и операции с ними...
Хочется как-то или перенаправить на другую функцию (прибавив к указателю, например, 0x12), или как-то заменять часть кода, перенаправляя результат в другой буфер...

Автор: Alexeis 29.1.2009, 16:36
  Есть такая функция VirtualProtect, ей можно разблокировать страницы помеченные как ReadOnly, но нужно знать исходный адрес по которому производилось выделение. Разумеется что узнать его нельзя. В инете встречается пример ручной загрузки DLL без LoadLibrary, там память выделяется руками, потому можно узнать этот адрес и разблокировать код на запись. Еще могу посоветовать поискать исходники упаковщика кода, там тоже осуществляется запись исполняемого кода. 

Автор: fridkaratel 29.1.2009, 17:23
Я использую упаковщик исполняемого кода... но одна защита - хорошо, а две - хорошо-хорошо ;)

Хочется сделать именно "увод" в сторону функционала, т.е. не сравнивать наподобие (if a == b) {} else {}, а сделать по-другому, без сравнения, именно оперируя указателями... потому как отловить, что куда - тяжелее, чем выдавать при сравнении всегда true (или false)...

Идея расшифровывать ту или иную часть хороша, но dll использовать не очень хочется...
PS: а если бы были две dll, то как бы они выглядели? хотя бы примерный код... может я просто еще не понимаю до конца всю концепцию....

Автор: Alexeis 29.1.2009, 17:40
Цитата(fridkaratel @  29.1.2009,  16:23 Найти цитируемый пост)
PS: а если бы были две dll, то как бы они выглядели? хотя бы примерный код... может я просто еще не понимаю до конца всю концепцию.... 

  Да вот как раз так бы и были 
  
  if (IsDemoKey(key)) {unpack("Demolib.dll", "lib.dll", key);} else {unpack("Prolib.dll", "lib.dll", key);}

Финт в том что если взломщик заменит условный переход if на безусловный, то это приведет к тому что Prolib.dll будет расшифрована неверным ключом, т.е. вместо Dll будет мусор.

Автор: xvr 29.1.2009, 17:57
Цитата(Alexeis @ 29.1.2009,  17:40)
Цитата(fridkaratel @  29.1.2009,  16:23 Найти цитируемый пост)
PS: а если бы были две dll, то как бы они выглядели? хотя бы примерный код... может я просто еще не понимаю до конца всю концепцию.... 

  Да вот как раз так бы и были 
  
  if (IsDemoKey(key)) {unpack("Demolib.dll", "lib.dll", key);} else {unpack("Prolib.dll", "lib.dll", key);}

Финт в том что если взломщик заменит условный переход if на безусловный, то это приведет к тому что Prolib.dll будет расшифрована неверным ключом, т.е. вместо Dll будет мусор.

Кстати, точно так же можно зашифровать процедуры в самом exe'нике. 2 штуки с разным функционалом разными ключами. Шифровать в уже откомпилированном имадже, расшифровывать предварительно сняв защиту по записи (черея VirtualProtect)

Автор: fridkaratel 29.1.2009, 18:10
Цитата(xvr @ 30.1.2009,  01:57)
Кстати, точно так же можно зашифровать процедуры в самом exe'нике. 2 штуки с разным функционалом разными ключами. Шифровать в уже откомпилированном имадже, расшифровывать предварительно сняв защиту по записи (черея VirtualProtect)

А можно поподробнее...
В качестве протектора использую Themid'у...
Там есть что-то, может быть как раз и это...

Но вот хочется реализовать часть защиты со своей стороны... ;)

Автор: Alexeis 29.1.2009, 18:14
Кстати нашел пример затирания точки входа

Код

#include <windows.h>
#include <iostream.h>

void __declspec(naked) start(void)
{

}

void func()
{
   cout << "func()\n";
}

void __declspec(naked) end(void) 
{

}

void main()
{
    void * addr = func;

    DWORD dwCodeSize = ((DWORD)&end) - ((DWORD)&start);

    DWORD OldProtect;
    VirtualProtect(addr, dwCodeSize, PAGE_READWRITE, &OldProtect);

    BYTE f = *((BYTE *)(addr));

    *((BYTE *)(addr)) = 0xFF;
    *((BYTE *)(addr)) = f;

    DWORD NewProtect;
    VirtualProtect(addr, dwCodeSize, OldProtect, &NewProtect);

    func();
}



Отсюда http://forum.sources.ru/index.php?showtopic=153591&hl=

Ток нужно отрубить оптимизацию и не запускать под дебагом.

Добавлено через 4 минуты и 39 секунд
Цитата(xvr @  29.1.2009,  16:57 Найти цитируемый пост)

Кстати, точно так же можно зашифровать процедуры в самом exe'нике. 2 штуки с разным функционалом разными ключами

  С шифровкой отдельных функций дело непросто, дело в том что в них могут использоваться статические адреса других функций относительно базового адреса или переходы по статическому адресу. Когда грузиться Dll для исправления адресов используется таблица релоков, если у нас отдельная функция, то таблицы релоков нет, потому распаковать ее в произвольное место и запустить не удастся. 

Автор: xvr 29.1.2009, 20:52
Цитата(fridkaratel @ 29.1.2009,  18:10)
Цитата(xvr @ 30.1.2009,  01:57)
Кстати, точно так же можно зашифровать процедуры в самом exe'нике. 2 штуки с разным функционалом разными ключами. Шифровать в уже откомпилированном имадже, расшифровывать предварительно сняв защиту по записи (черея VirtualProtect)

А можно поподробнее...
В качестве протектора использую Themid'у...
Там есть что-то, может быть как раз и это...

Но вот хочется реализовать часть защиты со своей стороны... ;)

Кто такой Themid не знаю, но шифровка своих функций делается довольно просто - в готовом exe'нике шифруются нужные функции (прямо в образе). Их адрес узнается из PE таблиц (например после tdump'а). Длинна берется фиксированная.
Расшифровка делается прямо в программе: 
Код

VirtualProtect(&my_function,R/W)
uncrypt(&my_function,<size>);
VirtualProtect(&my_function,R/O);


Цитата

С шифровкой отдельных функций дело непросто, дело в том что в них могут использоваться статические адреса других функций относительно базового адреса или переходы по статическому адресу. Когда грузиться Dll для исправления адресов используется таблица релоков, если у нас отдельная функция, то таблицы релоков нет, потому распаковать ее в произвольное место и запустить не удастся. 
 Не надо ничего никуда грузить, они уже там. Релоки в код не смотрят, так что ничего не испортится

Автор: Alexeis 29.1.2009, 21:55
Цитата(xvr @  29.1.2009,  19:52 Найти цитируемый пост)
Релоки в код не смотрят, так что ничего не испортится 

  Ну если например есть jmp на некоторый адрес внутри функции, если мы функцию переместим в памяти, то при выполнении этого jmp произойдет переход неизвестно куда.

Автор: xvr 30.1.2009, 11:57
Цитата(Alexeis @ 29.1.2009,  21:55)
Цитата(xvr @  29.1.2009,  19:52 Найти цитируемый пост)
Релоки в код не смотрят, так что ничего не испортится 

  Ну если например есть jmp на некоторый адрес внутри функции, если мы функцию переместим в памяти, то при выполнении этого jmp произойдет переход неизвестно куда.

Мы не будем эти функции никуда перемещать - они будут расшифровываться там же, где лежат. Т.е. функции есть в любом случае (до и после дешифровки), но до дешифровки они неработоспособны, т.к. их код зашифрован и с точки зрения процессора представляет собой практически мусор. Попытка их выполнить скорее всего приведет к падению программы. После расшифровки они содержат уже исполняемый код.

Автор: Alexeis 30.1.2009, 12:03
  Т.е. будет пост обработка после компиляции, с поиском нужного фрагмента, шифрованием и записью на тоже самое место. В принципе можно так сделать.

Автор: fridkaratel 30.1.2009, 12:52
Это все интересно, но что-то в последних постах я мало что понял... smile

Так, получается, что я пишу код, компилирую, а потом обрабатываю exe-файл?

Или компилирую, смотрю список функций, потом делаю изменения в исходном коде - и еще раз компилирую... Так?

Автор: dumb 30.1.2009, 14:16
fridkaratel, я тебе так скажу: если найдется человек, который не поленится снять Themid'у, то твои "защиты" не создадут ему вообще никаких проблем.

Автор: fridkaratel 30.1.2009, 14:27
dumb, вот я и хочу, чтобы защиты как таковой не было видно... ну увидят они протектор, снимут его.... а дальше им нужен файл лицензии, которого у них нет... во-от... сравнивать if (LicenceExists()) {} else {} я понятное дело не хочу...
хочу как-то незаметно, "неуловимо" просто подставлять другие адреса для вычислений...

например, имеется два буфера - buff1[*] и buff2[*]...
в файле лицензи записан buff2, соотвт. если файла лицензии нет, то запись будет идти в buff1, а при сохранении buff2 окажется пустым

а значит ничего не сохранится, что обеспечивает как бы защиту - функционала то нету smile

Автор: xvr 30.1.2009, 15:29
Цитата(fridkaratel @ 30.1.2009,  12:52)
Это все интересно, но что-то в последних постах я мало что понял... smile

Так, получается, что я пишу код, компилирую, а потом обрабатываю exe-файл?

Да

Цитата

Или компилирую, смотрю список функций, потом делаю изменения в исходном коде - и еще раз компилирую... Так?
Нет

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)