![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
CreateRemoteThread [D6, WinXP]
Тимохов © (2004-06-18 11:08:00)Когда читал Рихтера пропустил эту функцию. Но тут любопытство заело - не ужто можно в любом процессе создать поток. Во-первых, я понял, что не в любом - есть ограничения (правда не совсем понял какие). Во-вторых, почитав того же Рихтера понял, что в качестве потоковой функции он передает LoadLibrary, в функции инициализации которой он и делает нужные действия в другом процессе.
Насколько я понимаю точка входа в LoadLabriary определается в исходном процессе. Считается, что точка входа LoadLabriary в remote процессе будет таже, т.к. Kernel32.dll будет якобы загружена по тому же базовому адресу. Но как я понимаю никаких гарантий этого нет (Рихтер и сам говорит, что по опытуэто так и не более).
Поэтому возникло желание внедрить не LoadLibrary, а свою функцию в качестве потоковой.
Ясно, что она должна быть в адресном пространстве другого процесса. Т.е. нужно:
1. Зарезервировать и выделить памятиь в помощью VirtualAllocEx в remote процессе.
2. С помощью WriteProcessMemory в выделенной памяти сохранить функцию.
3. Вызвать CreateRemoteThread.
В связи в пунктом 2 и вопрос: как переписать функцию?Допустим, можно в текущем процессе описать функцию и затем ее скопировать в remote процесс. Но тогда поползут все адреса. К тому же непонятно как определять конец функции, т.е. сколько копировать.
:))Все, что после жирного - мои домыслы, предназначенные показать, что я сам над этим тоже думал :)) Скорее всего они абсолютно лажовые.
Тимохов (2004-06-23 11:51:00) [1]
> diMAN (23.06.04 11:43) [38]
Спасибо.
Очень интересно.
diMAN (2004-06-23 11:43:00) [2]Вот, взял кусочек из своего кода, только для примера. Надеюсь тут всё будет понятно, хотя есть конечно свои тонкости.
type
// Данные, которые необходимы для работы в remote thread
TRData = packed record
MessageBox : pointer;
end;
PRData = ^TRData;
// Собственно сам код, который будет работать в remote thread
function ThreadProc(RData: PRData): DWORD; stdcall;
asm
call @Where
@Where:
pop esi
sub esi, offset @Where
mov edi, RData
// Это эквивалент MessageBox(...)
push dword ptr MB_SYSTEMMODAL or MB_OK
lea ecx, [esi][@Caption]
push ecx
lea ecx, [esi][@Text]
push ecx
push dword ptr $00
call [edi + TRData.MessageBox]
jmp @Exit
@Caption: db "From ThreadProc", 0
@Text: db "Ну надо же, работает!", 0
@Exit:
mov Result, 0
end;
// Для вычисления размера ThreadProc
procedure EndThreadProc;
begin
end;
var
hProcess : THANDLE = 0;
hThread : THANDLE = 0;
RemoteFuncAddr : pointer = nil;
FuncSize : integer = 0;
lpNumberOfBytesWritten : Cardinal = 0;
RData : TRData;
procedure TForm1.btnRunClick(Sender: TObject);
var PID: DWORD;
begin
FillChar(RData, SizeOf(RData), #0);
PID := LoadLibrary('user32.dll');
with RData do
begin
MessageBox := GetProcAddress(PID, 'MessageBoxA');
end;
// Получаем PID процесса в котором мы собираемся запустить remote thread
if edtPID.Text <> ''
then PID := StrToInt( edtPID.Text )
else PID := GetCurrentProcessId;
// Открываем этот процесс
hProcess := OpenProcess(
PROCESS_CREATE_THREAD or // For CreateRemoteThread
PROCESS_QUERY_INFORMATION or // Required by Alpha
PROCESS_VM_OPERATION or // For VirtualAllocEx/VirtualFreeEx
PROCESS_VM_WRITE or // For WriteProcessMemory
PROCESS_VM_READ, // For ReadProcessMemory
FALSE, PID);
if (hProcess = 0) then
begin
memLog.Lines.Add('Error OpenProcess: ' + SysErrorMessage(GetLastError));
Abort;
end;
// Вычисляем размер ThreadProc
asm
push eax
mov eax, offset EndThreadProc
sub eax, offset ThreadProc
mov FuncSize, eax
pop eax
end;
// Выделяем память для кода и данных
RemoteFuncAddr :=
VirtualAllocEx(hProcess, nil, FuncSize + SizeOf(TRData), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (RemoteFuncAddr = nil)
then begin
memLog.Lines.Add('Error VirtualAllocEx: ' + SysErrorMessage(GetLastError));
Abort;
end;
// Копируем код
if not WriteProcessMemory(hProcess, RemoteFuncAddr,
@ThreadProc, FuncSize, lpNumberOfBytesWritten)
then begin
memLog.Lines.Add('Error WriteProcessMemory RemoteControl: ' + SysErrorMessage(GetLastError));
Abort;
end;
// Копируем данные
if not WriteProcessMemory(hProcess, Pointer(Integer(RemoteFuncAddr) + FuncSize),
@RData, SizeOf(TRData), lpNumberOfBytesWritten)
then begin
memLog.Lines.Add('Error WriteProcessMemory RData: ' + SysErrorMessage(GetLastError));
Abort;
end;
// ... и в путь :)
hThread := CreateRemoteThread(hProcess, nil, 4096,
RemoteFuncAddr, Pointer(Integer(RemoteFuncAddr) + FuncSize), 0, hThread);
if (hThread = 0)
then begin
memLog.Lines.Add('Error CreateRemoteThread: ' + IntToHex(GetLastError, 8) + ' ' + SysErrorMessage(GetLastError));
Abort;
end;
end;
Тимохов (2004-06-22 11:02:00) [3]
> Burmistroff (22.06.04 00:04) [35]
оно у меня тоже вылезало (только про другую библиотеку) при попытке расположиться по адресу kernel32.
Burmistroff (2004-06-22 00:06:00) [4]Ага, полагаю такое же что и у [29]
;)
Burmistroff (2004-06-22 00:04:00) [5]Кстати, по поводу размещений в памяти системных DLL. как-то раз вылезло забавное окошко:
http://mc.webm.ru/5/reloc.gif
Тимохов (2004-06-21 12:45:00) [6]Спасибо всем за обсуждение.
Я склонен постановить, что тема для меня раскрыта в полном объеме. Данный вопрос является скорее всего теоретическим.
Игорь Шевченко (2004-06-21 12:38:00) [7]
> Промотрел начиная с 19 главы. Не вижу, что Kernel32.dll
> проецируется по одному адресу.
> ПРоверил. Действительно ругается.
Насколько я помню, это было написано, где говорилось про bound import (Хотя, может, и ошибаюсь, Рихтера под рукой нет)
Тимохов (2004-06-21 12:34:00) [8]
> тоже хочу попробовать.
НАшел.
ПРоверил. Действительно ругается.
> Игорь Шевченко © (21.06.04 11:41) [30]
Не подумайте, что придираюсь, просто ищу правду.
Но вот это:
Рихтер 4 изд, глава 22.
"Вызов CreateRemoteThread предполагает, что Kerne32.dll спроецирована в локальном процессе на ту же область памяти, что и в удаленном. Kernel32.dll используется всеми приложениями, и, как показывает опыт, система проецирует эту DLL в каждом процессе по одному и тому же адресу."
Промотрел начиная с 19 главы. Не вижу, что Kernel32.dll проецируется по одному адресу.
Все ж таки интересно, как эту информацию обрабатывать...
Тимохов (2004-06-21 11:57:00) [9]
> VMcL © (21.06.04 11:33) [29]
тоже хочу попробовать.
Какой базовый адрес у kernel32?
Игорь Шевченко (2004-06-21 11:41:00) [10]
> Посидел в выходные не нашел документального подтверждения
> тому, что он во всех процессах обязательно будет одинаковым
У Рихтера написано. В главе DLL и следующей за ней.
VMcL (2004-06-21 11:33:00) [11]>>Тимохов © (21.06.04 11:19) [28]
>Все ж таки про базовый адрес kernel32.dll
см. [6] Я уже попробовал. Очень интересное окошко вылазит.
Тимохов (2004-06-21 11:19:00) [12]
> Игорь Шевченко © (18.06.04 21:48) [27]
т.е. проверять не надо, надо верить!
Так?
Все ж таки про базовый адрес kernel32.dll.
Посидел в выходные не нашел документального подтверждения тому, что он во всех процессах обязательно будет одинаковым.
Игорь Шевченко (2004-06-18 21:48:00) [13]
> Вы этот факт как то проверяли перед внедрением?
Вообще-то кроме SMSS.EXE все процессы импортируют KERNEL32.DLL (по крайней мере, я не встречал другого Native-процесса)
Тимохов (2004-06-18 18:23:00) [14]
> Burmistroff (18.06.04 18:16) [25]
спасибо.
Burmistroff (2004-06-18 18:16:00) [15]Пример со "своими" функциями. Правда довольно корявый. когда он писался, знания асма были близки к нулю ;)
(см. "DoRemoteJob")
http://www.maxcomputing.narod.ru/ahijack2.html
Тимохов (2004-06-18 16:50:00) [16]
> В процессы, которые функции из kernel32.dll не экспортируют,
Вы этот факт как то проверяли перед внедрением?
Т.о. еще раз суммирую полученные знания:
1. Все кто пользовался CreateRemoteThread делали это так, как написано у Рихтера, т.е. через LoadLibrary.
2. Явных указаний, что кто-то все-таки делал свою функцию я не увидел.
Игорь Шевченко (2004-06-18 16:42:00) [17]Тимохов © (18.06.04 16:29)
Не делал. А зачем, когда можно сделать LoadLibrary ? В процессы, которые функции из kernel32.dll не экспортируют, я не пытался внедряться, вроде незачем.
Тимохов (2004-06-18 16:29:00) [18]виноват "Вы" забыл в вопросе :)
Тимохов (2004-06-18 16:28:00) [19]
> Игорь Шевченко © (18.06.04 16:19) [20]
> В [6] я, насколько мне помнится, сказал, что делал позиционно-независимый
> код, а не CreateRemoteThread без LoadLibrary
ну в общем да, другого вы и не говорили.
значит я вас не так понял или вопрос не так задал.
Тогда поставлю вопрос более корректно (ну чтобы разночтений не было)
А все-таки без LoadLibrary со своей позиционнонезависимой поточной функциейделали CreateRemoteThread?
Игорь Шевченко (2004-06-18 16:19:00) [20]Тимохов © (18.06.04 16:13)
> Вы же в [6] сказали что делали без LoadLibrary. Вот и мне
> интересно как это.
В [6] я, насколько мне помнится, сказал, что делал позиционно-независимый код, а не CreateRemoteThread без LoadLibrary