Форум: "WinAPI";
Текущий архив: 2005.01.09;
Скачать: [xml.tar.bz2];
ВнизNTFS - Процесс без файла - глюк или фантастика ? Найти похожие ветки
← →
kaZaNoVa © (2004-11-20 15:38) [0]Недавно мне попалась статья о том, что используя механизм файловых потоков NTFS можно реализовывать некоторые интересные идеи.
Например если запустить программу из файлового потока, то можно "файл-носитель" удалить (!), а программа будет далее работать !
- имхо один из самых лучших способов самоудаления для инсталляторов, а также _очень_ хороший способ защиты от изменений ЕХЕ
- для защиты коммерческого ПО - основной ЕХЕ можно хранить зашифрованным, и используя этот механизм возможно фактически "процесс без исполняемого файла !" - то есть кракер НЕ СМОЖЕТ исследовать ЕХЕ так,как ЕГО НЕТ НА диске !!!
мой главный вопрос - это глюк, связанный с недоработкой файловой системы NTFS или стандарная возможность системы ?
и еще, работает ли это на ХР SP2 ? (просьба протестировать код)
и будет ли работать в ледующих версиях системы ? (LongHorn ?)
(у меня на 2003 работает) ;)
а также - есть ли документация на файловые потоки NTFS ?
код:program TestNTFS;
uses
Windows,SysUtils;
const StreamName=":sys_file_system";
Var zapusk:integer;
my,target:string;
function CopyFileI(source, dest:pchar):boolean;
var h,h2:integer;
mas:array[1..2048] of byte;
i:cardinal;
done:cardinal;
begin
result:=false; h:=0; h2:=0;
Try
h:=CreateFile(source,GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
h2:=CreateFile(dest,GENERIC_WRITE,FILE_SHARE_WRITE,nil,OPEN_ALWAYS,0,0);
if (h2<=0) or (h<=0) then exit;
while ReadFile(h,mas,sizeof(mas),done,nil) and (done<>0) do
WriteFile(h2,mas,done,i,nil);
Except End;
CloseHandle(h);
CloseHandle(h2);
result:=true;
end;
begin
if pos(StreamName,Paramstr(0))>0 then begin
MessageBox(0,"Ура, Мы свободны !!","Фантастика",mb_ok);
MessageBox(0,"Мы работаем без файла !!!","Фантастика v2",mb_ok);
Exit;
end;
my:=Paramstr(0);
target:=ChangeFileExt(my,".txt");
if CopyFileI(Pchar(my),Pchar(target+StreamName)) then
begin
zapusk:=WinExec(PChar(target+StreamName),SW_SHOWDEFAULT);
if zapusk<32 then MessageBox(0,Pchar(SysErrorMessage(GetLastError)),Pchar("Ошибка # "+IntToStr(GetLastError)),0);
Sleep(350);
if not DeleteFile(Pchar(target)) then MessageBox(0,Pchar(SysErrorMessage(GetLastError)),Pchar("Ошибка # "+IntToStr(GetLastError)),0);
end;
end.
← →
Игорь Шевченко © (2004-11-20 17:57) [1]А файл-то при этом на диске есть ? Который .txt ?
← →
Piter © (2004-11-20 18:14) [2]kaZaNoVa © (20.11.04 15:38)
Например если запустить программу из файлового потока, то можно "файл-носитель" удалить (!), а программа будет далее
а чего ты так переживаешь? Насчет вот удалить не получится - но вот переместить EXE"шник (в том числе переименовать его, дать ему расширение TXT например) во время работы программы в NT системах можно (NTFS не при чем)
← →
kaZaNoVa © (2004-11-20 18:19) [3]Напоминаю смысл кода:
первоначально файла .ТХТ нет!
он создаётся на время работы, при этом программа стартует из него, и ЕХЕ таким образом свободен ;)
- то еть его (ехе можно удалить программой, запущенной из .тхт, которая уже работает без файла на диске !)
Piter © (20.11.04 18:14) [2]
Ты не совсем понял смысла кода - попробуй запустить, велезет мессага - её не закрывай, удали ехе - и фактически программа работает сама по себе :)))
-
> Насчет вот удалить не получится
а у меня - именно УДАЛИТЬ !!
← →
kaZaNoVa © (2004-11-20 18:23) [4]файл тхт тоже удаляется ;)
← →
Игорь Шевченко © (2004-11-20 18:32) [5]Я нифига не понял. Ты переписываешь свой exeшник в именованный поток текстового файла, запускаешь его, после этого удаляешь безымянный поток текстового файла, и что тут нового ?
Точно также ты можешь переписать exeшник в один файл, запустить его, удалить любой другой файл и твой процесс будет работать. Что нового ?
← →
Piter © (2004-11-20 18:32) [6]Хм, ну и что? Не понимаю восторгов. С таким же успехом можно создать удаленный поток, который убьет любой файл (в том числе и EXE), после чего завершится.
← →
kaZaNoVa © (2004-11-20 18:38) [7]имхо .. новое то, что фактически ехе работает без файла ;)
Piter © (20.11.04 18:32) [6]
я в соседней теме уже долго над этим бьюсь ..
пока выходин не очень грамотно ...
← →
Игорь Шевченко © (2004-11-20 18:48) [8]
> имхо .. новое то, что фактически ехе работает без файла
> ;)
В этом ты здорово ошибаешься. Открой Process Explorer, найди свой процесс и посмотри, какие файлы им заняты.
← →
Leonid Troyanovsky (2004-11-20 19:09) [9]Приветствую, Игорь.
> В этом ты здорово ошибаешься. Открой Process Explorer, найди
> свой процесс и посмотри, какие файлы им заняты.
Не заняты.
Т.е., исходный может удалить даже запущенная копия
(если, конечно обходится без WinExec)
--
С уважением, LVT.
← →
Leonid Troyanovsky (2004-11-20 19:15) [10]Приветствую, kaZaNoVa.
> имхо .. новое то, что фактически ехе работает без файла
> ;)
Gary Nebbett когда-то показывал как запускать процесс
из памяти (NT4+).
В NTFS нет нужды, т.к. запуск идет, действительно,
из памяти.
--
С уважением, LVT.
← →
Leonid Troyanovsky (2004-11-20 19:19) [11]Приветствую, Piter.
> Хм, ну и что? Не понимаю восторгов. С таким же успехом можно
> создать удаленный поток, который убьет любой файл (в том
> числе и EXE), после чего завершится.
Память, распределенную для потока в чужом процессе
сам поток освободить не сможет. Если, конечно,
не пользоваться трюками в духе того же Gary Nebbett,
выполняя код из стека.
--
С уважением, LVT.
← →
Piter © (2004-11-20 19:32) [12]Leonid Troyanovsky (20.11.04 19:19) [11]
Память, распределенную для потока в чужом процессе
сам поток освободить не сможет
почему?!
← →
Игорь Шевченко © (2004-11-20 19:34) [13]Leonid Troyanovsky (20.11.04 19:09) [9]
Приветствую, Леонид!
Файл не занят (в списке Handles его нет, он есть в списке DLL).
Тогда вопрос - насколько мне известно, CreateProcess в какой-то момент создает FileMapping для исполняемого образа, получается, что этого недостаточно для блокировки файла от удаления ?
Если файл можно удалить после запуска, то, получается, что выделенное под него место может быть теоретически использовано сразу же под другое содержимое. А как же тогда будет работать подкачка страниц из исполняемого образа ?
С уважением,
Игорь Шевченко
PS: Какими судьбами здесь ?
← →
Leonid Troyanovsky (2004-11-20 19:43) [14]
> Память, распределенную для потока в чужом процессе
> сам поток освободить не сможет
> почему?!
После VirtualFree ему надо еще нормально завершиться,
то есть выйти из функции потока.
А такие трюки, как исполнение кода из стека скоро
будут запрещены, ввиду великой опасности.
--
С уважением, LVT.
← →
kaZaNoVa © (2004-11-20 19:44) [15]Leonid Troyanovsky (20.11.04 19:19) [11]
огромное спасибо за поддержку ;)
я тут уже давно интересуюсь "недокументированными возможностими системы" :))
по сабжу - я пока не смог открыть файл, который удалил ..:)
а из памяти - пока не знаю как ..
вариант с потоком - в другом процессе - без длл - наполовину уже реализован - в соседней ветке :)
← →
Piter © (2004-11-20 19:50) [16]Игорь Шевченко © (20.11.04 19:34) [13]
PS: Какими судьбами здесь ?
Леонид из ФИДО что ли? :)
Очень похоже, по крайней мере
И еще похоже - очень хороший спец, судя по реакции Игоря...
← →
Leonid Troyanovsky (2004-11-20 19:57) [17]Приветствую, Игорь.
> Тогда вопрос - насколько мне известно, CreateProcess в какой-то
> момент создает FileMapping для исполняемого образа, получается,
> что этого недостаточно для блокировки файла от удаления
> ?
В принципе, недостаточно. В исполняемом файле есть
его хендл (проекции файла). Если его закрыть, то
файл можно и удалить. Раньше это был (NT4,5), AFAIK.
THandle(4), а потом (XP), для exe спрятали дальше.
Для dll он пока там же.
http://groups.google.com/groups?selm=c14f01c1a0f7%24f9b3f010%249ae62ecf%40tkmsftngxa02
> Если файл можно удалить после запуска, то, получается, что
> выделенное под него место может быть теоретически использовано
> сразу же под другое содержимое. А как же тогда будет работать
> подкачка страниц из исполняемого образа ?
Ну, если помнишь, то екзешники с дискет можно было выполнять
даже вытащив ее. Т.е., видимо, д.б. еще что-то, предотвращение
предотвращения сброса страниц. Для дискет это было, IMHO,
проекция файла в свопе.
> PS: Какими судьбами здесь ?
Да, так - мимо проходил :)
--
С уважением, LVT.
← →
Leonid Troyanovsky (2004-11-20 20:08) [18]Приветствую.
> я тут уже давно интересуюсь "недокументированными возможностими
> системы" :))
>
> по сабжу - я пока не смог открыть файл, который удалил ..:)
>
> а из памяти - пока не знаю как ..
Ничего, если далее без поклонов? Я, понял, тут все по
домашнему, да и для оформления правилам не очень тут
приспособлено.
Gary Nebbett, как раз, целую книгу написал, типа справочника.
Можно найти и в электронном виде.
Насчет открытия удаленного файла я не очень понял.
А запуск из памяти делается так
http://groups.google.com/groups?selm=3e7f8d41%240%24227%24cc9e4d1f%40news.dial.pipex.com
Где-то я делал ему дельфийский перевод.
← →
Leonid Troyanovsky (2004-11-20 20:11) [19]
> Где-то я делал ему дельфийский перевод.
http://groups.google.com/groups?hl=ru&lr=&selm=1991108605%40f1003.n5080.z2.fidonet.ftn
← →
Игорь Шевченко © (2004-11-20 20:29) [20]Leonid Troyanovsky (20.11.04 20:11) [19]
> > Где-то я делал ему дельфийский перевод.
Вопрос такой:
" ReadProcessMemory(pi.hProcess, PCHAR(context.ebx) + 8, @x, sizeof (x), nb);
ZwUnmapViewOfSection(pi.hProcess, x);
..........
q := VirtualAllocEx( pi.hProcess,
..........
WriteProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, @q, sizeof(q), nb);"
Насколько я понимаю, адрес проекции заменяется на адрес полученный непосредственным выделением памяти.
Когда процесс завершается, IMHO, где в недрах завершателя должен быть вызов UnmapViewOfSection, при этом адрес памяти на проекцю не ссылается.
Проблем из-за этого не возникнет ?
С уважением,
Игорь Шевченко
← →
Leonid Troyanovsky (2004-11-20 20:45) [21]
> kaZaNoVa © (20.11.04 19:44) [15]
> вариант с потоком - в другом процессе - без длл - наполовину
> уже реализован - в соседней ветке :)
Для удаления экзешников можно воспользоваться Explorer.
Правда, совсем без dll неудобно, т.к. проще всего это
сделать устанавливая хук на WH_GETMESSAGE.
Послав окну проводника условленное сообщение (передавая
ему hhook и значение хендла с проекцией файла от
DuplicateHandle) , после обработки этого сообщения в хуковой
процедуре хук можно снять (и далее библиотека уже не нужна).
Сама обработка заключается в открытии проекции и выполнении
кода потока, записанного туда (вместе с FileName).
Сам код потока д.б. перемещаемым, т.е., обращаться только
к функциям kernel32 (обычно грузимым по одному адресу)
и переменным из стека и (возможно из проекции файла).
По сути, поток дожидается окончаний процесса WaitForSingleObject
делает DeleteFile и завершается. Хотя поток и сможет
сделать CloseHandle проекции файла, однако UnMapViewOfFile
ему сделать не удасться (вот они - утечки).
Т.е., библиотека, все же, пригодится и во второй раз -
для корректного завершения потока (в обратном порядке,
в ответ на еще одно сообщение).
Ну, а, вообще, такие схемы напоминают вредоносный код :)
← →
kaZaNoVa © (2004-11-20 20:48) [22]Leonid Troyanovsky (20.11.04 20:45) [21]
> Сам код потока д.б. перемещаемым, т.е., обращаться
>только
>к функциям kernel32 (обычно грузимым по одному адресу)
> и переменным из стека и (возможно из проекции файла).
для меня - самое сложное ...
> Ну, а, вообще, такие схемы напоминают вредоносный код
> :)
ага, все, что идёт глубже, чем обычный пользовательский уровень - в недра системы .. - можно назвать "хаком", однако, такие схемы позволяют то, что невозможно обычными способами .. а это здорово !!
← →
Leonid Troyanovsky (2004-11-20 21:11) [23]
> Игорь Шевченко © (20.11.04 20:29) [20]
> Насколько я понимаю, адрес проекции заменяется на адрес
> полученный непосредственным выделением памяти.
> Когда процесс завершается, IMHO, где в недрах завершателя
> должен быть вызов UnmapViewOfSection, при этом адрес памяти
> на проекцю не ссылается.
> Проблем из-за этого не возникнет ?
Насколько я представляю, поведение UnmapViewOfSection
аналогично UnMapViewOfFile и некорректный адрес смутить ее
не может. А если что-то и осталось замапленным, то система,
все равно, гарантирует очистку.
Вспомним, хотя бы, TerminateProcess, который может случится
даже на самых финальных стадиях.
Во всяком случае, утечек системных ресурсов от этого кода
мне наблюдать не удалось (NT4, w2k3).
← →
Leonid Troyanovsky (2004-11-20 21:44) [24]
> > Сам код потока д.б. перемещаемым, т.е., обращаться
> >только
> >к функциям kernel32 (обычно грузимым по одному адресу)
> > и переменным из стека и (возможно из проекции файла).
> для меня - самое сложное ...
library lib0;
uses
Messages,
Windows,
injdef;
function ThreadProc(Info: PRemoteInfo): DWord; stdcall;
begin
Result := 0;
if Info.Event <> 0 then
begin
Info.pSetEvent(Info.Event);
Info.pCloseHandle(Info.Event);
end;
if Info.hProcess <> 0 then
begin
Info.pWaitForSingleObject(Info.hProcess, INFINITE);
Info.pCloseHandle(Info.hProcess);
end;
Info.pDeleteFile(Info.FileName);
if Info.FileMap <> 0 then
Info.pCloseHandle(Info.FileMap);
Info.pExitThread(0);
end;
function DoThread( nCode: Integer; wprm: WParam; lprm:WParam):Lparam;
stdcall;
type
PMsg = ^TMsg;
var
HFileMap : THandle;
msg : PMsg;
Info : PRemoteInfo;
hThread : THandle;
tid : DWord;
HKernel : THandle;
mmfname : String;
begin
Result := 0;
msg := PMsg(lprm);
if (msg.Message = 0) and (msg.WParam = 1) then
begin
Str(msg.LParam, mmfname);
mmfname := "_filemap"+ mmfname;
HFileMap:=CreateFileMapping( $FFFFFFFF,
nil,
PAGE_READWRITE,
0,
$FFF,
PChar(mmfname));
if HFileMap = 0 then
Exit;
Info := MapViewOfFile( HFileMap,
FILE_MAP_WRITE,
0,
0,
0);
if (Info = nil) then
begin
CloseHandle(HFileMap);
Exit;
end;
Info.FileMap := HFileMap;
CopyMemory( @Info.InjectThreadCode[0],
@ThreadProc,
Longint(@DoThread)- Longint(@THreadProc));
HKernel := GetModuleHandle("Kernel32.dll");
Info.pSetEvent:= GetProcAddress(HKernel,"SetEvent");
Info.pCloseHandle := GetProcAddress(HKernel,"CloseHandle");
Info.pWaitForSingleObject:=GetProcAddress(HKernel,"WaitForSingleObject");
Info.pDeleteFile := GetProcAddress(HKernel, "DeleteFileA");
Info.pExitThread := GetProcAddress(HKernel, "ExitThread");
FlushViewOfFile(Info, 0);
hThread := CreateThread( nil,
1024,
@Info.InjectThreadCode[0],
Info,
0,
tid);
if hThread <> 0 then
CloseHandle(hThread);
end;
end;
exports
DoThread;
begin
end.
----
unit injdef;
interface
uses
Windows;
type
FDeleteFile = function (lpFilename: PChar): LongBool;stdcall;
FSetEvent = function (aHandle: THandle): LongBool;stdcall;
FCloseHandle = function(aHandle: THandle): LongBool;stdcall;
FWaitForSingleObject = function (aHandle: THandle; dwTime: Dword): Dword;stdcall;
FExitThread = procedure (ExitCode: DWord);stdcall;
TRemoteInfo = packed record
FileMap : THandle;
Event : THandle;
hProcess: THandle;
pSetEvent: FSetEvent;
pDeleteFile: FDeleteFile;
pCloseHandle : FCloseHandle;
pWaitForSingleObject: FWaitForSingleObject;
pExitThread : FExitThread;
FileName : array [0..MAX_PATH] of Char;
InjectThreadCode : Array [0..1023] of Byte;
end;
PRemoteInfo= ^TRemoteInfo;
implementation
end.
---
program ad2;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils,
injdef;
const
{Warning: use other target instead Explorer}
TargetWindowClass : PChar = "Progman";
var
tid : THandle;
AHook: THandle;
Event : THandle;
HookDll : THandle;
HFileMap:THandle;
Info : PRemoteInfo;
function DupHandle(RemoteProcess: DWord; Handle: THandle): THandle;
begin
Result := 0;
Win32Check(DuplicateHandle( GetCurrentProcess,
Handle,
RemoteProcess,
@Result,
0,
False,
DUPLICATE_SAME_ACCESS));
end;
procedure Inject(Target: THandle);
var
aproc : Pointer;
rpid : DWord;
hRProcess: THandle;
begin
HookDll:= LoadLibrary("lib0.dll");
Win32Check(HookDll> 0);
aproc := GetProcAddress(HookDll, "DoThread");
Win32Check(aproc <> nil);
tid := GetWindowThreadProcessId(Target, @rpid);
Win32Check(tid <> 0);
hRProcess := OpenProcess(PROCESS_ALL_ACCESS, False, rpid);
Win32Check(hRProcess <> 0);
Event:= CreateEvent(nil, True, False, nil);
HFileMap:=CreateFileMapping( $FFFFFFFF,
nil,
PAGE_READWRITE,
0,
$FFF,
PChar("_filemap"+IntToStr(GetCurrentProcessID)));
Win32Check(HFileMap <> INVALID_HANDLE_VALUE);
Info := MapViewOfFile( HFileMap,
FILE_MAP_WRITE,
0,
0,
0);
Win32Check(Info <> nil);
Info.Event := DupHandle(hRProcess, Event);
Info.hProcess := DupHandle(hRProcess, GetCurrentProcess);
if hRProcess <> 0 then
CloseHandle(hRProcess);
CopyMemory(@Info.FileName[0], PChar(ParamStr(0)), Length(ParamStr(0))+1);
FlushViewOfFile(Info, 0);
AHook := SetWindowsHookEx(WH_GETMESSAGE, aproc, HookDll, tID);
Win32Check(AHook <> 0);
PostThreadMessage(tid, 0, 1, GetCurrentProcessID);
Sleep(0);
end;
procedure Reject;
begin
if Info <> nil then
UnmapViewOfFile(Info);
if HFileMap <> 0 then
CloseHandle(HFileMap);
if AHook <> 0 then
begin
UnHookWindowsHookEx(AHook);
PostThreadMessage(tid, 0, 0, 0);
end;
if HookDll <> 0 then
FreeLibrary(HookDll);
if Event <> 0 then
CloseHandle(Event);
end;
var
hwnd : THandle;
begin
hwnd := FindWindow(TargetWindowClass, nil);
Win32Check(hwnd <> 0);
try
Inject(hwnd);
case WaitForSingleObject(Event, 1000) of
WAIT_OBJECT_0: ;
else
raise Exception.Create("Unable load dll")
end;
finally
Reject;
end;
writeln("Press Enter for delete this module..");
readln;
end.
← →
Leonid Troyanovsky (2004-11-20 21:54) [25]
> kaZaNoVa © (20.11.04 20:48) [22]
> > Ну, а, вообще, такие схемы напоминают вредоносный код :)
> ага, все, что идёт глубже, чем обычный пользовательский
> уровень - в недра системы .. - можно назвать "хаком", однако,
> такие схемы позволяют то, что невозможно обычными способами
> .. а это здорово !!
В данном случае, т.е. поток в чужом процессе - это недра
не системы, а лишь чужого процесса.
Ну, а позволяют оные схемы лишь то, что позволено.
Хотя, конечно, и дыры встречаются. Чего стоило одно лишь
сообщение WM_TIMER, исполнявшее код в чужом процессе :)
← →
kaZaNoVa © (2004-11-20 21:58) [26]Leonid Troyanovsky (20.11.04 21:54) [25]
спасибо за пример - буду разбираться ;))
> Ну, а позволяют оные схемы лишь то, что позволено.
имхо много позволяют :)))
особенно если пользователь с правами админа :))
← →
Leonid Troyanovsky (2004-11-20 22:13) [27]
> kaZaNoVa © (20.11.04 21:58) [26]
> > Ну, а позволяют оные схемы лишь то, что позволено.
> имхо много позволяют :)))
> особенно если пользователь с правами админа :))
Это палка о двух концах. Жизнь подсказывает,
что даже если есть возможность использовать чрезвычайные
полномочия, делать это надо весьма дозировано.
По-крайней мере, не применять их при написании приложений ;)
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.01.09;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.045 c