информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Spanning Tree Protocol: недокументированное применениеЗа кого нас держат?Где водятся OGRы
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
[Pascal] CreateRemoteThread подводные камни. Что делать? Help, please ;-((( 27.10.02 01:58  Число просмотров: 1639
Автор: :-) <:-)> Статус: Elderman
<"чистая" ссылка>
> Итак, как можно видеть, открывается дескриптор процесса
> RegEdit. В нём выделяется память под поток. Копируется в
> эту память исполняемый код потока. Запускается поток на
> выполнение. Работает допущение, что базовый адрес, куда
> загружен Kernel32 в чужом процессе и в моём одинаковые.
> Вопросы:
> 1) Существует ли более-менее "человеческий" способ
> определения размера исполняемого кода — или заходить в
> дебуггер и вручную его считать.

void F1() {}
void F2() {}

int SizeOfF1 = (int)F2 - (int)F1;

> 2) В этом простейшем случае инструкции в потоке идут одна
> за другой. Надо думать, что с появлением ветвлений, циклов
> и т.п., компилятор Delphi, "думая", что компилит для
> "родного" процесса, будет ставить
> абсолютные адреса переходов для
> ветвлений. Можно ли как-нибудь исхитриться и задать
> относительные? И вообще, возможно ли такое без применения
> in-line ассемблера?

А по-моему, для ветвлений, циклов и т.п большинство компиляторов (VC и Delphi в том числе) генерят относительные переходы...

> 3) Почему компилятор генерит такой код возврата из функции,
> помеченной как Stdcall: RET $0004. Я на всякий случай
> поставил просто RET. Как более правильно, поскольку что
> так, что эдак работает ;-)

Должно быть retn 4. Раз ф-я stdcall и принимает 1 параметр, она по возвращении сама должна снять со стека 4 байта. Мне вообще не понятно, зачем нужен этот код (и без него должно работать):
ASM // Correct return throm tread
POP EBP
RET
END;
К тому же этот код зависит от конкретного компилятора: компилятор может и не положить в стек EBP (или наоборот, кроме EBP в стеке может оказаться еще что-нибудь).

> И вообще, может я делаю что-то через задницу? ;-)) Что
> лучше всего использовать для создания кода, который будет
> исполняться в другом процессе?
> Всем спасибо, жду ответов.

Посмотри в книге Рихтера - он с помощью CreateRemoteThread загружает в чужой процесс свою DLL. Вызывая CreateRemoteThread, ей качестве threadfunc передает адрес LoadLibrary (раз Kernel32 в другом процессе загружен по тому же адресу), а в качестве параметра - адрес строки "c:\mydll.dll" (перед этим ее надо поместить в адресное пространство чужого процесса).
<programming>
[Pascal] CreateRemoteThread подводные камни. Что делать? Help, please ;-((( 26.10.02 23:06  
Автор: HandleX <Александр М.> Статус: The Elderman
Отредактировано 26.10.02 23:16  Количество правок: 1
<"чистая" ссылка>
Ну вот, доигрался. Не хватает мне возможностей моего любимого компилера. Что делать? Ума не преложу. Неужели на Asm писать весь код?

Итак, проблема. Нужно кое-что поделать в адресном пространстве запущенного приложения — к примеру, RegEdit.
Вот код примера, а конкретные вопросы смотрите после ;-)
implementation
{$R *.DFM}
Type TBeepProc = Function(dwFreq, dwDuration: DWORD): BOOL; StdCall;

  Function rThread(aValue: Pointer): DWORD; StdCall;
  Begin
    TBeepProc(aValue)(5000, 10);
    Result := 777;

    ASM // Correct return throm tread
      POP EBP
      RET
    END;
  End;

procedure TForm1.Button1Click(Sender: TObject);

  Function GetProcessIDByTopmostWindowClass(aClass: String): DWORD;
  Var wHndl: THandle;
  begin
    wHndl := FindWindow(PChar(aClass), Nil);
    Win32Check(wHndl <> 0);
    GetWindowThreadProcessID(wHndl, @Result);
  End;

  Function GetProcAddrFromKernel(aProcName: String): Pointer;
  Var hMod: THandle;
  Begin
    hMod := GetModuleHandle(Kernel32);
    Win32Check(hMod <> 0);
    Result := GetProcAddress(hMod, PChar(aProcName));
    Win32Check(Result <> Nil);
  End;

Const pMemSize = 32;
Var
  pID, pHndl, tHndl, tID: THandle;
  rMem: Pointer;
  S: DWORD;
begin
  pID := GetProcessIDByTopmostWindowClass('RegEdit_RegEdit');
  Win32Check(pID <> 0);
  pHndl := OpenProcess(PROCESS_ALL_ACCESS, False, pID);
  Win32Check(pHndl <> 0);
  Try
    rMem := VirtualAllocEx(pHndl, Nil, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    Win32Check(rMem <> Nil);
    Try
      Win32Check(WriteProcessMemory(pHndl, rMem, @rThread, pMemSize, S));
      Win32Check(S = pMemSize);
      Win32Check(VirtualProtectEx(pHndl, rMem, pMemSize, PAGE_EXECUTE_READ, S));
      tHndl := CreateRemoteThread(pHndl, Nil, 0, rMem, GetProcAddrFromKernel('Beep'), CREATE_SUSPENDED, tID);
      Win32Check(tHndl <> 0);
      Try
        ResumeThread(tHndl);
        WaitForSingleObject(tHndl, INFINITE);
        Win32Check(GetExitCodeThread(tHndl, S));
        Caption := IntToStr(S);
      Finally
        CloseHandle(tHndl);
      End;
    Finally
      Win32Check(VirtualFreeEx(pHndl, rMem, 0, MEM_RELEASE) <> Nil);
    End;
  Finally
    CloseHandle(pHndl);
  End
end;

---

Итак, как можно видеть, открывается дескриптор процесса RegEdit. В нём выделяется память под поток. Копируется в эту память исполняемый код потока. Запускается поток на выполнение. Работает допущение, что базовый адрес, куда загружен Kernel32 в чужом процессе и в моём одинаковые.
Вопросы:
1) Существует ли более-менее "человеческий" способ определения размера исполняемого кода — или заходить в дебуггер и вручную его считать.
2) В этом простейшем случае инструкции в потоке идут одна за другой. Надо думать, что с появлением ветвлений, циклов и т.п., компилятор Delphi, "думая", что компилит для "родного" процесса, будет ставить абсолютные адреса переходов для ветвлений. Можно ли как-нибудь исхитриться и задать относительные? И вообще, возможно ли такое без применения in-line ассемблера?
3) Почему компилятор генерит такой код возврата из функции, помеченной как Stdcall: RET $0004. Я на всякий случай поставил просто RET. Как более правильно, поскольку что так, что эдак работает ;-)

И вообще, может я делаю что-то через задницу? ;-)) Что лучше всего использовать для создания кода, который будет исполняться в другом процессе?
Всем спасибо, жду ответов.
[Pascal] CreateRemoteThread подводные камни. Что делать? Help, please ;-((( 27.10.02 01:58  
Автор: :-) <:-)> Статус: Elderman
<"чистая" ссылка>
> Итак, как можно видеть, открывается дескриптор процесса
> RegEdit. В нём выделяется память под поток. Копируется в
> эту память исполняемый код потока. Запускается поток на
> выполнение. Работает допущение, что базовый адрес, куда
> загружен Kernel32 в чужом процессе и в моём одинаковые.
> Вопросы:
> 1) Существует ли более-менее "человеческий" способ
> определения размера исполняемого кода — или заходить в
> дебуггер и вручную его считать.

void F1() {}
void F2() {}

int SizeOfF1 = (int)F2 - (int)F1;

> 2) В этом простейшем случае инструкции в потоке идут одна
> за другой. Надо думать, что с появлением ветвлений, циклов
> и т.п., компилятор Delphi, "думая", что компилит для
> "родного" процесса, будет ставить
> абсолютные адреса переходов для
> ветвлений. Можно ли как-нибудь исхитриться и задать
> относительные? И вообще, возможно ли такое без применения
> in-line ассемблера?

А по-моему, для ветвлений, циклов и т.п большинство компиляторов (VC и Delphi в том числе) генерят относительные переходы...

> 3) Почему компилятор генерит такой код возврата из функции,
> помеченной как Stdcall: RET $0004. Я на всякий случай
> поставил просто RET. Как более правильно, поскольку что
> так, что эдак работает ;-)

Должно быть retn 4. Раз ф-я stdcall и принимает 1 параметр, она по возвращении сама должна снять со стека 4 байта. Мне вообще не понятно, зачем нужен этот код (и без него должно работать):
ASM // Correct return throm tread
POP EBP
RET
END;
К тому же этот код зависит от конкретного компилятора: компилятор может и не положить в стек EBP (или наоборот, кроме EBP в стеке может оказаться еще что-нибудь).

> И вообще, может я делаю что-то через задницу? ;-)) Что
> лучше всего использовать для создания кода, который будет
> исполняться в другом процессе?
> Всем спасибо, жду ответов.

Посмотри в книге Рихтера - он с помощью CreateRemoteThread загружает в чужой процесс свою DLL. Вызывая CreateRemoteThread, ей качестве threadfunc передает адрес LoadLibrary (раз Kernel32 в другом процессе загружен по тому же адресу), а в качестве параметра - адрес строки "c:\mydll.dll" (перед этим ее надо поместить в адресное пространство чужого процесса).
Понятно, спасибо. Про DLL я понимаю что будет клёво работать, просто мне была интересна идея работы "впрыскивания кода" в чужой процесс. "Чисто впрыснутый" поток трудно отследить ;-) 27.10.02 19:17  
Автор: HandleX <Александр М.> Статус: The Elderman
<"чистая" ссылка>
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach