Программа, внедряющая библиотеку

Я тут подумал, как бы попроще внедрить свою библиотеку в адресное пространство чужого процесса. Использовать CreateRemoteThread? - её нет в Windows98. Предложенный Рихтером метод замены команд в точке входа - слишком сложен и неудобен. Проще выделить блок памяти в чужом адресном пространстве, скопировать туда вызов LoadLibrary, и манипулировать контекстом потока. Но выделить память - её нужно возвращать. А когда? - вот тут проблема. И тут меня осенило - а есть же стек! Там наверняка найдётся лишних байт 300 - имя библиотеки + вызов LoadLibrary. И мучиться с доступом не надо - стек доступен для чтения/выполнения/записи во всех версиях Windows. А прибить память можно add esp, xxx. Главное, чтобы kernel32.dll был спроецирован по одному и тому же адресу - но это соблюдается у всех процессов. Что ж, вот что у меня получилось. Программа внедряет библиотеку dll.dll (должна быть в той же папке) в программу, указанную пользователем.
.386
.model	flat

include	include\windows.inc
include	include\kernel32.inc
include	include\comdlg32.inc

.code
_start:
		xor	ebx,ebx			;В ebx будет 0
		push	offset written
		push	offset librname		;Сюда поместят полное имя
		push	260
		push	offset dllname		;Короткое имя
		call	GetFullPathName		;Получаем полное имя внедряемой библиотеки
		mov	byte ptr filename, bl
		push	offset fop		;Пусть пользователь выберет
		call	GetOpenFileName		;что нужно запускать
		test	eax,eax			;Если не выбрал - выйдем
		jz	exit
		mov	eax, LoadLibrary		;Сохраним адрес LoadLibrary
		mov	loadlibraddr, eax		;в копируемом блоке
		mov	stinfo.cb, size stinfo
		push	offset procinfo
		push	offset stinfo
		push	ebx
		push	ebx
		push	CREATE_SUSPENDED		;Запускаем программу, выбранную
		push	ebx			;пользователем в
		push	ebx			;остановленном состоянии
		push	ebx
		push	offset filename
		push	ebx
		call	CreateProcess
		or	eax, eax			;Если не запускается -
		jz	exit			;- выйдем
		mov	ProcCont.ContextFlags, CONTEXT_CONTROL
		push	offset ProcCont		;Получим значения
		push	procinfo.hThread		;регистров остановленного
		call	GetThreadContext		;главного потока
		mov	eax, ProcCont.regEip	;Вот откуда мы будем продолжать
		mov	entry, eax		;после загрузки библиотеки
		mov	eax, ProcCont.regEsp	;Уменьшим стек потока на размер
		sub	eax, ProcSize-4		;внедряемого кода
		mov	ProcCont.regEip, eax	;И установим eip на
		sub	eax, 4			;эту область
		mov	ProcCont.regEsp, eax
		push	offset written
		push	ProcSize			;Записываем туда
		push	offset ProcToExec		;нашу небольшую
		push	eax			;программу
		push	procinfo.hProcess		;Она находится у
		call	WriteProcessMemory		;нас в данных
		push	procinfo.hProcess		;Описатель процесса
		call	CloseHandle		;больше не нужен
		push	offset ProcCont
		push	procinfo.hThread		;Записываем изменённые
		call	SetThreadContext		;регистры
		push	procinfo.hThread
		call	ResumeThread		;Запускаем поток!
		push	procinfo.hThread
		call	CloseHandle		;Закрываем описатель
exit:		push	eax
		call	ExitProcess		;Завершаем нашу программу


data	segment	'DATA'
	assume	cs:data				;Нужно для кода в данных
filter		db	'Программы',0,'*.exe',0,0	;Фильтр для GetOpenFileName
dllname		db	'dll.dll',0		;Имя нашей библтотеки
align	4

fop	OPENFILENAME	<size fop,0,?,offset filter,0,0,0,offset filename,\
		260,0,0,0,0,\
	OFN_HIDEREADONLY or OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_EXPLORER,\
		?,?,0,0,0,0>
;Далее идёт программка, выполняемая в чужом стеке
;Так как неизвестно, где она, нельзя пользоваться offset xxx
ProcToExec:			;esp при входе указывает сюда
entry		dd	0
		pushad		;а eip сюда
		pushfd		;ОБЯЗАТЕЛЬНО всё сохраняем
		call	templab		;Эквивалентно mov eax,
templab:		pop	eax		;offset templab
		add	eax, (offset librname-offset templab)
		push	eax			;Имя нашей библиотеки
		call	dword ptr [eax-4]		;call LoadLibraryA
		popfd			;Всё восстанавливаем
		popad
		ret	120h	;ret (ProcSize-4), я посмотрел из листинга
;Это ключевая команда. Она :
;а) переходит по адресу, указанному в entry
;б) очищает стек, занятый программой
	align	4
loadlibraddr	dd	0		;Адрес LoadLibraryA
librname		db	260 dup(?)	;Полное имя нашей библиотеки

ProcSize	=	$ - offset ProcToExec

.data?
stinfo		STARTUPINFO	<>
procinfo		PROCESS_INFORMATION	<>
ProcCont		CONTEXT		<>	;Контекст главного потока
written		dd	?		;Временная переменная
filename		db	260 dup(?)	;Имя запускаемой программы
end	_start
Сайт управляется системой uCoz