![]() |
| ||
|
|
Новости |
Поиск |
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.
Меня интересует - всё ли в этом примере правильно - нет ли негде "подводных камней" ?
И, что будет, если в созданном потоке возникнет исключение - "процесс-носитель" в этом случае завершится ? - как в таком случае можно обрабатывать исключения ?
Digitman (2004-11-12 13:44:00) [101]
> код будет он неё звависеть
не выдумывай.
создай группу проектов, один проект - внедряющий ехе, другой - внедряемая ДЛЛ
в ходе разработки делай в них согласованные логические изменения, если предполагается, что внедряемая ДЛЛ будет по опред.соглашениям взаимодействовать с внедряющим ехе
строй все проекты разом, одним движением руки - build all
всех делов !
kaZaNoVa (2004-11-12 13:08:00) [102]Digitman © (12.11.04 12:46) [9]
ок, спасибо, попробую !
//вариант с длл недопустим хотя бы потому, что код будет он неё звависеть - то есть не будет "сам по себе" ;))
Digitman (2004-11-12 12:46:00) [103]
> 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-11 15:23:00) [104]Digitman © (11.11.04 15:01) [7]
спасибо за обьяснение, буду разбираться ;)))
Digitman (2004-11-11 15:01:00) [105]
> нужен PAGE_EXECUTE_READWRITE или PAGE_READWRITE ?
страницы региона, содержащего маш.инструкции, предполагаемые к выполнению, обязаны иметь в числе прочих EXECUTE-флаг доступа.
> почему-то в некоторых примерах MEM_COMMIT идёт без MEM_RESERVE
вот я купил билет в оперу.
я ЗАРЕЗЕРВИРОВАЛ т.н. "место".
я могу и не прийти на шоу или опоздать на него, но при сем билет, купленный мной, по идее РЕЗЕРВИРУЕТ за мной право воспользоваться всеми теми "благами", которыми я могу (но вовсе не обязан) воспользоваться, купив этот билет..
а именно хотя бы :
- не беспокоиться за сохранность своей пальты из ангорского баклана, сданной как и положено туда, где начинается театр;
- сидеть на своем месте в театр.зале (уж это безусловно);
- дышать (театральная система кондиционирования);
- лупануть в антракте 50гр. коньячку под "икру заморскую" в тетр.буфете (на меня делается расчет);
- и т.д. и т.п.
таки явившись в оперу я реализую свое право, и некие расчитанные под меня ресурсы оперной "кухни" реально работают на меня, т.е. я сделал RESERVE + COMMIT
таки не явившись в оперу я явил собой "собаку на сене", т.е. я сделал RESERVE
kaZaNoVa (2004-11-11 14:23:00) [106]Digitman © (11.11.04 14:13) [5]
да, нужна полная работоспособность ;))
ок .. буду рыть справку .. :)
а кстати, нуженPAGE_EXECUTE_READWRITEилиPAGE_READWRITE?
и почему-то в некоторых примерах MEM_COMMIT идёт без MEM_RESERVE ... ?
Digitman (2004-11-11 14:13:00) [107]
> kaZaNoVa © (11.11.04 13:58) [4]
> данный код всё-же работает
угу. в некоем частном случае.
но тебе же ОБЩИЙ случай, думаю, нужен, а не некий частный, который сработал случайно, хоть и неоднократно ?
> а как правильно ?
а в Справке не написано разве, как правильно анализировать рез-т работы этой ф-ции ?
kaZaNoVa (2004-11-11 13:58:00) [108]Digitman © (11.11.04 8:42) [3]
но самое интересное, что данный код всё-же работает ...
а как правильно ?
?
NewModule := VirtualAllocEx(ProcessHandle, nil, Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
Digitman (2004-11-11 08:42:00) [109]
> нет ли негде "подводных камней" ?
начнем с этой строчки
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-10 21:01:00) [110]Игорь Шевченко © (10.11.04 18:41) [1]
а насчёт исключений - как можно их обработать ?
зы ОСи 2000 XP 2003 LongHorn
Игорь Шевченко (2004-11-10 18:41:00) [111]
> Меня интересует - всё ли в этом примере правильно - нет
> ли негде "подводных камней" ?
Практика - критерий истины.