Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

CreateRemoteThread [D6, WinXP]


Страницы:   1 2

Тимохов ©   (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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо