для этого читаю таблицу экспорта и сравниваю по адресам первые 10 байт с длл в памяти и на диске в результате функция не соответствует NlsAnsiCodePage но это не функция а данные, как определить что это данные? спасибо
извините, за некорректное объяснение проблемы! я бегу по экспортируемым функциям, и сравниваю 10 байт, которые нахся в памяти процесса (по адресам где загружена длл), с 10 байтами, которые нахся в оригинальном файле. Проблема: экспортируемая функция NlsAnsiCodePage, не функция, а DWORD, поятому 10 байт сравнивать нельзя, ибо в файле оно равно 0, а в памяти 1250 (например). Так вот как можно определить, что это не функция, а дворд. Я хочу хочу восстановить оригинальную NTDLL, чтобы мой процесс не перехватывали таким способом. вот. простите если глупо выражаюсь - ибо только учусь!
Я совершенно точно понял, что ты хочешь. "Настоящие" функции будут находится в секциях .text, PAGE и им подобных, причём у таких секций будет выставлен флаг IMAGE_SCN_MEM_EXECUTE. Экспортируемые переменные, как правило, находятся в секциях типа .data, а для них этот флаг не устанавливается.
все в точности, как сказал AntiFreeze добавлю лишь, что я бы сравнил сразу всю секцию кода с секцией на диске. мало ли что там еще похукано может быть
mirtop Набросал небольшую табличку для GetProcAddress()(# - сепшен, [] - массив/сегмент, ловим в VEH, посредством бактрейса получим контекст): Код (Text): LdrGetProcedureAddress: | + _SEH_prolog -> Fs[] -> #AV | + ShowSnaps -> DbgPrint("NAME - %s") -> vDbgPrintExWithPrefix() | | | + Fs[] -> #AV | | | + vsnprintf() -> _output() -> _pctype[] -> #AV | | | + BeingDebugged -> #DBG | + LdrpInLdrInit -> RtlEnterCriticalSection(LdrpLoaderLock) -> Wait.. | + LdrpCheckForLoadedDllHandle() -> LdrpLoadedDllHandleCache[] -> #AV | + RtlImageDirectoryEntryToData() -> #AV | | | + RtlpImageNtHeader() -> IMAGE_DOS_HEADER.e_lfanew -> #AV | | | + RtlpImageDirectoryEntryToData32() -> IMAGE_DATA_DIRECTORY.VirtualAddress -> .. -> #AV | + !LDRP_ENTRY_PROCESSED -> LdrpRunInitializeRoutines() | | | + | | | + ShowSnaps -> DbgPrint("[%x,%x] LDR: Real INIT LIST..") -> .. -> #AV, #DBG | | | + LdrpShowInitRoutines -> DbgPrint() -> .. -> #AV, #DBG | | | + LdrpCallInitRoutine() | | | + Etc. | + g_ShimsEnabled -> g_pfnSE_GetProcAddress() | + (v5.1) _security_check_cookie() -> __report_gsfailure() -> .. -> PEB.ProcessParameters[] -> #AV Вот только несколько способов захвата одной функи. Ну и скажите кто будет юзать сплайс..
mirtop анализом исполняемого файла и сравнением данных в памяти и на дике определить данные ли это со 100% вероятностью нельзя, например rpcrt4.dll. Там десятки экспортируемых данных, которые находятся в секциях, где можно выполнять код. И мало того, дизассемблировав некоторые из них всё выглядит как самый настоящий код. Единственное что призодит в голову по поводу анализа это DIA SDK. Т.е. необходимо использовать отладочные сиволы. Можно скачать на сайте мелкософта.
multiarc спасибо! понял, что задача непроста!! Clerk объясните убогому что это и как это толковать. Заранее благодарен. З.Ы.: с нетерпением жду ответа!
mirtop Ваш код может полностью контролироваться сторонним кодом, но ни один байт в секциях кода изменён не будет, во как.
Clerk не замыкается ли RtlpCalloutEntryList само на себя. Если это так значит кто-то VEH юзает, если мы сами юзаем VEH, то проверить конечно сложнее, ибо насколько я помню там кодируется RtlEncodePointer() указатель на хендлер, и подменить всегда его можно.
Неужели вы думаете что если бы этот способ перехвата был широко распространенным его бы не расковыряли до сих пор?
n0name RtlAddVectoredExceptionHandler() вернёт указатель на хип с описателем хэндлера, в начале которого два линка(двусвязанный список), по которому можно вручную пройтись, декодировать поинтер и выполнить необходимые проверки. Но это только теоретически, на практике же никто это не делает, ни приложения с защитой, ни аверы.
onSide Это не способ, это концепция, смотрите шире. Если особо нужно, то можно создать глобальный стаб во всех процессах и выполнить редирект диспетчера исключений на него, не затрагивая вобще дефолтный
Clerk ну как бы да. Я и говорю про теоретическую возможность. Как только появится такая штука в itw, думаю через пару недель и аверы почешутся, благо кода там надо 3 строчки. ну 10 с учетом того что мы в другом ап.
n0name Не согласен. Каким образом определить что код стороний. Для текущего уровня эмуляции который в аверах это невозможно.
Надо смотреть на кукую секцию ссылается данная функция. И если у данной секции атрибуты защиты не соответствуют секции кода, то игнорировать. Я так в начале делал. Но потом решил, что проще восстанавливать всю секцию кода, а не отдельные кусочки памяти. А заодно восстанавливаю оригинальные атрибуты защиты всех секций модулей ntdll.dll, kernel32.dll и прочих по желанию.