diff --git a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/local/LocalWindowsNativeProcessPtySession.java b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/local/LocalWindowsNativeProcessPtySession.java index 5b6a71208d..4df5657b76 100644 --- a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/local/LocalWindowsNativeProcessPtySession.java +++ b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/local/LocalWindowsNativeProcessPtySession.java @@ -25,6 +25,7 @@ import com.sun.jna.ptr.IntByReference; import ghidra.pty.PtySession; import ghidra.pty.windows.Handle; +import ghidra.pty.windows.jna.JobApiNative; import ghidra.util.Msg; public class LocalWindowsNativeProcessPtySession implements PtySession { @@ -33,14 +34,16 @@ public class LocalWindowsNativeProcessPtySession implements PtySession { private final Handle processHandle; //private final Handle threadHandle; private final String ptyName; + private final Handle jobHandle; public LocalWindowsNativeProcessPtySession(int pid, int tid, Handle processHandle, - Handle threadHandle, String ptyName) { + Handle threadHandle, String ptyName, Handle jobHandle) { this.pid = pid; //this.tid = tid; this.processHandle = processHandle; //this.threadHandle = threadHandle; this.ptyName = ptyName; + this.jobHandle = jobHandle; Msg.info(this, "local Windows Pty session. PID = " + pid); } @@ -84,17 +87,8 @@ public class LocalWindowsNativeProcessPtySession implements PtySession { @Override public void destroyForcibly() { - if (!Kernel32.INSTANCE.TerminateProcess(processHandle.getNative(), 1)) { - int error = Kernel32.INSTANCE.GetLastError(); - switch (error) { - case Kernel32.ERROR_ACCESS_DENIED: - /** - * This indicates the process has already terminated. It's unclear to me whether - * or not that is the only possible cause of this error. - */ - return; - } - throw new LastErrorException(error); + if (!JobApiNative.INSTANCE.TerminateJobObject(jobHandle.getNative(), 1).booleanValue()) { + throw new LastErrorException(Kernel32.INSTANCE.GetLastError()); } } diff --git a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/ConPtyChild.java b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/ConPtyChild.java index 952ec903ce..7c7cd83404 100644 --- a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/ConPtyChild.java +++ b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/ConPtyChild.java @@ -31,6 +31,7 @@ import ghidra.pty.PtyChild; import ghidra.pty.local.LocalWindowsNativeProcessPtySession; import ghidra.pty.windows.jna.ConsoleApiNative; import ghidra.pty.windows.jna.ConsoleApiNative.STARTUPINFOEX; +import ghidra.pty.windows.jna.JobApiNative; public class ConPtyChild extends ConPtyEndpoint implements PtyChild { @@ -83,6 +84,11 @@ public class ConPtyChild extends ConPtyEndpoint implements PtyChild { * TODO: How to control local echo? */ + HANDLE hJob = JobApiNative.INSTANCE.CreateJobObjectW(null, null); + if (hJob == null) { + throw new LastErrorException(Kernel32.INSTANCE.GetLastError()); + } + STARTUPINFOEX si = prepareStartupInfo(); PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); @@ -102,9 +108,13 @@ public class ConPtyChild extends ConPtyEndpoint implements PtyChild { throw new LastErrorException(Kernel32.INSTANCE.GetLastError()); } + if (!JobApiNative.INSTANCE.AssignProcessToJobObject(hJob, pi.hProcess).booleanValue()) { + throw new LastErrorException(Kernel32.INSTANCE.GetLastError()); + } + return new LocalWindowsNativeProcessPtySession(pi.dwProcessId.intValue(), - pi.dwThreadId.intValue(), - new Handle(pi.hProcess), new Handle(pi.hThread), "ConPTY"); + pi.dwThreadId.intValue(), new Handle(pi.hProcess), new Handle(pi.hThread), "ConPTY", + new Handle(hJob)); } @Override diff --git a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/jna/JobApiNative.java b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/jna/JobApiNative.java new file mode 100644 index 0000000000..38d7638c81 --- /dev/null +++ b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/jna/JobApiNative.java @@ -0,0 +1,34 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.pty.windows.jna; + +import com.sun.jna.Native; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.WinDef.BOOL; +import com.sun.jna.platform.win32.WinNT.HANDLE; +import com.sun.jna.win32.StdCallLibrary; + +import ghidra.pty.windows.jna.ConsoleApiNative.SECURITY_ATTRIBUTES; + +public interface JobApiNative extends StdCallLibrary { + JobApiNative INSTANCE = Native.load("kernel32.dll", JobApiNative.class); + + HANDLE CreateJobObjectW(SECURITY_ATTRIBUTES.ByReference lpJobAttributes, WString lpName); + + BOOL AssignProcessToJobObject(HANDLE hJob, HANDLE hProcess); + + BOOL TerminateJobObject(HANDLE hJob, int uExitCode); +}