Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.01.23;
Скачать: CL | DM;

Вниз

Поток без длл или самодостаточный код   Найти похожие ветки 

 
kaZaNoVa ©   (2004-11-10 18:01) [0]

Идея: создать программу, которая могла бы "создавать самодостаточный код" - в плане того, чтобы возможно внедриться в другой процесс, и при этом НЕ подгружать дополнительных 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.


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

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


 
Игорь Шевченко ©   (2004-11-10 18:41) [1]


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


Практика - критерий истины.


 
kaZaNoVa ©   (2004-11-10 21:01) [2]

Игорь Шевченко ©   (10.11.04 18:41) [1]
а насчёт исключений - как можно их обработать ?

зы ОСи 2000 XP 2003 LongHorn


 
Digitman ©   (2004-11-11 08:42) [3]


> нет ли негде "подводных камней" ?


начнем с этой строчки

VirtualFreeEx(ProcessHandle, Module, 0, MEM_RELEASE);

на основании чего ты уверен, что в АП целевого процесса регион с базовым адресом Module занят ? какое право ты имеешь освобождать этот регион ?

далее

NewModule := VirtualAllocEx(ProcessHandle, Module, Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);

ну, предположим, предыдущей строчкой ты успешно освободил регион по требуемому адресу

с чего ты взял, что размер затребованного тобой региона по адресу Module будет не менее Size ? ведь ты даже результат работы ф-ции не проверяешь ! и следом ничтоже сумняшеся пишешь в в регион Size байт, даже не зная, зарезервирован ли в действительности регион требуемого тебе размера..

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


 
kaZaNoVa ©   (2004-11-11 13:58) [4]

Digitman ©   (11.11.04 8:42) [3]
но самое интересное, что данный код всё-же работает ...

а как правильно ?


NewModule := VirtualAllocEx(ProcessHandle,nil, Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
 ?


 
Digitman ©   (2004-11-11 14:13) [5]


> kaZaNoVa ©   (11.11.04 13:58) [4]


> данный код всё-же работает


угу. в некоем частном случае.
но тебе же ОБЩИЙ случай, думаю, нужен, а не некий частный, который сработал случайно, хоть и неоднократно ?


> а как правильно ?


а в Справке не написано разве, как правильно анализировать рез-т работы этой ф-ции ?


 
kaZaNoVa ©   (2004-11-11 14:23) [6]

Digitman ©   (11.11.04 14:13) [5]
да, нужна полная работоспособность ;))

ок ..  буду рыть справку .. :)

а кстати, нужен PAGE_EXECUTE_READWRITE или PAGE_READWRITE  ?

и почему-то в некоторых примерах MEM_COMMIT  идёт без MEM_RESERVE ...  ?


 
Digitman ©   (2004-11-11 15:01) [7]


> нужен PAGE_EXECUTE_READWRITE или PAGE_READWRITE  ?


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


> почему-то в некоторых примерах MEM_COMMIT  идёт без MEM_RESERVE


вот я купил билет в оперу.
я ЗАРЕЗЕРВИРОВАЛ т.н. "место".
я могу и не прийти на шоу или опоздать на него, но при сем билет, купленный мной, по идее РЕЗЕРВИРУЕТ за мной право воспользоваться всеми теми "благами", которыми я могу (но вовсе не обязан) воспользоваться, купив этот билет..

а именно хотя бы :

- не беспокоиться за сохранность своей пальты из ангорского баклана, сданной как и положено туда, где начинается театр;

- сидеть на своем месте в театр.зале (уж это безусловно);

- дышать (театральная система кондиционирования);

- лупануть в антракте 50гр. коньячку под "икру заморскую" в тетр.буфете (на меня делается расчет);

- и т.д. и т.п.

таки явившись в оперу я реализую свое право, и некие расчитанные под меня ресурсы оперной "кухни" реально работают на меня, т.е. я сделал RESERVE + COMMIT

таки не явившись в оперу я явил собой "собаку на сене", т.е. я сделал RESERVE


 
kaZaNoVa ©   (2004-11-11 15:23) [8]

Digitman ©   (11.11.04 15:01) [7]
спасибо за обьяснение, буду разбираться ;)))


 
Digitman ©   (2004-11-12 12:46) [9]


> kaZaNoVa ©   (11.11.04 15:23) [8]


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

но если таки вариант с внедрением ДЛЛ тебя никак не устраивает, в кач-ве разумной альтернативы я бы предложил след.схему

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

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

- стартуешь удаленный трэд, передавая ему параметром полученный адрес

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

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

- получив этот адрес ThreadFunc получает возможность определять хэндлы user32, gdi32 (и других уже загруженных сист.библ-к) и грузить прочие необходимые системные/несистемные библ-ки для обеспечения работоспособности дальнейшего своего алгоритма

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

-


 
kaZaNoVa ©   (2004-11-12 13:08) [10]

Digitman ©   (12.11.04 12:46) [9]
ок, спасибо, попробую !

//вариант с длл недопустим хотя бы потому, что код будет он неё звависеть - то есть не будет "сам по себе"  ;))


 
Digitman ©   (2004-11-12 13:44) [11]


> код будет он неё звависеть


не выдумывай.

создай группу проектов, один проект - внедряющий ехе, другой - внедряемая ДЛЛ

в ходе разработки делай в них согласованные логические изменения, если предполагается, что внедряемая ДЛЛ будет по опред.соглашениям взаимодействовать с внедряющим ехе

строй все проекты разом, одним движением руки - build all

всех делов !


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

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

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

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

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


 
kaZaNoVa ©   (2004-11-12 14:08) [13]

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


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


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


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

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


 
kaZaNoVa ©   (2004-11-12 14:51) [15]

Digitman ©   (12.11.04 12:46) [9]

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

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

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

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


 
kaZaNoVa ©   (2004-11-12 14:52) [16]

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


 
Digitman ©   (2004-11-12 15:35) [17]


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


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


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


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


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


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

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


 
kaZaNoVa ©   (2004-11-12 21:55) [18]

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


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

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


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

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


 
Digitman ©   (2004-11-15 08:36) [20]


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


GetProcAddress(hKernel32, "GetProcAddress");


> добавать 11771  


что такое 11771 ?


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


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


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


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

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


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

какие ?


> что такое 11771 ?

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


 
Digitman ©   (2004-11-15 12:35) [22]


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


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


> какие ?


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


 
kaZaNoVa ©   (2004-11-15 13:07) [23]

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

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

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

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

------

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

-----

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

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


 
kaZaNoVa ©   (2004-11-15 13:22) [24]

Digitman ©   (15.11.04 12:35) [22]

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

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

а что значит:

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

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


 
Digitman ©   (2004-11-15 13:27) [25]


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


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


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


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


 
kaZaNoVa ©   (2004-11-15 14:02) [26]

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

сделал так:

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 14:19) [27]

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

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

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

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

и пр.

?


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


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


 
kaZaNoVa ©   (2004-11-15 15:12) [28]

Digitman ©   (15.11.04 14:19) [27]

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

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

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

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

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


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


 
Digitman ©   (2004-11-15 15:26) [29]


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


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


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


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


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


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


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


 
kaZaNoVa ©   (2004-11-15 15:28) [30]

Digitman ©   (15.11.04 15:26) [29]

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

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


 
kaZaNoVa ©   (2004-11-15 15:29) [31]

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:30) [32]

Digitman ©   (15.11.04 15:26) [29]

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

постараюсь приводить только "значимый" код ;)))


 
Digitman ©   (2004-11-15 15:38) [33]


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


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


и это все что ты знаешь о ран-тайм пакетах ? применительно к поднятой тобой теме ?

те самые 15-20к твоего ехе - это ВЕСЬ код ? или код в расчете на использование кода из ран-тайм пакетов ?


 
kaZaNoVa ©   (2004-11-15 15:40) [34]

Digitman ©   (15.11.04 15:38) [33]

> те самые 15-20к твоего ехе - это ВЕСЬ код ? или код в
> расчете на использование кода из ран-тайм пакетов ?

весь код ...


 
Digitman ©   (2004-11-15 16:11) [35]


> kaZaNoVa ©   (15.11.04 15:40) [34]


слушай, я устал уже.
говорим на совершенно разных языках.
последний вопрос в надежде восстановить "понимание" - в опциях проекта, в котором ты пытаешься "влупить" некий код в "чужое" АП, галка "Build With Run-Time Packages" стоит или "висит" ?


 
kaZaNoVa ©   (2004-11-15 16:16) [36]

галки НЕТ


 
kaZaNoVa ©   (2004-11-15 16:18) [37]

а как отлаживать его ?
(код в чужом процессе ?)
и я почему-то не могу преобразовать cardinal в string . . выдвётся исключение


 
Digitman ©   (2004-11-15 16:36) [38]


> галки НЕТ


щзначит, остается проблема "статики".


> как отлаживать его ?


вопрос отдельный.


> почему-то не могу преобразовать cardinal в string


с какого перепугу "cardinal в string" преобразуется ?


 
kaZaNoVa ©   (2004-11-15 16:51) [39]

Digitman ©   (15.11.04 16:36) [38]
мне надо отладить ..
как ?  %_)))


> с какого перепугу "cardinal в string" преобразуется ?

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


 
kaZaNoVa ©   (2004-11-15 16:52) [40]

я хотел все адреса (Pointer"ы) - преобразовать в стринги и вывести мессагебоксом .. - в целях отладки ...


 
kaZaNoVa ©   (2004-11-15 16:53) [41]

так при  I(5) к примеры - выдаётся исключение .. прога завершается .. странно ..


 
Digitman ©   (2004-11-15 17:00) [42]


> мне надо отладить


на то есть, к примеру, оч даже неплохой дебаггер OllyDbg


> хотел все адреса (Pointer"ы) - преобразовать в стринги и
> вывести мессагебоксом .. - в целях отладки ...


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

жми F1 на фразе "Str" - в справке черным по белому написано, что декларация и реализация этой проц-ры находится в модуле system.pas


> выдаётся исключение .. прога завершается .. странно


ничего странного.


 
kaZaNoVa ©   (2004-11-15 17:09) [43]

Digitman ©   (15.11.04 17:00) [42]

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

так я же его (екзешник) полностью копирую, функции из System должны быть ..
функции из SysUtils не использую ...

- как можно тогда преобразовать ?


 
kaZaNoVa ©   (2004-11-15 21:00) [44]

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

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


 
Digitman ©   (2004-11-16 08:09) [45]


> как можно тогда преобразовать


ручками !


> при попытке вызвать какие-нить API-функции, могут возникнуть
> исключения


какие конкретно ?


 
kaZaNoVa ©   (2004-11-16 17:16) [46]

Digitman ©   (16.11.04 8:09) [45]
а ручками - это как ?
string(переменная типа cardinal) - ерунда получается ... ;(


 
Digitman ©   (2004-11-16 17:25) [47]


> string(переменная типа cardinal) - ерунда получается


разумеется ерунда ... ибо в дан.случае преобразование к неявному вызову п/программ, расположенных в system.pas


 
Игорь Шевченко ©   (2004-11-16 17:43) [48]

kaZaNoVa ©   (16.11.04 17:16) [46]


> string(переменная типа cardinal) - ерунда получается ...
> ;(


Я очень извиняюсь, но не рано ли с такими знаниями браться за "Поток без длл или самодостаточный код " ?


 
kaZaNoVa ©   (2004-11-16 18:53) [49]

Игорь Шевченко ©   (16.11.04 17:43) [48]
признаюсь ..  что некоторые вещи я вообще не знаю ..
- все мы специалисты в какой-то своей области ....


 
kaZaNoVa ©   (2004-11-16 19:06) [50]

Игорь Шевченко ©   (16.11.04 17:43) [48]
также, по поводу "рано ли":
можно годами изучать "основы", и изучить их в совершенстве, и топтаться на месте ...

можно изучить основы, а потом и всё более сложное- идеальный вариант, но не всегда для этого есть время и желание ...

а можно так -  поставить задачу, изучить быстро всё, что нужно именно для этой задачи - и выполнит её ! - пусть не будет глубоких систематических знаний, НО задача будет решена - а это главное !!!

п.с. раньше я всегда боялся "спросить что-нить простое" - так как боялся выглядеть некомпетентным ..
и этот подход мне принёс в своё время массу проблем ..
Теперь я считаю - лучше раз спросить что-то из азов, и , возможно, показаться "ламаком", но, при полученном грамотном ответе - понять это, и решить задачу более грамотно ..

по поводу "читай справку", "есть в FAQ" - не спорю, важно .. НО почему-то во всех университетах есть консультации с преподавателями - так как не каждая задача есть в справке, и не каждый сможет найти быстро ответ ..  а иначе бы никаких "консультаций" не существовало бы - всех бы отсылали  к энциклопедиям .. ;)

//извиняюсь за оффтоп - но это была моя самая главная мысль по поводу "внешне глупых вопросов" ...


 
Digitman ©   (2004-11-17 08:09) [51]


> kaZaNoVa


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

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


 
kaZaNoVa ©   (2004-11-17 18:42) [52]

Digitman ©   (17.11.04 8:09) [51]
ок, спасибо огромное, попробую под отладчиком всесторонне изучить :)


 
kaZaNoVa ©   (2004-11-19 12:18) [53]

Кто-нить пробовал реализовать сабж ?
- постите, плиз ..


 
Digitman ©   (2004-11-19 13:03) [54]


> kaZaNoVa ©   (19.11.04 12:18) [53]
> Кто-нить пробовал реализовать сабж ?


ты о чем ?


 
Cobalt ©   (2004-11-19 15:43) [55]

> по кр.мере на первых порах
Я бы сказал "на первых годах" :)


 
kaZaNoVa ©   (2004-11-19 15:48) [56]

Digitman ©   (19.11.04 13:03) [54]
мне просто некогда щас более заниматься этой идеей ..

- и хотел спросить - может кто уже пробовал .. - поучиться на примерах .. (так хочется "готовое решение" найти ..)

:)


 
Digitman ©   (2004-11-19 15:56) [57]


> мне просто некогда щас более заниматься этой идее


а это твои проблемы.


> хотел спросить - может кто уже пробовал .. - поучиться на
> примерах .. (так хочется "готовое решение" найти


готовых нет, не будет и быть не может по определению.
хочешь быстрое и беспроблемное решение ?
его ты уже знаешь - внедрение ДЛЛ ... и это решение - далеко не самое худшее.


 
kaZaNoVa ©   (2004-11-19 16:05) [58]

Digitman ©   (19.11.04 15:56) [57]
ок ;))
спасибо за совет .. :))

> внедрение ДЛЛ

эх .. старое решение ..  но надёжное :))


 
kaZaNoVa ©   (2004-11-19 16:08) [59]

Digitman ©   (19.11.04 15:56) [57]

> готовых нет, не будет и быть не может по определению.

я нашёл одно (оно в самом первом посте .. ) но оно, как я уже убедился в общем случае неверное ....

п.с. буду ждать примеры %)))


 
kaZaNoVa ©   (2004-11-19 16:09) [60]

а так я понял, что полностью грамотно пока сделать не могу ..  ;(


 
Игорь Шевченко ©   (2004-11-19 16:23) [61]

Если пустые сообщения не прекратятся ветка будет закрыта.

С уважением,
Ко-модератор


 
kaZaNoVa ©   (2004-11-20 15:40) [62]

Я проанализировал работу кода в "целевом" процессе и пришёл к выводу что "позиционно-независимый" код стандартными средствами Delphi создать крайне сложно и практически неприемлимо (как и драйвер).

После многочисленных экспериментов я пришёл к выводу , что единственный способ _достаточно простой и работоспособный_ - это способ с ImageBase.

Мой "финальный демонстрационный код" (итог моих "изысканий") :

program loader;
{$IMAGEBASE $70000000}
uses
 Windows;

Var
hProcess, hTh: THandle;
MemPtr: Pointer;
PID,ExitCode,Size,BytesWritten,ThreadID: Cardinal;

function Main(dwEntryPoint: Pointer): longword; stdcall;
begin
LoadLibrary("kernel32.dll");
LoadLibrary("user32.dll");
MessageBox(0,"Fantastika !!!", "Hijacked Process", 0);
Result:=0;
end;

begin
GetWindowThreadProcessId(FindWindow("Progman", nil), @PID);
if PID = 0 then Exit;

MemPtr:= Pointer(GetModuleHandle(nil));

Size := PImageOptionalHeader(Pointer(integer(MemPtr) + PImageDosHeader(MemPtr)._lfanew + SizeOf(dword) + SizeOf(TImageFileHeader))).SizeOfImage;

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

if hProcess = 0 then Exit;

BytesWritten:=0;
VirtualFreeEx(hProcess,MemPtr, 0, MEM_RELEASE);
 MemPtr := VirtualAllocEx(hProcess,MemPtr, Size , MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE );

 if MemPtr <> nil then
 begin
   if WriteProcessMemory(hProcess, MemPtr,MemPtr, Size, BytesWritten) then
   begin
   hTh := CreateRemoteThread(hProcess, nil, 0,@Main,MemPtr, 0, ThreadID);
     if hTh <> 0 then
     begin
       if (WaitForSingleObject(hTh,INFINITE) = WAIT_OBJECT_0) and
         GetExitCodeThread(hTh, ExitCode) then CloseHandle(hTh);
     end;
   end ;
   VirtualFreeEx(hProcess, MemPtr, 0, MEM_RELEASE);  //?
 end;
 CloseHandle(hProcess);
end.


Игорь Шевченко ©   (19.11.04 16:23) [61]
Со своей стороны считаю тему "закрытой" ;)


 
n0name   (2004-11-20 18:14) [63]

Я со своей стороны считаю что позиционно-независимый(так как я понимаю) создать в Delphi возможно. Основная трабла с определением API. Так вот алт. код GetProcAddress и GetModuleHandle.


unit xFuncs;

interface

uses
DrvTypes;

function xGetModuleHandle(ModuleName: PChar): HMODULE;
function xGetProcAddress(hMod: HMODULE; ProcName: PChar): Pointer;

implementation

function GetCurrentPEB: PPEB;
asm
mov eax, fs:[30h]
mov result, eax
end;

function CompareMultibyteWithAnsi(str1: PWChar; str2: PChar): boolean;
var
i: DWORD;
begin
result:=false;
i:=0;
while (PChar(DWORD(str1)+i*2)^<>#0) and (str2[i]<>#0) do
 begin
  if PChar(DWORD(str1)+i*2)^<>str2[i] then
   exit;
  inc(i);
 end;
result:=true;
end;

function GetPCharLength(str1: PChar): DWORD;
begin
result:=0;
while (str1[result]<>#0) do
 inc(result);
end;

function ComparePCharStrings(str1, str2: PChar): boolean;
var
i: DWORD;
begin
result:=false;
i:=0;
if GetPCharLength(str1)<>GetPCharLength(str2) then
 exit;
while (str1[i]<>#0) do
 begin
  if str1[i]<>str2[i] then
   exit;
  inc(i);
 end;
result:=true;
end;

function xGetModuleHandle(ModuleName: PChar): HMODULE;
var
FirstMod: Pointer;
CurrentMod: TLdrDataTableEntry;
begin
result:=0;

FirstMod:=GetCurrentPEB.Ldr.InLoadOrderModuleList.FLink;
CurrentMod:=PLdrDataTableEntry(FirstMod)^;
repeat
 if FirstMod=CurrentMod.InLoadOrderLinks.FLink then
  exit;
 if CompareMultibyteWithAnsi(CurrentMod.BaseDllName.Buffer, ModuleName) then
  begin
   result:=DWORD(CurrentMod.DllBase);
   exit;
  end;
 CurrentMod:=PLdrDataTableEntry(CurrentMod.InLoadOrderLinks.Flink)^;
until (not true);
end;

function xGetProcAddress(hMod: HMODULE; ProcName: PChar): Pointer;
var
ExportDir: PImageExportDirectory;
dwAddressOfNames: DWORD;
dwAddressOfFunctions: DWORD;
i: DWORD;
begin
result:=nil;
ExportDir:=PImageExportDirectory(PImageNtHeaders(hMod+DWORD(PImageDosHeader(hMod)._lfanew)).OptionalHeader.
 DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+hMod);
dwAddressOfNames:=DWORD(ExportDir.AddressOfNames);
dwAddressOfFunctions:=DWORD(ExportDir.AddressOfFunctions);
for i:=0 to ExportDir.NumberOfNames-1 do
 if ComparePCharStrings(PChar(PDWORD(dwAddressOfNames+hMod+i*4)^+hMod), ProcName) then
  result:=Pointer(PDWORD(dwAddressOfFunctions+hMod+i*4)^+hMod);
end;

end.


PS: Весь код написан мною.


 
kaZaNoVa ©   (2004-11-20 18:27) [64]

n0name   (20.11.04 18:14) [63]
огромное спасибо :)

можно ещё

>unit xFuncs;
>
>interface
>
>uses
> DrvTypes;

- можно ещё на юнит DrvTypes посмотреть  ?


 
Игорь Шевченко ©   (2004-11-20 18:39) [65]


> PS: Весь код написан мною.


А кажется таким знакомым...отдельные места.

Кстати, совет - в процедуре GetModuleHandle блокируй загрузчик, а по выходе разблокируй.


 
n0name   (2004-11-21 18:27) [66]

Игорь Шевченко ©   (20.11.04 18:39) [65]    
Не знаю почему он тебе кажется знакомым.
Писал полностью я. Без привлечения сторонних исходников и документации. Корме ,пожалуй, описания PE-формата.

Про какой загрузчик ты говоришь?
Если ты насчёт того, что во время перебора TLdrDataTableEntry могут загрузиться новые модули, то я не знаю какой функцией это выполняется. Можешь подсказать? (Мне неохота заниматься дизасмингом GetModuleHandle).

kaZaNoVa ©   (20.11.04 18:27) [64]
Весь DrvTypes я выкладывать не буду(47,7 KB   1831 строк кода).
Скажи нужные тебе типы и константы.


 
n0name   (2004-11-21 19:21) [67]

n0name   (21.11.04 18:27) [66]

Я не вытерпел и дизасмил всё-таки GetModuleHandle :)
Нашёл эти функции - LdrLockLoaderLock и LdrUnlockLoaderLock.
Пока искал их прототипы нашёл для себя много интересного. Например предпологаемый код некоторых фунций, используемых загрузчиком(т.е. LdrLoadDll, LdrUnloadDll, etc).

Если интересно, вот ковая версия xGetModuleHandle(greet Игорь Шевченко):

function LdrLockLoaderLock(Flags: DWORD; result, Magic: PDWORD): NTSTATUS; stdcall; external "ntdll.dll";
function LdrUnlockLoaderLock(Flags, Magic: DWORD): NTSTATUS; stdcall; external "ntdll.dll";
....
function xGetModuleHandle(ModuleName: PChar): HMODULE;
var
FirstMod: Pointer;
CurrentMod: TLdrDataTableEntry;
LdrLockMagic: DWORD;
begin
result:=0;

LdrLockLoaderLock(0, nil, @LdrLockMagic);

FirstMod:=GetCurrentPEB.Ldr.InLoadOrderModuleList.FLink;
CurrentMod:=PLdrDataTableEntry(FirstMod)^;
repeat
 if FirstMod=CurrentMod.InLoadOrderLinks.FLink then
  exit;
 if CompareMultibyteWithAnsi(CurrentMod.BaseDllName.Buffer, ModuleName) then
  begin
   result:=DWORD(CurrentMod.DllBase);
   exit;
  end;
 CurrentMod:=PLdrDataTableEntry(CurrentMod.InLoadOrderLinks.Flink)^;
until (not true);

LdrUnlockLoaderLock(0, LdrLockMagic);
end;


 
Игорь Шевченко ©   (2004-11-21 20:01) [68]


> Не знаю почему он тебе кажется знакомым.


Где-то видел, может, аналогичный. Что-то сам писал пару лет назад, только идентификаторы брались из WinDbg, а они там несколько иные в структуре LDR_DATA_TABLE_ENTRY


 
n0name   (2004-11-22 11:11) [69]

Не знаешь, всегда ли ntdll.dll загружается первым?(не в драйверах). Мне просто лучше использовать дин. загрузку.


 
Игорь Шевченко ©   (2004-11-22 11:17) [70]

n0name   (22.11.04 11:11) [69]

Всегда. Там же находится загрузчик, который загружает все-все остальное.


 
Xaker ©   (2004-11-22 11:26) [71]

n0name   (20.11.04 18:14) [63]
ловко ты придумал
а что такое TLdrDataTableEntry ?


 
n0name   (2004-11-22 11:57) [72]

Xaker ©   (22.11.04 11:26) [71]

TLdrDataTableEntry=packed record
 InLoadOrderLinks: TListEntry;                  //+0
 InMemoryOrderLinks: TListEntry;                //+8
 InInitializationOrderLinks: TListEntry;        //+16
 DllBase: Pointer;                              //+24
 EntryPoint: Pointer;                           //+28
 SizeOfImage: Cardinal;                         //+32
 FullDllName: UNICODE_STRING;                   //+36
 BaseDllName: UNICODE_STRING;                   //+44
 Flags: cardinal;                               //+52
 LoadCount: word;                               //+56
 TlsIndex: word;                                //+58
 HashLinks: TListEntry;                         //+60
 SectionPointer: Pointer;                       //+68
 CheckSum: Cardinal;                            //+72
 TimeDateStamp: Cardinal;                       //+76
 LoadedImports: Pointer;                        //+80
end;                                            //Size: 84
PLdrDataTableEntry=^TLdrDataTableEntry;

TLdrListEntry=packed record
 ListEntry: TListEntry;
 LdrDataTableEntry: TLdrDataTableEntry;
end;
PLdrListEntry=^TLdrListEntry;

TPebLdrData=packed record
 length: Cardinal;    
 initialized: Cardinal;    
 SsHandle: Pointer;    
 InLoadOrderModuleList: TListEntry;  
 InMemoryOrderModuleList: TListEntry;
 InInitializationOrderModuleList: TListEntry;
end;
PPebLdrData=^TPebLdrData;



Игорь Шевченко ©   (22.11.04 11:17) [70]
Я так и думал :)


 
Xaker ©   (2004-11-22 12:17) [73]

n0name   (22.11.04 11:57) [72]
big thanks ещё проблема с FirstMod:=GetCurrentPEB.Ldr.InLoadOrderModuleList.FLink; - где там Ldr и  InLoadOrderModuleList  ?
(интересует PPEB)


 
n0name   (2004-11-22 13:30) [74]

Xaker ©   (22.11.04 12:17) [73]


TPEB=packed record
 InheritedAddressSpace: boolean;
 ReadImageFileExecOptions: boolean;
 BeingDebugged: boolean;
 b003: byte;
 d004: DWORD;
 SectionBaseAddress: Pointer;
 Ldr: PPebLdrData;
 ProcessParameters: PPROCESS_PARAMETERS;
 SubSystemData: DWORD;
 ProcessHeap: THandle;
 FastPebLock: PCRITICAL_SECTION;
 AcquireFastPebLock: Pointer;
 ReleaseFastPebLock: Pointer;
 d028: DWORD;
 User32Dispatch: PPointer;
 d030: DWORD;
 do34: DWORD;
 d038: DWORD;
 TlsBitMapSize: DWORD;
 TlsBitMap: PRTL_BITMAP;
 TlsBitMapData: array [0..1] of DWORD;
 p04C: Pointer;
 p050: Pointer;
 TextInfo: Pointer;
 InitAnsiCodePageData: Pointer;
 InitOemCodePageData: Pointer;
 InitUnicodeCaseTableData: Pointer;
 KeNumberProcessors: DWORD;
 NtGlobalFlag: DWORD;
 d6C: DWORD;
 MmCriticalSectionTimeout: LARGE_INTEGER;
 MmHeapSegmentReserve: DWORD;
 MmHeapSegmentCommit: DWORD;
 MmHeapDeCommitTotalFreeThreshold: DWORD;
 MmHeapDeCommitFreeBlockThreshold: DWORD;
 NumberOfHeaps: DWORD;
 AvailableHeaps: DWORD;
 ProcessHeapsListBuffer: PHandle;
 d094: DWORD;
 d098: DWORD;
 d09C: DWORD;
 LoaderLock: PCRITICAL_SECTION;
 NtMajorVersion: DWORD;
 NtMinorVersion: DWORD;
 NtBuildNumber: WORD;
 CmNtCSDVersion: WORD;
 PlatformId: DWORD;
 Subsystem: DWORD;
 MajorSubsystemVersion: DWORD;
 MinorSubsystemVersion: DWORD;
 AffinityMask: KAFFINITY;
 ad0C4: array [0..34] of DWORD;
 p150: Pointer;
 ad154: array [0..31] of DWORD;
 Win32WindowStation: THandle;
 d1D8: DWORD;
 d1DC: DWORD;
 CSDVersion: PWORD;
 d1E4: DWORD;
end;


 
Игорь Шевченко ©   (2004-11-22 15:04) [75]

n0name   (22.11.04 13:30) [74]

b003: byte;
d004: DWORD;
--------------
   SpareBool        : UChar;
   Mutant           : Ptr32;
==============
d028: DWORD;
--------------
   EnvironmentUpdateCount : Uint4B;
==============
d030: DWORD;
do34: DWORD;
d038: DWORD;
-------------
   SystemReserved   : Uint4B;
   ExecuteOptions   : Uint4B; {Pos 0, 2 Bits, SpareBits  : Pos 2, 30 Bits }
   FreeList         : Ptr32; { _PEB_FREE_BLOCK }
=============
p04C: Pointer;
p050: Pointer;
TextInfo: Pointer;
-----------
   ReadOnlySharedMemoryBase : Ptr32;
   ReadOnlySharedMemoryHeap : Ptr32;
   ReadOnlyStaticServerData : Ptr32;
===========

И так далее.


 
Piter ©   (2004-11-22 15:41) [76]

Извините, а можно вопрос? Зачем вы пишете свой GetModuleHandle? Ведь он находится в kernel, который грузится по одному и тому же адресу. Сори, если я чего-то не понял...


 
n0name   (2004-11-23 19:32) [77]

Игорь Шевченко ©   (22.11.04 15:04) [75]
Спасибо, можешь подсказать, откуда у тебя эти сведения?

Piter ©   (22.11.04 15:41) [76]
Kernel32.dll не всегда грузится по одному адресу. Если ImageBase программы равен адресу ImageBase kernel32.dll, то используются релоки и длл грузится по другому адресу.


 
Piter ©   (2004-11-23 23:26) [78]

>Kernel32.dll не всегда грузится по одному адресу

понятно. Просто я почитал:

Digitman ©   (12.11.04 12:46) [9]
основываясь на достаточно устойчивом факте загрузки kernel32 по фикс.адресу


и понял, что на это фактически можно полагаться...


 
Игорь Шевченко ©   (2004-11-24 00:13) [79]

n0name   (23.11.04 19:32) [77]

Из отладчика WinDbg и символов Windows.
Есть предложение - если тебя интересуют знания потрохов, структур и так далее - пиши на [email protected]


 
Digitman ©   (2004-11-24 08:18) [80]


> Piter ©   (23.11.04 23:26) [78]


имелся ввиду не какой-то конкретный адрес, а то что в рамках одной и той же сессии ОС образ модуля kernel32 в АП всех использующих его приложениях будет находиться по одному и тому же адресу, поскольку как правило статически загружается одним из первых системных модулей, импортируемых win32-приложениями.


 
n0name   (2004-11-24 09:36) [81]

>Игорь Шевченко ©   (24.11.04 00:13) [79]
Спасибо за информацию, обязательно напишу.

>Digitman ©   (24.11.04 08:18) [80]
Вот именно, как правило :)
Win32-приложение может и не импортировать никаких функций из kernel32.dll, но он будет грузиться вторым(после ntdll.dll).


 
Digitman ©   (2004-11-24 10:37) [82]


> n0name   (24.11.04 09:36) [81]


> Win32-приложение может и не импортировать никаких функций
> из kernel32.dll


Нормальное (без выкрутасов с RET) win32-приложение импортирует из kernel32.dll как минимум одну ф-цию - ExitProcess(), поскольку в соответствии с док-цией Майкрософт вызов этой ф-ции есть предпочтительный способ нормального завершения процесса.


> будет грузиться вторым(после ntdll.dll)


ну и что ? предпочтительный адрес загрузки kernel32 выбран разработчиком ОС таким образом, что вынужденное изменение его системой в подавляющем большинстве не требуется. Особенно это касается НТ-платформы, где kernel32 грузится в верхние (системные) 2Гб АП процесса, куда при всем желании пользовательские модули загрузить (дабы вынудить систему "подвинуть" kernel32) не удастся. К тому же докум.загрузка пользов. PE-модулей осуществляется с пом. LoadLibrary(), которая опять же требует уже загруженной kernel32.
Так что вероятность изменения факт.адреска загрузки kernel32 по отношения к предпочтительному в НТ практически равна нулю. Она (такая вероятность), конечно же, больше нуля в Маздае, но с учетом того, что нормальные приложения грузят kernel32 первым модулем в цепочке требуемых к импорту, этой вероятностью опять же можно пренебречь.

В конечном итоге, ДАЖЕ если сомнения существуют, можно просканировать АП целевого процесса на предмет обнаружения какой-либо сигнатуры, идентифицирующей kernel32, и найдя таковую с учетом ее смещения отн-но начала образа получить фактический базовый адрес.


 
Игорь Шевченко ©   (2004-11-24 10:59) [83]

Digitman ©   (24.11.04 10:37) [82]


> Особенно это касается НТ-платформы, где kernel32 грузится
> в верхние (системные) 2Гб АП процесса, куда при всем желании
> пользовательские модули загрузить (дабы вынудить систему
> "подвинуть" kernel32) не удастся


Это ты с Win9x перепутал, извини.


> Так что вероятность изменения факт.адреска загрузки kernel32
> по отношения к предпочтительному в НТ практически равна
> нулю


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


 
Digitman ©   (2004-11-24 11:04) [84]


> Игорь Шевченко ©   (24.11.04 10:59) [83]


да, точно, перепутал.
строго наоборот.


> Про попытке запустить программу, которая в адресном пространстве
> занимает область kernel32.dll такая программа просто не
> запускается


и анализ исх.текста это также подтверждает ?


 
Игорь Шевченко ©   (2004-11-24 11:30) [85]

Digitman ©   (24.11.04 11:04) [84]

Нет, исходный текст тут не причем, такая связь при импорте символов устанавливается, насколько мне известно. Опытным путем было установлено, что при попытке залезть в область адресов kernel32.dll программа не запускается из-за того, что kernel32.dll не может быть перемещена.


 
n0name   (2004-11-24 12:06) [86]

>Digitman ©   (24.11.04 10:37) [82]
На это (ExitProcess) я отвечу : ха!
Никаких извращений - NtTerminateProcess(DWORD(-1), 0).

Что насчёт загрузки кернела, то измени ImageBase в PE-заголовке  при компиляции на предпологаемый адрес кернела.

Загрузчик PE ВСЕГДА для Win32-приложений грузит kernel32.dll. Причём обязательно вторым по счету.


 
Digitman ©   (2004-11-24 13:16) [87]


> n0name   (24.11.04 12:06) [86]


> Никаких извращений - NtTerminateProcess


это ты - про НТ... а про маздайную линейку ?


> Причём обязательно вторым по счету


опять же - а для маздая кто будет первым ?


 
-SeM-   (2004-11-24 16:43) [88]

Digitman ©   (24.11.04 13:16) [87]

И на маздай то же - ха! Но для этого надо как-то узнать адрес загрузки кернел. Что и пытаюсь определить http://predskazanie-wunschpunsch.ru/view/4-1101201473/&web=1


 
Xaker ©   (2004-11-24 17:40) [89]

n0name   (24.11.04 12:06) [86]

> Что насчёт загрузки кернела, то измени ImageBase в
> PE-заголовке  при компиляции на предпологаемый адрес
> кернела.

Ошибка: Недопустимое перемещение системной DLL

- не хочет запускаться ..

самое интересное, что можно больше сделать и меньше - будет работать ...


 
Digitman ©   (2004-11-24 17:41) [90]


> -SeM-   (24.11.04 16:43) [88]


ХАкать я бы не посоветовал.


 
n0name   (2004-11-25 11:35) [91]

Digitman мне кажется что Win9X это анахроизм.
У меня его нет, и я не могу программировать под него.


 
Digitman ©   (2004-11-25 12:03) [92]


> -SeM-   (24.11.04 16:43) [88]
> для этого надо как-то узнать
> адрес загрузки кернел. Что и пытаюсь определить http://predskazanie-wunschpunsch.ru/view/4-1101201473/&web=1


в той ветке ты поехал в совершенно иной огород - создание KMD ..

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


 
Digitman ©   (2004-11-25 12:09) [93]


> мне кажется что Win9X это анахроизм


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


 
-SeM-   (2004-11-25 12:21) [94]

Digitman ©   (25.11.04 12:03) [92]
Да нет, ты не правильно понял. Ответ там же.

n0name   (25.11.04 11:35) [91]
А ты, как программист, разве не должен учитывать то, что твоя прога может быть запущена на другой линейке ОС. Или ты предпочитаешь писать в реадми, что прога работает только на NT линейке?


 
n0name   (2004-11-25 14:03) [95]

Digitman ©   (25.11.04 12:09) [93]
-SeM-   (25.11.04 12:21) [94]
Как программист я должен учитывать эту возможность(есть же слабые компы). А как юзер давно простился с линейкой Win9X.
Но еа каждый хитрый болт есть своя хитрая гайка.
Что можно сделать в WinNT+ можно сделать и в Win9X. Вопрос в другом сколько займёт реализация...
Например в Win9X нет NativeAPI. Если хочешь реализуй нужную функцию сам.


 
n0name   (2004-11-25 14:03) [96]

Удалено модератором
Примечание: Дубль


 
Xaker ©   (2004-11-28 23:25) [97]

Остался вопрос, а как можно подправить стёа потока, чтобы он был "нормальным"  ?


 
n0name   (2004-11-30 10:33) [98]

Для чего тебе "подправлять" стек?


 
Xaker ©   (2004-11-30 13:24) [99]

n0name   (30.11.04 10:33) [98]
чтобы не выделялся ;))


 
Digitman ©   (2004-11-30 13:29) [100]


> Xaker ©   (30.11.04 13:24) [99]


размер стека трэда задается 2-м параметром при вызове ф-ций CreateThread/CreateRemoteThread


 
Xaker ©   (2004-11-30 14:24) [101]

Digitman ©   (30.11.04 13:29) [100]
ок, спасибо, постараюсь сделать его более "нормальным"  :))
- а что там лучше указывать ? - какое значение ?
- чтобя вообще не выделялся ?


 
TankMan ©   (2004-11-30 15:01) [102]

Прочитал я эту ветку...и у меня вопрос возник, вы всетаки хотите довести этот код до ~100% вероятности работоспособности или просто так спорите?


 
n0name   (2004-11-30 15:08) [103]

//TankMan ©   (30.11.04 15:01) [102]
Какой код?


 
TankMan ©   (2004-11-30 20:58) [104]

>>n0name
:)) Самый самый верхний :)


 
Piter ©   (2004-11-30 21:01) [105]

Xaker ©   (30.11.04 13:24) [99]

а чем выделяется стек потока трояна? Колись...


 
Xaker ©   (2004-11-30 23:14) [106]

TankMan ©   (30.11.04 15:01) [102]
код работает ..  улучшаем . :)

Piter ©   (30.11.04 21:01) [105]
я сам пока точно не выяснил...


 
n0name   (2004-12-01 10:52) [107]

Если ты про xGetModuleHandle и xGetProcAddress. Я сделал новую версию. В прошлых было несколько багов, теперь их нет.


 
Xaker ©   (2004-12-01 13:14) [108]

n0name   (01.12.04 10:52) [107]
выкладывай :))
потестим :)


 
n0name   (2004-12-01 13:47) [109]

unit xFuncs;

interface

uses
CommonTypes,
StrFuncs,
PETypes,
xTypes;

function xGetModuleHandle(ModuleName: PChar): HMODULE;
function xGetProcAddress(hMod: HMODULE; ProcName: PChar): Pointer;

implementation

var
LdrLockLoaderLock: function (Flags: DWORD; result, Magic: PDWORD): NTSTATUS; stdcall;
LdrUnlockLoaderLock: function (Flags, Magic: DWORD): NTSTATUS; stdcall;

function GetCurrentPEB: PPEB;
asm
mov eax, fs:[30h]
mov result, eax
end;

function xGetProcAddress(hMod: HMODULE; ProcName: PChar): Pointer;
var
ExportDir: PImageExportDirectory;
i, IndInAddr: DWORD;
begin
result:=nil;
ExportDir:=PImageExportDirectory(PImageNtHeaders(hMod+DWORD(PImageDosHeader(hMod).e_lfanew)).OptionalHeader.
 DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+hMod);
for i:=0 to ExportDir.NumberOfNames-1 do
begin
 if ComparePCharStrings(PChar(PDWORD(DWORD(ExportDir.AddressOfNames)+hMod+i*4)^+hMod), ProcName) then
  begin
   IndInAddr:=PWORD(DWORD(ExportDir.AddressOfNameOrdinals)+hMod+i*2)^;
   result:=Pointer(PDWORD(DWORD(ExportDir.AddressOfFunctions)+hMod+IndInAddr*4)^+hMod);
  end;
end;
end;

function GetNtDLLHandle: HModule;
begin
result:=DWORD(PLdrDataTableEntry(PLdrDataTableEntry(GetCurrentPEB.Ldr.InLoadOrderModuleList.FLink)^.
 InLoadOrderLinks.Flink)^.DllBase);
end;

procedure InitAPI;
var
NtDLLHandle: THandle;
begin
NtDLLHandle:=GetNtDLLHandle;
@LdrLockLoaderLock:=xGetProcAddress(NtDLLHandle, "LdrLockLoaderLock");
@LdrUnlockLoaderLock:=xGetProcAddress(NtDLLHandle, "LdrUnlockLoaderLock");
end;

function xGetModuleHandle(ModuleName: PChar): HMODULE;
var
FirstMod: Pointer;
CurrentMod: TLdrDataTableEntry;
LdrLockMagic: DWORD;
begin
InitAPI;
result:=0;

LdrLockLoaderLock(0, nil, @LdrLockMagic);

FirstMod:=GetCurrentPEB.Ldr.InLoadOrderModuleList.FLink;
CurrentMod:=PLdrDataTableEntry(FirstMod)^;
repeat
 if FirstMod=CurrentMod.InLoadOrderLinks.FLink then
  exit;
 if CompareMultibyteWithAnsi(CurrentMod.BaseDllName.Buffer, ModuleName) then
  begin
   result:=DWORD(CurrentMod.DllBase);
   exit;
  end;
 CurrentMod:=PLdrDataTableEntry(CurrentMod.InLoadOrderLinks.Flink)^;
until (not true);

LdrUnlockLoaderLock(0, LdrLockMagic);
end;

end.


 
Игорь Шевченко ©   (2004-12-01 23:08) [110]

n0name   (01.12.04 13:47) [109]

Я бы тебе посоветовал переделать функции LdrLockLoaderLock и LdrUnlockLoaderLock

на


type
 TLdrLockLoaderLock: function (Flags: DWORD; Aresult, Magic: PDWORD): NTSTATUS; stdcall;
 TLdrUnlockLoaderLock: function (Flags, Magic: DWORD): NTSTATUS; stdcall;

var
 _LdrLockLoaderLock: TLdrLockLoaderLock;
 _LdrUnlockLoaderLock: TLdrUnlockLoaderLock;

procedure InitAPI;
var
NtDLLHandle: THandle;
begin
NtDLLHandle:=GetNtDLLHandle;
@_LdrLockLoaderLock:=xGetProcAddress(NtDLLHandle, "LdrLockLoaderLock");
@_LdrUnlockLoaderLock:=xGetProcAddress(NtDLLHandle, "LdrUnlockLoaderLock");
end;

function LdrLockLoaderLock (Flags: DWORD; Aresult, Magic: PDWORD): NTSTATUS; stdcall;
begin
 if Assigned(_LdrLockLoaderLock) then
   Result := _LdrLockLoaderLock (Flags, Aresult, Magic)
 else begin
   Result := NT_SUCCESS;
   EnterCriticalSection(CurrentPEB.LoaderLock);
 end;
end;

function LdrUnlockLoaderLock (Flags, Magic: DWORD): NTSTATUS; stdcall;
begin
 if Assigned(_LdrUnlockLoaderLock) then
   Result := _LdrUnlockLoaderLock (Flags, Magic)
 else begin
   Result := NT_SUCCESS;
   LeaveCriticalSection(CurrentPEB.LoaderLock);
 end;
end;


Причина в том, что функции блокировки загрузчика экспортируются из NTDLL только в WinXP, Win2003 и в LongHorn.


 
Xaker ©   (2004-12-05 02:21) [111]

Удалено модератором
Примечание: Создание пустых сообщений. Предупреждение тебе



Страницы: 1 2 3 вся ветка

Текущий архив: 2005.01.23;
Скачать: CL | DM;

Наверх




Память: 0.84 MB
Время: 0.04 c
4-1102330500
delel
2004-12-06 13:55
2005.01.23
cd-rom


9-1097692756
rts111
2004-10-13 22:39
2005.01.23
Полезные утилиты


1-1104923323
franky
2005-01-05 14:08
2005.01.23
messagedlg


3-1103555237
Сергей Яковлев
2004-12-20 18:07
2005.01.23
lblPage в QuickRep - это кто?


14-1104551223
Думкин
2005-01-01 06:47
2005.01.23
С днем рождения! 1 января