Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/Ghidra_11.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
ghidra1 committed May 22, 2024
2 parents a858bd3 + 5bc70c4 commit 1bf26ac
Show file tree
Hide file tree
Showing 16 changed files with 152 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ def main():
from ghidradbg import commands as cmd
from ghidradbg.util import dbg

# So that the user can re-enter by typing repl()
global repl
repl = cmd.repl

cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
args = os.getenv('OPT_TARGET_ARGS')
if args:
Expand All @@ -51,7 +55,10 @@ def main():
cmd.ghidra_trace_sync_enable()

# TODO: HACK
dbg.wait()
try:
dbg.wait()
except KeyboardInterrupt as ki:
dbg.interrupt()

cmd.repl()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from pybag import pydbg, userdbg, kerneldbg
from pybag.dbgeng import core as DbgEng
from pybag.dbgeng import exception
from pybag.dbgeng.win32.kernel32 import STILL_ACTIVE

from . import util, arch, methods, hooks
from .dbgmodel.imodelobject import ModelObjectKind
Expand Down Expand Up @@ -841,6 +842,9 @@ def ghidra_trace_disassemble(address):

@util.dbg.eng_thread
def compute_proc_state(nproc=None):
exit_code = util.GetExitCode()
if exit_code is not None and exit_code != STILL_ACTIVE:
return 'TERMINATED'
status = util.dbg._base._control.GetExecutionStatus()
if status == DbgEng.DEBUG_STATUS_BREAK:
return 'STOPPED'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ def on_process_selected():
@log_errors
def on_process_deleted(*args):
# print("ON_PROCESS_DELETED")
proc = args[0]
exit_code = args[0]
proc = util.selected_process()
on_exited(proc)
if proc in PROC_STATE:
del PROC_STATE[proc]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def record(self, description=None):
except BaseException as e:
print(f"Couldn't record page with SP: {e}")
self.visited.add(hashable_frame)
if first or self.regions or self.threads or self.modules:
if first or self.regions or self.modules:
# Sections, memory syscalls, or stack allocations
commands.put_regions()
self.regions = False
Expand Down Expand Up @@ -153,7 +153,7 @@ def process_event(self, listener, event):
print(f"Ignoring {desc} because target is invalid")
return
event_process = util.get_process()
if event_process.IsValid() and event_process not in PROC_STATE:
if event_process.IsValid() and event_process.GetProcessID() not in PROC_STATE:
PROC_STATE[event_process.GetProcessID()] = ProcessState()
rc = event_process.GetBroadcaster().AddListener(listener, ALL_EVENTS)
if not rc:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ def read_mem(process: sch.Schema('Process'), range: AddressRange):
f'ghidra trace putmem 0x{offset_start:x} {range.length()}', result)
if result.Succeeded():
return
print(f"Could not read 0x{offset_start:x}: {result}")
#print(f"Could not read 0x{offset_start:x}: {result}")
exec_convert_errors(
f'ghidra trace putmem-state 0x{offset_start:x} {range.length()} error')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.*;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.memory.TraceMemoryState;
Expand Down Expand Up @@ -65,7 +64,8 @@ default Address computeTraceAddress(ServiceProvider provider, DebuggerCoordinate
if (reg == null) {
return null;
}
if (!thread.getLifespan().contains(snap)) {
Lifespan lifespan = thread.getLifespan();
if (lifespan == null || !lifespan.contains(snap)) {
return null;
}
TraceMemorySpace regs = reg.getAddressSpace().isRegisterSpace()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
import ghidra.app.plugin.core.debug.event.*;
import ghidra.app.services.DebuggerLogicalBreakpointService;
import ghidra.app.services.DebuggerTraceManagerService;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus;

Expand All @@ -31,6 +32,7 @@
status = PluginStatus.RELEASED,
servicesRequired = {
DebuggerLogicalBreakpointService.class,
DebuggerTraceManagerService.class,
},
eventsConsumed = {
TraceOpenedPluginEvent.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import ghidra.features.bsim.query.file.BSimH2FileDBConnectionManager;
import ghidra.features.bsim.query.file.BSimH2FileDBConnectionManager.BSimH2FileDataSource;
import ghidra.features.bsim.query.protocol.*;
import ghidra.framework.model.DomainFolder;
import ghidra.framework.model.DomainFile;
import ghidra.framework.protocol.ghidra.GhidraURL;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionManager;
Expand Down Expand Up @@ -100,14 +100,23 @@ protected void run() throws Exception {
gensig.addFunctionTags(dbInfo.functionTags);
gensig.addDateColumnName(dbInfo.dateColumnName);

DomainFolder df = currentProgram.getDomainFile().getParent();
URL folderURL = df.getSharedProjectURL();
if (folderURL == null) {
folderURL = df.getLocalProjectURL();
DomainFile dFile = currentProgram.getDomainFile();
URL fileURL = dFile.getSharedProjectURL(null);
if (fileURL == null) {
fileURL = dFile.getLocalProjectURL(null);
}
String path = GhidraURL.getProjectPathname(folderURL);
if (fileURL == null) {
popup("Cannot add signatures for program which has never been saved");
return;
}

String path = GhidraURL.getProjectPathname(fileURL);
//bsim adds the program name to the path so we need to remove the program
//name here
int lastSlash = path.lastIndexOf('/');
path = lastSlash == 0 ? "/" : path.substring(0, lastSlash);

URL normalizedProjectURL = GhidraURL.getProjectURL(folderURL);
URL normalizedProjectURL = GhidraURL.getProjectURL(fileURL);
String repo = normalizedProjectURL.toExternalForm();

gensig.openProgram(this.currentProgram, null, null, null, repo, path);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,8 +19,7 @@
import ghidra.app.services.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Listing;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.util.task.TaskMonitor;

Expand All @@ -42,8 +40,6 @@ public ExternalEntryFunctionAnalyzer() {
*/
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) {

Listing listing = program.getListing();

AddressSet funcStarts = new AddressSet();

monitor.setMessage("Finding External Entry Functions");
Expand All @@ -53,9 +49,17 @@ public boolean added(Program program, AddressSetView set, TaskMonitor monitor, M
AddressIterator entryIter = program.getSymbolTable().getExternalEntryPointIterator();
while (entryIter.hasNext() && !monitor.isCancelled()) {
Address entry = entryIter.next();
if (set.contains(entry) && listing.getInstructionAt(entry) != null) {
funcStarts.addRange(entry, entry);
if (!set.contains(entry)) {
continue;
}

// check for any indicators this is a good start of a function
// must have an instruction at the entry, and not be part of another function
if (!isGoodFunctionStart(program, entry)) {
continue;
}

funcStarts.addRange(entry, entry);
}

// remove any addresses that are already functions
Expand All @@ -76,5 +80,35 @@ public boolean added(Program program, AddressSetView set, TaskMonitor monitor, M

return true;
}

/**
* Check if address is a good function start.
* Instruction exists at the location.
* No instruction falls through to this one.
*
* @param program the program
* @param addr address to check if is a good function start
* @return true if would be a good function start, false otherwise
*/
public static boolean isGoodFunctionStart(Program program, Address addr) {
// check location starts with an instruction
if (program.getListing().getInstructionAt(addr) == null) {
return false;
}

Address addrBefore = addr.previous();
if (addrBefore == null) {
return true;
}

// check if instruction before, falls into this one.
// other code is responsible for creating functions from references
Instruction instr = program.getListing().getInstructionContaining(addrBefore);
if (instr != null && addr.equals(instr.getFallThrough())) {
return false;
}

// didn't find anything that would indicate is a bad function start
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -800,15 +800,10 @@ private void clearProgress() {
* If the status message fits then there is no tool tip.
*/
private void updateStatusToolTip() {
String text = statusLabel.getText();
// Get the width of the message.
FontMetrics fm = statusLabel.getFontMetrics(statusLabel.getFont());
int messageWidth = 0;
if ((fm != null) && (text != null)) {
messageWidth = fm.stringWidth(text);
}
if (messageWidth > statusLabel.getWidth()) {
statusLabel.setToolTipText(text);
Dimension preferredSize = statusLabel.getPreferredSize();
Dimension size = statusLabel.getSize();
if (preferredSize.width > size.width || preferredSize.height > size.height) {
statusLabel.setToolTipText(statusLabel.getOriginalText());
}
else {
statusLabel.setToolTipText(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ public void setText(String text) {
updateHtmlView();
}

/**
* Returns the original text of the label.
* <p>
* The {@link #getText()} method for this class can return a value that is missing the leading
* &lt;html&gt; tag.
*
* @return text of this label
*/
public String getOriginalText() {
return isHtml ? HTML_TAG + getText() : getText();
}

@Override
public void updateUI() {
super.updateUI();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import ghidra.pty.PtySession;
import ghidra.pty.windows.Handle;
import ghidra.pty.windows.jna.JobApiNative;
import ghidra.util.Msg;

public class LocalWindowsNativeProcessPtySession implements PtySession {
Expand All @@ -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);
}
Expand Down Expand Up @@ -84,17 +87,8 @@ public int waitExited(long timeout, TimeUnit unit) throws TimeoutException {

@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());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
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 {

Expand Down Expand Up @@ -83,6 +84,11 @@ public LocalWindowsNativeProcessPtySession session(String[] args, Map<String, St
* 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();

Expand All @@ -102,9 +108,13 @@ public LocalWindowsNativeProcessPtySession session(String[] args, Map<String, St
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
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
Loading

0 comments on commit 1bf26ac

Please sign in to comment.