Имя пользователя:
Пароль:
 

Показать сообщение отдельно

Аватара для DillerInc

Обратный инженер


Сообщения: 644
Благодарности: 47

Профиль | Отправить PM | Цитировать


В общем,подумал,что может кому-то будет интересно,каким образом можно всё-таки поймать вызов какой-нибудь API-функции,заменив первые команды последней банальным EB FE,то есть попросту зациклив эту функцию.
Случай относится к тому варианту,когда вы запускаете подопытный процесс в режиме CREATE_SUSPENDED.
Причина,из-за которой у меня в своё время не получалось поймать функцию,заключалась в следующем.
При подобной технике необходимо,чтобы процесс был разморожен и как бы начал физически выполняться,если так можно выразиться.
Достигается это с помощью предварительного зацикливания процесса на точке входа,а именно:
Код: Выделить весь код
var
 OpenDlgBox : TOpenFileName;
 sInfo : TStartupInfo;
 pInfo : TProcessInformation;
 EntryPoint : Cardinal;
 RestoreEP : WORD;

// Функция для зацикливания адреса,которая возвращает два оригинальных байта,заменённых нашим опкодом 
function EndlessLoopRVA(RVA : DWORD) : WORD;
const
 Code : WORD = $FEEB; // наш магический опкод
 error : LPCTSTR = 'Произошла ошибка во время зацикливания RVA';
var
 OriginalData : WORD;
 Temp_Protect : Cardinal;
 nBytesRead, nBytesWritten : Cardinal;
begin
try
 VirtualProtectEx(pInfo.hProcess, PPointer(RVA), 2,
                  PAGE_EXECUTE_READWRITE, Temp_Protect);
 ReadProcessMemory(pInfo.hProcess, PPointer(RVA),
                   @OriginalData, 2, nBytesRead);
 WriteProcessMemory(pInfo.hProcess, PPointer(RVA), @Code,
                    SizeOf(WORD), nBytesWritten);
 VirtualProtectEx(pInfo.hProcess, PPointer(RVA), 2,
                  Temp_Protect, Temp_Protect);

 Result := OriginalData;

except MessageBox(Handle, error, NIL, MB_OK);
end; // try...except

end; // EndlessLoopRVA

// Процедура,которая восстанавливает оригинальные байты
procedure RestoreData(RVAs : DWORD; RestoreCode : WORD);
var
 Trash : WORD; // это просто для размещения мусора
 Temp_Protect : Cardinal;
 nBytesRead, nBytesWritten : Cardinal;
begin
try
 VirtualProtectEx(pInfo.hProcess, PPointer(RVAs), 2,
                  PAGE_EXECUTE_READWRITE, Temp_Protect);
 ReadProcessMemory(pInfo.hProcess, PPointer(RVAs), @Trash,
                     2, nBytesRead);
 WriteProcessMemory(pInfo.hProcess, PPointer(RVAs),
                    @RestoreCode, SizeOf(WORD), nBytesWritten);
 VirtualProtectEx(pInfo.hProcess, PPointer(RVAs), 2,
                  Temp_Protect, Temp_Protect);

except MessageBox(Handle, 'Произошла ошибка при восстановлении кода',
                                                      NIL, MB_OK);
end; // try...except

end; // RestoreData

begin

if CreateProcess(OpenDlgBox.lpstrFile, nil, nil, nil, False, CREATE_SUSPENDED,
               nil, nil, sInfo, pInfo) then
begin
 RestoreEP := EndlessLoopRVA(EntryPoint);  // Помещаем наш опкод на точку входа
 ResumeThread(pInfo.hThread);                    // Размораживаем процесс
 Sleep(300);                                                   // Даём ему немножко времени очухаться
 SuspendThread(pInfo.hThread);                   // Снова замораживаем его 
 RestoreData(EntryPoint, RestoreEP);            // И восстанавливаем оригинальные байты
 end;
end;
После того как процесс,только набрав обороты,упрётся в наш опкод на точке входа мы будем в состоянии работать с API-функциями,отображёнными в адресное пространство подопытного процесса.

Под конец стоит заметить,что зацикливание библиотечных функций не будет работать на 9х-ой линейке Windows,т.к. если я не ошибаюсь,библиотеки там отображаются в некую общую область памяти,а не в каждый процесс отдельно.

-------
То,что неясно,следует выяснить.То,что трудно творить,следует делать с великой настойчивостью. © Конфуций


Отправлено: 16:53, 21-04-2006 | #16