Вычислить CRC кода
От: zheka2  
Дата: 21.04.11 12:39
Оценка: :))) :)
Мне нужно защитить часть кода от изменения, этот код расположен в функции-члене. Как мне получить адрес памяти в которой расположен этот код чтобы рассчитать его контрольную сумму? Примеры из интернета предоставляют указатель на функцию-член, но он в дальнейшем используется для вызова этого метода, да и к void* его не приведёшь, он занимает больше байт.
Re: Вычислить CRC кода
От: Igore Россия  
Дата: 21.04.11 13:44
Оценка:
Здравствуйте, zheka2, Вы писали:

Z>Мне нужно защитить часть кода от изменения, этот код расположен в функции-члене. Как мне получить адрес памяти в которой расположен этот код чтобы рассчитать его контрольную сумму? Примеры из интернета предоставляют указатель на функцию-член, но он в дальнейшем используется для вызова этого метода, да и к void* его не приведёшь, он занимает больше байт.


Если твой код изменят, то изменить проверку CRC с jz на jnz так же легко. Озаботился защитой программы, почитай форум Shareware и бизнес, там про это много говорится.
Re: Вычислить CRC кода
От: baily Россия  
Дата: 21.04.11 13:55
Оценка: +2
Здравствуйте, zheka2, Вы писали:

Z>Мне нужно защитить часть кода от изменения, этот код расположен в функции-члене. Как мне получить адрес памяти в которой расположен этот код чтобы рассчитать его контрольную сумму? Примеры из интернета предоставляют указатель на функцию-член, но он в дальнейшем используется для вызова этого метода, да и к void* его не приведёшь, он занимает больше байт.


CRC предназначен для защиты от случайных изменений — помехоустойчивый код. Нельзя с помощью него защищать от злонамеренного изменения. Ненадежно.
Re[2]: Вычислить CRC кода
От: zheka2  
Дата: 21.04.11 17:35
Оценка:
Здравствуйте, baily, Вы писали:

B>Здравствуйте, zheka2, Вы писали:


Z>>Мне нужно защитить часть кода от изменения, этот код расположен в функции-члене. Как мне получить адрес памяти в которой расположен этот код чтобы рассчитать его контрольную сумму? Примеры из интернета предоставляют указатель на функцию-член, но он в дальнейшем используется для вызова этого метода, да и к void* его не приведёшь, он занимает больше байт.


B>CRC предназначен для защиты от случайных изменений — помехоустойчивый код. Нельзя с помощью него защищать от злонамеренного изменения. Ненадежно.


Спасибо за совет, ну пусть не CRC, алгоритм можно подобрать и потом, сейчас я указатель не могу получить.
Re[2]: Вычислить CRC кода
От: zheka2  
Дата: 21.04.11 17:36
Оценка:
Здравствуйте, Igore, Вы писали:

I>Здравствуйте, zheka2, Вы писали:


Z>>Мне нужно защитить часть кода от изменения, этот код расположен в функции-члене. Как мне получить адрес памяти в которой расположен этот код чтобы рассчитать его контрольную сумму? Примеры из интернета предоставляют указатель на функцию-член, но он в дальнейшем используется для вызова этого метода, да и к void* его не приведёшь, он занимает больше байт.


I>Если твой код изменят, то изменить проверку CRC с jz на jnz так же легко. Озаботился защитой программы, почитай форум Shareware и бизнес, там про это много говорится.


Всё же лучше чем ничего, я планирую разместить проверку в совсем другой части программы и замаскировать. От дурака поможет.. В любом случае, как получить указатель?
За ссылку спасибо, посмотрю
Re: Вычислить CRC кода
От: Abyx Россия  
Дата: 21.04.11 19:01
Оценка:
Здравствуйте, zheka2, Вы писали:

купите прот. не с вашими знаниями браться за защиту.
In Zen We Trust
Re: Вычислить CRC кода
От: rg45 СССР  
Дата: 21.04.11 19:05
Оценка: 48 (5)
Здравствуйте, zheka2, Вы писали:

Z>Мне нужно защитить часть кода от изменения, этот код расположен в функции-члене. Как мне получить адрес памяти в которой расположен этот код чтобы рассчитать его контрольную сумму? Примеры из интернета предоставляют указатель на функцию-член, но он в дальнейшем используется для вызова этого метода, да и к void* его не приведёшь, он занимает больше байт.


Сейчас я тебе покажу одно черное шаманство, которое сам когда-то использовал по молодости. Ты только никому не говори, что это я тебе посоветовал.

Допустим, функция, дамп тела которой ты хочешь получить, выглядит так:

void foo(const char* text)
{
  std::cout << text << std::endl;
}


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

typedef unsigned char byte;

void foo(const char* text, const byte** begin = 0, const byte** end = 0)
{
_begin:
    if(begin && end)
    {
        __asm
        {
            mov eax, dword ptr [begin]  
            lea edx, _begin
            mov dword ptr [eax], edx          
            mov eax, dword ptr [end]  
            lea edx, _end
            mov dword ptr [eax], edx          
        }
        return;
    }
    std::cout << text << std::endl;

_end:
    ;
}


Эти два новых параметра мы снабжаем нулевыми значениями по умолчанию. Теперь эту функцию можно вызывать в двух режимах: если последние два параметра не указаны, то функция выполняет свою штатную работу как и раньше:

foo("Hello, World!!!");


Если же последние два параметра заданы, то функция вместо своей штатной работы возвращает через них начало и конец своего тела:

const byte* begin;
const byte* end;
foo(0, &begin, &end);


Вот полный текст работающего примера:
  Скрытый текст
#include <iostream>

typedef unsigned char byte;

void foo(const char* text, const byte** begin = 0, const byte** end = 0)
{
_begin:
    if(begin && end)
    {
        __asm
        {
            mov eax, dword ptr [begin]  
            lea edx, _begin
            mov dword ptr [eax], edx          
            mov eax, dword ptr [end]  
            lea edx, _end
            mov dword ptr [eax], edx          
        }
        return;
    }
    std::cout << text << std::endl;

_end:
    ;
}

int main()
{
    foo("hello");

    const byte* begin;
    const byte* end;
    foo(0, &begin, &end);

    std::cout << "begin = 0x" << (void*)begin << std::endl;
    std::cout << "end = 0x" << (void*)end << std::endl;

    for(const byte* p = begin; p != end; ++p)
        std::cout << " 0x" << std::hex << (int)*p;

    std::cout << std::endl;
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Вычислить CRC кода
От: andrey_nado  
Дата: 21.04.11 20:16
Оценка: +1
Здравствуйте, rg45, Вы писали:

Никто не может гарантировать, что полезный код функции будет располагаться между метками _begin и _end.
Сама функция может оказаться встроенной (inline), если компилятор так решит.
И нужно уточнить у автора, сможет ли он обойтись без кроссплатформенности.
Re: Вычислить CRC кода
От: nen777w  
Дата: 21.04.11 21:47
Оценка:
Здравствуйте, zheka2, Вы писали:

Z>Мне нужно защитить часть кода от изменения, этот код расположен в функции-члене. Как мне получить адрес памяти в которой расположен этот код чтобы рассчитать его контрольную сумму? Примеры из интернета предоставляют указатель на функцию-член, но он в дальнейшем используется для вызова этого метода, да и к void* его не приведёшь, он занимает больше байт.


Вот так я это делаю у себя:

#ifdef  PLATFORM_32
    typedef     agg::int32u    hack_label;
#elif   PLATFORM_64
    typedef     agg::int64u      hack_label;
#endif
}

#ifdef WIN
    #define set_label_address( to, lbl )    __asm { mov dword ptr to, offset lbl }
#else
    #define set_label_address( to, lbl )    to = reinterpret_cast<hack_label>(&&lbl)
#endif

#define define_label( name ) \
    name: ;

#define define_label_begin( name ) \
    name##_BEGIN: ;

#define define_label_end( name ) \
    name##_END: ;

#define label_begin( name ) name##_BEGIN
#define label_end( name ) name##_END

#define define_var_label_begin( name ) \
    code_hacks::hack_label var_##name; \
    set_label_address( var_##name, name ); \
    name:

#define define_var_label_end( name ) \
    name: \
    code_hacks::hack_label var_##name; \
    set_label_address( var_##name, name );


Использование:


void foo()
{
    hack_label lb, le, len;
    set_label_address( lb, label_begin(protect_code) );
    set_label_address( le, label_end(protect_code) );
    
    //длинна
    le -= lb;
    //делаешь чо тебе там надо

define_label_begin( protect_code )
  //protected code
  int kkk = 0;
  kkk += 1;
define_label_end( protect_code )

}


Во общем разберешься. Это работает как для Win так и для Mac в том числе ppc.
Dump или что там тебе надо делаешь до меток.
Проблема в другом, всякое изменение кода, даже не в этом модуле трансляции повлечет изменения сгенерированого кода между между метками
, в частности особенно если в коде используются инструкции перехода или сравнения.
Как это победить уже думай сам.
Re: Вычислить CRC кода
От: Erop Россия  
Дата: 22.04.11 02:17
Оценка:
Здравствуйте, zheka2, Вы писали:

Z>Мне нужно защитить часть кода от изменения, этот код расположен в функции-члене. Как мне получить адрес памяти в которой расположен этот код чтобы рассчитать его контрольную сумму? Примеры из интернета предоставляют указатель на функцию-член, но он в дальнейшем используется для вызова этого метода, да и к void* его не приведёшь, он занимает больше байт.


Проблемы-то нет.
1) Выносишь метод в отдельный cpp
2) Транслируешь его до asm'а
3) asm обрабатываешь зашифровщиком и добавляешь туда две метки на начало и на конец кода + добавляешь, например, две функции, одна возвращает начало. а другая длину...

Только не понятно как ты будешь это всё грузить. Так как загрузчик при загрузке настраивает адреса...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Вычислить CRC кода
От: zheka2  
Дата: 22.04.11 03:50
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, zheka2, Вы писали:


Z>>Мне нужно защитить часть кода от изменения, этот код расположен в функции-члене. Как мне получить адрес памяти в которой расположен этот код чтобы рассчитать его контрольную сумму? Примеры из интернета предоставляют указатель на функцию-член, но он в дальнейшем используется для вызова этого метода, да и к void* его не приведёшь, он занимает больше байт.


R>Сейчас я тебе покажу одно черное шаманство, которое сам когда-то использовал по молодости. Ты только никому не говори, что это я тебе посоветовал.


R>Допустим, функция, дамп тела которой ты хочешь получить, выглядит так:


R>
R>void foo(const char* text)
R>{
R>  std::cout << text << std::endl;
R>}
R>


R>Теперь, чтоб осуществить задуманное, нам надо добавить к списку параметров этой функции пару указателей (на указатели), которые будут принимать адреса начала и конца тела функции. Ну и добавить в саму функцию код, заполняющий эти указатели нужными значениями:


R>
R>typedef unsigned char byte;

R>void foo(const char* text, const byte** begin = 0, const byte** end = 0)
R>{
R>_begin:
R>    if(begin && end)
R>    {
R>        __asm
R>        {
R>            mov eax, dword ptr [begin]  
R>            lea edx, _begin
R>            mov dword ptr [eax], edx          
R>            mov eax, dword ptr [end]  
R>            lea edx, _end
R>            mov dword ptr [eax], edx          
R>        }
R>        return;
R>    }
R>    std::cout << text << std::endl;

R>_end:
R>    ;
R>}
R>


R>Эти два новых параметра мы снабжаем нулевыми значениями по умолчанию. Теперь эту функцию можно вызывать в двух режимах: если последние два параметра не указаны, то функция выполняет свою штатную работу как и раньше:


R>
R>foo("Hello, World!!!");
R>


R>Если же последние два параметра заданы, то функция вместо своей штатной работы возвращает через них начало и конец своего тела:


R>
R>const byte* begin;
R>const byte* end;
R>foo(0, &begin, &end);
R>


R>Вот полный текст работающего примера:

R>
  Скрытый текст
R>
R>#include <iostream>

R>typedef unsigned char byte;

R>void foo(const char* text, const byte** begin = 0, const byte** end = 0)
R>{
R>_begin:
R>    if(begin && end)
R>    {
R>        __asm
R>        {
R>            mov eax, dword ptr [begin]  
R>            lea edx, _begin
R>            mov dword ptr [eax], edx          
R>            mov eax, dword ptr [end]  
R>            lea edx, _end
R>            mov dword ptr [eax], edx          
R>        }
R>        return;
R>    }
R>    std::cout << text << std::endl;

R>_end:
R>    ;
R>}

R>int main()
R>{
R>    foo("hello");

R>    const byte* begin;
R>    const byte* end;
R>    foo(0, &begin, &end);

R>    std::cout << "begin = 0x" << (void*)begin << std::endl;
R>    std::cout << "end = 0x" << (void*)end << std::endl;

R>    for(const byte* p = begin; p != end; ++p)
R>        std::cout << " 0x" << std::hex << (int)*p;

R>    std::cout << std::endl;
R>}
R>



Спасибо, очень понятный пример, об использовании меток я и не подумал.
Re[3]: Вычислить CRC кода
От: zheka2  
Дата: 22.04.11 03:52
Оценка:
Здравствуйте, andrey_nado, Вы писали:

_>Здравствуйте, rg45, Вы писали:


_>Никто не может гарантировать, что полезный код функции будет располагаться между метками _begin и _end.

_>Сама функция может оказаться встроенной (inline), если компилятор так решит.
_>И нужно уточнить у автора, сможет ли он обойтись без кроссплатформенности.

Посмотрю в отладчике, на inline она вроде не тянет, слишком большая. За заметку спасибо.
А кроссплатформенность там вообще не нужна
Re[2]: Вычислить CRC кода
От: zheka2  
Дата: 22.04.11 03:58
Оценка:
Здравствуйте, nen777w

Спасибо за ответ, хочу уточнить

N>Проблема в другом, всякое изменение кода, даже не в этом модуле трансляции повлечет изменения сгенерированого кода между между метками

N>, в частности особенно если в коде используются инструкции перехода или сравнения.

это имеется в виду, что если я вношу изменения в текст программы не имеющий отношения к защищаемой функции, то её контрольной значение поменяется из-за изменения адресов в jmp инструкциях, так?
Re[2]: Вычислить CRC кода
От: zheka2  
Дата: 22.04.11 03:59
Оценка:
Здравствуйте, Erop, Вы писали:

E>3) asm обрабатываешь зашифровщиком и добавляешь туда две метки на начало и на конец кода + добавляешь, например, две функции, одна возвращает начало. а другая длину...


а что за зашивровщик?
Re[3]: Вычислить CRC кода
От: rg45 СССР  
Дата: 22.04.11 04:52
Оценка:
Здравствуйте, andrey_nado, Вы писали:

_>Никто не может гарантировать, что полезный код функции будет располагаться между метками _begin и _end.

_>Сама функция может оказаться встроенной (inline), если компилятор так решит.
_>И нужно уточнить у автора, сможет ли он обойтись без кроссплатформенности.

Ну побороть inline не трудно — просто выносишь определение функции в отдельный модуль.

А в том, что этот код не переносим меня можно не убеждать, я и сам это прекрасно понимаю. Я ж сразу написал — шаманство черное
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Вычислить CRC кода
От: nen777w  
Дата: 22.04.11 07:44
Оценка:
Здравствуйте, zheka2, Вы писали:

Z>Здравствуйте, nen777w


Z>Спасибо за ответ, хочу уточнить


N>>Проблема в другом, всякое изменение кода, даже не в этом модуле трансляции повлечет изменения сгенерированого кода между между метками

N>>, в частности особенно если в коде используются инструкции перехода или сравнения.

Z>это имеется в виду, что если я вношу изменения в текст программы не имеющий отношения к защищаемой функции, то её контрольной значение поменяется из-за изменения адресов в jmp инструкциях, так?


Не обязательно такое случается если это происходит в другом модуле компиляции (тут как линкеру понравится), но гарантировано если в этом же.
По крайней мере мне пришлось у себя бороть эту проблему.
Борол кстати таким образом.
Брал под метки код защищаемой части и отдельно под метки ту часть которая сбрасывала код.
Код который занимался сбросом защищаемой части также сбрасывал в файл свой размер.
Код который сбрасывал защищаемую часть был описан макросами это давало возможность в одном режиме (в зависимости от конфигурации макросов) сбрасывать в другом генерировать вместо него инструкции nop, благодаря тому что размер nop — 1 байт.
Чуть сложнее пришлось под ppc там nop занимает аж 4-ре байта, поэтому пришлось предусмотреть выравнивание.
Re[3]: Вычислить CRC кода
От: Erop Россия  
Дата: 22.04.11 07:57
Оценка:
Здравствуйте, zheka2, Вы писали:
Z>это имеется в виду, что если я вношу изменения в текст программы не имеющий отношения к защищаемой функции, то её контрольной значение поменяется из-за изменения адресов в jmp инструкциях, так?

И даже от загрузке к загрузке может меняться...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Вычислить CRC кода
От: mike_rs Россия  
Дата: 22.04.11 08:07
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, zheka2, Вы писали:

Z>>это имеется в виду, что если я вношу изменения в текст программы не имеющий отношения к защищаемой функции, то её контрольной значение поменяется из-за изменения адресов в jmp инструкциях, так?

E>И даже от загрузке к загрузке может меняться...


разве что в длл, в конкретном скомпилированном экземпляре EXE файла CRC участка будет неизменна при всех загрузках.
Проблемы никакой нет, есть куча протектором, позволяющих маркирвать участки кода и проверять их целосность либо дешифровывать в процессе работы программы. И написать такое — это 2 вечера посидеть.
Re[5]: Вычислить CRC кода
От: mike_rs Россия  
Дата: 22.04.11 08:08
Оценка:
_>разве что в длл
и то — только в том случае, если внутри защищаемого кода будут настраиваемые ссылки на данные.
Re[4]: Вычислить CRC кода
От: zheka2  
Дата: 22.04.11 09:21
Оценка:
Здравствуйте, nen777w, Вы писали:

N>Здравствуйте, zheka2, Вы писали:


Z>>Здравствуйте, nen777w


Z>>Спасибо за ответ, хочу уточнить


N>>>Проблема в другом, всякое изменение кода, даже не в этом модуле трансляции повлечет изменения сгенерированого кода между между метками

N>>>, в частности особенно если в коде используются инструкции перехода или сравнения.

Z>>это имеется в виду, что если я вношу изменения в текст программы не имеющий отношения к защищаемой функции, то её контрольной значение поменяется из-за изменения адресов в jmp инструкциях, так?


N>Не обязательно такое случается если это происходит в другом модуле компиляции (тут как линкеру понравится), но гарантировано если в этом же.

N>По крайней мере мне пришлось у себя бороть эту проблему.
N>Борол кстати таким образом.
N>Брал под метки код защищаемой части и отдельно под метки ту часть которая сбрасывала код.
N>Код который занимался сбросом защищаемой части также сбрасывал в файл свой размер.
N>Код который сбрасывал защищаемую часть был описан макросами это давало возможность в одном режиме (в зависимости от конфигурации макросов) сбрасывать в другом генерировать вместо него инструкции nop, благодаря тому что размер nop — 1 байт.
N>Чуть сложнее пришлось под ppc там nop занимает аж 4-ре байта, поэтому пришлось предусмотреть выравнивание.

В общих чертах понятно, но вопросы есть, если мы заменяем код сброса в файл хеша на nop'ы как избежать перекомпиляции? это опять приведёт к изменению хеша
На данный момент я не могу понять как запихнуть полученный хэш в программу, так чтобы после сборки он не изменился. Работаю в Visual C++ 2008 и после изменению любого файла проекта хеш получается новый. Разве что править в hex-редакторе
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.