Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Какой ресурс в NT жестко ассоциирован с хэндлом со значением 4 ? [NT4]


Страницы:   1 2

Digitman ©   (2001-11-05 13:30:00) 

См. не так давно обсуждавшуюся тему про самоудаление файла в разделе "Общие вопросы", фрагмент кода именно для WinNT

вот эта строчка :

CloseHandle(THandle(4));

Итак, что мы здесь закрываем в действительности, господа ?
Пошевелим мозгами вместе ?


paul_shmakov   (2001-12-18 19:21:00) [1]

2 Milz:
да, здорово, но, к сожалению, только для win9x. может даже в winme уже работать не будет :(
а вот бы для nt такое найти.


Milz   (2001-12-17 14:24:00) [2]

На счёт самомодификации: посмотрите http://z0mbie.host.sk/w9xshare.html, работает, но только один раз, наверное "нестандартный" поток неверно завершается. Может удастся адаптировать это для дельфов?.


paul_shmakov   (2001-11-09 17:00:00) [3]

ну это вряд ли осуществимо... к сожалению


Digitman   (2001-11-09 16:52:00) [4]

>paul_shmakov
Именно поэтому оно и "через ж." . В этом и потенциальные преимущества - не разрушая объектную Делфи-среду суметь воспользоваться трюком)


paul_shmakov   (2001-11-09 16:15:00) [5]

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


Digitman   (2001-11-09 15:43:00) [6]

>paul_shmakov
imho, это решение через ж. ) мало чем принципиально отличается от варианта с *.bat


paul_shmakov   (2001-11-09 15:29:00) [7]

создаешь в этом классе объект файл, проецируемый в память. записываешь туда данные, необходимые для модификации, а в перехватчике ExitProcess эти данные считываешь и делаешь все, что нужно.


Digitman   (2001-11-09 14:55:00) [8]

>paul_shmakov

Ты ведь рассматриваешь частный случай - удаление файла. А если стоит задача самомодификации ? И исх.данные для модификации на момент вызова эпилога находятся в некоем экземпляре некоего объекта одного из классов, порожденных от TObject ?


paul_shmakov   (2001-11-09 14:39:00) [9]

а зачем нам Application? я же предлагаю перехватывать ExitProcess своей процедурой примерно такого содержания:

procedure OurExitProcess(uExitCode: UINT); stdcall;
var
FileName: PChar;
hkrnl: HMODULE;
pUnmapViewOfFile: Pointer;
pDeleteFile: Pointer;
pCloseHandle: Pointer;
hInstance: Cardinal;
begin
{ используем динамически выделяемую память из кучи, потому как иначе
компилятор размещает массив FileName вовсе не в стеке потока }
FileName := HeapAlloc(GetProcessHeap, 0, MAX_PATH);
GetModuleFileName(GetModuleHandle(nil), FileName, MAX_PATH);

hkrnl := GetModuleHandle("kernel32.dll");

pUnmapViewOfFile := GetProcAddress(hkrnl, "UnmapViewOfFile");
pDeleteFile := GetProcAddress(hkrnl, "DeleteFileA");
pCloseHandle := GetProcAddress(hkrnl, "CloseHandle");

hInstance := Cardinal(GetModuleHandle(nil));

asm
push 0
mov eax, FileName
push eax
push pOriginalExitProcess // !!!!!!!!!!!!!!!!!!!!
push 4
push pDeleteFile
push hInstance
push pCloseHandle
push pUnmapViewOfFile
ret
end;
end.


Digitman   (2001-11-09 14:19:00) [10]

>paul_shmakov
В момент вызова ExitProcess из эпилога как ты обратишься, например, к тому же объекту Application (если это необходимо по внутренней логике приложения) ? Его уже нет ! Как нет уже и многого из того, что может быть крайне необходимо на момент работы с "освобожденным" файлом после трюковых действий, но разрушено при деинициализации модулей в эпилоге.


paul_shmakov   (2001-11-09 13:59:00) [11]

более реально (и правильно) будет не в эпилог внедряться, а перехватывать ExitProcess, что просто. там выполняем трюковый код и вызываем оригинальный ExiotProcess.


Digitman   (2001-11-08 17:20:00) [12]

Давайте, чтобы не объясняться на пальцах, "оперировать" скелет :

label Epiloque;

begin
Application.Initialize;
Application.CreateForm(Form1, TForm1);
Application.Run;

... здесь - предположительно - трюковой код

Epiloque: // адрес точки вызова п/п эпилога (call -$000023b5 у меня здесь)
end.


Digitman   (2001-11-08 16:53:00) [13]

>paul_shmakov
Ок. Сойдемся во мнении, что невыполнение п.п 2, 4 может привести (с достаточной долей вероятности) к непредсказуемым последствиям для системы в целом при выполнении трюка.

Похали дальше ?
Исх.текст эпилога в System.pas править неразумно. Попробуем оценить потенциально возможные варианты внедриться в код эпилога ("перехватить" его вызов) в run-time. Трезво оценивая при этом проблемы совместимости с различными версиями Делфи (для простоты, скажем - от Д3 до Д6)


paul_shmakov   (2001-11-08 16:26:00) [14]

Что делает эпилог (для тех, кому лениво посмотреть в окне CPU :) :
1) вызывает зарегистрированные процедурой AddExitProc
функции-обработчики завершения приложения
2) вызывает Finalization у всех unit-ов
3) выгружает продгруженные package-ы
4) убирает обработчик исключений
5) вызывает ExitProcess, на чем все и заканчивается

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

А что касается mmf, то все будет нормально. Если конечно один из юнитов
или package не вызвал во время своей инициализации или работы
MapViewOfFile(4,....) или DuplicateHandle(GetCurrentProcess(), 4, ....),
что увеличивает reference count объекта. Но если он это вызвал, значит
он тоже как-то пытается использовать наш недокументированный трюк,
который мы тут обсуждаем. Это крайне маловероятно!

А насчет того, что "Packages ведь грузятся в то же адр.пр-во", то и здесь
все нормально, т.к. загрузка package, как и обычной dll, счетчик mmf
exe-шника не трогает.


Digitman   (2001-11-08 13:06:00) [15]

>Алексей Петров
А Packages ведь грузятся в то же адр.пр-во ! И сч-ки у их хэндлов не сами по себе работают ! Или ты по иному мыслишь сие ?


Алексей Петров   (2001-11-08 12:57:00) [16]

Посмотрел - Packages он выгружает. Себя - нет.


Digitman   (2001-11-08 12:22:00) [17]

>Алексей Петров
Явно - нет. Но - погляди внимательно на call @Halt0.....


Алексей Петров   (2001-11-08 11:51:00) [18]

> Digitman © (08.11.01 11:33)
> А занятие ресурсов в контексте этого объекта может быть связано и с дополнительным инкрементом mmf.RefCount ... Какие у тебя соображения на эту тему ?

Можно мне?
На сколько я понимаю, TApplication явно mmf не использует => refCount не должен меняться.


Digitman   (2001-11-08 11:33:00) [19]

>Polevi
У меня работает и под Win98SE и под NT4(SP6). Именно - в оригинальном виде.

>paul_shmakov
Спасибо за детальное исследование темы. Я двигался тем же курсом и, в принципе, получил те же результаты в NT - закрытие хэндла 4 и UnmapViewOfFile можно свободно менять местами (действительно, здесь работает RefCount обного и того же объекта - mmf)

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

А вот что ты скажешь про пролог/эпилог Делфи-приложения, когда в нем задействуется и инициализируется/деинициализируется TApplication ? Ведь тот же ExitProcess вызывается в эпилоге лишь после корректного освобождения ресурсов, занятых объектом Application и его деинициализации !
А занятие ресурсов в контексте этого объекта может быть связано и с дополнительным инкрементом mmf.RefCount ... Какие у тебя соображения на эту тему ?


paul_shmakov   (2001-11-07 20:51:00) [20]

ну и для любителей delphi

{
test.pas
deletes itself. winnt only
dcc32 test.pas
}
program test;

uses Windows;

var
FileName: PChar;
hkrnl: HMODULE;
pUnmapViewOfFile: Pointer;
pDeleteFile: Pointer;
pExitProcess: Pointer;
pCloseHandle: Pointer;
hInstance: Cardinal;
begin
{ используем динамически выделяемую память из кучи, потому как иначе
компилятор размещает массив FileName вовсе не в стеке потока }
FileName := HeapAlloc(GetProcessHeap, 0, MAX_PATH);
GetModuleFileName(GetModuleHandle(nil), FileName, MAX_PATH);

hkrnl := GetModuleHandle("kernel32.dll");

pUnmapViewOfFile := GetProcAddress(hkrnl, "UnmapViewOfFile");
pDeleteFile := GetProcAddress(hkrnl, "DeleteFileA");
pExitProcess := GetProcAddress(hkrnl, "ExitProcess");
pCloseHandle := GetProcAddress(hkrnl, "CloseHandle");

hInstance := Cardinal(GetModuleHandle(nil));

asm
push 0
mov eax, FileName
push eax
push pExitProcess
push 4
push pDeleteFile
push hInstance
push pCloseHandle
push pUnmapViewOfFile
ret
end;
end.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо