Killing suspicious processes
As a result of an experiment, we found out that one process was being run in my local machine by an unknown user and this trigger my curiosity to know more about this and which actions I could do to fix it. Firstly, I decided to monitor the process and gather data from it by using some Delphi API libraries and secondly, build a little application to kill the process and keep a little log just in case. The application is called Thundax Suspicious process watcher v1.1 and it's able to filter processes by unknown/known users and apply actions to them.
Once the application is found (by the process to inspect text box) the utility kills the process and shows the resulted information. We can also force the killing system to the known processes and use it to force the end of and application by filtering it by name and user name.
In the next picture you can notice that I've terminated the execution of the notepad.exe by simply adding it name and process user name (me).
The application core is based on two parts, the first one that is able to search for the applications that are being run in your machine and the second one that is able to kill a process by its PID. Here you can get the implemented code:
Get process list:
procedure ProcessList(); var hProcSnap: THandle; pe32: TProcessEntry32; Domain, User: string; listItem: TListItem; begin hProcSnap := CreateToolHelp32SnapShot(TH32CS_SNAPALL, 0); if hProcSnap = INVALID_HANDLE_VALUE then Exit; pe32.dwSize := Sizeof(ProcessEntry32); ListView1.Clear; listCompare.List1.Clear; if Process32First(hProcSnap, pe32) = True then while Process32Next(hProcSnap, pe32) = True do begin if GetUserAndDomainFromPID(pe32.th32ProcessID, User, Domain) then begin if RadioButton2.Checked then begin listItem := ListView1.Items.Add; listItem.Caption := pe32.szExeFile; listItem.SubItems.Add(IntToStr(pe32.th32ProcessID)); listItem.SubItems.Add(User); listItem.SubItems.Add(Domain); listCompare.List1.Add(pe32.szExeFile); if AnsiUpperCase(pe32.szExeFile) = AnsiUpperCase(Edit2.text) then begin if Edit3.text <> '' then begin if AnsiUpperCase(User) = AnsiUpperCase(Edit3.text) then begin Log('Application founded ->' + AnsiUpperCase(Edit2.text)); if CheckBox3.Checked then begin KillProcess(pe32.th32ProcessID); Sleep(300); Log('Application killed ->' + AnsiUpperCase(Edit2.text)); end end; end else begin Log('Application founded ->' + AnsiUpperCase(Edit2.text)); if CheckBox3.Checked then begin KillProcess(pe32.th32ProcessID); Sleep(300); Log('Application killed ->' + AnsiUpperCase(Edit2.text)); end end; end; end end else begin if RadioButton1.Checked then begin // Suspicious Items listItem := ListView1.Items.Add; listItem.Caption := pe32.szExeFile; listItem.SubItems.Add(IntToStr(pe32.th32ProcessID)); listItem.SubItems.Add('UNKNOW'); listItem.SubItems.Add('UNKNOW'); listCompare.List1.Add(pe32.szExeFile); if AnsiUpperCase(pe32.szExeFile) = AnsiUpperCase(Edit1.text) then begin Log('Application founded ->' + AnsiUpperCase(Edit1.text)); if CheckBox2.Checked then begin KillProcess(pe32.th32ProcessID); Sleep(300); Log('Application killed ->' + AnsiUpperCase(Edit1.text)); end end; end end; Application.ProcessMessages; end; CloseHandle(hProcSnap); end; function GetUserAndDomainFromPID(ProcessId: DWORD; var User, Domain: string): Boolean; var hToken: THandle; cbBuf: Cardinal; ptiUser: PTOKEN_USER; snu: SID_NAME_USE; ProcessHandle: THandle; UserSize, DomainSize: DWORD; bSuccess: Boolean; begin Result := false; ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, false, ProcessId); if ProcessHandle <> 0 then begin if OpenProcessToken(ProcessHandle, TOKEN_QUERY, hToken) then begin bSuccess := GetTokenInformation(hToken, TokenUser, nil, 0, cbBuf); ptiUser := nil; while (not bSuccess) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) do begin ReallocMem(ptiUser, cbBuf); bSuccess := GetTokenInformation(hToken, TokenUser, ptiUser, cbBuf, cbBuf); end; CloseHandle(hToken); if not bSuccess then begin Exit; end; UserSize := 0; DomainSize := 0; LookupAccountSid(nil, ptiUser.User.Sid, nil, UserSize, nil, DomainSize, snu); if (UserSize <> 0) and (DomainSize <> 0) then begin SetLength(User, UserSize); SetLength(Domain, DomainSize); if LookupAccountSid(nil, ptiUser.User.Sid, PChar(User), UserSize, PChar(Domain), DomainSize, snu) then begin Result := True; User := StrPas(PChar(User)); Domain := StrPas(PChar(Domain)); end; end; if bSuccess then begin FreeMem(ptiUser); end; end; CloseHandle(ProcessHandle); end; end;
Kill process by PID:
procedure KillProcess(pid: integer); var h: THandle; begin try h := OpenProcess(PROCESS_TERMINATE, false, pid); try if h <> 0 then TerminateProcess(h, 0); finally CloseHandle(h); end; except ShowMessage('Error'); end; end;
Let me know if you have any doubt about the program or any improvement!.
Related links:
Comments
Post a Comment