nedsociety / pysandboxie

A python binding to Sandboxie
MIT License
12 stars 2 forks source link

Terminating specific app #3

Closed nubonics closed 3 years ago

nubonics commented 3 years ago

if there is more than one program in a single sandbox, can i shut down / stop one of the programs without terminating / killing the entire sandbox?

nedsociety commented 3 years ago

AFAIK there's no API for a single app termination from sandboxie, hence there's no API in this package as well.

However I'm getting a feeling that you can kill them with psutil package just as fine as any other processes. Can you try it first?

nubonics commented 3 years ago

Here is an example of a failure to close a specific program within a sandbox:

import sandboxie
import psutil
from time import sleep

# Initialize Sandboxie object
sbie = sandboxie.Sandboxie()

# Create a sandbox "testpy" with default settings
settings = sbie.make_sandbox_setting('default')
# sbie.create_sandbox('testpy', settings=settings)

# Executes notepad inside it
proc = sbie.execute(['notepad.exe'], 'testpy')
# and retrieve its exit code
# print(proc.wait())
sleep(5)
PID = proc.pid
p = psutil.Process(PID)
p.terminate()
print('pid killed')
nedsociety commented 3 years ago

sbie.execute() returns the proc object for host-side invocation process (Start.exe), not the one for notepad. Killing Start.exe effectively makes your process zombie isolated inside the sandboxie. The return value for sbie.execute() is meant for waiting and checking the exit code.

Here's a modified example working with notepad:

import sandboxie
import psutil
from time import sleep

# Initialize Sandboxie object
sbie = sandboxie.Sandboxie()

# Create a sandbox "testpy" with default settings
settings = sbie.make_sandbox_setting('default')
# sbie.create_sandbox('testpy', settings=settings)

# Executes notepad inside it
proc = sbie.execute(['notepad.exe'], 'testpy')

sleep(5)

notepads = [process for process in psutil.process_iter(['pid', 'name']) if process.name().lower() == 'notepad.exe']

if len(notepads) == 1:
    pid = notepads[0].pid
    notepads[0].terminate()
    print(f'notepad (pid {pid}) killed')
else:
    print('multiple notepad.exe exists')

Does this solve your use case?

nubonics commented 3 years ago

is there a way i can identify the program that is within the sandbox? lets say im running 5 notepads, one per sandbox

really appreciate the help, you do not have to continue, feel free to close the issue if you want, would like a continuation of you dont mind

nubonics commented 3 years ago

also, I know this is more of a sandboxie question but was wondering if you knew / could help me out. so the program I am running should be reading and writing to the local filesystem or at least it does when it is running outside of sandboxie. I've looked at the same location to see if the file has been read or modified when I place it in a sandbox, but because of the isolation [i think] it does not create and then read the file I am expecting, but im almost positive it has to get it from somewhere and was wondering if there is a cache or somewhere that this is done?

nedsociety commented 3 years ago

is there a way i can identify the program that is within the sandbox? lets say im running 5 notepads, one per sandbox

really appreciate the help, you do not have to continue, feel free to close the issue if you want, would like a continuation of you dont mind

This actually might be something can be helped: there's a listpid API that I can add. Then you can just do something like this to filter the sandboxed app:

sandboxed_notepads = set(sbie.listpid()) & set(notepad.pid for notepad in notepads)

Do you want this approach to be implemented?

also, I know this is more of a sandboxie question but was wondering if you knew / could help me out. so the program I am running should be reading and writing to the local filesystem or at least it does when it is running outside of sandboxie. I've looked at the same location to see if the file has been read or modified when I place it in a sandbox, but because of the isolation [i think] it does not create and then read the file I am expecting, but im almost positive it has to get it from somewhere and was wondering if there is a cache or somewhere that this is done?

Eh, a bit confusing description for me, but basically raw app should access raw path and sandboxed app should access the corresponding path inside the Sandbox directory, unless direct access settings are present. If you think some behavior is unexpected, then you should report here: https://github.com/sandboxie-plus/Sandboxie/issues . Personally I also had several experiences of file system bugs before (e.g., this and that) so you'll get much better chance solving your problem there.

nubonics commented 3 years ago

Mm, I dont think its a bug, just extended functionality / trying to automate a right click terminate from within the sandbox. When I open two programs within a sandbox [my apologies for not declaring this earlier], I am able to right click and terminate one out of the two programs without killing the other program and without terminating the sandbox and was hoping for this feature to be allowed within programming.

What I think you are saying by filtering and what I see by code are two different things so I'll have to ask for clarification. If I could get the pids and names of the programs running in each sandbox that would be perfect. As an example sandbox_information = [{'notepad.exe': 4335, 'otherprogram.exe': 5622, 'sandbox_name': 'sandbox1' {'notepad.exe': 2456, 'otherprogram.exe': 8910, 'sandbox_name': 'sandbox2'}]

This gives me all of the pids and their corresponding pid within each sandbox so that I can get the exact program that I am looking for and interact with it [getting a handle].

Your approach above looks similar but I think it is lacking the specificity I am looking for as it isnt any different than using psutil, as psutil you can find pids associated with names, but i cant distinguish one notepad from another as the same name is provided for multiple pids. An example of using psutil to find notepad.exe would be [4335, 2456], but I would be unable to know which pid belongs to which sandbox.

If there is a way to specify a sandbox when looking for names and getting the pids that would work perfectly.

nedsociety commented 3 years ago

I believe it's possible to filter pids if sandbox name is given (like sbie.listpids('testpy') should work), though I need to test it.

OTOH I'm not sure if you could fetch the names of all sandboxes that are currently active, so for example taking sandbox_information in your example, or Kill all notepads from sandbox prefixed with 'mysandbox_'. won't be trivial.

nubonics commented 3 years ago

If I have more than that I need to kill, as long as I can find them individually and kill one by one, this would be perfect. I think this also might be useful to others [this functionality]

killing in bulk isnt required, but killing a specific program from a specific sandbox is definitely what im after. You would definitely be doing me a solid if you could implement this somehow

:D :D :D

nedsociety commented 3 years ago

listpids() added in the latest commit. If you still have a problem, let me know 😉

AlexeyArtemev commented 2 years ago

listpids() is not working when an executed process is terminated, yet there's another process created by it. For example, if you open an app and it opens another app and terminates itself, listpids will not be able to show you the child app's PID

nedsociety commented 2 years ago

@AlexeyArtemev Seems working fine for me:

>>> import sandboxie
>>> sbie=sandboxie.Sandboxie()
>>> # Ran cmd in DefaultBox
>>> sbie.listpids('DefaultBox')
[451716, 477484, 440748]
>>> # Ran notepad from cmd
>>> sbie.listpids('DefaultBox')
[451716, 477484, 440748, 445648]
>>> # Closed cmd
>>> sbie.listpids('DefaultBox')
[451716, 440748, 445648]

Is there a repro step for your issue?