Есть ли способ найти dl по имени во всех процессах из kernel mode не делая инжект в user mode (для поиска там)?
ну допустим можно найти PEB через QueryInformationProcess, затем зачитать PEB_LDR_DATA из памяти и распарсить ее руками... но тут нужно еще помнить, что тут есть много мест, где можно накосячить... например, что внутри WOW64 у процесса есть два PEB'а, нужен именно 32-битный... если есть возможность загрузить драйвер до запуска целевого процесса, то можно решить через PsSetLoadImageNotifyRoutine... можно из ядра запустить вспомогательный процесс от система или от юзера и использовать Module32First/Module32Next из тулхелпа...
ну да я наверно так и поступлю: перечислю процессы, приатачусь к каждому и чезер PEB перечислю модули
перед доступом к user space хочу проверить доступность через ProbeForRead, но она если что бросит исключение, которое я не смогу обработать, так как у меня шелкод и обработчик исключения не зарегистрирован (код x64) Есть ли альтернативные способы проверить доступность юзермодной памяти? --- Сообщение объединено, 1 фев 2019 --- Я что то не понял вот функция, а где проверки? Код (ASM): PAGE:00000001405505E0 ; void __stdcall ProbeForRead(const void *Address, SIZE_T Length, ULONG Alignment) PAGE:00000001405505E0 public ProbeForRead PAGE:00000001405505E0 ProbeForRead proc near ; DATA XREF: .pdata:00000001403D18D8o PAGE:00000001405505E0 000 sub rsp, 28h PAGE:00000001405505E4 028 test rdx, rdx PAGE:00000001405505E7 028 jz short PAGE_140550609 PAGE:00000001405505E7 PAGE:00000001405505E9 028 dec r8d PAGE:00000001405505EC 028 test rcx, r8 PAGE:00000001405505EF 028 jnz short PAGE_14055060E PAGE:00000001405505EF PAGE:00000001405505F1 028 lea rax, [rcx+rdx] PAGE:00000001405505F5 028 mov rdx, 7FFFFFFF0000h PAGE:00000001405505FF 028 cmp rax, rdx PAGE:0000000140550602 028 ja short PAGE_140550614 PAGE:0000000140550602 PAGE:0000000140550604 028 cmp rax, rcx PAGE:0000000140550607 028 jb short PAGE_140550614 PAGE:0000000140550607 PAGE:0000000140550609 PAGE:0000000140550609 PAGE_140550609: ; CODE XREF: ProbeForRead+7j PAGE:0000000140550609 ; ProbeForRead+36j PAGE:0000000140550609 028 add rsp, 28h PAGE:000000014055060D 000 retn PAGE:000000014055060D PAGE:000000014055060E ; --------------------------------------------------------------------------- PAGE:000000014055060E PAGE:000000014055060E PAGE_14055060E: ; CODE XREF: ProbeForRead+Fj PAGE:000000014055060E 028 call ExRaiseDatatypeMisalignment PAGE:000000014055060E PAGE:0000000140550613 ; --------------------------------------------------------------------------- PAGE:0000000140550613 028 int 3 ; Trap to Debugger PAGE:0000000140550613 PAGE:0000000140550614 ; --------------------------------------------------------------------------- PAGE:0000000140550614 PAGE:0000000140550614 PAGE_140550614: ; CODE XREF: ProbeForRead+22j PAGE:0000000140550614 ; ProbeForRead+27j PAGE:0000000140550614 028 mov eax, [rdx] PAGE:0000000140550616 028 jmp short PAGE_140550609 PAGE:0000000140550616 PAGE:0000000140550616 ProbeForRead endp
Проверка на читабельность сводится к этому: *(PBYTE)(UsermodeAddress) Чтобы проверить без чтения, можешь пройтись по PTE и посмотреть, присутствует ли страница в памяти. НО! Это не сработает, если страница сброшена в файл подкачки, и проверить её наличие можно только через ProbeForRead и try..except. --- Сообщение объединено, 1 фев 2019 --- Способ проще (внутри тоже читает PTE и тоже не покажет присутствие сброшенной в подкачку страницы): Код (C): KeStackAttachProcess(...); PHYSICAL_ADDRESS Phys = MmGetPhysicalAddress(UsermodeAddress); KeUnstackDetachProcess(...); if (Phys.QuadPart != 0) { // Память есть }
HoShiMin, Подкачка происходит при выборке(обращении прямом) из страницы. Состояние области памяти хранится в виде системных высокоуровневых структур(VAD etc). А для работы с ними есть соотвествующий интерфейс(апи). Штатная апи NtQueryVM к примеру. А есчо можно использовать любую процедуру, которая защищена от исключений(seh). Она вернёт соответствующий статус, после выборки по заданному адресу. Это использовалось именно в шеллах, для обхода NX защиты(передача управления на доверенный обработчик при фаултах).
Экспортируется ядром только в последних Win, или искать сигнатурами и привязываться к билдам ~ Хм, точно, тоже хорошее решение. Не подумал об этом варианте
HoShiMin, Значит вы много чего не знаете Через передачу указателя на выборку из шелла использовались многие апи, а есчо были манипуляции с фреймами(seh_prolog). Что бы доступ из км не закрэшил ось. Это довольно старая техника. Тут решение очевидно, раз шелл - обращаемся в память через системные апи, которые обёрнуты сех. А для получения списка модулей листаем через такого типа выборку загрузочные списки. Можно поизвращаться, дёрнуть какие то апи, которые дадут список проекций, но как вы заметили - не экспортные, либо придётся их искать, либо впрыскивать код в юзер что бы это вызвать. Размер кода будет куда больше, чем безопасный проход по загрузочным структурам. Это не найдёт образы, сформированные протекторами/пакерами/загрузчиками. Думаю наверно тс это и не надо.
Indy_ Шо поделать, я не из VX'овой среды, у меня задачи сделать максимально надёжно, портабельно и с минимумом андока, не сталкивался с подобными техниками)
HoShiMin, Это использовалось часто. Во первых проверка памяти через сервисный вызов - ядро возвращает статус, но не вызывает исключение. Тут немного иная задача, км. Был руткит, точнее сервисный монитор(обработка ловушек через KDR) - сайд(2013). Архитектура была довольно продуманной, именно там первый раз использовалась данная техника. У меня на ядиске это есть https://yadi.sk/d/uQZFHH8REhsEx vx Смотри пролог и работу с ним: Были и другие проекты где такое использовалось.
HoShiMin, Там всё просто. Жесть была при попытке использовать код, который выполняет подкачку, для скрытия в памяти. Вот там была жесть. Но так и не получилось.