![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поток без длл или самодостаточный код
kaZaNoVa © (2004-11-10 18:01:00)Идея: создать программу, которая могла бы "создавать самодостаточный код" - в плане того, чтобы возможно внедриться в другой процесс, и при этом НЕ подгружать дополнительных DLL ;)
Я давно интересовался этой темой, и только недавно нащёл реализацию:
(использованы материалы с сайта http://www.iamaphex.cjb.net)
код:
program Project1;
{$IMAGEBASE $13140000}
uses
Windows;
function Main(dwEntryPoint: Pointer): longword; stdcall;
begin
LoadLibrary('kernel32.dll');
LoadLibrary('user32.dll');
MessageBox(0, 'Ok', 'Hijacked Process', 0);
// ExitProcess(0);
Result := 0;
end;
procedure Inject(ProcessHandle: longword; EntryPoint: pointer);
var
Module, NewModule: Pointer;
Size, BytesWritten, TID: longword;
begin
Module := Pointer(GetModuleHandle(nil));
Size := PImageOptionalHeader(Pointer(integer(Module) + PImageDosHeader(Module)._lfanew + SizeOf(dword) + SizeOf(TImageFileHeader))).SizeOfImage;
VirtualFreeEx(ProcessHandle, Module, 0, MEM_RELEASE);
NewModule := VirtualAllocEx(ProcessHandle, Module, Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(ProcessHandle, NewModule, Module, Size, BytesWritten);
CreateRemoteThread(ProcessHandle, nil, 0, EntryPoint, Module, 0, TID);
end;
var
ProcessHandle, PID: longword;
begin
GetWindowThreadProcessId(FindWindow('Progman', nil), @PID);
ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
Inject(ProcessHandle, @Main);
CloseHandle(ProcessHandle);
end.
Меня интересует - всё ли в этом примере правильно - нет ли негде "подводных камней" ?
И, что будет, если в созданном потоке возникнет исключение - "процесс-носитель" в этом случае завершится ? - как в таком случае можно обрабатывать исключения ?
Xaker (2004-11-22 11:26:00) [41]n0name (20.11.04 18:14) [63]
ловко ты придумал
а что такоеTLdrDataTableEntry?
Игорь Шевченко (2004-11-22 11:17:00) [42]n0name (22.11.04 11:11) [69]
Всегда. Там же находится загрузчик, который загружает все-все остальное.
n0name (2004-11-22 11:11:00) [43]Не знаешь, всегда ли ntdll.dll загружается первым?(не в драйверах). Мне просто лучше использовать дин. загрузку.
Игорь Шевченко (2004-11-21 20:01:00) [44]
> Не знаю почему он тебе кажется знакомым.
Где-то видел, может, аналогичный. Что-то сам писал пару лет назад, только идентификаторы брались из WinDbg, а они там несколько иные в структуре LDR_DATA_TABLE_ENTRY
n0name (2004-11-21 19:21:00) [45]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;
n0name (2004-11-21 18:27:00) [46]Игорь Шевченко © (20.11.04 18:39) [65]
Не знаю почему он тебе кажется знакомым.
Писал полностью я. Без привлечения сторонних исходников и документации. Корме ,пожалуй, описания PE-формата.
Про какой загрузчик ты говоришь?
Если ты насчёт того, что во время перебора TLdrDataTableEntry могут загрузиться новые модули, то я не знаю какой функцией это выполняется. Можешь подсказать? (Мне неохота заниматься дизасмингом GetModuleHandle).
kaZaNoVa © (20.11.04 18:27) [64]
Весь DrvTypes я выкладывать не буду(47,7 KB 1831 строк кода).
Скажи нужные тебе типы и константы.
Игорь Шевченко (2004-11-20 18:39:00) [47]
> PS: Весь код написан мною.
А кажется таким знакомым...отдельные места.
Кстати, совет - в процедуре GetModuleHandle блокируй загрузчик, а по выходе разблокируй.
kaZaNoVa (2004-11-20 18:27:00) [48]n0name (20.11.04 18:14) [63]
огромное спасибо :)
можно ещё
>unit xFuncs;
>
>interface
>
>uses
> DrvTypes;
- можно ещё на юнит DrvTypesпосмотреть ?
n0name (2004-11-20 18:14:00) [49]Я со своей стороны считаю что позиционно-независимый(так как я понимаю) создать в 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 15:40:00) [50]Я проанализировал работу кода в "целевом" процессе и пришёл к выводу что "позиционно-независимый" код стандартными средствами 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]
Со своей стороны считаю тему "закрытой" ;)
Игорь Шевченко (2004-11-19 16:23:00) [51]Если пустые сообщения не прекратятся ветка будет закрыта.
С уважением,
Ко-модератор
kaZaNoVa (2004-11-19 16:09:00) [52]а так я понял, что полностью грамотно пока сделать не могу .. ;(
kaZaNoVa (2004-11-19 16:08:00) [53]Digitman © (19.11.04 15:56) [57]
> готовых нет, не будет и быть не может по определению.
я нашёл одно (оно в самом первом посте .. ) но оно, как я уже убедился в общем случае неверное ....
п.с. буду ждать примеры %)))
kaZaNoVa (2004-11-19 16:05:00) [54]Digitman © (19.11.04 15:56) [57]
ок ;))
спасибо за совет .. :))
> внедрение ДЛЛ
эх .. старое решение .. но надёжное :))
Digitman (2004-11-19 15:56:00) [55]
> мне просто некогда щас более заниматься этой идее
а это твои проблемы.
> хотел спросить - может кто уже пробовал .. - поучиться на
> примерах .. (так хочется "готовое решение" найти
готовых нет, не будет и быть не может по определению.
хочешь быстрое и беспроблемное решение ?
его ты уже знаешь - внедрение ДЛЛ ... и это решение - далеко не самое худшее.
kaZaNoVa (2004-11-19 15:48:00) [56]Digitman © (19.11.04 13:03) [54]
мне просто некогда щас более заниматься этой идеей ..
- и хотел спросить - может кто уже пробовал .. - поучиться на примерах .. (так хочется "готовое решение" найти ..)
:)
Cobalt (2004-11-19 15:43:00) [57]> по кр.мере на первых порах
Я бы сказал "на первых годах" :)
Digitman (2004-11-19 13:03:00) [58]
> kaZaNoVa © (19.11.04 12:18) [53]
> Кто-нить пробовал реализовать сабж ?
ты о чем ?
kaZaNoVa (2004-11-19 12:18:00) [59]Кто-нить пробовал реализовать сабж ?
- постите, плиз ..
kaZaNoVa (2004-11-17 18:42:00) [60]Digitman © (17.11.04 8:09) [51]
ок, спасибо огромное, попробую под отладчиком всесторонне изучить :)