Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Как "заморозить" процесс?


Автор: Jetus 24.2.2005, 12:57
Каким образом можно приостановить выбранный процесс?
Например, приостановить процесс чата в локальной сети, чтобы окно оставалось, но никаких сообщений программа не обрабатывала.

Я так понимаю, что сначала надо по имени процесса получить его PID, потом по этому PID найти главный поток и сделать ему SuspendThread(ThreadHandle)? smile

Автор: Александра 24.2.2005, 13:36
Jetus
совершенно верно smile

Автор: Петрович 24.2.2005, 13:46
Только тогда и его окошко перерисовываться не будет.

Автор: legwar 24.2.2005, 15:21
Sleep(dwMilliseconds:DWORD);
Kernel32.dll

Автор: Александра 24.2.2005, 16:10
legwar
слип не останавливает, а передает процессорное время на указанное кол-во милисекунд другим процессам или потокам, причем удаленно его не сделать.

Петрович
??? тут же останавливается поток, который сообшения по сетки ловит?

Автор: Петрович 24.2.2005, 16:31
Цитата
Петрович
??? тут же останавливается поток, который сообшения по сетки ловит?

Я не понял что этим ты хотела сказать.
Я в http://forum.vingrad.ru/index.php?showtopic=43506&view=findpost&p=335056 имел ввиду то, что отрисовка окна делается самим процессом, причем обычно его главным потоком. Соответственно, если приостановить тот поток процесса который обрабатывает WM_PAINT то, окно на экране останется лиш до тех мор пока его не подпортят. Например, если по нему проедутся другим окном, то затертая часть изображения не восстановится. Кроме того, естественно, такое окно нельзя будет ни таскать, ни перемещать, пока не "отпустят" поток.
А я так понял, что Jetus хочет что-бы окно-то осталось. Он хочет только приостановить прием сообщений по сетке.

Автор: Александра 24.2.2005, 16:50
Петрович
ну да, т.е. все и будет рисоваться а прием просто остановится... все верно...

Автор: Jetus 24.2.2005, 18:45
Так мне так и надо - чтобы процесс полностью "замёрз".
А как это осуществить? Я пробовал, но ничего не вышло smile

Автор: _hunter 24.2.2005, 19:01
останавливай все потоки процесса. а что пробовал?

Автор: p0s0l 26.2.2005, 12:17
Код
uses TlHelp32;

function OpenThread (dwDesiredAccess : DWORD; bInheritHandle : BOOL; dwThreadId : DWORD) : THandle; stdcall; external 'kernel32.dll';

const
 THREAD_SUSPEND_RESUME = $0002;

procedure SetSuspendState (PID : DWORD; Resume : Boolean);
var
 hSnap, hThread : THandle;
 te32 : THREADENTRY32;
begin
 hSnap := CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0);
 te32.dwSize := SizeOf(te32);
 if Thread32First (hSnap, te32) then
 repeat
   if te32.th32OwnerProcessID = PID then
   begin
     hThread := OpenThread (THREAD_SUSPEND_RESUME, False, te32.th32ThreadID);
     if Resume then ResumeThread (hThread)
     else SuspendThread (hThread);      
     CloseHandle (hThread);
   end;
 until not Thread32Next (hSnap, te32);
 CloseHandle (hSnap);
end;

Если нужно остановить какой-то процесс, к примеру, на 5 сек, то будет так:
Код
SetSuspendState (ProcessID, False);
Sleep (5000);
SetSuspendState (ProcessID, True);


PS: OpenThread нет в Win9x, поэтому там будет облом. Если надо, чтобы работало под 9x, то смотри "Арсенал" - там Girder приводил функцию OpenThread для всех версий винды...

Автор: Jetus 27.2.2005, 21:39
Большое спасибо, p0s0l! smile

Автор: Jetus 28.2.2005, 10:16
Уважаемый p0s0l, твой код отлично работает и я стал пробовать его на всех процессах подряд - останавливался даже поток System. Однако меня постигло разочарование, когда я попробовал остановить процесс navapsvc.exe - это служба Norton Antivirus'a. Этот процесс не желал останавливаться ни в какую! Даже принудительно завершатся не хочет через TaskManager и другие подобные менеджеры процессов. Как это может быть? Неубиваемый процесс??? smile

Автор: Girder 28.2.2005, 10:29
попробуй включить привелегию: SE_DEBUG_NAME

Автор: p0s0l 28.2.2005, 13:39
Делается это так:
Код
procedure SetDebugPrivilege (Enabled : Boolean);
var hToken : THandle;
   TokenPriv, PrevTokenPriv : TOKEN_PRIVILEGES;
   Tmp : DWORD;
begin
 OpenProcessToken (GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);
 LookupPrivilegeValue (nil, 'SeDebugPrivilege', TokenPriv.Privileges[0].Luid);
 TokenPriv.PrivilegeCount := 1;
 TokenPriv.Privileges[0].Attributes := 0;
 if Enabled then TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
 Tmp := 0;
 PrevTokenPriv := TokenPriv;
 AdjustTokenPrivileges (hToken, False, TokenPriv, SizeOf(PrevTokenPriv), PrevTokenPriv, Tmp);
 CloseHandle (hToken);
end;
Тогда выглядеть всё будет примерно так:
Код
 SetDebugPrivilege (True);
 SetSuspendState (ProcessID, False);
 Sleep (5000);
 SetSuspendState (ProcessID, True);


Автор: RA 28.2.2005, 19:43
Цитата(Girder @ 28.2.2005, 10:29)
попробуй включить привелегию: SE_DEBUG_NAME


Не поможет.
Добавлено @ 19:52
Цитата(Jetus @ 28.2.2005, 10:16)
Как это может быть? Неубиваемый процесс???


Теоретически процесс убиваемый просто нужно обойти хук, каторым он защищен.
Как правило речь идет о некой специфической dll в каждом твоём процессе.





Автор: Jetus 28.2.2005, 21:30
Большое спасибо ещё раз, г-н p0s0l!
Действительно, SetDebugPrivilege позволила его тормознуть.

Однако RAdmin тоже прав. Когда я для проверки (после того как остановил 4 процесса антивиря) решил скопировать вирус с одного места на другое, то у меня ничего не вышло, правда никакого предупредительного сообщения (как должно быть) не вылетело. Так и есть - стоит хук и хоть процессы заморожены, но хук работает. Как же "заморозить" хук? Может вопрос звучит глупо, но всё же?

Автор: RA 28.2.2005, 21:50
Jetus Тебе нужно выгружать чужую dll () из процесса каторому ты хочешь дать свободу действий.

Автор: bartram 28.2.2005, 21:55
RAdmin, а как узнать имя этой Dll?

Автор: RA 28.2.2005, 22:51
Ну это уже самому смотреть нужно какие длл-ки системные а какие подозрительные.
Добавлено @ 22:52
Смотри описание, пути запуска, информацию о файле.

Автор: Jetus 1.3.2005, 08:39
Спасибо, RAdmin, именно так я и думал, только вот я умею выгружать dll лишь из собственных процессов smile а как выгрузить нужную dll из чужого??? smile

Автор: Girder 1.3.2005, 10:29
Цитата(RAdmin @ 28.2.2005, 22:51)
Ну это уже самому смотреть нужно какие длл-ки системные а какие подозрительные.
Наврятли так приметивно... кто-то делает smile

Jetus смотри какие драйверы подключаются.

Цитата(Jetus @ 1.3.2005, 08:39)
а как выгрузить нужную dll из чужого???
Для динамически загруженных: FreeLibrary в контексе процесса

Автор: Jetus 1.3.2005, 13:41
Спасибо, Girder. Понятно, что FreeLibrary, только это для своего процесса. А у меня вопрос такой: я знаю, что определённый чужой процесс (назовём его "а.ехе") подгрузил библиотеку ("х.dll"). Как вугрузить из а.ехе библиотеку х.dll?

Автор: Girder 1.3.2005, 15:34
Типо так:
Код
uses tlhelp32;

procedure FreeLibraryPID(pID:Cardinal; NameDLL:string);
type
TInjectCode=packed record
 Push:Byte;
 PushValue:DWord;
 Call:Byte;
 CallValue:DWord;
 IsZero:Word;
 JmpZero:Word;
 Ret:Byte;
end;
var H:THandle;
   Module32:TModuleEntry32;
   InjectCode:TInjectCode;
   KernelDLL:DWord;
   oProcess,oProcessThread:DWord;
   PID_Mem:Pointer;
   t:DWord;
begin
InjectCode.CallValue:=0;
KernelDLL:=LoadLibrary('Kernel32.dll');
if KernelDLL<>0 then
 begin
  InjectCode.CallValue:=DWord(GetProcAddress(KernelDLL,'FreeLibrary'));
  FreeLibrary(KernelDLL);
 end;
if (pID=0)or(InjectCode.CallValue=0) then exit;
oProcess:=OpenProcess(PROCESS_ALL_ACCESS,False,PID);
if oProcess=0 then exit;
PID_Mem:=VirtualAllocEx(oProcess,nil,SizeOf(InjectCode),MEM_RESERVE or MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if PID_Mem=nil then
 begin
  CloseHandle(oProcess);
  exit;
 end;
NameDLL:=trim(NameDLL);
H:=CreateToolHelp32Snapshot(TH32CS_SNAPMODULE,pID);
if H<>INVALID_HANDLE_VALUE then
 begin
  InjectCode.Push:=$68;
  InjectCode.Call:=$e8;
  InjectCode.IsZero:=$C021;
  InjectCode.JmpZero:=$F275;
  InjectCode.Ret:=$C3;
  Module32.dwSize:=SizeOf(TModuleEntry32);
  if Module32First(H,Module32) then
   repeat
    if AnsiCompareText(NameDLL,Module32.szModule)=0 then
     begin
      InjectCode.PushValue:=DWord(Module32.modBaseAddr);
      InjectCode.CallValue:=InjectCode.CallValue-DWord(PID_Mem)-10;
      if (WriteProcessMemory(oProcess,PID_Mem,@InjectCode,SizeOf(InjectCode),t)and(t=SizeOf(InjectCode))) then
       begin
        oProcessThread:=CreateRemoteThread(oProcess,nil,0,PID_Mem,nil,0,t);
        if oProcessThread<>0 then
         begin
          if WaitForSingleObject(oProcessThread,1000)<>WAIT_TIMEOUT then //Даем на выгрузку одну секунду.
           ShowMessage('Один есть!');
          CloseHandle(oProcessThread);
         end;
       end;
     end;
   until (Module32Next(H,Module32)=false);
  CloseHandle(H);
 end;
VirtualFreeEx(oProcess,PID_Mem,0,MEM_RELEASE);  
CloseHandle(oProcess);
end;


Использование:
Код
procedure TForm1.Button1Click(Sender: TObject);
var pID:DWord;
   NameDLL:String;
begin
pID:=StrToInt(Edit1.Text);
NameDLL:=Edit2.Text;
FreeLibraryPID(pID,NameDLL);
end;


PS: Выгрузка только динамически загруженных DLL. Если ты выгрузиш(попытаешся) статическую... то процесс-жертва скорее всего прибьется системой. smile

Автор: Jetus 1.3.2005, 19:03
Girder, ты меня просто выручил! Отличный код! smile
Резюме по топику или для чего всё это было нужно: пробрался ко мне на комп вирь, который инжектирует свою dll-библиотеку в другие процессы. "Замораживать" процессы меня тут уже научили (ещё раз спасибо г-ну p0s0l), выгружать библиотеки из чужих процессов научили (ещё раз спасибо, Girder).
Остался ещё только один вопрос. Я не уверен, но по моему вирь запихивает свою dll-библиотеку в адресное пространство Kernel32.dll. Вопрос: Как можно просмотреть, какие библиотеки загружены Kernel32.dll?

Автор: Girder 1.3.2005, 22:29
Цитата(Jetus @ 1.3.2005, 19:03)
Я не уверен, но по моему вирь запихивает свою dll-библиотеку в адресное пространство Kernel32.dll
Енто как... так? smile smile

PS: Вирь может сидеть! в адрессном пространстве Kernel32 и т.п. Он может не много(или много) переписать код Kernel32(или других Dll) в нутри адрессного пространства. Тогда так... енто проверяется: Сравнивается код Dll в контексте процесса жертвы... и в твоем контексте... (или с образом на диске - но енто чуть сложнее)

PS2: Ты б лудше антивирь... запустил smile

Автор: Jetus 2.3.2005, 17:37
Гы smile Антивирь его не видит - я специально даже новые базы скачал.
Но он вроде как притих, кажись я замочил его инжектор и теперь он не проявляется.

Огромная благодарность всем, кто принимал участие в топике! Спасибо! smile

Автор: RA 3.3.2005, 21:23
Цитата(Girder @ 1.3.2005, 10:29)
Наврятли так приметивно... кто-то делает


Нормально smile !

Автор: Competitor 31.1.2006, 13:34
А монжо ли приостановить выполнение программы до наступления события OnActivate? Прошу пример

Автор: _hunter 31.1.2006, 13:57
а она и так после него работать начинает...
что именно тебе нужно?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)