mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-24 13:11:47 +00:00
GP-1007: Fix GADP agent nodepJar issues
This commit is contained in:
parent
865cd22cab
commit
3be53dc05e
@ -18,8 +18,10 @@ apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
apply from: "$rootProject.projectDir/gradle/debugger/hasNodepJar.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Debugger-agent-dbgeng'
|
||||
|
||||
dependencies {
|
||||
@ -33,53 +35,12 @@ dependencies {
|
||||
testImplementation project(path: ":Debugger-gadp", configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
def boolean filterJar(File jarfile) {
|
||||
if (jarfile.name.contains("gradle-api")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("groovy-all")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("gradle-installation-beacon")) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
jar {
|
||||
tasks.nodepJar {
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.dbgeng.gadp.DbgEngGadpServer'
|
||||
}
|
||||
}
|
||||
|
||||
task configureNodepJar {
|
||||
dependsOn(configurations.default)
|
||||
|
||||
doLast {
|
||||
configurations.default.files.forEach {
|
||||
if (filterJar(it)) {
|
||||
nodepJar.from(zipTree(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task nodepJar(type: Jar) {
|
||||
inputs.file(file(jar.archivePath))
|
||||
dependsOn(configureNodepJar)
|
||||
dependsOn(jar)
|
||||
|
||||
archiveAppendix = 'nodep'
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.dbgeng.gadp.DbgEngGadpServer'
|
||||
}
|
||||
|
||||
from(zipTree(jar.archivePath))
|
||||
// TODO: This kind of stinks. I could probably apply some judicious excludes
|
||||
// images I don't care.
|
||||
// I probably must include duplicate LICENSE files, so that all are included
|
||||
// IDK why the duplicate OSGi framework classes, but I probably don't care.
|
||||
duplicatesStrategy = 'include'
|
||||
}
|
||||
|
||||
test {
|
||||
jvmArgs('-Xrs') // TODO: Is this needed, or left over from trial-and-error
|
||||
if ("win_x86_64".equals(getCurrentPlatformName())) {
|
||||
|
@ -30,10 +30,28 @@ import ghidra.dbg.agent.AgentWindow;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public interface DbgEngGadpServer extends AutoCloseable {
|
||||
public static final String USAGE =
|
||||
"""
|
||||
This is the GADP server for Windows dbgeng.dll. Usage:
|
||||
|
||||
gadp-agent-gdbeng [-H HOST/ADDR] [-p PORT] [-i ID] [-t TRANSPORT]
|
||||
[-r REMOTE]
|
||||
|
||||
Options:
|
||||
|
||||
--host/-H The address of the interface on which to listen.
|
||||
--port/-p The TCP port on which to listen for GADP. Default is 12345
|
||||
--transport/-t The transport specification for the Process Server. Default
|
||||
is tcp:port=11200
|
||||
--remote/-r The transport specification for a remote server.
|
||||
|
||||
Starts a dbgeng.dll-based GADP server "agent". Once the server has started, it
|
||||
will print the interface IP and port.
|
||||
""";
|
||||
public static final String DEFAULT_DBGSRV_TRANSPORT = "tcp:port=11200";
|
||||
|
||||
/**
|
||||
* The entry point for the SCTL-DBGENG server in stand-alone mode
|
||||
* The entry point for the GADP-DBGENG server in stand-alone mode
|
||||
*
|
||||
* Run it to see help.
|
||||
*
|
||||
@ -55,7 +73,7 @@ public interface DbgEngGadpServer extends AutoCloseable {
|
||||
/**
|
||||
* Create a new instance of the server
|
||||
*
|
||||
* @param addr the address to bind the SCTL server to
|
||||
* @param addr the address to bind the GADP server to
|
||||
* @param busId the client ID the server should use on the bus for synthesized commands
|
||||
* @param dbgSrvTransport the transport specification for the {@code dbgeng.dll} server
|
||||
* @return the server instance
|
||||
@ -71,7 +89,6 @@ public interface DbgEngGadpServer extends AutoCloseable {
|
||||
public class DbgEngRunner {
|
||||
protected InetSocketAddress bindTo;
|
||||
protected List<String> dbgengArgs = new ArrayList<>();
|
||||
protected byte busId = 1;
|
||||
protected String dbgSrvTransport = DEFAULT_DBGSRV_TRANSPORT;
|
||||
protected String remote = null;
|
||||
|
||||
@ -134,23 +151,6 @@ public interface DbgEngGadpServer extends AutoCloseable {
|
||||
}
|
||||
iface = ait.next();
|
||||
}
|
||||
else if ("-i".equals(a) || "--bus-id".equals(a)) {
|
||||
if (!ait.hasNext()) {
|
||||
System.err.println("Expected ID");
|
||||
printUsage();
|
||||
System.exit(-1);
|
||||
}
|
||||
String busIdStr = ait.next();
|
||||
try {
|
||||
busId = Byte.parseByte(busIdStr);
|
||||
//dbgengArgs.add(busIdStr);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
System.err.println("Byte required. Got " + busIdStr);
|
||||
printUsage();
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
else if ("-t".equals(a) || "--transport".equals(a)) {
|
||||
if (!ait.hasNext()) {
|
||||
System.err.println("Expected TRANSPORT");
|
||||
@ -181,23 +181,7 @@ public interface DbgEngGadpServer extends AutoCloseable {
|
||||
}
|
||||
|
||||
protected void printUsage() {
|
||||
System.out.println("This is the GADP server for Windows dbgeng.dll. Usage:");
|
||||
System.out.println();
|
||||
System.out.println(" [-H HOST/ADDR] [-p PORT] [-i ID] [-t TRANSPORT] [-r REMOTE]");
|
||||
System.out.println();
|
||||
System.out.println("Options:");
|
||||
System.out.println(
|
||||
" --host/-H The address of the interface on which to listen.");
|
||||
System.out.println(" Default is localhost");
|
||||
System.out.println(
|
||||
" --port/-p The TCP port on which to listen for GADP. Default is 12345");
|
||||
System.out.println(
|
||||
" --bus-id/-i The numeric client id for synthetic requests. Default is 1");
|
||||
System.out.println(
|
||||
" --transport/-t The transport specification for the Process Server.");
|
||||
System.out.println(" Default is tcp:port=11200");
|
||||
System.out.println(
|
||||
" --remote/-r The transport specification for a remote server.");
|
||||
System.out.println(USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,7 +193,7 @@ public interface DbgEngGadpServer extends AutoCloseable {
|
||||
CompletableFuture<Void> startDbgEng(String[] args);
|
||||
|
||||
/**
|
||||
* Get the local address to which the SCTL server is bound.
|
||||
* Get the local address to which the GADP server is bound.
|
||||
*
|
||||
* @return the local socket address
|
||||
*/
|
||||
|
@ -19,6 +19,8 @@ apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||
|
||||
apply from: "$rootProject.projectDir/gradle/debugger/hasNodepJar.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Debugger-agent-dbgmodel'
|
||||
|
||||
@ -31,52 +33,12 @@ dependencies {
|
||||
testImplementation project(path: ":Debugger-gadp", configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
def boolean filterJar(File jarfile) {
|
||||
if (jarfile.name.contains("gradle-api")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("groovy-all")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("gradle-installation-beacon")) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
jar {
|
||||
tasks.nodepJar {
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.dbgmodel.gadp.DbgModelGadpServer'
|
||||
}
|
||||
}
|
||||
|
||||
task configureNodepJar {
|
||||
dependsOn(configurations.default)
|
||||
doLast {
|
||||
configurations.default.files.forEach {
|
||||
if (filterJar(it)) {
|
||||
nodepJar.from(zipTree(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task nodepJar(type: Jar) {
|
||||
inputs.file(file(jar.archivePath))
|
||||
dependsOn(configureNodepJar)
|
||||
dependsOn(jar)
|
||||
|
||||
archiveAppendix = 'nodep'
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.dbgmodel.gadp.DbgModelGadpServer'
|
||||
}
|
||||
|
||||
from(zipTree(jar.archivePath))
|
||||
// TODO: This kind of stinks. I could probably apply some judicious excludes
|
||||
// images I don't care.
|
||||
// I probably must include duplicate LICENSE files, so that all are included
|
||||
// IDK why the duplicate OSGi framework classes, but I probably don't care.
|
||||
duplicatesStrategy = 'include'
|
||||
}
|
||||
|
||||
test {
|
||||
jvmArgs('-Xrs') // TODO: Is this needed, or left over from trial-and-error
|
||||
if ("win_x86_64".equals(getCurrentPlatformName())) {
|
||||
|
@ -28,47 +28,35 @@ import ghidra.dbg.agent.AgentWindow;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* The interface for the SCTL-{@code dbgeng.dll} server
|
||||
* The interface for the GADP-{@code dbgeng.dll} server
|
||||
*
|
||||
* <p>
|
||||
* This is just an interface to specify the truly public methods. This is also a convenient place to
|
||||
* put all the command-line parsing logic.
|
||||
*
|
||||
* This server implements the SCTL commands necessary to have a smooth debugging experience in
|
||||
* <p>
|
||||
* This server implements the GADP commands necessary to have a smooth debugging experience in
|
||||
* Ghidra. It implements almost every command that has use on a binary without debugging
|
||||
* information. It operates as a standalone debugging server based on {@code dbgeng.dll}, which can
|
||||
* accept other {@code dbgeng.dll}-based clients as well as SCTL clients.
|
||||
* accept other {@code dbgeng.dll}-based clients as well as GADP clients.
|
||||
*
|
||||
* <p>
|
||||
* Without limitation, the caveats are listed here:
|
||||
*
|
||||
* 1) The {@code Tnames} request in not implemented. The only namespaces available are those given
|
||||
* in the {@code Rstat} response.
|
||||
*
|
||||
* 2) For binaries without a debugging database (pdb file), the symbol commands only search the
|
||||
* exported symbols.
|
||||
*
|
||||
* 3) The type commands are not implemented. Ghidra can read most PDB files directly.
|
||||
*
|
||||
* 4) While SCTL presents thread-specific control, {@code dbgeng.dll} does not. Continue ("g" in
|
||||
* {@code dbgeng.dll}) affects all debugged targets, except those with higher suspect counts and
|
||||
* <ol>
|
||||
* <li>For binaries without a debugging database (pdb file), the symbol commands only search the
|
||||
* exported symbols.</li>
|
||||
* <li>The type commands are not implemented. Ghidra can read most PDB files directly.</li>
|
||||
* <li>While GADP presents thread-specific control, {@code dbgeng.dll} does not. Continue ("g" in
|
||||
* {@code dbgeng.dll}) affects all debugged targets, except those with higher suspend counts and
|
||||
* those that are frozen. The API makes it impossible to perfectly track which threads are actually
|
||||
* executed by "g". The server thus assumes that all threads run when any thread runs, and it will
|
||||
* synthesize the commands to reflect that in the connected clients.
|
||||
*
|
||||
* 5) The {@code Ttrace} command is not supported. The user can configure filters in the host
|
||||
* debugger; however, some events will always be trapped by the SCTL server. Future versions may
|
||||
* adjust this.
|
||||
*
|
||||
* 6) Snapshots are not supported. {@code dbgeng.dll} as no equivalent.
|
||||
*
|
||||
* 7) System calls are no yet reported. Windows programs do not use {@code fork} and {@code exec}.
|
||||
* Instead, calls to {@code CreateProcess} cause the server to synthesize {@code Tattach} commands.
|
||||
*
|
||||
* 8) The {@code Tunwind1} command is not supported. Ghidra should unwind instead.
|
||||
* executed by "g". The server thus assumes that all threads run when any thread runs.</li>
|
||||
* </ol>
|
||||
*/
|
||||
public interface DbgModelGadpServer extends DbgEngGadpServer {
|
||||
|
||||
/**
|
||||
* The entry point for the SCTL-DBGENG server in stand-alone mode
|
||||
* The entry point for the GADP-DBGMODEL server in stand-alone mode
|
||||
*
|
||||
* Run it to see help.
|
||||
*
|
||||
@ -90,7 +78,7 @@ public interface DbgModelGadpServer extends DbgEngGadpServer {
|
||||
/**
|
||||
* Create a new instance of the server
|
||||
*
|
||||
* @param addr the address to bind the SCTL server to
|
||||
* @param addr the address to bind the GADP server to
|
||||
* @param busId the client ID the server should use on the bus for synthesized commands
|
||||
* @param dbgSrvTransport the transport specification for the {@code dbgeng.dll} server
|
||||
* @return the server instance
|
||||
|
@ -19,6 +19,8 @@ apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||
|
||||
apply from: "$rootProject.projectDir/gradle/debugger/hasExecutableJar.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Debugger-agent-frida'
|
||||
|
||||
@ -33,68 +35,14 @@ dependencies {
|
||||
testImplementation project(path: ':Debugger-gadp', configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
def boolean filterJar(File jarfile) {
|
||||
if (jarfile.name.contains("gradle-api")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("groovy-all")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("gradle-installation-beacon")) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
jar {
|
||||
tasks.nodepJar {
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.lldb.gadp.FridaGadpServer'
|
||||
}
|
||||
}
|
||||
|
||||
task configureNodepJar {
|
||||
doLast {
|
||||
configurations.default.files.forEach {
|
||||
if (filterJar(it)) {
|
||||
nodepJar.from(zipTree(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task nodepJar(type: Jar) {
|
||||
inputs.file(file(jar.archivePath))
|
||||
dependsOn(configureNodepJar)
|
||||
dependsOn(jar)
|
||||
|
||||
archiveAppendix = 'nodep'
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.lldb.gadp.FridaGadpServer'
|
||||
}
|
||||
|
||||
from(zipTree(jar.archivePath))
|
||||
}
|
||||
|
||||
task executableJar {
|
||||
ext.execsh = file("src/main/sh/execjar.sh")
|
||||
ext.jarfile = file(nodepJar.archivePath)
|
||||
tasks.executableJar {
|
||||
ext.outjar = file("${buildDir}/bin/gadp-agent-frida")
|
||||
dependsOn(nodepJar)
|
||||
inputs.file(execsh)
|
||||
inputs.file(jarfile)
|
||||
outputs.file(outjar)
|
||||
doLast {
|
||||
outjar.parentFile.mkdirs()
|
||||
outjar.withOutputStream { output ->
|
||||
execsh.withInputStream { input ->
|
||||
output << input
|
||||
}
|
||||
jarfile.withInputStream { input ->
|
||||
output << input
|
||||
}
|
||||
}
|
||||
exec {
|
||||
commandLine("chmod", "+x", outjar)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
|
@ -28,6 +28,17 @@ import ghidra.dbg.agent.AgentWindow;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public interface FridaGadpServer extends AutoCloseable {
|
||||
public static final String USAGE =
|
||||
"""
|
||||
This is the GADP server for Frida. Usage:
|
||||
|
||||
gadp-agent-frida [-H HOST/ADDR] [-p PORT]
|
||||
|
||||
Options:
|
||||
--host/-H The address of the interface on which to listen. Default is
|
||||
localhost
|
||||
--port/-p The TCP port on which to listen for GADP. Default is 12345
|
||||
""";
|
||||
|
||||
/**
|
||||
* The entry point for the Frida server in stand-alone mode
|
||||
@ -133,16 +144,7 @@ public interface FridaGadpServer extends AutoCloseable {
|
||||
}
|
||||
|
||||
protected void printUsage() {
|
||||
System.out.println("This is the GADP server for Frida. Usage:");
|
||||
System.out.println();
|
||||
System.out.println(" [-H HOST/ADDR] [-p PORT] [-i ID] [-t TRANSPORT] [-r REMOTE]");
|
||||
System.out.println();
|
||||
System.out.println("Options:");
|
||||
System.out.println(
|
||||
" --host/-H The address of the interface on which to listen.");
|
||||
System.out.println(" Default is localhost");
|
||||
System.out.println(
|
||||
" --port/-p The TCP port on which to listen for GADP. Default is 12345");
|
||||
System.out.println(USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
22
Ghidra/Debug/Debugger-agent-frida/src/main/sh/execjar.sh
Normal file
22
Ghidra/Debug/Debugger-agent-frida/src/main/sh/execjar.sh
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/bash
|
||||
## ###
|
||||
# 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.
|
||||
##
|
||||
# This clever bit can be prepended to a JAR to make it self-executable
|
||||
|
||||
set -e
|
||||
|
||||
java -jar "$0" ${@:1}
|
||||
exit
|
@ -19,6 +19,8 @@ apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||
|
||||
apply from: "$rootProject.projectDir/gradle/debugger/hasExecutableJar.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Debugger-agent-gdb'
|
||||
|
||||
@ -33,74 +35,14 @@ dependencies {
|
||||
testImplementation project(path: ':Debugger-gadp', configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
def boolean filterJar(File jarfile) {
|
||||
if (jarfile.name.contains("gradle-api")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("groovy-all")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("gradle-installation-beacon")) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
jar {
|
||||
tasks.nodepJar {
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.gdb.gadp.GdbGadpServer'
|
||||
}
|
||||
}
|
||||
|
||||
task configureNodepJar {
|
||||
dependsOn(configurations.default)
|
||||
doLast {
|
||||
configurations.default.files.forEach {
|
||||
if (filterJar(it)) {
|
||||
nodepJar.from(zipTree(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task nodepJar(type: Jar) {
|
||||
inputs.file(file(jar.archivePath))
|
||||
dependsOn(configureNodepJar)
|
||||
dependsOn(jar)
|
||||
|
||||
archiveAppendix = 'nodep'
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.gdb.gadp.GdbGadpServer'
|
||||
}
|
||||
|
||||
from(zipTree(jar.archivePath))
|
||||
// TODO: This kind of stinks. I could probably apply some judicious excludes
|
||||
// images I don't care.
|
||||
// I probably must include duplicate LICENSE files, so that all are included
|
||||
// IDK why the duplicate OSGi framework classes, but I probably don't care.
|
||||
duplicatesStrategy = 'include'
|
||||
}
|
||||
|
||||
task executableJar {
|
||||
ext.execsh = file("src/main/sh/execjar.sh")
|
||||
ext.jarfile = file(nodepJar.archivePath)
|
||||
tasks.executableJar {
|
||||
ext.outjar = file("${buildDir}/bin/gadp-agent-gdb")
|
||||
dependsOn(nodepJar)
|
||||
inputs.file(execsh)
|
||||
inputs.file(jarfile)
|
||||
outputs.file(outjar)
|
||||
doLast {
|
||||
outjar.parentFile.mkdirs()
|
||||
outjar.withOutputStream { output ->
|
||||
execsh.withInputStream { input ->
|
||||
output << input
|
||||
}
|
||||
jarfile.withInputStream { input ->
|
||||
output << input
|
||||
}
|
||||
}
|
||||
exec {
|
||||
commandLine("chmod", "+x", outjar)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
|
@ -30,6 +30,38 @@ import ghidra.dbg.agent.AgentWindow;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public interface GdbGadpServer extends AutoCloseable {
|
||||
public static final String USAGE =
|
||||
"""
|
||||
This is the GADP wrapper for GDB. Usage:
|
||||
|
||||
gadp-agent-gdb [GDB options] [--agent-args [-H HOST/ADDR] [-p PORT]
|
||||
[-g CMD] [-x]]
|
||||
|
||||
Options:
|
||||
|
||||
Use gdb -h for suitable [GDB options]
|
||||
|
||||
THE FOLLOWING OPTIONS MUST BE PRECEDED BY --agent-args
|
||||
--host/-H The address of the interface on which to listen. Default is
|
||||
localhost
|
||||
--port/-p The TCP port on which to listen. Default is 12345. 0 for
|
||||
automatic.
|
||||
--gdb-cmd/-g The command to launch gdb. Default is 'gdb'
|
||||
--existing/-x Do not launch gdb. Instead just open a pty
|
||||
|
||||
Starts a GDB-based GADP server "agent". In general, it can be invoked in the
|
||||
same manner as standard gdb. Arguments to control the GADP server and GDB
|
||||
invocation are given after the --gadp-args flag. Once the server has started, it
|
||||
will print the interface IP and port. The -g and -x flags are mutually
|
||||
exclusive. The one appearing last get preference. The -x flags causes the agent
|
||||
to refrain from launching its own gdb process. Instead, it prints the file name
|
||||
of a pseudo terminal (pty) where it expects a GDB/MI v2 interpreter from an
|
||||
existing gdb process. Use the new-ui command (available since GDB version 7.12)
|
||||
to join the agent to the existing session:
|
||||
|
||||
(gdb) new-ui mi2 /dev/ptyXX
|
||||
""";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try {
|
||||
new Runner().run(args);
|
||||
@ -73,7 +105,7 @@ public interface GdbGadpServer extends AutoCloseable {
|
||||
Iterator<String> ait = Arrays.asList(args).iterator();
|
||||
while (ait.hasNext()) {
|
||||
String a = ait.next();
|
||||
if ("--gadp-args".equals(a)) {
|
||||
if ("--agent-args".equals(a)) {
|
||||
break;
|
||||
}
|
||||
else if ("-h".equals(a) || "--help".equals(a)) {
|
||||
@ -131,45 +163,7 @@ public interface GdbGadpServer extends AutoCloseable {
|
||||
}
|
||||
|
||||
private void printUsage() {
|
||||
System.out.println("This is the GADP wrapper for GDB. Usage:");
|
||||
System.out.println();
|
||||
System.out.println(
|
||||
" gadpgdb [GDB options] [--gadp-args [-H HOST/ADDR] [-p PORT] [-g CMD] [-x]]");
|
||||
System.out.println();
|
||||
System.out.println("Options:");
|
||||
System.out.println();
|
||||
System.out.println("Use gdb -h for suitable [GDB options]");
|
||||
System.out.println();
|
||||
System.out.println(
|
||||
" --host/-H The address of the interface on which to listen. Default is localhost");
|
||||
System.out.println(
|
||||
" --port/-p The TCP port on which to listen. Default is 12345. 0 for automatic.");
|
||||
System.out.println(
|
||||
" --gdb-cmd/-g The command to launch gdb. Default is 'gdb'");
|
||||
System.out.println(
|
||||
" --existing/-x Do not launch gdb. Instead just open a pty");
|
||||
System.out.println();
|
||||
System.out.println(
|
||||
"Starts a GDB-based GADP server \"agent\". In general, it can be invoked in");
|
||||
System.out.println(
|
||||
"the same manner as standard gdb. Arguments to control the GADP server and");
|
||||
System.out.println(
|
||||
"GDB invocation are given after the --gadp-args flag. Once the server has");
|
||||
System.out.println(
|
||||
"started, it will print the interface IP and port. The -g and -x flags are");
|
||||
System.out.println(
|
||||
"mutually exclusive. The one appearing last get preference. The -x flags");
|
||||
System.out.println(
|
||||
"causes the agent to refrain from launching its own gdb process. Instead,");
|
||||
System.out.println(
|
||||
"it prints the file name of a private terminate (pty) where it expects a");
|
||||
System.out.println(
|
||||
"GDB/MI v2 interpreter from an existing gdb process. Use the new-ui command");
|
||||
System.out.println(
|
||||
"(available since GDB version 7.12) to join the agent to the existing");
|
||||
System.out.println("session:");
|
||||
System.out.println();
|
||||
System.out.println("(gdb) new-ui mi2 /dev/ptyXX");
|
||||
System.out.println(USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,5 +18,5 @@
|
||||
|
||||
set -e
|
||||
|
||||
java -jar "$0"
|
||||
java -jar "$0" ${@:1}
|
||||
exit
|
||||
|
@ -19,6 +19,8 @@ apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||
|
||||
apply from: "$rootProject.projectDir/gradle/debugger/hasExecutableJar.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Debugger-agent-lldb'
|
||||
|
||||
@ -33,68 +35,14 @@ dependencies {
|
||||
testImplementation project(path: ':Debugger-gadp', configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
def boolean filterJar(File jarfile) {
|
||||
if (jarfile.name.contains("gradle-api")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("groovy-all")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("gradle-installation-beacon")) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
jar {
|
||||
tasks.nodepJar {
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.lldb.gadp.LldbGadpServer'
|
||||
}
|
||||
}
|
||||
|
||||
task configureNodepJar {
|
||||
doLast {
|
||||
configurations.default.files.forEach {
|
||||
if (filterJar(it)) {
|
||||
nodepJar.from(zipTree(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task nodepJar(type: Jar) {
|
||||
inputs.file(file(jar.archivePath))
|
||||
dependsOn(configureNodepJar)
|
||||
dependsOn(jar)
|
||||
|
||||
archiveAppendix = 'nodep'
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.lldb.gadp.LldbGadpServer'
|
||||
}
|
||||
|
||||
from(zipTree(jar.archivePath))
|
||||
}
|
||||
|
||||
task executableJar {
|
||||
ext.execsh = file("src/main/sh/execjar.sh")
|
||||
ext.jarfile = file(nodepJar.archivePath)
|
||||
tasks.executableJar {
|
||||
ext.outjar = file("${buildDir}/bin/gadp-agent-lldb")
|
||||
dependsOn(nodepJar)
|
||||
inputs.file(execsh)
|
||||
inputs.file(jarfile)
|
||||
outputs.file(outjar)
|
||||
doLast {
|
||||
outjar.parentFile.mkdirs()
|
||||
outjar.withOutputStream { output ->
|
||||
execsh.withInputStream { input ->
|
||||
output << input
|
||||
}
|
||||
jarfile.withInputStream { input ->
|
||||
output << input
|
||||
}
|
||||
}
|
||||
exec {
|
||||
commandLine("chmod", "+x", outjar)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
|
@ -28,6 +28,17 @@ import ghidra.dbg.agent.AgentWindow;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public interface LldbGadpServer extends AutoCloseable {
|
||||
public static final String USAGE =
|
||||
"""
|
||||
This is the GADP server for Frida. Usage:
|
||||
|
||||
gadp-agent-lldb [-H HOST/ADDR] [-p PORT]
|
||||
|
||||
Options:
|
||||
--host/-H The address of the interface on which to listen. Default is
|
||||
localhost
|
||||
--port/-p The TCP port on which to listen for GADP. Default is 12345
|
||||
""";
|
||||
|
||||
/**
|
||||
* The entry point for the LLDB server in stand-alone mode
|
||||
@ -133,16 +144,7 @@ public interface LldbGadpServer extends AutoCloseable {
|
||||
}
|
||||
|
||||
protected void printUsage() {
|
||||
System.out.println("This is the GADP server for LLVM's lldb. Usage:");
|
||||
System.out.println();
|
||||
System.out.println(" [-H HOST/ADDR] [-p PORT] [-i ID] [-t TRANSPORT] [-r REMOTE]");
|
||||
System.out.println();
|
||||
System.out.println("Options:");
|
||||
System.out.println(
|
||||
" --host/-H The address of the interface on which to listen.");
|
||||
System.out.println(" Default is localhost");
|
||||
System.out.println(
|
||||
" --port/-p The TCP port on which to listen for GADP. Default is 12345");
|
||||
System.out.println(USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
22
Ghidra/Debug/Debugger-agent-lldb/src/main/sh/execjar.sh
Normal file
22
Ghidra/Debug/Debugger-agent-lldb/src/main/sh/execjar.sh
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/bash
|
||||
## ###
|
||||
# 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.
|
||||
##
|
||||
# This clever bit can be prepended to a JAR to make it self-executable
|
||||
|
||||
set -e
|
||||
|
||||
java -jar "$0" ${@:1}
|
||||
exit
|
41
gradle/debugger/hasExecutableJar.gradle
Normal file
41
gradle/debugger/hasExecutableJar.gradle
Normal file
@ -0,0 +1,41 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
apply from: "$rootProject.projectDir/gradle/debugger/hasNodepJar.gradle"
|
||||
|
||||
|
||||
task executableJar {
|
||||
ext.execsh = file("src/main/sh/execjar.sh")
|
||||
ext.jarfile = file(nodepJar.archivePath)
|
||||
ext.outjar = file("${buildDir}/bin/run")
|
||||
dependsOn(nodepJar)
|
||||
inputs.file { execsh }
|
||||
inputs.file { jarfile }
|
||||
outputs.file { outjar }
|
||||
doLast {
|
||||
outjar.parentFile.mkdirs()
|
||||
outjar.withOutputStream { output ->
|
||||
execsh.withInputStream { input ->
|
||||
output << input
|
||||
}
|
||||
jarfile.withInputStream { input ->
|
||||
output << input
|
||||
}
|
||||
}
|
||||
exec {
|
||||
commandLine("chmod", "+x", outjar)
|
||||
}
|
||||
}
|
||||
}
|
61
gradle/debugger/hasNodepJar.gradle
Normal file
61
gradle/debugger/hasNodepJar.gradle
Normal file
@ -0,0 +1,61 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
def boolean filterJar(File jarfile) {
|
||||
if (jarfile.name.contains("gradle-api")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("groovy-all")) {
|
||||
return false
|
||||
} else if (jarfile.name.contains("gradle-installation-beacon")) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
task configureNodepJar {
|
||||
dependsOn(configurations.default)
|
||||
doLast {
|
||||
configurations.default.files.forEach { jar ->
|
||||
if (filterJar(jar)) {
|
||||
nodepJar.from(zipTree(jar)) {
|
||||
// The real solution here is probably to sort out the dependency graph
|
||||
// Still, I imagine some of the excludes will be necessary
|
||||
exclude "help/**"
|
||||
exclude "images/**"
|
||||
exclude "OSGI-OPT/**"
|
||||
exclude "org/osgi/**"
|
||||
exclude "aQute/**"
|
||||
// Duplicate. And signature breaks nodep jar
|
||||
exclude "META-INF/*.SF"
|
||||
exclude "META-INF/*.DSA"
|
||||
exclude "META-INF/*.RSA"
|
||||
// Ensure all LICENSES are included, by renaming to avoid collisions
|
||||
rename("((LICENSE)|(AL2\\.0)|(LGPL2\\.1)|(NOTICE)|(NOTICE.txt)|(DEPENDENCIES))", "${jar.name}-\$1")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task nodepJar(type: Jar) {
|
||||
inputs.file(file(jar.archivePath))
|
||||
dependsOn(configureNodepJar)
|
||||
dependsOn(jar)
|
||||
|
||||
archiveAppendix = 'nodep'
|
||||
|
||||
from(zipTree(jar.archivePath))
|
||||
duplicatesStrategy = 'exclude'
|
||||
}
|
Loading…
Reference in New Issue
Block a user