Технология шифрование DLL

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by slesh, 1 Mar 2012.

  1. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Собственно такой вопрос возник, по технологии шифрования(криптования) dll:
    Каким образом восстановить работу оригинальной DLL ?

    Ситуация такая:
    1) в EntryPoint при DLL_PROCESS_ATTACH начинается расшифровка DLL
    2) непосредственно восстановление DLL делает шелкод
    3) шелкод вызывается где-то глубоко внутри кода.

    И вот получаются такая глюки:
    [Технология 1]:
    1) Если DLL восстанавливать на место (которое занято шифрованной dll), то возврат из EntryPoint расшифрованной dll идет в шелкод, а возврат из шелкода уже идет в некуда (т.к. код уже подменился)
    2) Найти адрес возврата в ntdll нереально, потому что если раскручивать фреймы, то неизвестным остаются то, на сколько чистить стек, т.к. каждая функций вызывается с разным числом параметров. К тому же очень сильная привязка к структуре генерации фрейма
    3) Даже если както найти точку возврата, то получится что надо будет как-то хитро править структуры системные (список модулей в PEB)


    [Технология 2]:
    1) Если DLL загружать в любое место (благо релоки помогают это сделать), то возврат из EntryPoint расшифрованной dll идет в шелкод, а далее рекурсивно при завершении функций он будут передаваться обратно и тогда всё норм.
    2) но тогда придется делать проброс экспорта и события DLL_PROCESS_DETACH, а также некоторые функции не смогут работать так. К томуже из-за проброса экспорта будет светить имя функции. Вообще весь этот проброс будет довольно проблематично выглядеть

    [Технология 3]:
    1) Тоже что и у технологии 2
    2) Вместо проброса экспорта и прочих хреней, сразу подставить в PEB новые значения для DLL (ImageBase и EntryPoint) таким образом вроде как сразу отбрасывается необходимость в пробросе экспорта, события DLL_PROCESS_DETACH, а также многие функции будут работать корректно.
    3) Но придется сильно привязываться к структуре PEB и списку DLL, если это еще не проблема, то еще неизвестно как отреагирует на это LoadLibrary т.к. по факту DLL загружена по одному адресу (и секция DLL туда же), а по структурам из PEB будут другое место.
    Вернее сказать неизвестно что вернет LoadLibrary - адрес по которому загрузилась DLL или уже подправленный адрес из PEB.

    Если бы не была бы обязательна поддержка экспорта и DLL_PROCESS_DETACH то не было бы проблем.

    Кто что может посоветовать в данном случае? Какую технологию выбрать? Или может есть еще какой-либо способ?
     
    1 person likes this.
  2. DooD

    DooD Elder - Старейшина

    Joined:
    30 Sep 2010
    Messages:
    1,168
    Likes Received:
    442
    Reputations:
    288
    мне кажется с 3 технологией меньше всего проблем.Опробуй ее.Кстати ,можно поинтересоваться от чего возникла такая необходимость?
     
  3. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Банальная защита от патчей файлов (плагинов) + кое какие защиты от реалтайм патча.
     
  4. DooD

    DooD Elder - Старейшина

    Joined:
    30 Sep 2010
    Messages:
    1,168
    Likes Received:
    442
    Reputations:
    288
    а если взять протектор какой нить,или криптор?или ,допустим организовать сравнение контрольной суммы?
    это если я правильно понял.
     
  5. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Криптеры - дают паливность рано или поздно, а нормальному софту както некрасиво палиться из-за того что там криптер какойто. почти все протекторы снимаются очень легко.

    Я тоже склоняюсь к третьему варианту, но есть одно но - чтобы получить доступ к списку загруженных модулей, необходимо получить доступ к PEB (а это ассемблер, а при компиляции Си под x64 нельзя использовать ассемблер)
     
    #5 slesh, 1 Mar 2012
    Last edited: 1 Mar 2012
  6. GRRRL Power

    GRRRL Power Elder - Старейшина

    Joined:
    13 Jul 2010
    Messages:
    823
    Likes Received:
    185
    Reputations:
    84
    Насколько мне известно, можно, если ассемблерные функции в отдельный файл собрать, скомпилить его в объектник отдельно, а из сишного кода дергать.
     
  7. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    http://exelab.ru/faq/Armadillo
    Нельзя ли подобный подход применить к шифрованию экспортируемых ф-ций длл?
     
  8. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 __nic есть свои заморочки, нужен именно такой подход как я описал.

    Скорее всего попробую реализовать третий вариант. судя по исходникам win 2k
    LoadLibrary ведет далеко во внутрь и вызывает LdrpLoadDll, которая возвращает DllHandle
    И код там:
    *DllHandle = (PVOID)LdrDataTableEntry->DllBase;
    т.е. можно смело говорить что LoadLibrary вернет адрес не тот по которому загружена DLL, а тот который в таблице. (и который собственно говоря можно подменить)

    2 GRRRL Power на васме подсказали про Intrinsics. Которые дают возможность без асма юзать многие асм команды.
    к примеру для x32
    mov eax, fs:[0x30]
    ret

    равноценно сишной строке
    __readfsdword(0x30);
     
  9. GRRRL Power

    GRRRL Power Elder - Старейшина

    Joined:
    13 Jul 2010
    Messages:
    823
    Likes Received:
    185
    Reputations:
    84
    Знаю я про Intrinsics, но забыл про них написать :)
    Для X64 получение указателя на PEB это __readgsqword( 0x60 )
     
    1 person likes this.
  10. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    GRRRL Power, спас меня прям. а то я тыкаюсь в gs:0x30 а там какая-то фигня. думал структура PEB другая )
     
  11. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    конечно достаточно завести в проекте один файлик с чистым ассемблером

    Code:
    hack.asm
    
    include \masm32\include\masm32rt.inc
    
    .code
    
    dummy proc uses esi
    mov esi, 100
    .while esi
    	invoke Beep, 700, 10
    	dec esi
    .endw
    ret
    dummy endp
    
    end
    
    настроить ему custom build step чтобы компилился вместе с сишными
    файлами
    Code:
    Command Line: ml.exe /c /coff /nologo /Zi /Fo $(InputDir)$(IntDir)\$(InputName).obj $(InputName).asm
    Description: Assembling...
    Outputs: $(InputDir)$(IntDir)\$(InputName).obj
    
    и все инлайн вставки оформлять отдельными процедурами
    и дергать их из сишных файлов

    Code:
    main.cpp
    
    extern "C" void __stdcall dummy();
    
    int main()
    {
    	dummy();
    }
    
    очень удобно имхо компиляется все за один клик и
    из встроеннрого дебаггера можно не вылазить для отладки асмокода
     
  12. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    но смысла нет от такого, когда нужна буквально одна асм команда.
     
  13. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    это да но с другой стороны у этого подхода
    есть тоже свои плюсы главное выход есть