Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.01.23;
Скачать: [xml.tar.bz2];

Вниз

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

 
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.
Есть предложение - если тебя интересуют знания потрохов, структур и так далее - пиши на whitefranz@hotmail.com


 
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://delphimaster.net/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://delphimaster.net/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 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.01.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.96 MB
Время: 0.034 c
4-1101833290
Георгий
2004-11-30 19:48
2005.01.23
Создать текстовой файл на десктопе


3-1103574058
Макс
2004-12-20 23:20
2005.01.23
Сложный запрос с вложенными запросами для Access (ADO)


14-1104753892
Чеширский_Кот
2005-01-03 15:04
2005.01.23
Софт-хиты 2004 года


3-1103292908
able
2004-12-17 17:15
2005.01.23
Два поля с разных баз


14-1105046621
Gero
2005-01-07 00:23
2005.01.23
Права доступа





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский