информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Где водятся OGRыАтака на InternetПортрет посетителя
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Очередное исследование 19 миллиардов... 
 Оптимизация ввода-вывода как инструмент... 
 Зловреды выбирают Lisp и Delphi 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
если вы видите этот текст, отключите в настройках форума использование JavaScript
ФОРУМ
все доски
FAQ
IRC
новые сообщения
site updates
guestbook
beginners
sysadmin
programming
operating systems
theory
web building
software
hardware
networking
law
hacking
gadgets
job
dnet
humor
miscellaneous
scrap
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
[Pascal] CreateRemoteThread подводные камни. Что делать? Help, please ;-((( 27.10.02 01:58  Число просмотров: 1735
Автор: :-) <:-)> Статус: 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-2025 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach