Скрыть адрес вызываемой функции. С/C++?

Здравствуйте! Есть задача - спрятать адрес функции в программе, чтобы при статическом анализе "злоумышленник" не смог найти места вызова этой функции.

С переменными (глобальными) я делал так:
char gStr[] = "Hello Toster!"; // Глобальная переменная

Далее где-нибудь в функции:
void foo(int a)
{
    char *str = gStr + 10;
    ...
    puts(str-a); // параметр a - всегда равен 10
}

Смысл был в том, что при компиляции выражение gStr + 10, содержащее две константы, будет автоматически посчитано (а результат будет присвоен в str) и в будущем, если кому-либо удастся найти адрес gStr - он не найдет место, где она была использована.

Я хотел сделать тоже самое с функциями: взял функцию foo(из примера выше) и попробовал сделать на нее указатель со смещением:
void foo2(int a)
{
    void (*fptr)(int) = (void(*)(int)) &((int*)f)[3]; // сложная конструкция :(((
    // void (*fptr)(int) = (void(*)(int)) (f+3); // пробовал и так
    ...
}

Но компилятор упорно не хочет вычислять выражение &((int*)f)[3] при компилировании. Хотя имя функции - это константа на момент компиляции. Подскажите - в чем проблема и как быть? Заранее спасибо!)

PS Компилировал в Visual Studio 2012 под win32. Пробовал и debug и release. Пример с константой работал всегда, с функцией - никогда.
  • Вопрос задан
  • 3984 просмотра
Решения вопроса 1
iNikNik
@iNikNik Автор вопроса
Я нашел решение: делаем указатель - глобальной переменной. А не локальной, как у нас было до этого.

void (*gFunPtr)(int) = (void(*)(int)) ((int*)f+3); // Глобальная переменная

И, тогда в функции foo2 :
void foo2(int a)
{
    void (*fptr)(int) = gFunPtr;
    ...
}

В release-сборке это присваивание будет выглядеть так:
mov eax,[000403024]
...

В свою очередь, по адресу 00403024 (это адрес нашей глобальной переменной gFunPtr) мы видим:
6C104000
Как известно у нас обратный порядок байт - следовательно в переменной gFunPtr содержится значение 0040106C. А это не что иное как:
00401060(адрес функции f) + С (3 * sizeof int)
Все получилось!)
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
jcmvbkbc
@jcmvbkbc
http://dilbert.com/strip/1998-08-24
компилятор упорно не хочет вычислять выражение &((int*)f)[3] при компилировании

Что говорит?

имя функции - это константа на момент компиляции

Ложное утверждение. Адрес функции становится известен только на этапе линковки, а если функция импортирована из dll -- то только в момент загрузки. Если линковка релоцируемая, то адрес может измениться в момент загрузки. Другое дело, что константная строка в этом смысле мало отличается от функции.

Сложная конструкция должна выглядеть вот так:
void (*fptr)(int) = (void(*)(int)) (((int*)f) + 3);
Вариант с (f+3) компилироваться не будет, т.к. арифметика указателей не работает с указателями на функции.

В линуксе эта конструкция компилируется и работает.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы