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

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

Поток без длл или самодостаточный код


Страницы:   1 2 3 4 5 6

kaZaNoVa ©   (2004-11-10 18:01:00) 

Идея: создать программу, которая могла бы "создавать самодостаточный код" - в плане того, чтобы возможно внедриться в другой процесс, и при этом НЕ подгружать дополнительных DLL ;)
Я давно интересовался этой темой, и только недавно нащёл реализацию:
(использованы материалы с сайта   http://www.iamaphex.cjb.net)
код:
program Project1;

{$IMAGEBASE $13140000}

uses
 Windows;

function Main(dwEntryPoint: Pointer): longword; stdcall;
begin
 LoadLibrary('kernel32.dll');
 LoadLibrary('user32.dll');
    MessageBox(0, 'Ok', 'Hijacked Process', 0);
// ExitProcess(0);
 Result := 0;
end;

procedure Inject(ProcessHandle: longword; EntryPoint: pointer);
var
 Module, NewModule: Pointer;
 Size, BytesWritten, TID: longword;
begin
 Module := Pointer(GetModuleHandle(nil));
 Size := PImageOptionalHeader(Pointer(integer(Module) + PImageDosHeader(Module)._lfanew + SizeOf(dword) + SizeOf(TImageFileHeader))).SizeOfImage;
 VirtualFreeEx(ProcessHandle, Module, 0, MEM_RELEASE);
 NewModule := VirtualAllocEx(ProcessHandle, Module, Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
 WriteProcessMemory(ProcessHandle, NewModule, Module, Size, BytesWritten);
 CreateRemoteThread(ProcessHandle, nil, 0, EntryPoint, Module, 0, TID);
end;

var
 ProcessHandle, PID: longword;
begin
 GetWindowThreadProcessId(FindWindow('Progman', nil), @PID);
 ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
 Inject(ProcessHandle, @Main);
 CloseHandle(ProcessHandle);
end.


Меня интересует - всё ли в этом примере правильно - нет ли негде "подводных камней" ?

И, что будет, если в созданном потоке возникнет исключение - "процесс-носитель" в этом случае завершится ? - как в таком случае можно обрабатывать исключения ?


kaZaNoVa   (2004-11-15 15:29:00) [81]

Function I(t:cardinal):string;
Begin
Str(t,Result);
End;

function ThreadF1(dwEntryPoint: Pointer): longword; stdcall;
Var t:string;
begin
LoadLibrary('kernel32.dll');
LoadLibrary('user32.dll');
sleep(500);
t:='1';
t:=i(1);
Result := 0;
end;

такой код выдаёт исключение ..  странно ..


kaZaNoVa   (2004-11-15 15:28:00) [82]

Digitman ©   (15.11.04 15:26) [29]

> ты о ран-тайм-пакетах что-нть слыхал ?

слыхал ..  но это имхо не то ..
(их таскать за собой придётся ...)


Digitman   (2004-11-15 15:26:00) [83]


> kaZaNoVa ©   (15.11.04 15:12) [28]


> у меня маленький


ты о ран-тайм-пакетах что-нть слыхал ?


> что будет если я свой ехе упакую UPX ?


ничего не будет.
это - из другой оперы.


> осталось от старой попытки


и долго ты тут будешь захламлять ветку, без конца дублируя код от "старых попыток" ? например, код установки привелегий чего-то там, НЕ имеющий к сабжу никакого отношения ?


kaZaNoVa   (2004-11-15 15:12:00) [84]

Digitman ©   (15.11.04 14:19) [27]

> каша у тебя в голове..

да уж .. надо справку почитать ..

> и опять ты пытаешься влупить в чужое АП образ всего
> своего ехе-модуля .. и опять - в предположении о
> фиксированном его Imagebase

так как у меня маленький ехе (15-20 кб) я думаю, что ничего плохого не будет, если загружу его целиком ..

у меня появился ОЧЕНЬ важный вопрос, а что будет если я свой ехе упакую UPX ?


> Pointer(Integer(@Main1)-Integer(Module)+Integer(MemPtr)
> )
осталось от старой попытки загрузить по другому адресу ...


Digitman   (2004-11-15 14:19:00) [85]

каша у тебя в голове..

и опять ты пытаешься влупить в чужое АП образ всего своего ехе-модуля .. и опять - в предположении о фиксированном его Imagebase

спрашивается, на кой шут все эти выкрутасы с

Pointer(Integer(@Main1)-Integer(Module)+Integer(MemPtr))

и пр.

?


> думаю, вероятность


до тех пор пока ты полагаешься в этом деле на "вероятность", ничего путного у тебя не выйдет


kaZaNoVa   (2004-11-15 14:02:00) [86]

эх ...  что-то ничего у меня с м "изменяющимися" адресами функций не вышло ..

сделал так:

program loader;
{$IMAGEBASE $72780000}
uses
 Windows,Tlhelp32;

function Main1(dwEntryPoint: Pointer): longword; stdcall;
begin
LoadLibrary('kernel32.dll');
LoadLibrary('user32.dll');
MessageBox(0, 'Ok', 'Hijacked Process', 0);
// ExitProcess(0);
Result := 0;
end;

function SetDebugPriv: Boolean;
var
Token: THandle;
tkp: TTokenPrivileges;
begin
Result := false;
if OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token) then
begin
 if LookupPrivilegeValue(nil, PChar('SeDebugPrivilege'), tkp.Privileges[0].Luid) then
 begin
   tkp.PrivilegeCount := 1;
   tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
   Result := AdjustTokenPrivileges(Token, false, tkp, 0, PTokenPrivileges(nil)^, PDWord(nil)^);
 end;
end;
end;

function Start(ProcessID: Cardinal; DllFileName: string): Boolean;
var
hProcess, hTh: THandle;
BytesWritten, ThreadID: Cardinal;
MemPtr: Pointer;
ExitCode: DWord;
Size: longword;
Module: Pointer;

begin
Module := Pointer(GetModuleHandle(nil));
Size := PImageOptionalHeader(Pointer(integer(Module) + PImageDosHeader(Module)._lfanew + SizeOf(dword) + SizeOf(TImageFileHeader))).SizeOfImage;

Result := false;

SetDebugPriv();

hProcess := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE,true, ProcessID);

if hProcess <> 0 then
begin
BytesWritten:=0;
 VirtualFreeEx(hProcess, Module, 0, MEM_RELEASE);
 MemPtr := VirtualAllocEx(hProcess,Module, Size , MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE );

 if MemPtr <> nil then
 begin
   if WriteProcessMemory(hProcess, MemPtr,Module, Size, BytesWritten) then
   begin
   hTh := CreateRemoteThread(hProcess, nil, 0,Pointer(Integer(@Main1)-Integer(Module)+Integer(MemPtr)),MemPtr, 0, ThreadID);
     if hTh <> 0 then
     begin
       if (WaitForSingleObject(hTh, INFINITE) = WAIT_OBJECT_0) and
         GetExitCodeThread(hTh, ExitCode) then
         Result := ExitCode <> 0;

       CloseHandle(hTh);
     end;
   end;

   VirtualFreeEx(hProcess, MemPtr, 0, MEM_RELEASE);
 end;

 CloseHandle(hProcess);
end;

end;

function UpperCase(const S: string): string;
var I : Integer;
begin
 Result := S;
 for I := 1 to Length( S ) do
   if Result[ I ] in [ 'a'..'z' ] then
      Dec( Result[ I ], 32 );
end;
               

var
ProcessID: Cardinal;
DllName,ppp: string;
ContinueLoop: BOOL;
FSnapshotHandle: THandle;
FProcessEntry32: TProcessEntry32;
begin
ProcessID:=0;

FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);

ContinueLoop := Process32First(FSnapshotHandle,FProcessEntry32);
while integer(ContinueLoop) <> 0 do
 begin
ppp:=FProcessEntry32.szExeFile;
if (pos('CALC.EXE',UpperCase(ppp))>0) then  ProcessID:=FProcessEntry32.th32ProcessID;
ContinueLoop := Process32Next(FSnapshotHandle,  FProcessEntry32);
 end;
CloseHandle(FSnapshotHandle);

if ProcessID <> 0 then Start(ProcessID, DllName);

end.


думаю, вероятность того, что $72780000 будет занят - очень мала ..
пока везде, где запускал - код работает ...
буду тестировать на разных процессах ...


Digitman   (2004-11-15 13:27:00) [87]


> обнаружил там мой ЕХЕшник целеком ;))
> прикольно ..  :)
> (поначалу не ожидал, думал что будет только код  нужной
> процедуры ..)


что ж "прикольного" ?
тебе еще в [9] об этом сказано


> хотелось бы по грамотнее реализовать


"грамотная" реализация сводится к размещению в "чужом" АП всего того что минимально необходимо для корректной работы стартуемого там трэда, а так же позиционная независимость кода этого трэда, если это необходимо.


kaZaNoVa   (2004-11-15 13:22:00) [88]

Digitman ©   (15.11.04 12:35) [22]

>> а какой этот адрес ?
>
>
> какая тебе разница, "какой" он ? важно что этот адрес
> должен иметь одно и то же значение для любого
> win32-процесса, использующего модуль kernel32

нашёл, кажется 2011430912 (в десятичной системе)
или 0x77E40000   ;))

а что значит:

> - стартовавшая ThreadFunc первым делом получает хэндл
> hKernel32, накладывая маску $FFF00000 на переданный ей
> параметром адрес

как такую маску наложить ?
(integer(dwEntryPoint) xor $FFF00000)?


kaZaNoVa   (2004-11-15 13:07:00) [89]

тут я попробовал залезть в память "целевого" процесса и посмотреть, что там по загружаемому адресу находидится (лазил через Редактор Памяти ArtMoney) - и обнаружил там мой ЕХЕшник целеком ;))
прикольно ..  :)
(поначалу не ожидал, думал что будет только код  нужной процедуры ..)

Всё-таки сама эта моя идея "самостоятельный поток в чужом процессе" сейчас мне кажется немного "бредовой", но она , как я уже убедился, реализуема ;)
только бы хотелось бы по грамотнее реализовать .. :)
---

тут я на одном форуме видел обсуждения подобной идеи:

----
загрузить модуль, скопировать всю память модуля в "карман"
выгрузить модуль, произвести аллокацию по тому же адресу, и скопировать память обратно. Правда здесь не факт, что я смогу аллоцировтаь память по тому же адресу.

------

Не сможешь по тому адресу (хотя должОн смочь) - сможешь по другому. Потом придется только reloc поправить :) Вот только если ты его скопируешь целиком, то можно будет распознать MZ/PE заголовок, и таким образом узнать о наличии постороннего модуля. С другой стороны, ты можешь и сам этот заголовок подпортить... А с третьей стороны, я, как админ, тебя за такие идеи "убыв бы!" :-E

-----

ну насчет - смогу по другому - не хоцца мне релоки править.
-----

там они так и не реализовали .. (а может и реализовали, но не запостили ;((


Digitman   (2004-11-15 12:35:00) [90]


> а какой этот адрес ?


какая тебе разница, "какой" он ? важно что этот адрес должен иметь одно и то же значение для любого win32-процесса, использующего модуль kernel32


> какие ?


например, в "чужом" АП в ходе выполнения ThreadFunc определить адрес X т.входа в "саму себя" .. и если известно, что перед непосредственно телом ThreadFunc находится некая структура размером в Y байт, то смещение абс.адреса начала этой структуры будет равно X - Y


kaZaNoVa   (2004-11-15 12:21:00) [91]


> - основываясь на достаточно устойчивом факте загрузки
> kernel32 по фикс.адресу, получаешь адрес ф-ции
> kernel32.GetProcAddress()

а какой этот адрес ?


>> как расчитывается это смещение
>
>
> есть масса самых разных способов

какие ?


> что такое 11771 ?

это я сравнивал адреса разных функций, одно из смещений ...


Digitman   (2004-11-15 08:36:00) [92]


> а как ?
> Cardinal(@GetProcAddress) ?


GetProcAddress(hKernel32, 'GetProcAddress');


> добавать 11771  


что такое 11771 ?


> как расчитывается это смещение


есть масса самых разных способов


kaZaNoVa   (2004-11-15 00:32:00) [93]

или может попробывать добавлять по 1 - и каждый раз пробовать вызывать функцию .. хотя, не, это изврат ..


kaZaNoVa   (2004-11-12 21:55:00) [94]

- основываясь на достаточно устойчивом факте загрузки kernel32 по фикс.адресу, получаешь адрес ф-ции kernel32.GetProcAddress()
а как ?
Cardinal(@GetProcAddress)?


> - далее ThreadFunc вызвает GetProcAddress(hKernel32,
> адрес_константы_содержащей_строку_LoadLibraryA) для
> получения адреса точки входа в
> kernel32.LoadLibraryA(); отн.смещение константы со
> строкой 'LoadLibraryA' расчитывается отн-но @ThreadFunc

а как расчитывается это смещение ?
(добавать 11771  ?)


Digitman   (2004-11-12 15:35:00) [95]


> а почему плох вариант с Imagebase


я тебе уже сказал - ненадежность.
сегодня сработал (регион нужного размера оказался незанятым), завтра не сработал.... и нафих такой код нужен, гарантия успешной работы которого заведомо не 100%-на ? причем по независящим от тебя причинам ?


> легко определить, где он будет загружен


что там определять-то ? ты сам и говоришь системе, куда ты влупить свой код хочешь ... только вот система вовсе не обязана "выпихивать" с требуемого тебе места того кто там уже до тебя "поселился", если факт обнаружится, ситема просто вернет тебе отлуп в ответ на VirtualAllocEx и ты сел в лужу - что дальше делать будешь ?


> или он (код в памяти) может загрузиться по другому адресу,
> игнорируя Imagebase  


с какого перепугу-то ? ты же явно говоришь системе : мне, мол, надыть регион размером в 100мб начиная с $13140000 ..

вот если ты скажешь, что тебе надо те же 100мб где угодно (т.е. где найдется местечко), вот тогда система либо найдет такое местечко и скажет тебе его адрес либо ты опять же получишь отлуп


kaZaNoVa   (2004-11-12 14:52:00) [96]

Digitman ©   (12.11.04 14:18) [14]
а какие меры он может предпринять ?


kaZaNoVa   (2004-11-12 14:51:00) [97]

Digitman ©   (12.11.04 12:46) [9]

> Естественно, маш.код ThreadFunc() д.б.
> позиционно-независимым, иначе придется прибегать к
> тому же ненадежному способу жесткой привязки к
> Imagebase, который ты сейчас пытаешься реализовать

а почему плох вариант с Imagebase- он же даёт возможность загружаться именно так,как нужно  ;))

(легко определить, где он будет загружен :))
- нет гимора с определением адресов .. :)))

- или он (код в памяти) может загрузиться по другому адресу, игнорируя Imagebase ?


Digitman   (2004-11-12 14:18:00) [98]


> "код без файла" (длл, ехе)- в другом процессе - это новое
> слово в системном программировании !!!


ой да ладно, не загибай уж ... теб более про "системное" : все эти потуги ничего общего с системным программированием не имеют

к тому же, если "суррогатный" процесс заинтересован не допустить в свой контекст "инородные тела" (типа "чужого" модуля, трэда, региона и т.д. и т.п.), то он всегда в состоянии принять для этого вполне эффективные меры. И как ты не пытайся, воткнуть в него тело своего трэда тебе в этом случае попросту не удастся


kaZaNoVa   (2004-11-12 14:08:00) [99]

с длл - "вчерашний день"  ;)


kaZaNoVa   (2004-11-12 14:07:00) [100]

Digitman ©   (12.11.04 13:44) [11]
с длл всё конечно хорошо :))
но моя цель сейчас реализовать именно грамотно "без длл"  ;))
так как очень хочется возможности создавать удалённые потоки "чисстые" - то есть без подгрузки всяких дополнительных длл ;)))

а применение просто обширно - от реализации "чистого" перехвата апи-функций (так как например если перехватить внедрённой длл, то она будет видна в списке модулей процесса, и может дать подозрения "что с процессом что-то не то") и до реализации "изяшного" (!) способа самоудаления - например для инсталляторов, так как в результате работы кода НЕ остаётся никаких "дополнительных" длл  %)

поэтому мне очень важно именно "код в памяти", я раньше думал что это невозможно, но первый пример, хоть и корявый, но рабочий доказывает то, что это ВОЗМОЖНО :))
а "код без файла" (длл, ехе)- в другом процессе - это новое слово в системном программировании !!!

("вирусные" технологии типа подмен секций и точки входа - грязно и нехорошо, а внедрение "чистого" (относительно) кода в другой процесс и работа в нём открывают поистине фантастические возможности ;)))))  и при этом всё "законно" - так как никакие фацлы не изменяются и нет ничего вредного ;)))) )


Страницы:   1 2 3 4 5 6

Наверх

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