На главную | Содержание | Назад | Вперёд
Наши друзья

 

 

Создание собственных средств взлома

Согласитесь, восстановление исходного кода — это довольно скучный процесс, предполагающий выполнение тысяч мелких действий и учет миллионов фактов. Че­ловек не в состоянии запомнить всю эту информацию. Если вы не отличаетесь от других людей, то для управления данными вам потребуется помощь специальных средств. На рынке доступно множество средств для отладки кода (как коммерче­ских, так и бесплатных), но большинство из них не предоставляют универсального решения любой задачи. По этой причине часто возникает потребность в создании собственных средств.
Самостоятельное написание программ — это отличный способ узнать побольше о программном обеспечении. При этом требуются знания архитектуры программного обеспечения, но самое главное — это способ размещения программы в памяти и спо­соб работы стека и кучи. Исследование программного обеспечения с помощью средств программирования намного эффективнее, чем прямолинейные атаки по взлому с использованием карандаша и листа бумаги. Ваши умения значительно улучшатся, а период обучения не будет слишком долгим.
Средства для платформы х86
В большинстве рабочих станций установлены процессоры Intel семейства х86, включая процессоры моделей 386, 486 и Pentium. Другие производители также соз­дают совместимые чипы. Эти чипы называют семейством, поскольку все эти процес­соры обладают общим набором свойств и возможностей. Программа, которая запус­кается на платформе х86, как правило, имеет стек, кучу и набор команд. В процессо­ре семейства х86 есть регистры, в которых сохраняются адреса ячеек памяти. Эти адреса соответствуют месту в памяти, в котором хранятся данные.
Отладчик для платформ х86
Компания Microsoft предоставляет относительно простые в использовании API для отладки в Windows-системах. Интерфейс API позволяет пользователям полу­чать доступ к отладочным событиям из программы, запускаемой в режиме пользова­теля. Структура программы довольно проста.
DEBUG_E¥EffiTdbg_evt ;
mJiProcess = 0penProce3S3>((        №ОСЕ88_ЖЫЬ_ШШЖ|  РМЮ7ЖГЩ_@№КАТ10Ы,
0,
mPID) ;
{
..error_out <•" [ !] Opeffi430ce%%s Fliie&d !\n"> ;
return;
1

// Ok, мы подключились к процессу; можно начинать отладку.
if(!DebugActiveProcess(mPID))
{
_error_out("[!] DebugActiveProcess failed !\n"); return;
//He уничтожайте процесс при выходе из потока. // замечание:  поддерживается только в Windows XP. fDebugSetProcessKillOnExit(FALSE) ;
while(1) {
if (WaitForDebugEvent(Sdbg_evt,  DEBUGL0OP_WAIT_TIME)) {
// Обработка отладочных событий. OnDebugEvent(dbg evt);
if (IContinueDebugEvent( mPID,
dbg_evt.dwThreadId,  DBG_CONTINUE))
{
_error_out("ContinueDebugEvent failedNn"); break;
)
else
I
// Игнорировать ошибки,  связанные с истечением срока, int err = GetLastError() ; if(121   != err) i
error out("WaitForDebugEvent failed\n"); break;

// Выйти,  если отладчик был отключен, if(FALSE == raDebugActive)
break;
}
RemoveAllBreakPoints();
// Ok,   мы подключились к процессу;   можно начинать отладку. if(!DebugActiveProcess(mPID))
{
error   out ("[И   DebugActiveProcess   failed   ! \ n") ; return;
}
//He уничтожайте процесс при выходе из потока. // замечание:   поддерживается только в Windows XP. fDebugSetProcessKillOnExit(FALSE); while (1)
{
if(WaitForDebugEvent(&dbg_evt,   DEBUGLO0P_WAIT_TIME))
{
// Обработка отладочных событий. 0nDebugEvent(dbg_evt); if(IContinueDebugEvent( mPID,
dbg_evt.dwThreadId,   DBG_C0NTINUE))
{
_error_out("ContinueDebugEvent failed\n") ; break;
}
}
else
{
// Игнорировать ошибки,   связанные с истечением срока, int err = GetLastError() ; if(121   != err)

точки останова х86-программ является прерывание 3. Очень ценной представляется возможность закодировать прерывание 3 как один байт данных. Таким образом, при его удалении из программного кода потребуются минимальные изменения в окру­жающих байтах. Эту точку останова легко устанавливать скопировав оригинальный файл в безопасное место и заменив его байтом ОхСС.
Инструкции останова иногда объединяются в блоки и записываются в недоступ­ные области памяти. Таким образом, если программа "случайно" перейдет в одну из этих "неправильных"областей памяти, будет вызвано прерывание отладчика. Ино­гда эти инструкции можно увидеть в стеке между стековыми фреймами.
Безусловно, вовсе необязательно обрабатывать точку останова с помощью пре­рывания 3. С тем же успехом может быть использовано прерывание 1 или еще что-то. Прерывания управляются программным обеспечением. И именно программное обеспечение операционной системы принимает решение о том, как обрабатывать со­бытие. Это контролируется посредством таблицы дескрипторов прерываний (когда процессор запущен в защищенном режиме) или таблицы векторов прерываний (когда процессор запущен в реальном режиме).
Для установки точки останова нужно сначала сохранить оригинальную инструк­цию, которая заменяется точкой останова, чтобы при удалении точки останова эту инструкцию можно было вернуть обратно. В следующем листинге демонстрируется сохранение оригинального значения до установки точки останова.
Н Изменяем защиту страницы, чтобы можно было считать оригинальную инструкцию, // затем восстанавливаем защиту.
MEMORi_BASIC_INF0RMATION mbi; VirtualQueryEx( rahProcess,
(void *){m_bp address),
smbi,
Sizeof [MEMORl_BASIC_INFORMATION)) ;
// теперь выполняем чтение оригинального байта, if(!ReadProcessMemory[m_hProcess,
(void *)(m_bp_address),
& [m original byte),
1, " MULL))
errorout (" [! ] Failed to read process memory ! \n"),-return NULL,-
I
if(m_original_byte OxCC) {
_error_out("[!] Multiple setting of the same breakpoint ! \n"); return NULL;
}
DWORD dwOldProteCt;
// Возвращаем защиту.
if(!VirtualProtectEx( ra_hProcess,
mbi.BaseAddress,
mbi,RegionSi ze,
mbi.Protect,
fidwOldProtect ))

I
_error_out("VirtualProtect failed!">; return NULL; )
SetBreakpointO ;
Приведенный выше код изменяет защиту памяти, чтобы мы могли считать иско­мый адрес. Затем мы сохраняем оригинальный байт данных. Следующий код позво­ляет затереть в памяти оригинальную инструкцию инструкцией ОхСС. Обратите внимание, что мы сначала проверяем память, чтобы определить, не была ли установ­лена точка останова ранее, bool SetBreakpointO {
char a box = '\хСС'; -
if(!ra hProcess)
error out ("Попытка установить точку останова без указания процесса") return FALSE;
]
II Меняем защиту страницы памяти, чтобы получить возможность записи. // Затем восстанавливаем защиту.
ПIПII11II11111111П ПIП111111П111П11П11! 1111 III III11П11111ПI и и НIIПI
MEMORY_ВASIС_INFORMATION mbi; VirtualQueryEx( mhProcess,
(void *)(m_bp_address),
& mbi,
sizeof(MEMORY_BASIC_IN FORMATION));
if(!WriteProcessMemory(m_hProcess,   (void *)(m_bp_address),   iabpx, 1, NULL) )
char _c[255); sprintf(_c,
"[!] Ошибка при записи в память процесса %d ! \п" _error_out(_с); return FALSE;
GetLastError());
if(!m_persistent) I
ra refcount++;
DWORD dwOldProtect;
// Восстанавливаем защиту.
if(!VirtualProtectEx( m_hProcess,
mbi.BaseAddress, mbi.RegionSize, mbi.Protect, bdwOldProtect >)
_error_out("VirtualProtect failed!") j return FALSE;
// TODO: Flush instruction cache, return TRUE;

В предьщущем фрагменте кода в память исследуемого процесса записывается один байт ОхСС. Как инструкция этот байт интерпретируется, как прерывание 3. Прежде всего, следует изменить защиту для страницы в области памяти для иссле­дуемого процесса, чтобы получить возможность выполнить запись. Перед тем как продолжить выполнение программы, надо восстановить исходную защиту. Исполь­зованные здесь вызовы API полностью документированы в MSDN (Microsoft Devel­oper Network), и мы рекомендуем прочитать эту документацию.

 

На главную | Содержание | Назад | Вперёд
 
Яндекс.Метрика