Подмена адреса возврата с маскировкой

Discussion in 'Реверсинг' started by VERte][, 13 Feb 2010.

  1. VERte][

    VERte][ Elder - Старейшина

    Joined:
    17 May 2007
    Messages:
    240
    Likes Received:
    163
    Reputations:
    32
    Имеется такой кусок кода:

    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 должно быть вычисленно на стадии компиляции.
     
    #1 VERte][, 13 Feb 2010
    Last edited: 13 Feb 2010
  2. VERte][

    VERte][ Elder - Старейшина

    Joined:
    17 May 2007
    Messages:
    240
    Likes Received:
    163
    Reputations:
    32
    Хоть кто-нибудь попробуйте покомпилить у себя на разных компилерах и системах, ибо имхо идея такой закщиты вполне интересна, если уж нигде не будет работать то придется все-таки хитрить через hiew, либо ещё как
     
  3. Protorus

    Protorus New Member

    Joined:
    17 Jan 2010
    Messages:
    22
    Likes Received:
    0
    Reputations:
    0
    на С не пишу, но может так можно
    Code:
    asm{
    push &B ^ 12345
    call &A
    }
    
     
  4. VERte][

    VERte][ Elder - Старейшина

    Joined:
    17 May 2007
    Messages:
    240
    Likes Received:
    163
    Reputations:
    32
    В том то и дело что так нельзя, ибо задание - сделать это только методами чистого с со стандартной библиотекой, без всяких ассемблерных вставок, в расчете на переносимость такого метода защиты. Во-вторых такая вставка не должна работать в принципе. Решение точно связано с работой компилятора, может какие-то директивы есть, чтоб компановка не происходила до тех пор пока не будут вычислены все адреса и выражения с ними
     
  5. kori256

    kori256 Member

    Joined:
    7 Feb 2009
    Messages:
    49
    Likes Received:
    33
    Reputations:
    6
    не нашел где включить это в своем xcode, возможно в этом проблемма?
     
  6. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,032
    Likes Received:
    1,320
    Reputations:
    327
    Code:
    int B2 = (int)B^1234;
    void B()
    {}
    
    void A(int E_addr)
    {}
    
    int main()
    {
        A(B2);
        return 0;
    }
    
    или я чето не понял?
     
  7. VERte][

    VERte][ Elder - Старейшина

    Joined:
    17 May 2007
    Messages:
    240
    Likes Received:
    163
    Reputations:
    32
    ну если точнее, то

    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). В вижуал студии в настройках пробовал фиксировать адрес базы, но тоже не дало результата =( Вообщем у Касперски волшебные компиляторы =(
     
  8. Hiro Protagonist

    Joined:
    26 Aug 2009
    Messages:
    132
    Likes Received:
    24
    Reputations:
    -2
    попробуй отключить релоки (чето типа strip relocations).
    >>хотя вполне очевидно, что адреса в готовом приложении вполне известны
    Это не очевидно, в соответствии с форматом PE, все отображения могут перемещаться (exe и dll с точки зрения формата не сильно отличаются). В exe можно отрубать релоки. Возможно тогда компилятор посчитает адрес константным.
     
  9. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,032
    Likes Received:
    1,320
    Reputations:
    327
    не, я и с динамичной базой включал и тд - все работает,
    компилер из студии 2008
     
  10. VERte][

    VERte][ Elder - Старейшина

    Joined:
    17 May 2007
    Messages:
    240
    Likes Received:
    163
    Reputations:
    32
    Релоки отключал, студия как и у sn0w 2008я, но вот почему-то не работает =(