Ремаппинг модулей

Тема в разделе "WASM.BEGINNERS", создана пользователем HoShiMin, 19 апр 2017.

  1. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    Приветствую. В качестве защиты от перехвата решил попробовать перемапить модуль защищаемой библиотеки, задав отображению права только на чтение и исполнение. Но при попытке отмапить секцию на прежний адрес получаю ERROR_MAPPED_ALIGNMENT. В чём же проблема, ведь все адреса и смещения выровнены по размеру страницы?

    Код: https://hastebin.com/qoyekisudu.cpp
     
  2. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.568
    Адрес:
    Russia
    Не соблюдена гранулярность

    Код (C++):
    1.  
    2. GetSystemInfo(&SysInfo);
    3. DWORD dwSysGran = SysInfo.dwAllocationGranularity;
    4.  
    И ее используйте для выравнивания. Это касается всех 3х последних параметров MapViewOfFileEx, а не только одного размера секции, который вы пытались выровнять.
     
  3. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    dwSysGran = 65 килобайт (0x10000). С таким выравниванием все адреса съезжают, а нужно замапить на прежние адреса
     
  4. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.568
    Адрес:
    Russia
    HoShiMin, ну так и делаем вывод - функция MapViewOfFileEx для этих целей неуместна. Переделывайте логику работы вашего ремаппера.
     
  5. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    Отсюда следующий вопрос - чем можно мапить без ограничения на гранулярность? Секции должны отмапиться на прежние адреса, причём с разными правами, но гранулярность делает это невозможным. Как быть?
     
  6. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    Мапь весь образ целиком:
    Код (C++):
    1. void start() {
    2.     HMODULE    hgdi32 = LoadLibrary(_T("gdi32"));
    3.  
    4.     RemapModule(hgdi32);
    5.  
    6.     HDC dc = GetDC(0);
    7.     Ellipse(dc, 0, 0, 200, 200);
    8.  
    9.     return;
    10. }
    11.  
    12. int RemapModule(HMODULE hModule) {
    13.  
    14.     PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)hModule;
    15.     PIMAGE_NT_HEADERS NtHeaders = (PIMAGE_NT_HEADERS)((PBYTE)hModule + DosHeader->e_lfanew);
    16.  
    17.     PIMAGE_OPTIONAL_HEADER OptionalHeader = &NtHeaders->OptionalHeader;
    18.     ULONG ImageSize = OptionalHeader->SizeOfImage;
    19.  
    20.     // Копируем образ целиком в теневую память:
    21.     HANDLE hShadowImage = CreateFileMapping(NULL, NULL, PAGE_EXECUTE_READWRITE, 0, ImageSize, NULL);
    22.     PVOID ShadowImage = MapViewOfFile(hShadowImage, FILE_MAP_ALL_ACCESS, 0, 0, ImageSize);
    23.    
    24.     // Заголовки
    25.     CopyMemory(ShadowImage, hModule, OptionalHeader->SizeOfHeaders);
    26.  
    27.     for (int i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++) {
    28.  
    29.         PIMAGE_SECTION_HEADER pHdr = (PIMAGE_SECTION_HEADER)(OptionalHeader + 1) + i;
    30.         CopyMemory((PBYTE)ShadowImage + pHdr->VirtualAddress, (PBYTE)hModule + pHdr->VirtualAddress, pHdr->Misc.VirtualSize);
    31.  
    32.     }
    33.  
    34.     // Отцепляем оригинальную секцию:
    35.     VirtualFree(hModule, 0, MEM_RELEASE);
    36.     UnmapViewOfFile(hModule);
    37.  
    38.     PVOID SectionMapping = MapViewOfFileEx(hShadowImage, FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, ImageSize, hModule);
    39.  
    40.     UnmapViewOfFile(ShadowImage);
    41.     CloseHandle(hShadowImage);
    42.  
    43.     return 0;
    44. }
     
    HoShiMin и TermoSINteZ нравится это.
  7. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    Хм, спасибо, так работает, но беспокоит одно: у вас весь модуль мапится с правами на запись (а смысл ремапинга именно в отключении возможности как-либо менять память кода). Для отображений образов можно оставить только READ и EXECUTE?
     
  8. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    HoShiMin,
    Я, может, чего-то не догоняю, но как ты ремапингом защитишься от VirtualProtect (PAGE_READWRITE) с последующим изменением кода?
     
  9. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    Я так сделал потому что я не обрабатывал каждую секцию. Правильно нужно задавать атрибуты в соответствии с атрибутами секций. Если ты укажешь только READ и EXECUTE, будет вызвано исключение если образ будет что-то писать в секцию с изначальными правами на запись, к примеру .data.
     
  10. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    У VirtualProtect'a почему-то не получается изменить права перемапленного модуля

    Вот и вернулись к первому посту, где обрабатывал каждую секцию индивидуально и наткнулся на гранулярность... Как у системы получилось так размапить образ, не задумываясь о выравнивании и почему не могу сделать то же самое?
     
  11. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    ?
    Ну типа того:
    Код (C++):
    1.     for (int i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++) {
    2.         DWORD old, attr;
    3.         PIMAGE_SECTION_HEADER pHdr = (PIMAGE_SECTION_HEADER)(OptionalHeader + 1) + i;
    4.  
    5.         if (pHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE)
    6.             if (pHdr->Characteristics & IMAGE_SCN_MEM_READ)
    7.                 if (pHdr->Characteristics & IMAGE_SCN_MEM_WRITE)
    8.                     attr = PAGE_EXECUTE_READWRITE;
    9.                 else
    10.                     attr = PAGE_EXECUTE_READ;
    11.             else
    12.                 if (pHdr->Characteristics & IMAGE_SCN_MEM_WRITE)
    13.                     attr = PAGE_EXECUTE_WRITECOPY;
    14.                 else
    15.                     attr = PAGE_EXECUTE;
    16.         else
    17.             if (pHdr->Characteristics & IMAGE_SCN_MEM_READ)
    18.                 if (pHdr->Characteristics & IMAGE_SCN_MEM_WRITE)
    19.                     attr = PAGE_READWRITE;
    20.                 else
    21.                     attr = PAGE_READONLY;
    22.             else
    23.                 if (pHdr->Characteristics & IMAGE_SCN_MEM_WRITE)
    24.                     attr = PAGE_WRITECOPY;
    25.                 else
    26.                     attr = PAGE_NOACCESS;
    27.  
    28.         VirtualProtect((PBYTE)hModule + pHdr->VirtualAddress, pHdr->Misc.VirtualSize, attr, &old);
    29.     }
     
  12. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    Так проблема в том, что адреса отдельных секций не выравниваются по гранулярности и MapViewOfFileEx не может смапить их на прежние адреса - т.е., работает маппинг образа целиком, но не маппинг каждой секции по отдельности.
     
  13. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    rmn, Thetrik
    Вот полный пример ремапа обычного куска памяти с последующей попыткой изменить её права (VirtualProtect возвращает ERROR_INVALID_PARAMETER): https://hastebin.com/ludafavuyi.cpp
    [​IMG]
     
    Последнее редактирование: 20 апр 2017
  14. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    Насколько мне известно чтобы замапить исполняемый образ нужно юзать SEC_IMAGE флаг в функции CreateFileMapping, но это не спасет от дальнейшего изменения через VirtualProtect.
    Просто я не пойму логику. Т.е. ты хочешь сделать чтобы образ не мог изменяться, но как быть тогда с writeble-секциями?
     
  15. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    Writeable-секции оставить изменяемыми, но кодовые оставить ридонли. При условии, конечно, что там нет самомодифицирующегося кода.
     
  16. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.788
    HoShiMin,

    Как же вы до сих пор не поймёте, что защита, которую вы строете совершенно бессмысленна. Ваш код всегда может быть запущен под визором, что означает полный контроль над каждой инструкцией. Это в предельных случаях, так как отрицательно сказывается на профайле, но визор может запускаться по каким то событиям.
    Обычно такое не нужно и достаточно обычных техник.

    На кряклабе есть пример, вмпрот взят автоматикой - инструкции накоплены(и выборка данных) и собраны(графы, конструктор) воедино.

    В аттаче обсуждение такой защиты.
     

    Вложения:

    Последнее редактирование: 22 апр 2017
  17. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    Защита, которую я строю, не предполагает защиту от визоров. У меня нет задачи защититься от всего на свете, но есть задача защититься от юзермодных инъекций (или запретить менять исполняемую память образа из юзермода, что сделает инъекции отчасти бессмысленными). Это достаточный минимум, чтобы быть уверенным, что никто из игроков его не обойдёт. Так как защищаю джава-процесс, нужно как-то отсечь подгрузку сторонних классов через JNI, который дёргают из внедряемой библиотеки (кроме перехвата некоторых функций из самой JVM). С такой постановкой задачи мне совсем не нужна защита от хардкорных способов обхода через визоры и нулевое кольцо - их никто применять не будет, т.к. никто в этом не разбирается. А обычные инъекции через CreateRemoteThread -> LoadLibrary делают все кому не лень, т.к. на просторах огромное количество готовых инъекторов. И в такой ситуации, когда нежелательно писать драйвер для защиты (т.к. у игроков зачастую нет админских прав, чтобы его установить), нужно придумать юзермодную защиту от юзермодных обходов. Не больше.
     
  18. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.788
    HoShiMin,

    Тоесть вам нужна не реальная защита, а создание видимости её получается. Невозможно создать полноценную защиту в нт, такая у неё архитектура - приложения не изолированы друг от друга и от км. Написать ровные сервисные фильтры - это слишком сложная для вас задача, это даже крупные корпорации не могут сделать командой.
    Архитектура нт позволяет делать что угодно с приложением, во время работы его или есчо до запуска(инфекты, инжекты етц).
    Сам же концепт защиты нт - ограничение прав. Если есть доступ к открытию обьекта, то с ним можно делать что угодно. Но реально же это бессмысленно, так как способы поднятия прав доступны даже детям.

    Есть два варианта реализации.
    1. Виртуализация кода, таким образом даже при доступе к коду нельзя вмешаться в механизмы его работы, так как для этого необходима девиртуализация - выяснение логики работы.
    2. Системные анклавы. Но для этого нужно реализовать свой визор.

    Остальное всё бесперспективно.
     
  19. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.486
    Адрес:
    Россия, Нижний Новгород
    Я ведь и не спорю. Но как быть в ситуации, когда ставить драйвера нельзя, а защититься нужно? Вот и получается, что что-то юзермодное можно сделать через ремаппинг. И с ним такой облом, что гранулярность делает невозможным накрывать модули. Или всё же можно размапить образ руками без SEC_IMAGE в обход требований гранулярности?
     
  20. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.788
    HoShiMin,

    Я не вполне понимаю что вам нужно. Ремап проекции юзался в качестве защиты, основываясь на том, что область памяти, которая является не файловой проекцией изменить из юм невозможно, не ремапив её повторно, но такой ремап будет отображён на вторую проекцию, которая служит для такого детекта ремапа.

    То что у вас при проецировании ошибка - я не помню, но это проблема была решена, поищите сурки, толи самой этой защиты, то ли это был загрузчик(LWE), либо крякми. Подробности я не помню.
     
    Последнее редактирование: 22 апр 2017