Имеется такой кусок кода: Code: void B() {} void A(int E_addr) {} int main() { A(((int)B)^12345); return 0; } вопрос: как сделать чтоб выражение ((int)B)^12345 вычислялось на стадии компиляции? у меня что в M$, что в gcc компилируется только в виде: Code: mov eax, offset B xor eax, 12345d с чего я взял, что вообще так можно: http://www.insidepro.com/kk/199/199r.shtml смотрим "Маскировка указателей", Крис утверждает, что у него все ок, достаточно лишь установить флаг компиляции /Ox (-O2). У меня, как я уже сказал, не на мс, не на гцц компилерах не работает (перебрал хуеву тучу возможных комбинаций флагов и там и там) Кто сталкивался с такой штукой отпишитесь. И да, сделать надо чисто методами C, т.е. взять hiew и там вписать нужное значение, забив лишнее nop'ами не прокатит (хотя это и решение, но задание было дано так) Весь код, кому интересно: Code: #include <stdio.h> #include <stdlib.h> #define PASS 12345 void B() { printf("%s \n", "Hello world"); exit(0); } void _cdecl A(int E_addr) { int pass; scanf("%d", &pass); pass^=E_addr; *(((int*)&E_addr)-1)=pass; } int main() { #ifdef _ATT asm("int $0x3"); #endif #ifdef _INTEL _asm{int 0x3}; #endif A(((int)B)^PASS); return 0; } В планах реализовать защиту таким способом, что адрес перехода на full version функции программы будет замаскирован на некотором пароле (даже скорее всего на хэше пароля), в результате чего только правильный ввод пароля даст доступ к полной версии. В связи с этим естественно, что в программе выражение ((int)B)^PASS должно быть вычисленно на стадии компиляции.
Хоть кто-нибудь попробуйте покомпилить у себя на разных компилерах и системах, ибо имхо идея такой закщиты вполне интересна, если уж нигде не будет работать то придется все-таки хитрить через hiew, либо ещё как
В том то и дело что так нельзя, ибо задание - сделать это только методами чистого с со стандартной библиотекой, без всяких ассемблерных вставок, в расчете на переносимость такого метода защиты. Во-вторых такая вставка не должна работать в принципе. Решение точно связано с работой компилятора, может какие-то директивы есть, чтоб компановка не происходила до тех пор пока не будут вычислены все адреса и выражения с ними
Code: int B2 = (int)B^1234; void B() {} void A(int E_addr) {} int main() { A(B2); return 0; } или я чето не понял?
ну если точнее, то Code: void B() {} int B2 = (int)B^1234; но тут засада: C:\Users\Vertex\Documents\test\main.c|12|error: initializer element is not constant| на строчке int B2 = (int)B^1234; Выходит, что gcc считает, что адреса имен неизвестны (хотя вполне очевидно, что адреса в готовом приложении вполне известны, так как обычно они делаются фиксированными в отличии от dll). В вижуал студии в настройках пробовал фиксировать адрес базы, но тоже не дало результата =( Вообщем у Касперски волшебные компиляторы =(
попробуй отключить релоки (чето типа strip relocations). >>хотя вполне очевидно, что адреса в готовом приложении вполне известны Это не очевидно, в соответствии с форматом PE, все отображения могут перемещаться (exe и dll с точки зрения формата не сильно отличаются). В exe можно отрубать релоки. Возможно тогда компилятор посчитает адрес константным.