├── .gitignore
├── LICENSE.md
├── Module.manifest
├── README.md
├── angryghidra_script
└── angryghidra.py
├── build.gradle
├── extension.properties
├── images
├── AngryPluginDemo.gif
├── ApplyPatchedBytes.png
├── Icon.png
├── Trace.png
└── View.png
└── src
└── main
├── java
└── angryghidra
│ ├── AngrProcessing.java
│ ├── AngryGhidraPlugin.java
│ ├── AngryGhidraPopupMenu.java
│ ├── AngryGhidraProvider.java
│ ├── HookHandler.java
│ ├── LocalColorizingService.java
│ └── UserAddressStorage.java
└── resources
└── images
├── add.png
├── delete.png
├── flag.png
├── ico.png
├── reset.png
└── stop.png
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | build
3 | dist
4 | lib
5 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Nalen98
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Module.manifest:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AngryGhidra
2 |
3 |
4 |
5 | The plugin allows you to use [angr](https://github.com/angr/angr) for binary analysis and symbolic execution in Ghidra interface.
6 |
7 | Solving [CTF challenge from SecurityFest 2016 "fairlight"](https://github.com/angr/angr-doc/blob/master/examples/securityfest_fairlight/fairlight) with AngryGhidra plugin:
8 |
9 | 
10 |
11 | # Hotkeys
12 |
13 | ##### Set:
14 | `Z` – **destination** address
15 | `X` – **start** address
16 | `J` – **avoid** address (multiple choice)
17 |
18 | ##### Reset:
19 | `K` – **destination** address
20 | `T` – **start** address
21 | `P` – **avoid** address
22 |
23 | ##### Apply bytes:
24 | `U` – apply patched bytes to angr project memory
25 |
26 | # Screenshots
27 |
28 | Let's keygen:
29 |
30 | 
31 |
32 | Apply patched bytes to write them into the memory of angr project:
33 |
34 | 
35 |
36 | # Installation
37 |
38 | 1) `pip3 install angr`
39 | 2) Make sure `python3` directory is added to the `PATH` (required, `Python 3` only)
40 | 3) Use Gradle to build the plugin: `GHIDRA_INSTALL_DIR=${GHIDRA_HOME} gradle` and use Ghidra to install it: `File → Install Extensions...`
41 | 4) Check the box in the "New Plugins Found" window to apply AngryGhidra plugin to your project
42 | 5) If "New Plugins Found" window doesn't appear, go to your CodeBrowser project and tick the plugin in `File → Configure → Miscellaneous → AngryGhidraPlugin`
43 |
--------------------------------------------------------------------------------
/angryghidra_script/angryghidra.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import angr
3 | import claripy
4 | import json
5 |
6 | EXPLORE_OPT = {}
7 | REGISTERS = []
8 | SYMVECTORS = []
9 |
10 | def hook_function(state):
11 | global SYMVECTORS
12 | for object in EXPLORE_OPT["hooks"]:
13 | for frame in object.items():
14 | if frame[0] == hex(state.solver.eval(state.regs.ip)):
15 | for option, data in frame[1].items():
16 | if "sv" in data:
17 | symbvector_length = int(data[2:], 0)
18 | symbvector = claripy.BVS('symvector', symbvector_length * 8)
19 | SYMVECTORS.append(symbvector)
20 | data = symbvector
21 | else:
22 | data = int(str(data), 0)
23 | for REG in REGISTERS:
24 | if REG == option:
25 | setattr(state.regs, option, data)
26 | break
27 |
28 | def main(file):
29 | global EXPLORE_OPT
30 | global REGISTERS
31 | global SYMVECTORS
32 | find = None
33 | avoid = None
34 | blank_state = None
35 | vectors = None
36 |
37 | with open(file, encoding='utf-8') as json_file:
38 | EXPLORE_OPT = json.load(json_file)
39 |
40 | if "blank_state" in EXPLORE_OPT:
41 | blank_state = int(EXPLORE_OPT["blank_state"], 16)
42 |
43 | find = int(EXPLORE_OPT["find_address"], 16)
44 |
45 | if "avoid_address" in EXPLORE_OPT:
46 | avoid = [int(x, 16) for x in EXPLORE_OPT["avoid_address"].split(',')]
47 |
48 | # User can input hex or decimal value (argv length / symbolic memory length)
49 | argv = [EXPLORE_OPT["binary_file"]]
50 | if "arguments" in EXPLORE_OPT:
51 | index = 1
52 | for arg, length in EXPLORE_OPT["arguments"].items():
53 | argv.append(claripy.BVS("argv" + str(index), int(str(length), 0) * 8))
54 | index += 1
55 |
56 | if "base_address" in EXPLORE_OPT:
57 | base_address = int(EXPLORE_OPT["base_address"], 16)
58 |
59 | if "raw_binary_arch" in EXPLORE_OPT:
60 | arch = EXPLORE_OPT["raw_binary_arch"]
61 | p = angr.Project(EXPLORE_OPT["binary_file"],
62 | load_options={'main_opts': {'backend': 'blob', 'arch': arch,
63 | 'base_addr': base_address}, 'auto_load_libs': EXPLORE_OPT["auto_load_libs"]})
64 | else:
65 | p = angr.Project(EXPLORE_OPT["binary_file"], load_options={'main_opts': {'base_addr': base_address}, "auto_load_libs": EXPLORE_OPT["auto_load_libs"]})
66 |
67 | REGISTERS = p.arch.default_symbolic_registers
68 |
69 | if len(argv) > 1:
70 | state = p.factory.entry_state(args=argv)
71 | elif blank_state != None:
72 | state = p.factory.blank_state(addr=blank_state)
73 | else:
74 | state = p.factory.entry_state()
75 |
76 | # Store symbolic vectors in memory
77 | if "vectors" in EXPLORE_OPT:
78 | vectors = {}
79 | for addr, length in EXPLORE_OPT["vectors"].items():
80 | symbmem_addr = int(addr, 16)
81 | symbmem_len = int(length, 0)
82 | vectors.update({symbmem_addr: symbmem_len})
83 | symb_vector = claripy.BVS('input', symbmem_len * 8)
84 | state.memory.store(symbmem_addr, symb_vector)
85 |
86 | # Write to memory
87 | if "mem_store" in EXPLORE_OPT:
88 | for addr, value in EXPLORE_OPT["mem_store"].items():
89 | store_addr = int(addr, 16)
90 | store_value = int(value, 16)
91 | store_length = len(value) - 2
92 | state.memory.store(store_addr, state.solver.BVV(store_value, 4 * store_length))
93 |
94 | # Handle symbolic registers
95 | if "regs_vals" in EXPLORE_OPT:
96 | for register, data in EXPLORE_OPT["regs_vals"].items():
97 | if "sv" in data:
98 | symbvector_length = int(data[2:], 0)
99 | symbvector = claripy.BVS('symvector', symbvector_length * 8)
100 | SYMVECTORS.append(symbvector)
101 | data = symbvector
102 | else:
103 | data = int(str(data), 0)
104 | for REG in REGISTERS:
105 | if REG == register:
106 | setattr(state.regs, register, data)
107 | break
108 |
109 | # Handle hooks
110 | if "hooks" in EXPLORE_OPT:
111 | for object in EXPLORE_OPT["hooks"]:
112 | for frame in object.items():
113 | hook_address = frame[0]
114 | for option, data in frame[1].items():
115 | data = int(str(data), 0)
116 | if option == "length":
117 | hook_length = data
118 | break
119 | p.hook(int(hook_address, 16), hook_function, length=hook_length)
120 |
121 | simgr = p.factory.simulation_manager(state)
122 | if avoid != None:
123 | simgr.use_technique(angr.exploration_techniques.Explorer(find=find, avoid=avoid))
124 | else:
125 | simgr.use_technique(angr.exploration_techniques.Explorer(find=find))
126 | simgr.run()
127 |
128 | if simgr.found:
129 | found_path = simgr.found[0]
130 | win_sequence = ""
131 | finishedTracing = False
132 | for win_block in found_path.history.bbl_addrs.hardcopy:
133 | win_block = p.factory.block(win_block)
134 | addresses = win_block.instruction_addrs
135 | for address in addresses:
136 | win_sequence += 't:' + hex(address) + '\n'
137 | if address == find:
138 | # Prevent sending the rest of the block addresses that aren't desired
139 | finishedTracing = True
140 | break
141 | if finishedTracing:
142 | break
143 | win_sequence = win_sequence[:-1]
144 | print(win_sequence)
145 |
146 | if len(argv) > 1:
147 | for i in range(1, len(argv)):
148 | print("argv[{id}] = {solution}".format(id=i, solution=found_path.solver.eval(argv[i], cast_to=bytes)))
149 |
150 | if vectors != None and len(vectors) != 0:
151 | for address, length in vectors.items():
152 | print("{addr} = {value}".format(addr=hex(address),
153 | value=found_path.solver.eval(found_path.memory.load(address, length),
154 | cast_to=bytes)))
155 |
156 | if len(SYMVECTORS) > 0:
157 | for SV in SYMVECTORS:
158 | print(found_path.solver.eval(SV, cast_to=bytes))
159 |
160 | found_stdins = found_path.posix.stdin.content
161 | if len(found_stdins) > 0:
162 | std_id = 1
163 | for stdin in found_stdins:
164 | print(
165 | "stdin[{id}] = {solution}".format(id=std_id,
166 | solution=found_path.solver.eval(stdin[0], cast_to=bytes)))
167 | std_id += 1
168 | else:
169 | print("")
170 | return
171 |
172 |
173 | if __name__ == '__main__':
174 | if len(sys.argv) < 2:
175 | print("Usage: *thisScript.py* angr_options.json")
176 | exit()
177 | main(sys.argv[1])
178 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Builds a Ghidra Extension for a given Ghidra installation.
2 | //
3 | // An absolute path to the Ghidra installation directory must be supplied either by setting the
4 | // GHIDRA_INSTALL_DIR environment variable or Gradle project property:
5 | //
6 | // > export GHIDRA_INSTALL_DIR=
7 | // > gradle
8 | //
9 | // or
10 | //
11 | // > gradle -PGHIDRA_INSTALL_DIR=
12 | //
13 | // Gradle should be invoked from the directory of the project to build. Please see the
14 | // application.gradle.version property in /Ghidra/application.properties
15 | // for the correction version of Gradle to use for the Ghidra installation you specify.
16 |
17 | //----------------------START "DO NOT MODIFY" SECTION------------------------------
18 | def ghidraInstallDir
19 |
20 | if (System.env.GHIDRA_INSTALL_DIR) {
21 | ghidraInstallDir = System.env.GHIDRA_INSTALL_DIR
22 | }
23 | else if (project.hasProperty("GHIDRA_INSTALL_DIR")) {
24 | ghidraInstallDir = project.getProperty("GHIDRA_INSTALL_DIR")
25 | }
26 |
27 | if (ghidraInstallDir) {
28 | apply from: new File(ghidraInstallDir).getCanonicalPath() + "/support/buildExtension.gradle"
29 | }
30 | else {
31 | throw new GradleException("GHIDRA_INSTALL_DIR is not defined!")
32 | }
33 | //----------------------END "DO NOT MODIFY" SECTION-------------------------------
34 |
35 | apply plugin: 'base'
36 |
37 | repositories {
38 | mavenCentral()
39 | }
40 |
41 | dependencies {
42 | implementation 'org.json:json:20200518'
43 | }
44 |
45 | task copyLib(type: Copy) {
46 | from configurations.runtimeOnly
47 | into "lib"
48 | }
49 |
50 | tasks.assemble.dependsOn copyLib
51 |
52 |
53 |
--------------------------------------------------------------------------------
/extension.properties:
--------------------------------------------------------------------------------
1 | name=AngryGhidra
2 | description=One click symbolic execution using Angr from Your Ghidra
3 | author=Nalen98
4 | createdOn=
5 | version=@extversion@
6 |
--------------------------------------------------------------------------------
/images/AngryPluginDemo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/images/AngryPluginDemo.gif
--------------------------------------------------------------------------------
/images/ApplyPatchedBytes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/images/ApplyPatchedBytes.png
--------------------------------------------------------------------------------
/images/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/images/Icon.png
--------------------------------------------------------------------------------
/images/Trace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/images/Trace.png
--------------------------------------------------------------------------------
/images/View.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/images/View.png
--------------------------------------------------------------------------------
/src/main/java/angryghidra/AngrProcessing.java:
--------------------------------------------------------------------------------
1 | package angryghidra;
2 |
3 | import java.awt.Color;
4 | import java.io.BufferedReader;
5 | import java.io.File;
6 | import java.io.InputStreamReader;
7 | import java.net.URISyntaxException;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | import javax.swing.JLabel;
12 | import javax.swing.JScrollPane;
13 | import javax.swing.SwingUtilities;
14 | import javax.swing.SwingWorker;
15 | import ghidra.program.model.address.Address;
16 | import ghidra.program.model.address.AddressFactory;
17 |
18 |
19 | public class AngrProcessing {
20 | private AddressFactory mAddressFactory;
21 | private LocalColorizingService mColorService;
22 | private UserAddressStorage mAddressStorage;
23 | private AngryGhidraProvider mProvider;
24 | private String solution;
25 | private JLabel statusLabelFound;
26 | private JLabel statusLabel;
27 | private JScrollPane scrollSolutionTextArea;
28 | private List traceList;
29 |
30 | public AngrProcessing(UserAddressStorage addressStorage, LocalColorizingService colorService,
31 | AngryGhidraProvider provider, AddressFactory addressFactory) {
32 | mAddressStorage = addressStorage;
33 | mColorService = colorService;
34 | mProvider = provider;
35 | mAddressFactory = addressFactory;
36 | traceList = new ArrayList ();
37 | statusLabelFound = provider.getStatusLabelFound();
38 | scrollSolutionTextArea = provider.getScrollSolutionTextArea();
39 | statusLabel = provider.getStatusLabel();
40 | }
41 |
42 | public void setSolutionExternal(String value) {
43 | solution = value;
44 | }
45 |
46 | public void preparetoRun(File angrFile) {
47 | SwingWorker sw = new SwingWorker() {
48 | @Override
49 | protected String doInBackground() throws Exception {
50 | String angrFilePath = angrFile.getAbsolutePath();
51 | String jarPath = null;
52 | try {
53 | jarPath = new File(AngryGhidraProvider.class.getProtectionDomain().getCodeSource()
54 | .getLocation().toURI()).getPath();
55 | } catch (URISyntaxException e) {
56 | e.printStackTrace();
57 | angrFile.delete();
58 | return null;
59 | }
60 | String scriptPath = new File(jarPath.substring(0, jarPath.indexOf("lib")) +
61 | "angryghidra_script" + File.separator + "angryghidra.py").getAbsolutePath();
62 |
63 | //PythonVersion check (issue#5)
64 | if (runAngr("python3", scriptPath, angrFilePath) == 0) {
65 | ProcessBuilder pb = new ProcessBuilder("python", "--version");
66 | try {
67 | Process process = pb.start();
68 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
69 | String line = "";
70 | while ((line = reader.readLine()) != null) {
71 | String parsedVersion = line.substring(7);
72 | if (compareVersion(parsedVersion, "3.4") == -1 &&
73 | compareVersion(parsedVersion, "3.0") == 1) {
74 | runAngr("python", scriptPath, angrFilePath);
75 | }
76 | }
77 | process.waitFor();
78 | reader.close();
79 | } catch (Exception e) {
80 | e.printStackTrace();
81 | }
82 | }
83 | angrFile.delete();
84 | return null;
85 | }
86 |
87 | @Override
88 | protected void done() {
89 | if (mProvider.getIsTerminated()) {
90 | statusLabel.setText(mProvider.configuringString);
91 | return;
92 | }
93 | if (solution != null && !solution.isEmpty()) {
94 | statusLabelFound.setText("[+] Solution's been found:");
95 | scrollSolutionTextArea.setVisible(true);
96 | mProvider.getSolutionTextArea().setText(solution.trim());
97 | for (String traceAddress: traceList) {
98 | Address address = mAddressFactory.getAddress(traceAddress);
99 | if (!shouldAvoidColor(address)){
100 | try {
101 | mColorService.setColor(address,
102 | Color.getHSBColor(247, 224, 98));
103 | } catch (Exception ex) {}
104 | }
105 | }
106 | } else {
107 | statusLabelFound.setText("[–] No solution!");
108 | }
109 | }
110 | };
111 | SwingUtilities.invokeLater(new Runnable() {
112 | @Override
113 | public void run() {
114 | statusLabel.setText("[+] angr in progress...");
115 | scrollSolutionTextArea.setVisible(false);
116 | }
117 | });
118 | sw.execute();
119 | }
120 |
121 | private int runAngr(String pythonVersion, String scriptPath, String angrFilePath) {
122 | solution = "";
123 | ProcessBuilder processBuilder = new ProcessBuilder(pythonVersion, scriptPath, angrFilePath);
124 | Reader runnable = new Reader(processBuilder);
125 | Thread thread = new Thread(runnable);
126 | thread.start();
127 | while(thread.isAlive()) {
128 | if (mProvider.getIsTerminated()) {
129 | thread.interrupt();
130 | break;
131 | }
132 | }
133 | return runnable.getResult();
134 | }
135 |
136 | private class Reader implements Runnable {
137 | private volatile int result = -1;
138 | private BufferedReader reader;
139 | private Process proc;
140 |
141 | public Reader(ProcessBuilder processBuilder) {
142 | try {
143 | proc = processBuilder.start();
144 | } catch (Exception ex) {
145 | setResult(0);
146 | return;
147 | }
148 | reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
149 | }
150 |
151 | @Override
152 | public void run() {
153 | // BufferedReader is empty because of the exception above, we can't start
154 | if (getResult() == 0) {
155 | return;
156 | }
157 | String line = "";
158 | try {
159 | while ((line = reader.readLine()) != null &&
160 | !Thread.currentThread().isInterrupted()) {
161 | if (line.contains("t:")) {
162 | traceList.add(line.substring(2));
163 | } else {
164 | solution += line + "\n";
165 | }
166 | }
167 | if (Thread.currentThread().isInterrupted()) {
168 | proc.destroy();
169 | reader.close();
170 | return;
171 | }
172 | proc.waitFor();
173 | reader.close();
174 | setResult(1);
175 | return;
176 | } catch (Exception e) {
177 | setResult(0);
178 | return;
179 | }
180 | }
181 |
182 | public int getResult() {
183 | return result;
184 | }
185 |
186 | public void setResult(int value) {
187 | result = value;
188 | }
189 | }
190 |
191 | private int compareVersion(String version1, String version2) {
192 | String[] arr1 = version1.split("\\.");
193 | String[] arr2 = version2.split("\\.");
194 | int i=0;
195 | while (i Integer.parseInt(arr2[i])) {
200 | return 1;
201 | }
202 | } else if (i();
247 | }
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/src/main/java/angryghidra/AngryGhidraPlugin.java:
--------------------------------------------------------------------------------
1 | package angryghidra;
2 |
3 | import ghidra.MiscellaneousPluginPackage;
4 | import ghidra.app.plugin.PluginCategoryNames;
5 | import ghidra.app.plugin.ProgramPlugin;
6 | import ghidra.framework.plugintool.PluginInfo;
7 | import ghidra.framework.plugintool.PluginTool;
8 | import ghidra.framework.plugintool.util.PluginStatus;
9 | import ghidra.program.model.listing.Program;
10 |
11 | @PluginInfo(
12 | status = PluginStatus.STABLE,
13 | packageName = MiscellaneousPluginPackage.NAME,
14 | category = PluginCategoryNames.ANALYSIS,
15 | shortDescription = "Use angr in Ghidra",
16 | description = "One-click symbolic execution using angr in Ghidra"
17 | )
18 |
19 | public class AngryGhidraPlugin extends ProgramPlugin {
20 | private PluginTool mTool;
21 | private AngryGhidraProvider provider;
22 | private AngryGhidraPopupMenu popup;
23 | private UserAddressStorage addressStorage;
24 | private LocalColorizingService colorService;
25 | private Program mProgram;
26 |
27 | public AngryGhidraPlugin(PluginTool tool) {
28 | super(tool);
29 | mTool = tool;
30 | addressStorage = new UserAddressStorage();
31 | provider = new AngryGhidraProvider(this, getName(), mProgram);
32 | popup = new AngryGhidraPopupMenu(this);
33 | }
34 |
35 | @Override
36 | protected void programActivated(Program program) {
37 | mProgram = program;
38 | provider.setProgram(program);
39 | provideColorService();
40 | }
41 |
42 | public void provideColorService() {
43 | colorService = new LocalColorizingService(mTool, mProgram);
44 | popup.setColorService(colorService);
45 | provider.setColorService(colorService);
46 | }
47 |
48 | public AngryGhidraProvider getProvider() {
49 | return provider;
50 | }
51 |
52 | public UserAddressStorage getAddressStorage() {
53 | return addressStorage;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/angryghidra/AngryGhidraPopupMenu.java:
--------------------------------------------------------------------------------
1 | package angryghidra;
2 |
3 | import java.awt.Color;
4 | import java.awt.GridBagConstraints;
5 | import java.awt.Insets;
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 | import java.awt.event.KeyEvent;
9 | import java.math.BigInteger;
10 |
11 | import javax.swing.JButton;
12 | import javax.swing.JCheckBox;
13 | import javax.swing.JPanel;
14 | import javax.swing.JTextArea;
15 | import javax.swing.JTextField;
16 |
17 | import docking.action.KeyBindingData;
18 | import docking.action.MenuData;
19 | import docking.widgets.textfield.IntegerTextField;
20 | import ghidra.app.context.ListingActionContext;
21 | import ghidra.app.context.ListingContextAction;
22 | import ghidra.framework.plugintool.PluginTool;
23 | import ghidra.program.model.address.Address;
24 | import ghidra.program.model.address.AddressIterator;
25 | import ghidra.program.model.mem.MemoryAccessException;
26 |
27 |
28 | public class AngryGhidraPopupMenu extends ListingContextAction {
29 | private final String menuName = "AngryGhidraPlugin";
30 | private final String groupName = "SymEx";
31 | private PluginTool tool;
32 | private LocalColorizingService mColorService;
33 | private UserAddressStorage mAddressStorage;
34 | private AngryGhidraProvider provider;
35 | private JTextField findAddressField;
36 | private JTextField blankStateAddressField;
37 | private JTextArea textArea;
38 | private JCheckBox blankStateCB;
39 | private JCheckBox avoidAddrsCB;
40 | private JPanel writeMemoryPanel;
41 | private IntegerTextField storeAddressTF;
42 | private IntegerTextField storeValueTF;
43 |
44 | public AngryGhidraPopupMenu(AngryGhidraPlugin plugin) {
45 | super("AngryGhidraPlugin", plugin.getName());
46 | tool = plugin.getTool();
47 | mAddressStorage = plugin.getAddressStorage();
48 | provider = plugin.getProvider();
49 | setupActions();
50 | }
51 |
52 | public void setColorService(LocalColorizingService colorService){
53 | mColorService = colorService;
54 | }
55 |
56 | private void setupActions() {
57 | setupComponents();
58 | tool.setMenuGroup(new String[] {
59 | menuName
60 | }, groupName);
61 |
62 | ListingContextAction setDstAddress = new ListingContextAction("Set destination address", getName()) {
63 | @Override
64 | protected void actionPerformed(ListingActionContext context) {
65 | Address dstAddress = mAddressStorage.getDestinationAddress();
66 | if (dstAddress != null) {
67 | mColorService.resetColor(dstAddress);
68 | }
69 | Address thisAddress = context.getLocation().getAddress();
70 | mAddressStorage.setDestinationAddress(thisAddress);
71 | mColorService.setColor(thisAddress, Color.GREEN);
72 | findAddressField.setText("0x" + thisAddress.toString());
73 | }
74 | };
75 | setDstAddress.setKeyBindingData(new KeyBindingData(KeyEvent.VK_Z, 0));
76 | setDstAddress.setPopupMenuData(new MenuData(new String[] {
77 | menuName,
78 | "Set",
79 | "Address to Find"
80 | }, null, groupName));
81 | tool.addAction(setDstAddress);
82 |
83 | ListingContextAction setBlankStateAddr = new ListingContextAction("Set blank state address", getName()) {
84 | @Override
85 | protected void actionPerformed(ListingActionContext context) {
86 | Address blankStateAddress = mAddressStorage.getBlankStateAddress();
87 | if (blankStateAddress != null) {
88 | mColorService.resetColor(blankStateAddress);
89 | }
90 | Address thisAddress = context.getLocation().getAddress();
91 | mAddressStorage.setBlankStateAddress(thisAddress);
92 | mColorService.setColor(thisAddress, Color.CYAN);
93 | blankStateCB.setSelected(true);
94 | blankStateAddressField.setText("0x" + thisAddress.toString());
95 | }
96 | };
97 | setBlankStateAddr.setKeyBindingData(new KeyBindingData(KeyEvent.VK_X, 0));
98 | setBlankStateAddr.setPopupMenuData(new MenuData(new String[] {
99 | menuName,
100 | "Set",
101 | "Blank State Address"
102 | }, null, groupName));
103 | tool.addAction(setBlankStateAddr);
104 |
105 | ListingContextAction setAvoidAddr = new ListingContextAction("Set avoid address", getName()) {
106 | @Override
107 | protected void actionPerformed(ListingActionContext context) {
108 | Address address = context.getLocation().getAddress();
109 | if (!mAddressStorage.getAvoidAddresses().contains(address)){
110 | mColorService.setColor(address, Color.RED);
111 | avoidAddrsCB.setSelected(true);
112 | String strAddress = "0x" + address.toString();
113 | if (textArea.getText().isEmpty()) {
114 | textArea.setText(strAddress);
115 | } else {
116 | textArea.append("," + System.getProperty("line.separator") + strAddress);
117 | }
118 | mAddressStorage.addAvoidAddress(address);
119 | }
120 | }
121 | };
122 | setAvoidAddr.setKeyBindingData(new KeyBindingData(KeyEvent.VK_J, 0));
123 | setAvoidAddr.setPopupMenuData(new MenuData(new String[] {
124 | menuName,
125 | "Set",
126 | "Avoid Address"
127 | }, null, groupName));
128 | tool.addAction(setAvoidAddr);
129 |
130 | ListingContextAction resetDstAddress = new ListingContextAction("Reset destination address", getName()) {
131 | @Override
132 | protected void actionPerformed(ListingActionContext context) {
133 | Address dstAddress = mAddressStorage.getDestinationAddress();
134 | if (dstAddress != null) {
135 | Address address = context.getLocation().getAddress();
136 | if (address.equals(dstAddress)){
137 | mColorService.resetColor(dstAddress);
138 | mAddressStorage.setDestinationAddress(null);
139 | findAddressField.setText("");
140 | }
141 | }
142 | }
143 | };
144 | resetDstAddress.setKeyBindingData(new KeyBindingData(KeyEvent.VK_K, 0));
145 | resetDstAddress.setPopupMenuData(new MenuData(new String[] {
146 | menuName,
147 | "Unset",
148 | "Address to Find"
149 | }, null, groupName));
150 | tool.addAction(resetDstAddress);
151 |
152 | ListingContextAction resetBlankStateAddr = new ListingContextAction("Reset blank state address", getName()) {
153 | @Override
154 | protected void actionPerformed(ListingActionContext context) {
155 | Address blankStateAddress = mAddressStorage.getBlankStateAddress();
156 | if (blankStateAddress != null) {
157 | Address address = context.getLocation().getAddress();
158 | if (address.equals(blankStateAddress)){
159 | mColorService.resetColor(blankStateAddress);
160 | mAddressStorage.setBlankStateAddress(null);
161 | blankStateAddressField.setText("");
162 | blankStateCB.setSelected(false);
163 | }
164 | }
165 | }
166 | };
167 | resetBlankStateAddr.setKeyBindingData(new KeyBindingData(KeyEvent.VK_T, 0));
168 | resetBlankStateAddr.setPopupMenuData(new MenuData(new String[] {
169 | menuName,
170 | "Unset",
171 | "Blank State Address"
172 | }, null, groupName));
173 | tool.addAction(resetBlankStateAddr);
174 |
175 | ListingContextAction resetAvoidAddr = new ListingContextAction("Reset avoid address", getName()) {
176 | @Override
177 | protected void actionPerformed(ListingActionContext context) {
178 | Address address = context.getLocation().getAddress();
179 | if (mAddressStorage.getAvoidAddresses().contains(address)) {
180 | mColorService.resetColor(address);
181 | String separator = System.getProperty("line.separator");
182 | String content = textArea.getText();
183 | String addressStr = "0x" + address.toString();
184 | int addrIndex = content.indexOf(addressStr);
185 | int commaIndex = content.indexOf(",");
186 | if (addrIndex == 0 && commaIndex != -1) {
187 | content = content.replace(addressStr + "," + separator, "");
188 | }
189 | if (addrIndex == 0 && commaIndex == -1) {
190 | content = content.replace(addressStr, "");
191 | }
192 | if (addrIndex != 0) {
193 | content = content.replace("," + separator + addressStr, "");
194 | }
195 | textArea.setText(content);
196 | mAddressStorage.removeAvoidAddress(address);
197 | }
198 | }
199 | };
200 | resetAvoidAddr.setKeyBindingData(new KeyBindingData(KeyEvent.VK_P, 0));
201 | resetAvoidAddr.setPopupMenuData(new MenuData(new String[] {
202 | menuName,
203 | "Unset",
204 | "Avoid Address"
205 | }, null, groupName));
206 | tool.addAction(resetAvoidAddr);
207 |
208 | ListingContextAction applyPatchedBytes = new ListingContextAction("Apply patched bytes", getName()) {
209 | @Override
210 | protected void actionPerformed(ListingActionContext context) {
211 | Address minAddress = context.getSelection().getMinAddress();
212 | AddressIterator addressRange = context.getSelection().getAddresses(true);
213 | StringBuilder hexStringBuilder = new StringBuilder();
214 | for (Address address: addressRange) {
215 | byte selectedByte = 0;
216 | try {
217 | selectedByte = context.getProgram().getMemory().getByte(address);
218 | } catch (MemoryAccessException e) {
219 | e.printStackTrace();
220 | }
221 | hexStringBuilder.append(String.format("%02X", selectedByte));
222 | }
223 | String hexValueString = hexStringBuilder.toString();
224 | BigInteger hexValue = new BigInteger(hexValueString, 16);
225 |
226 | if (!storeAddressTF.getText().isEmpty()) {
227 | int currentGuiStoreCounter = provider.getGuiStoreCounter();
228 | IntegerTextField addrTF = new IntegerTextField();
229 | addrTF.setHexMode();
230 | addrTF.setValue(minAddress.getOffset());
231 | GridBagConstraints gbc_addrTF = new GridBagConstraints();
232 | gbc_addrTF.fill = GridBagConstraints.HORIZONTAL;
233 | gbc_addrTF.anchor = GridBagConstraints.CENTER;
234 | gbc_addrTF.gridx = 1;
235 | gbc_addrTF.insets = new Insets(0, 0, 0, 5);
236 | gbc_addrTF.gridy = currentGuiStoreCounter;
237 | gbc_addrTF.weightx = 1;
238 | gbc_addrTF.weighty = 0.1;
239 | writeMemoryPanel.add(addrTF.getComponent(), gbc_addrTF);
240 |
241 | IntegerTextField valTF = new IntegerTextField();
242 | valTF.setHexMode();
243 | valTF.setValue(hexValue);
244 | GridBagConstraints gbc_valTF = new GridBagConstraints();
245 | gbc_valTF.fill = GridBagConstraints.HORIZONTAL;
246 | gbc_valTF.anchor = GridBagConstraints.CENTER;
247 | gbc_valTF.insets = new Insets(0, 0, 0, 5);
248 | gbc_valTF.gridx = 3;
249 | gbc_valTF.gridy = currentGuiStoreCounter;
250 | gbc_valTF.weightx = 1;
251 | gbc_valTF.weighty = 0.1;
252 | writeMemoryPanel.add(valTF.getComponent(), gbc_valTF);
253 | provider.putIntoMemStore(addrTF, valTF);
254 |
255 | JButton btnDel = new JButton("");
256 | btnDel.setBorder(null);
257 | btnDel.setContentAreaFilled(false);
258 | btnDel.setIcon(provider.getDeleteIcon());
259 | GridBagConstraints gbc_btnDel = new GridBagConstraints();
260 | gbc_btnDel.fill = GridBagConstraints.HORIZONTAL;
261 | gbc_btnDel.anchor = GridBagConstraints.CENTER;
262 | gbc_btnDel.insets = new Insets(0, 0, 0, 5);
263 | gbc_btnDel.gridx = 0;
264 | gbc_btnDel.gridy = currentGuiStoreCounter;
265 | gbc_btnDel.weighty = 0.1;
266 | writeMemoryPanel.add(btnDel, gbc_btnDel);
267 | provider.setGuiStoreCounter(++currentGuiStoreCounter);
268 | provider.putIntoDelStoreBtns(btnDel);
269 | btnDel.addActionListener(new ActionListener() {
270 | public void actionPerformed(ActionEvent e) {
271 | provider.setGuiStoreCounter(provider.getGuiStoreCounter() - 1);
272 | provider.removeFromDelStoreBtns(btnDel);
273 | provider.removeFromMemStore(addrTF, valTF);
274 | writeMemoryPanel.remove(addrTF.getComponent());
275 | writeMemoryPanel.remove(valTF.getComponent());
276 | writeMemoryPanel.remove(btnDel);
277 | writeMemoryPanel.repaint();
278 | writeMemoryPanel.revalidate();
279 | }
280 | });
281 | writeMemoryPanel.repaint();
282 | writeMemoryPanel.revalidate();
283 | }
284 | else {
285 | storeAddressTF.setValue(minAddress.getOffset());
286 | storeValueTF.setValue(hexValue);
287 | }
288 | }
289 | };
290 | applyPatchedBytes.setKeyBindingData(new KeyBindingData(KeyEvent.VK_U, 0));
291 | applyPatchedBytes.setPopupMenuData(new MenuData(new String[] {
292 | menuName,
293 | "Apply Patched Bytes"}, null, groupName));
294 | tool.addAction(applyPatchedBytes);
295 | }
296 |
297 | private void setupComponents() {
298 | findAddressField = provider.getFindAddressTF();
299 | blankStateAddressField = provider.getBSAddressTF();
300 | textArea = provider.getTextArea();
301 | blankStateCB = provider.getCBBlankState();
302 | avoidAddrsCB = provider.getCBAvoidAddresses();
303 | writeMemoryPanel = provider.getWriteMemoryPanel();
304 | storeAddressTF = provider.getStoreAddressTF();
305 | storeValueTF = provider.getStoreValueTF();
306 | }
307 | }
308 |
--------------------------------------------------------------------------------
/src/main/java/angryghidra/AngryGhidraProvider.java:
--------------------------------------------------------------------------------
1 | package angryghidra;
2 |
3 | import java.awt.Color;
4 | import java.awt.Dimension;
5 | import java.awt.Font;
6 | import java.awt.GridBagConstraints;
7 | import java.awt.GridBagLayout;
8 | import java.awt.Insets;
9 | import java.awt.event.ActionEvent;
10 | import java.awt.event.ActionListener;
11 | import java.awt.event.ItemEvent;
12 | import java.awt.event.ItemListener;
13 | import java.awt.event.KeyAdapter;
14 | import java.awt.event.KeyEvent;
15 | import java.io.File;
16 | import java.io.FileWriter;
17 | import java.util.ArrayList;
18 | import java.util.Arrays;
19 | import java.util.HashMap;
20 | import java.util.List;
21 | import java.util.Map.Entry;
22 | import javax.swing.BorderFactory;
23 | import javax.swing.GroupLayout;
24 | import javax.swing.GroupLayout.Alignment;
25 | import javax.swing.ImageIcon;
26 | import javax.swing.JButton;
27 | import javax.swing.JCheckBox;
28 | import javax.swing.JComponent;
29 | import javax.swing.JLabel;
30 | import javax.swing.JPanel;
31 | import javax.swing.JScrollPane;
32 | import javax.swing.JTextArea;
33 | import javax.swing.JTextField;
34 | import javax.swing.LayoutStyle.ComponentPlacement;
35 | import javax.swing.ScrollPaneConstants;
36 | import javax.swing.SwingConstants;
37 | import javax.swing.border.LineBorder;
38 | import javax.swing.border.TitledBorder;
39 | import org.json.JSONArray;
40 | import org.json.JSONObject;
41 | import docking.ComponentProvider;
42 | import docking.widgets.textfield.IntegerTextField;
43 | import ghidra.program.model.address.Address;
44 | import ghidra.program.model.listing.Program;
45 | import resources.ResourceManager;
46 |
47 | public class AngryGhidraProvider extends ComponentProvider {
48 | public final String htmlString = "Registers
Hint: to create and store symbolic vector enter \"sv{length}\", for example \"sv16\"";
49 | public final String configuringString = "[+] Configuring options";
50 | private boolean isHookWindowClosed;
51 | private boolean isTerminated;
52 | private boolean isWindows;
53 | private int guiRegNextId;
54 | private int guiArgNextId;
55 | private int guiMemNextId;
56 | private int guiStoreNextId;
57 | private String tmpDir;
58 | private Program thisProgram;
59 | private LocalColorizingService mColorService;
60 | private HookHandler hookHandler;
61 | private AngrProcessing angrProcessing;
62 | private UserAddressStorage addressStorage;
63 | private JPanel mainPanel;
64 | private JPanel customOptionsPanel;
65 | private JPanel argumentsPanel;
66 | private JPanel mainOptionsPanel;
67 | private JPanel statusPanel;
68 | private JPanel hookLablesPanel;
69 | private JPanel writeMemoryPanel;
70 | private JPanel argSetterPanel;
71 | private JPanel vectorsPanel;
72 | private JPanel regPanel;
73 | private JScrollPane scrollSolutionTextArea;
74 | private JScrollPane scrollAvoidAddrsArea;
75 | private JTextField blankStateTF;
76 | private JTextField dstAddressTF;
77 | private JTextField valueTF;
78 | private JTextField registerTF;
79 | private IntegerTextField firstArgTF;
80 | private IntegerTextField vectorAddressTF;
81 | private IntegerTextField vectorLenTF;
82 | private IntegerTextField memStoreAddrTF;
83 | private IntegerTextField memStoreValueTF;
84 | private JCheckBox chckbxBlankState;
85 | private JCheckBox chckbxAvoidAddresses;
86 | private JCheckBox chckbxAutoLoadLibs;
87 | private JCheckBox chckbxArg;
88 | private JTextArea avoidTextArea;
89 | private JTextArea solutionTextArea;
90 | private JLabel statusLabel;
91 | private JLabel statusLabelFound;
92 | private JLabel lbStatus;
93 | private JLabel lbStoreAddr;
94 | private JLabel lbStoreVal;
95 | private JLabel lblWriteToMemory;
96 | private JLabel lbArgLen;
97 | private JButton btnReset;
98 | private JButton btnRun;
99 | private JButton btnStop;
100 | private JButton btnAddWM;
101 | private JButton btnAddArg;
102 | private HashMap vectors;
103 | private HashMap memStore;
104 | private HashMap presetRegs;
105 | private HashMap hooks;
106 | private ArrayList argsTF;
107 | private ArrayList delRegsBtns;
108 | private ArrayList delMemBtns;
109 | private ArrayList delStoreBtns;
110 | private ArrayList delBtnArgs;
111 | private ArrayList delHookBtns;
112 | private ArrayList lbHooks;
113 | private ImageIcon deleteIcon;
114 | private ImageIcon addIcon;
115 |
116 | public AngryGhidraProvider(AngryGhidraPlugin plugin, String owner, Program program) {
117 | super(plugin.getTool(), owner, owner);
118 | addressStorage = plugin.getAddressStorage();
119 | setIcon(ResourceManager.loadImage("images/ico.png"));
120 | if (program != null){
121 | setProgram(program);
122 | }
123 | initFields();
124 | buildPanel();
125 | }
126 |
127 | public void setColorService(LocalColorizingService colorService) {
128 | mColorService = colorService;
129 | angrProcessing = new AngrProcessing(addressStorage, mColorService, this, thisProgram.getAddressFactory());
130 | }
131 |
132 | private void initFields() {
133 | ImageIcon addIconNonScaled = new ImageIcon(getClass().getResource("/images/add.png"));
134 | ImageIcon deleteIconNonScaled = new ImageIcon(getClass().getResource("/images/delete.png"));
135 | addIcon = new ImageIcon(addIconNonScaled.getImage().getScaledInstance(21, 21, java.awt.Image.SCALE_SMOOTH));
136 | deleteIcon = new ImageIcon(deleteIconNonScaled.getImage().getScaledInstance(21, 21, java.awt.Image.SCALE_SMOOTH));
137 |
138 | setHookWindowState(true);
139 | setIsTerminated(false);
140 | guiArgNextId = 2;
141 | guiMemNextId = 2;
142 | guiRegNextId = 2;
143 | guiStoreNextId = 2;
144 | delRegsBtns = new ArrayList ();
145 | delBtnArgs = new ArrayList ();
146 | delMemBtns = new ArrayList ();
147 | delStoreBtns = new ArrayList ();
148 | delHookBtns = new ArrayList ();
149 | argsTF = new ArrayList ();
150 | presetRegs = new HashMap<>();
151 | vectors = new HashMap<>();
152 | memStore = new HashMap<>();
153 | hooks = new HashMap ();
154 | lbHooks = new ArrayList ();
155 | isWindows = System.getProperty("os.name").contains("Windows");
156 | tmpDir = System.getProperty("java.io.tmpdir");
157 | if (!isWindows) {
158 | tmpDir += "/";
159 | }
160 | }
161 |
162 | private void buildPanel() {
163 | mainPanel = new JPanel();
164 | mainPanel.setMinimumSize(new Dimension(210, 510));
165 | setVisible(true);
166 |
167 | // Some preparations
168 | ImageIcon startIcon = new ImageIcon(getClass().getResource("/images/flag.png"));
169 | ImageIcon stopIcon = new ImageIcon(getClass().getResource("/images/stop.png"));
170 | ImageIcon resetIcon = new ImageIcon(getClass().getResource("/images/reset.png"));
171 | resetIcon = new ImageIcon(resetIcon.getImage().getScaledInstance(18, 18, java.awt.Image.SCALE_SMOOTH));
172 | Font sansSerif12 = new Font("SansSerif", Font.PLAIN, 12);
173 | Font sansSerif13 = new Font("SansSerif", Font.PLAIN, 13);
174 |
175 | TitledBorder borderMPO = BorderFactory.createTitledBorder("Main project options");
176 | borderMPO.setTitleFont(sansSerif12);
177 |
178 | TitledBorder borderCSO = BorderFactory.createTitledBorder("Custom symbolic options");
179 | borderCSO.setTitleFont(sansSerif12);
180 |
181 | TitledBorder borderSA = BorderFactory.createTitledBorder("Program arguments");
182 | borderSA.setTitleFont(sansSerif12);
183 |
184 | argSetterPanel = new JPanel();
185 | vectorsPanel = new JPanel();
186 | regPanel = new JPanel();
187 | writeMemoryPanel = new JPanel();
188 | hookLablesPanel = new JPanel();
189 | statusPanel = new JPanel();
190 | statusPanel.setBorder(null);
191 | argSetterPanel.setBorder(null);
192 | writeMemoryPanel.setBorder(null);
193 |
194 | mainOptionsPanel = new JPanel();
195 | mainOptionsPanel.setForeground(new Color(46, 139, 87));
196 | mainOptionsPanel.setBorder(borderMPO);
197 |
198 | customOptionsPanel = new JPanel();
199 | customOptionsPanel.setBorder(borderCSO);
200 |
201 | chckbxArg = new JCheckBox("Arguments");
202 | chckbxArg.setFont(sansSerif12);
203 |
204 | argumentsPanel = new JPanel();
205 | argumentsPanel.setForeground(new Color(46, 139, 87));
206 | argumentsPanel.setBorder(borderSA);
207 |
208 | GroupLayout gl_argumentsPanel = new GroupLayout(argumentsPanel);
209 | gl_argumentsPanel.setHorizontalGroup(
210 | gl_argumentsPanel.createParallelGroup(Alignment.TRAILING)
211 | .addGroup(gl_argumentsPanel.createSequentialGroup()
212 | .addContainerGap()
213 | .addComponent(chckbxArg, GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
214 | .addGap(31)
215 | .addComponent(argSetterPanel, GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE)
216 | .addContainerGap())
217 | );
218 | gl_argumentsPanel.setVerticalGroup(
219 | gl_argumentsPanel.createParallelGroup(Alignment.LEADING)
220 | .addGroup(gl_argumentsPanel.createSequentialGroup()
221 | .addGroup(gl_argumentsPanel.createParallelGroup(Alignment.LEADING)
222 | .addGroup(gl_argumentsPanel.createSequentialGroup()
223 | .addContainerGap()
224 | .addComponent(chckbxArg))
225 | .addComponent(argSetterPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
226 | .addGap(20))
227 | );
228 | argumentsPanel.setLayout(gl_argumentsPanel);
229 |
230 | GridBagLayout gbl_argSetterPanel = new GridBagLayout();
231 | gbl_argSetterPanel.columnWidths = new int[] {
232 | 0,
233 | 0,
234 | 0,
235 | 0,
236 | 0
237 | };
238 | gbl_argSetterPanel.rowHeights = new int[] {
239 | 0,
240 | 0
241 | };
242 | gbl_argSetterPanel.columnWeights = new double[] {
243 | 0.0,
244 | 0.0,
245 | 0.0,
246 | 0.0,
247 | Double.MIN_VALUE
248 | };
249 | gbl_argSetterPanel.rowWeights = new double[] {
250 | 0.0,
251 | 0.0
252 | };
253 | argSetterPanel.setLayout(gbl_argSetterPanel);
254 |
255 | btnAddArg = new JButton("");
256 | GridBagConstraints gbc_btnAddArg = new GridBagConstraints();
257 | gbc_btnAddArg.anchor = GridBagConstraints.CENTER;
258 | gbc_btnAddArg.fill = GridBagConstraints.HORIZONTAL;
259 | gbc_btnAddArg.insets = new Insets(0, 0, 0, 5);
260 | gbc_btnAddArg.gridx = 0;
261 | gbc_btnAddArg.gridy = 1;
262 | gbc_btnAddArg.weighty = 0.1;
263 | argSetterPanel.add(btnAddArg, gbc_btnAddArg);
264 | btnAddArg.setContentAreaFilled(false);
265 | btnAddArg.setIcon(addIcon);
266 | btnAddArg.setBorder(null);
267 | btnAddArg.setVisible(false);
268 |
269 | lbArgLen = new JLabel("Length");
270 | GridBagConstraints gbc_lbArgLen = new GridBagConstraints();
271 | gbc_lbArgLen.insets = new Insets(0, 0, 0, 5);
272 | gbc_lbArgLen.anchor = GridBagConstraints.CENTER;
273 | gbc_lbArgLen.gridwidth = 3;
274 | gbc_lbArgLen.gridx = 1;
275 | gbc_lbArgLen.gridy = 0;
276 | gbc_lbArgLen.weightx = 1;
277 | argSetterPanel.add(lbArgLen, gbc_lbArgLen);
278 | lbArgLen.setFont(sansSerif12);
279 | lbArgLen.setVisible(false);
280 |
281 | firstArgTF = new IntegerTextField();
282 | GridBagConstraints gbc_TFArglen = new GridBagConstraints();
283 | gbc_TFArglen.insets = new Insets(0, 0, 0, 5);
284 | gbc_TFArglen.fill = GridBagConstraints.HORIZONTAL;
285 | gbc_TFArglen.anchor = GridBagConstraints.NORTH;
286 | gbc_TFArglen.gridwidth = 3;
287 | gbc_TFArglen.gridx = 1;
288 | gbc_TFArglen.gridy = 1;
289 | gbc_TFArglen.weightx = 1;
290 | gbc_TFArglen.weighty = 0.1;
291 | argSetterPanel.add(firstArgTF.getComponent(), gbc_TFArglen);
292 | firstArgTF.getComponent().setVisible(false);
293 | chckbxArg.addItemListener(
294 | new ItemListener() {
295 | public void itemStateChanged(ItemEvent e) {
296 | if (chckbxArg.isSelected()) {
297 | firstArgTF.getComponent().setVisible(true);
298 | lbArgLen.setVisible(true);
299 | btnAddArg.setVisible(true);
300 | for (JButton btnDel: delBtnArgs) {
301 | btnDel.setVisible(true);
302 | }
303 | for (IntegerTextField argTF: argsTF) {
304 | argTF.getComponent().setVisible(true);
305 | }
306 | } else {
307 | firstArgTF.getComponent().setVisible(false);
308 | lbArgLen.setVisible(false);
309 | btnAddArg.setVisible(false);
310 | for (JButton btnDel: delBtnArgs) {
311 | btnDel.setVisible(false);
312 | }
313 | for (IntegerTextField argTF: argsTF) {
314 | argTF.getComponent().setVisible(false);
315 | }
316 | }
317 | }
318 | }
319 | );
320 |
321 | btnAddArg.addActionListener(new ActionListener() {
322 | public void actionPerformed(ActionEvent e) {
323 | IntegerTextField argTF = new IntegerTextField();
324 | GridBagConstraints gbc_TFArg = new GridBagConstraints();
325 | gbc_TFArg.fill = GridBagConstraints.HORIZONTAL;
326 | gbc_TFArg.anchor = GridBagConstraints.CENTER;
327 | gbc_TFArg.gridwidth = 3;
328 | gbc_TFArg.gridx = 1;
329 | gbc_TFArg.insets = new Insets(0, 0, 0, 5);
330 | gbc_TFArg.gridy = guiArgNextId;
331 | gbc_TFArg.weightx = 1;
332 | gbc_TFArg.weighty = 0.1;
333 | argSetterPanel.add(argTF.getComponent(), gbc_TFArg);
334 | argsTF.add(argTF);
335 |
336 | JButton btnDel = new JButton("");
337 | btnDel.setBorder(null);
338 | btnDel.setContentAreaFilled(false);
339 | btnDel.setIcon(deleteIcon);
340 | GridBagConstraints gbc_btnDel = new GridBagConstraints();
341 | gbc_btnDel.insets = new Insets(0, 0, 0, 5);
342 | gbc_btnDel.fill = GridBagConstraints.HORIZONTAL;
343 | gbc_btnDel.anchor = GridBagConstraints.CENTER;
344 | gbc_btnDel.gridx = 0;
345 | gbc_btnDel.gridy = guiArgNextId++;
346 | gbc_btnDel.weighty = 0.1;
347 | argSetterPanel.add(btnDel, gbc_btnDel);
348 | delBtnArgs.add(btnDel);
349 | btnDel.addActionListener(new ActionListener() {
350 | public void actionPerformed(ActionEvent actionEvent) {
351 | guiArgNextId--;
352 | argSetterPanel.remove(argTF.getComponent());
353 | argSetterPanel.remove(btnDel);
354 | delBtnArgs.remove(btnDel);
355 | argsTF.remove(argTF);
356 | argSetterPanel.repaint();
357 | argSetterPanel.revalidate();
358 | }
359 | });
360 | argSetterPanel.repaint();
361 | argSetterPanel.revalidate();
362 | }
363 | });
364 | chckbxAutoLoadLibs = new JCheckBox("Auto load libs");
365 | chckbxAutoLoadLibs.setFont(sansSerif12);
366 | blankStateTF = new JTextField();
367 | blankStateTF.setVisible(false);
368 | blankStateTF.addKeyListener(new KeyAdapter() {
369 | public void keyReleased(KeyEvent e) {
370 | Address blankStateAddress = addressStorage.getBlankStateAddress();
371 | if (blankStateAddress != null) {
372 | mColorService.resetColor(blankStateAddress);
373 | addressStorage.setBlankStateAddress(null);
374 | }
375 | }
376 | });
377 | chckbxBlankState = new JCheckBox("Blank state");
378 | chckbxBlankState.setFont(sansSerif12);
379 | chckbxBlankState.addItemListener(
380 | new ItemListener() {
381 | public void itemStateChanged(ItemEvent e) {
382 | if (chckbxBlankState.isSelected()) {
383 | blankStateTF.setVisible(true);
384 | } else {
385 | blankStateTF.setVisible(false);
386 | }
387 | mainOptionsPanel.revalidate();
388 | }
389 | }
390 | );
391 |
392 | JLabel lbFind = new JLabel("Find address");
393 | lbFind.setForeground(new Color(60, 179, 113));
394 | lbFind.setFont(sansSerif12);
395 |
396 | dstAddressTF = new JTextField();
397 | dstAddressTF.setMinimumSize(new Dimension(100, 20));
398 | dstAddressTF.addKeyListener(new KeyAdapter() {
399 | public void keyReleased(KeyEvent e) {
400 | Address dstAddress = addressStorage.getDestinationAddress();
401 | if (dstAddress != null) {
402 | mColorService.resetColor(dstAddress);
403 | addressStorage.setDestinationAddress(null);
404 | }
405 | }
406 | });
407 |
408 | chckbxAvoidAddresses = new JCheckBox("Аvoid addresses");
409 | chckbxAvoidAddresses.setForeground(new Color(255, 0, 0));
410 | chckbxAvoidAddresses.setToolTipText("");
411 | chckbxAvoidAddresses.setFont(sansSerif12);
412 |
413 | avoidTextArea = new JTextArea();
414 | avoidTextArea.setMinimumSize(new Dimension(40, 40));
415 | avoidTextArea.setToolTipText("Enter the hex values separated by comma.");
416 | avoidTextArea.setFont(dstAddressTF.getFont());
417 | avoidTextArea.addKeyListener(new KeyAdapter() {
418 | public void keyReleased(KeyEvent e) {
419 | List userAvoidAddresses = new ArrayList(addressStorage.getAvoidAddresses());
420 | if (!userAvoidAddresses.isEmpty()) {
421 | try {
422 | List avoidAddresses = Arrays.asList(avoidTextArea.getText().split(","));
423 | // Sanitize the list
424 | String separator = System.getProperty("line.separator");
425 | for (int i = 0; i < avoidAddresses.size(); i++) {
426 | avoidAddresses.set(i, avoidAddresses.get(i).replace(separator, ""));
427 | }
428 | for (int i = 0; i < userAvoidAddresses.size(); i++) {
429 | Address address = userAvoidAddresses.get(i);
430 | String strAddress = "0x" + address.toString();
431 | if (!avoidAddresses.contains(strAddress)) {
432 | mColorService.resetColor(address);
433 | addressStorage.removeAvoidAddress(address);
434 | }
435 | }
436 | } catch (Exception ex) {}
437 | }
438 | }
439 | });
440 |
441 | scrollAvoidAddrsArea = new JScrollPane(avoidTextArea);
442 | scrollAvoidAddrsArea.setMinimumSize(new Dimension(50, 50));
443 | scrollAvoidAddrsArea.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
444 | scrollAvoidAddrsArea.setVisible(false);
445 | chckbxAvoidAddresses.addItemListener(
446 | new ItemListener() {
447 | public void itemStateChanged(ItemEvent e) {
448 | if (chckbxAvoidAddresses.isSelected()) {
449 | scrollAvoidAddrsArea.setVisible(true);
450 | } else {
451 | scrollAvoidAddrsArea.setVisible(false);
452 | }
453 | mainOptionsPanel.revalidate();
454 | }
455 | }
456 | );
457 |
458 | // Unfortunately, it was found that GUI gaps look different on different operating systems
459 | int blankStateTFGap = 10;
460 | int findAddressGap = 13;
461 | int blankStateCBGap = 11;
462 | int scrollAvoidAddrsAreaGap = 11;
463 | int avoidAreaGap = 11;
464 | int bufferGap = 8;
465 | int horizontalFindAddressGap = 22;
466 | if (isWindows) {
467 | blankStateTFGap = 11;
468 | findAddressGap = 10;
469 | blankStateCBGap = 6;
470 | scrollAvoidAddrsAreaGap = 13;
471 | avoidAreaGap = 8;
472 | bufferGap = 0;
473 | horizontalFindAddressGap = 21;
474 | }
475 |
476 | GroupLayout gl_mainOptionsPanel = new GroupLayout(mainOptionsPanel);
477 | gl_mainOptionsPanel.setHorizontalGroup(
478 | gl_mainOptionsPanel.createParallelGroup(Alignment.TRAILING)
479 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
480 | .addGap(11)
481 | .addGroup(gl_mainOptionsPanel.createParallelGroup(Alignment.LEADING)
482 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
483 | .addComponent(chckbxAutoLoadLibs, GroupLayout.PREFERRED_SIZE, 134, GroupLayout.PREFERRED_SIZE)
484 | .addContainerGap(73, Short.MAX_VALUE))
485 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
486 | .addGroup(gl_mainOptionsPanel.createParallelGroup(Alignment.LEADING)
487 | .addGroup(gl_mainOptionsPanel.createParallelGroup(Alignment.LEADING)
488 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
489 | .addComponent(chckbxBlankState, GroupLayout.PREFERRED_SIZE, 134, GroupLayout.PREFERRED_SIZE)
490 | .addPreferredGap(ComponentPlacement.RELATED, 18, Short.MAX_VALUE))
491 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
492 | .addComponent(chckbxAvoidAddresses, GroupLayout.PREFERRED_SIZE, 134, GroupLayout.PREFERRED_SIZE)
493 | .addPreferredGap(ComponentPlacement.RELATED, 18, Short.MAX_VALUE)))
494 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
495 | .addGap(horizontalFindAddressGap)
496 | .addComponent(lbFind, GroupLayout.PREFERRED_SIZE, 102, GroupLayout.PREFERRED_SIZE)
497 | .addPreferredGap(ComponentPlacement.RELATED)))
498 | .addGroup(gl_mainOptionsPanel.createParallelGroup(Alignment.LEADING)
499 | .addComponent(blankStateTF, GroupLayout.DEFAULT_SIZE, 54, Short.MAX_VALUE)
500 | .addComponent(dstAddressTF, GroupLayout.DEFAULT_SIZE, 54, Short.MAX_VALUE)
501 | .addComponent(scrollAvoidAddrsArea, GroupLayout.DEFAULT_SIZE, 54, Short.MAX_VALUE))
502 | .addGap(15))))
503 | );
504 |
505 | gl_mainOptionsPanel.setVerticalGroup(
506 | gl_mainOptionsPanel.createParallelGroup(Alignment.LEADING)
507 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
508 | .addGap(6)
509 | .addComponent(chckbxAutoLoadLibs)
510 | .addGap(bufferGap)
511 | .addGroup(gl_mainOptionsPanel.createParallelGroup(Alignment.BASELINE)
512 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
513 | .addGap(blankStateCBGap)
514 | .addComponent(chckbxBlankState))
515 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
516 | .addGap(blankStateTFGap)
517 | .addComponent(blankStateTF, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))
518 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
519 | .addGroup(gl_mainOptionsPanel.createParallelGroup(Alignment.BASELINE)
520 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
521 | .addGap(findAddressGap)
522 | .addComponent(lbFind))
523 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
524 | .addGap(10)
525 | .addComponent(dstAddressTF, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))
526 | .addGroup(gl_mainOptionsPanel.createParallelGroup(Alignment.BASELINE)
527 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
528 | .addGap(avoidAreaGap)
529 | .addComponent(chckbxAvoidAddresses))
530 | .addGroup(gl_mainOptionsPanel.createSequentialGroup()
531 | .addGap(scrollAvoidAddrsAreaGap)
532 | .addComponent(scrollAvoidAddrsArea, GroupLayout.PREFERRED_SIZE, 45, Short.MAX_VALUE))))
533 | .addContainerGap())
534 | );
535 | gl_mainOptionsPanel.setAutoCreateContainerGaps(false);
536 | gl_mainOptionsPanel.setAutoCreateGaps(false);
537 | gl_mainOptionsPanel.setHonorsVisibility(false);
538 | mainOptionsPanel.setLayout(gl_mainOptionsPanel);
539 |
540 | JLabel lbMemory = new JLabel("Store symbolic vector:");
541 | lbMemory.setHorizontalAlignment(SwingConstants.CENTER);
542 | lbMemory.setFont(sansSerif12);
543 | JLabel lbRegisters = new JLabel(htmlString);
544 | lbRegisters.setFont(sansSerif12);
545 |
546 | GridBagLayout gbl_writeMemoryPanel = new GridBagLayout();
547 | gbl_writeMemoryPanel.columnWidths = new int[] {
548 | 0,
549 | 0,
550 | 0,
551 | 0,
552 | 0,
553 | 0
554 | };
555 | gbl_writeMemoryPanel.rowHeights = new int[] {
556 | 0,
557 | 0,
558 | 0
559 | };
560 | gbl_writeMemoryPanel.columnWeights = new double[] {
561 | 0.0,
562 | 0.0,
563 | 0.0,
564 | 0.0,
565 | 0.0,
566 | Double.MIN_VALUE
567 | };
568 | gbl_writeMemoryPanel.rowWeights = new double[] {
569 | 0.0,
570 | 0.0,
571 | Double.MIN_VALUE
572 | };
573 | writeMemoryPanel.setLayout(gbl_writeMemoryPanel);
574 |
575 | lblWriteToMemory = new JLabel("Write to memory:");
576 | lblWriteToMemory.setHorizontalAlignment(SwingConstants.CENTER);
577 | lblWriteToMemory.setFont(sansSerif12);
578 |
579 | lbStoreAddr = new JLabel("Address");
580 | lbStoreAddr.setFont(sansSerif12);
581 | GridBagConstraints gbc_lbStoreAddr = new GridBagConstraints();
582 | gbc_lbStoreAddr.weightx = 1.0;
583 | gbc_lbStoreAddr.insets = new Insets(0, 0, 0, 5);
584 | gbc_lbStoreAddr.gridx = 1;
585 | gbc_lbStoreAddr.gridy = 0;
586 | writeMemoryPanel.add(lbStoreAddr, gbc_lbStoreAddr);
587 |
588 | lbStoreVal = new JLabel("Value");
589 | lbStoreVal.setFont(sansSerif12);
590 | GridBagConstraints gbc_lbStoreVal = new GridBagConstraints();
591 | gbc_lbStoreVal.weightx = 1.0;
592 | gbc_lbStoreVal.insets = new Insets(0, 0, 0, 5);
593 | gbc_lbStoreVal.gridx = 3;
594 | gbc_lbStoreVal.gridy = 0;
595 | writeMemoryPanel.add(lbStoreVal, gbc_lbStoreVal);
596 |
597 | memStoreAddrTF = new IntegerTextField();
598 | memStoreAddrTF.setHexMode();
599 | GridBagConstraints gbc_memStoreAddrTF = new GridBagConstraints();
600 | gbc_memStoreAddrTF.anchor = GridBagConstraints.CENTER;
601 | gbc_memStoreAddrTF.fill = GridBagConstraints.HORIZONTAL;
602 | gbc_memStoreAddrTF.insets = new Insets(0, 0, 0, 5);
603 | gbc_memStoreAddrTF.gridx = 1;
604 | gbc_memStoreAddrTF.gridy = 1;
605 | gbc_memStoreAddrTF.weightx = 1;
606 | gbc_memStoreAddrTF.weighty = 0.1;
607 | writeMemoryPanel.add(memStoreAddrTF.getComponent(), gbc_memStoreAddrTF);
608 |
609 | memStoreValueTF = new IntegerTextField();
610 | memStoreValueTF.setHexMode();
611 | GridBagConstraints gbc_memStoreValueTF = new GridBagConstraints();
612 | gbc_memStoreValueTF.insets = new Insets(0, 0, 0, 5);
613 | gbc_memStoreValueTF.fill = GridBagConstraints.HORIZONTAL;
614 | gbc_memStoreValueTF.anchor = GridBagConstraints.CENTER;
615 | gbc_memStoreValueTF.gridx = 3;
616 | gbc_memStoreValueTF.gridy = 1;
617 | gbc_memStoreValueTF.weightx = 1;
618 | gbc_memStoreValueTF.weighty = 0.1;
619 | writeMemoryPanel.add(memStoreValueTF.getComponent(), gbc_memStoreValueTF);
620 |
621 | btnAddWM = new JButton("");
622 | btnAddWM.setContentAreaFilled(false);
623 | btnAddWM.setBorder(null);
624 | btnAddWM.setIcon(addIcon);
625 | GridBagConstraints gbc_btnAddWM = new GridBagConstraints();
626 | gbc_btnAddWM.weighty = 0.1;
627 | gbc_btnAddWM.fill = GridBagConstraints.HORIZONTAL;
628 | gbc_btnAddWM.anchor = GridBagConstraints.CENTER;
629 | gbc_btnAddWM.insets = new Insets(0, 0, 0, 5);
630 | gbc_btnAddWM.gridx = 0;
631 | gbc_btnAddWM.gridy = 1;
632 | gbc_btnAddWM.weighty = 0.1;
633 | writeMemoryPanel.add(btnAddWM, gbc_btnAddWM);
634 | btnAddWM.addActionListener(new ActionListener() {
635 | public void actionPerformed(ActionEvent e) {
636 | IntegerTextField addrTF = new IntegerTextField();
637 | addrTF.setHexMode();
638 | GridBagConstraints gbc_addrTF = new GridBagConstraints();
639 | gbc_addrTF.fill = GridBagConstraints.HORIZONTAL;
640 | gbc_addrTF.anchor = GridBagConstraints.CENTER;
641 | gbc_addrTF.gridx = 1;
642 | gbc_addrTF.insets = new Insets(0, 0, 0, 5);
643 | gbc_addrTF.gridy = guiStoreNextId;
644 | gbc_addrTF.weightx = 1;
645 | gbc_addrTF.weighty = 0.1;
646 | writeMemoryPanel.add(addrTF.getComponent(), gbc_addrTF);
647 |
648 | IntegerTextField valTF = new IntegerTextField();
649 | valTF.setHexMode();
650 | GridBagConstraints gbc_valTF = new GridBagConstraints();
651 | gbc_valTF.fill = GridBagConstraints.HORIZONTAL;
652 | gbc_valTF.anchor = GridBagConstraints.CENTER;
653 | gbc_valTF.insets = new Insets(0, 0, 0, 5);
654 | gbc_valTF.gridx = 3;
655 | gbc_valTF.gridy = guiStoreNextId;
656 | gbc_valTF.weightx = 1;
657 | gbc_valTF.weighty = 0.1;
658 | writeMemoryPanel.add(valTF.getComponent(), gbc_valTF);
659 | memStore.put(addrTF, valTF);
660 |
661 | JButton btnDel = new JButton("");
662 | btnDel.setBorder(null);
663 | btnDel.setContentAreaFilled(false);
664 | btnDel.setIcon(deleteIcon);
665 | GridBagConstraints gbc_btnDel = new GridBagConstraints();
666 | gbc_btnDel.fill = GridBagConstraints.HORIZONTAL;
667 | gbc_btnDel.anchor = GridBagConstraints.CENTER;
668 | gbc_btnDel.insets = new Insets(0, 0, 0, 5);
669 | gbc_btnDel.gridx = 0;
670 | gbc_btnDel.gridy = guiStoreNextId++;
671 | gbc_btnDel.weighty = 0.1;
672 | writeMemoryPanel.add(btnDel, gbc_btnDel);
673 | delStoreBtns.add(btnDel);
674 | btnDel.addActionListener(new ActionListener() {
675 | public void actionPerformed(ActionEvent actionEvent) {
676 | guiStoreNextId--;
677 | writeMemoryPanel.remove(addrTF.getComponent());
678 | writeMemoryPanel.remove(valTF.getComponent());
679 | writeMemoryPanel.remove(btnDel);
680 | delStoreBtns.remove(btnDel);
681 | memStore.remove(addrTF, valTF);
682 | writeMemoryPanel.repaint();
683 | writeMemoryPanel.revalidate();
684 | }
685 | });
686 | writeMemoryPanel.repaint();
687 | writeMemoryPanel.revalidate();
688 | }
689 | });
690 |
691 | GroupLayout gl_customOptionsPanel = new GroupLayout(customOptionsPanel);
692 | gl_customOptionsPanel.setHorizontalGroup(
693 | gl_customOptionsPanel.createParallelGroup(Alignment.LEADING)
694 | .addGroup(gl_customOptionsPanel.createSequentialGroup()
695 | .addContainerGap()
696 | .addComponent(vectorsPanel, GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE)
697 | .addGap(25))
698 | .addGroup(gl_customOptionsPanel.createSequentialGroup()
699 | .addContainerGap()
700 | .addGroup(gl_customOptionsPanel.createParallelGroup(Alignment.LEADING)
701 | .addGroup(gl_customOptionsPanel.createSequentialGroup()
702 | .addComponent(lblWriteToMemory)
703 | .addPreferredGap(ComponentPlacement.RELATED, 237, GroupLayout.PREFERRED_SIZE))
704 | .addComponent(writeMemoryPanel, GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE))
705 | .addGap(25))
706 | .addGroup(gl_customOptionsPanel.createSequentialGroup()
707 | .addContainerGap()
708 | .addComponent(regPanel, GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE)
709 | .addGap(25))
710 | .addGroup(gl_customOptionsPanel.createSequentialGroup()
711 | .addContainerGap()
712 | .addComponent(lbRegisters, GroupLayout.PREFERRED_SIZE, 327, Short.MAX_VALUE)
713 | )
714 | .addGroup(gl_customOptionsPanel.createSequentialGroup()
715 | .addComponent(lbMemory, GroupLayout.PREFERRED_SIZE, 148, GroupLayout.PREFERRED_SIZE)
716 | .addContainerGap(232, Short.MAX_VALUE))
717 | );
718 | gl_customOptionsPanel.setVerticalGroup(
719 | gl_customOptionsPanel.createParallelGroup(Alignment.LEADING)
720 | .addGroup(gl_customOptionsPanel.createSequentialGroup()
721 | .addContainerGap()
722 | .addComponent(lbMemory, GroupLayout.PREFERRED_SIZE, 13, GroupLayout.PREFERRED_SIZE)
723 | .addPreferredGap(ComponentPlacement.RELATED)
724 | .addComponent(vectorsPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
725 | .addGap(23)
726 | .addComponent(lblWriteToMemory)
727 | .addPreferredGap(ComponentPlacement.RELATED)
728 | .addComponent(writeMemoryPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
729 | .addGap(18)
730 | .addComponent(lbRegisters)
731 | .addGap(9)
732 | .addComponent(regPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
733 | .addGap(54))
734 | );
735 | customOptionsPanel.setLayout(gl_customOptionsPanel);
736 |
737 | GridBagLayout gbl_regPanel = new GridBagLayout();
738 | gbl_regPanel.columnWidths = new int[] {
739 | 0,
740 | 0,
741 | 0,
742 | 0,
743 | 0
744 | };
745 | gbl_regPanel.rowHeights = new int[] {
746 | 0,
747 | 0
748 | };
749 | gbl_regPanel.columnWeights = new double[] {
750 | 0.0,
751 | 0.0,
752 | 0.0,
753 | 0.0,
754 | Double.MIN_VALUE
755 | };
756 | gbl_regPanel.rowWeights = new double[] {
757 | 0.0,
758 | 0.0
759 | };
760 | regPanel.setLayout(gbl_regPanel);
761 |
762 | JLabel lblReg = new JLabel("Register");
763 | lblReg.setFont(sansSerif12);
764 | GridBagConstraints gbc_lblReg = new GridBagConstraints();
765 | gbc_lblReg.anchor = GridBagConstraints.SOUTH;
766 | gbc_lblReg.insets = new Insets(0, 0, 0, 5);
767 | gbc_lblReg.gridx = 1;
768 | gbc_lblReg.gridy = 0;
769 | gbc_lblReg.weightx = 1;
770 | regPanel.add(lblReg, gbc_lblReg);
771 |
772 | JLabel lblValue = new JLabel(" Value ");
773 | lblValue.setFont(sansSerif12);
774 | GridBagConstraints gbc_lblValue = new GridBagConstraints();
775 | gbc_lblValue.anchor = GridBagConstraints.SOUTH;
776 | gbc_lblValue.insets = new Insets(0, 0, 0, 5);
777 | gbc_lblValue.gridx = 3;
778 | gbc_lblValue.gridy = 0;
779 | gbc_lblValue.weightx = 1;
780 | regPanel.add(lblValue, gbc_lblValue);
781 |
782 | JButton btnAddButton = new JButton("");
783 | GridBagConstraints gbc_btnAddButton = new GridBagConstraints();
784 | gbc_btnAddButton.anchor = GridBagConstraints.CENTER;
785 | gbc_btnAddButton.fill = GridBagConstraints.HORIZONTAL;
786 | gbc_btnAddButton.insets = new Insets(0, 0, 0, 5);
787 | gbc_btnAddButton.gridx = 0;
788 | gbc_btnAddButton.gridy = 1;
789 | gbc_btnAddButton.weighty = 0.1;
790 | regPanel.add(btnAddButton, gbc_btnAddButton);
791 | btnAddButton.setBorder(null);
792 | btnAddButton.setContentAreaFilled(false);
793 | btnAddButton.setIcon(addIcon);
794 |
795 | valueTF = new JTextField();
796 | valueTF.setColumns(5);
797 | GridBagConstraints gbc_valueTF = new GridBagConstraints();
798 | gbc_valueTF.insets = new Insets(0, 0, 0, 5);
799 | gbc_valueTF.anchor = GridBagConstraints.CENTER;
800 | gbc_valueTF.fill = GridBagConstraints.HORIZONTAL;
801 | gbc_valueTF.gridx = 3;
802 | gbc_valueTF.gridy = 1;
803 | gbc_valueTF.weightx = 1;
804 | gbc_valueTF.weighty = 0.1;
805 | regPanel.add(valueTF, gbc_valueTF);
806 |
807 | registerTF = new JTextField();
808 | registerTF.setColumns(5);
809 | GridBagConstraints gbc_registerTF = new GridBagConstraints();
810 | gbc_registerTF.anchor = GridBagConstraints.CENTER;
811 | gbc_registerTF.fill = GridBagConstraints.HORIZONTAL;
812 | gbc_registerTF.insets = new Insets(0, 0, 0, 5);
813 | gbc_registerTF.gridx = 1;
814 | gbc_registerTF.gridy = 1;
815 | gbc_registerTF.weighty = 0.1;
816 | regPanel.add(registerTF, gbc_registerTF);
817 |
818 | btnAddButton.addActionListener(new ActionListener() {
819 | public void actionPerformed(ActionEvent e) {
820 | JTextField regTF = new JTextField();
821 | regTF.setColumns(5);
822 | GridBagConstraints gbc_regTF = new GridBagConstraints();
823 | gbc_regTF.fill = GridBagConstraints.HORIZONTAL;
824 | gbc_regTF.anchor = GridBagConstraints.CENTER;
825 | gbc_regTF.gridx = 1;
826 | gbc_regTF.insets = new Insets(0, 0, 0, 5);
827 | gbc_regTF.gridy = guiRegNextId;
828 | gbc_regTF.weightx = 1;
829 | gbc_regTF.weighty = 0.1;
830 | regPanel.add(regTF, gbc_regTF);
831 |
832 | JTextField valTF = new JTextField();
833 | valTF.setColumns(5);
834 | GridBagConstraints gbc_valTF = new GridBagConstraints();
835 | gbc_valTF.fill = GridBagConstraints.HORIZONTAL;
836 | gbc_valTF.anchor = GridBagConstraints.CENTER;
837 | gbc_valTF.insets = new Insets(0, 0, 0, 5);
838 | gbc_valTF.gridx = 3;
839 | gbc_valTF.gridy = guiRegNextId;
840 | gbc_valTF.weightx = 1;
841 | gbc_valTF.weighty = 0.1;
842 | regPanel.add(valTF, gbc_valTF);
843 | presetRegs.put(regTF, valTF);
844 |
845 | JButton btnDel = new JButton("");
846 | btnDel.setBorder(null);
847 | btnDel.setContentAreaFilled(false);
848 | btnDel.setIcon(deleteIcon);
849 | GridBagConstraints gbc_btnDel = new GridBagConstraints();
850 | gbc_btnDel.insets = new Insets(0, 0, 0, 5);
851 | gbc_btnDel.fill = GridBagConstraints.HORIZONTAL;
852 | gbc_btnDel.anchor = GridBagConstraints.CENTER;
853 | gbc_btnDel.gridx = 0;
854 | gbc_btnDel.gridy = guiRegNextId++;
855 | gbc_btnDel.weighty = 0.1;
856 | regPanel.add(btnDel, gbc_btnDel);
857 | delRegsBtns.add(btnDel);
858 | btnDel.addActionListener(new ActionListener() {
859 | public void actionPerformed(ActionEvent actionEvent) {
860 | guiRegNextId--;
861 | delRegsBtns.remove(btnDel);
862 | presetRegs.remove(regTF, valTF);
863 | regPanel.remove(regTF);
864 | regPanel.remove(valTF);
865 | regPanel.remove(btnDel);
866 | regPanel.repaint();
867 | regPanel.revalidate();
868 | }
869 | });
870 | regPanel.repaint();
871 | regPanel.revalidate();
872 | }
873 | });
874 |
875 | GridBagLayout gbl_vectorsPanel = new GridBagLayout();
876 | gbl_vectorsPanel.columnWidths = new int[] {
877 | 0,
878 | 0,
879 | 0,
880 | 0,
881 | 0,
882 | 0
883 | };
884 | gbl_vectorsPanel.rowHeights = new int[] {
885 | 0,
886 | 0
887 | };
888 | gbl_vectorsPanel.columnWeights = new double[] {
889 | 0.0,
890 | 0.0,
891 | 0.0,
892 | 0.0,
893 | 0.0,
894 | Double.MIN_VALUE
895 | };
896 | gbl_vectorsPanel.rowWeights = new double[] {
897 | 0.0,
898 | 0.0
899 | };
900 | vectorsPanel.setLayout(gbl_vectorsPanel);
901 | JButton btnAddMem = new JButton("");
902 | GridBagConstraints gbc_btnAddMem = new GridBagConstraints();
903 | gbc_btnAddMem.anchor = GridBagConstraints.CENTER;
904 | gbc_btnAddMem.fill = GridBagConstraints.HORIZONTAL;
905 | gbc_btnAddMem.insets = new Insets(0, 0, 0, 5);
906 | gbc_btnAddMem.gridx = 0;
907 | gbc_btnAddMem.gridy = 1;
908 | gbc_btnAddMem.weighty = 0.1;
909 | vectorsPanel.add(btnAddMem, gbc_btnAddMem);
910 | btnAddMem.setIcon(addIcon);
911 | btnAddMem.setBorder(null);
912 | btnAddMem.setContentAreaFilled(false);
913 |
914 | JLabel lbMemAddr = new JLabel("Address");
915 | lbMemAddr.setFont(sansSerif12);
916 | GridBagConstraints gbc_lbMemAddr = new GridBagConstraints();
917 | gbc_lbMemAddr.insets = new Insets(0, 0, 0, 5);
918 | gbc_lbMemAddr.gridx = 1;
919 | gbc_lbMemAddr.gridy = 0;
920 | gbc_lbMemAddr.weightx = 1;
921 | vectorsPanel.add(lbMemAddr, gbc_lbMemAddr);
922 |
923 | JLabel lblLentgh = new JLabel("Length");
924 | lblLentgh.setFont(sansSerif12);
925 | GridBagConstraints gbc_lblLentgh = new GridBagConstraints();
926 | gbc_lblLentgh.insets = new Insets(0, 0, 0, 5);
927 | gbc_lblLentgh.gridx = 3;
928 | gbc_lblLentgh.gridy = 0;
929 | gbc_lblLentgh.weightx = 1;
930 | vectorsPanel.add(lblLentgh, gbc_lblLentgh);
931 |
932 | vectorAddressTF = new IntegerTextField();
933 | vectorAddressTF.setHexMode();
934 | GridBagConstraints gbc_vectorAddressTF = new GridBagConstraints();
935 | gbc_vectorAddressTF.anchor = GridBagConstraints.CENTER;
936 | gbc_vectorAddressTF.fill = GridBagConstraints.HORIZONTAL;
937 | gbc_vectorAddressTF.insets = new Insets(0, 0, 0, 5);
938 | gbc_vectorAddressTF.gridx = 1;
939 | gbc_vectorAddressTF.gridy = 1;
940 | gbc_vectorAddressTF.weightx = 1;
941 | gbc_vectorAddressTF.weighty = 0.1;
942 | vectorsPanel.add(vectorAddressTF.getComponent(), gbc_vectorAddressTF);
943 |
944 | vectorLenTF = new IntegerTextField();
945 | GridBagConstraints gbc_vectorLenTF = new GridBagConstraints();
946 | gbc_vectorLenTF.insets = new Insets(0, 0, 0, 5);
947 | gbc_vectorLenTF.fill = GridBagConstraints.HORIZONTAL;
948 | gbc_vectorLenTF.anchor = GridBagConstraints.CENTER;
949 | gbc_vectorLenTF.gridx = 3;
950 | gbc_vectorLenTF.gridy = 1;
951 | gbc_vectorLenTF.weightx = 1;
952 | gbc_vectorLenTF.weighty = 0.1;
953 | vectorsPanel.add(vectorLenTF.getComponent(), gbc_vectorLenTF);
954 |
955 | btnAddMem.addActionListener(new ActionListener() {
956 | public void actionPerformed(ActionEvent e) {
957 | IntegerTextField addrTF = new IntegerTextField();
958 | addrTF.setHexMode();
959 | GridBagConstraints gbc_addrTF = new GridBagConstraints();
960 | gbc_addrTF.fill = GridBagConstraints.HORIZONTAL;
961 | gbc_addrTF.anchor = GridBagConstraints.CENTER;
962 | gbc_addrTF.gridx = 1;
963 | gbc_addrTF.insets = new Insets(0, 0, 0, 5);
964 | gbc_addrTF.gridy = guiMemNextId;
965 | gbc_addrTF.weightx = 1;
966 | gbc_addrTF.weighty = 0.1;
967 | vectorsPanel.add(addrTF.getComponent(), gbc_addrTF);
968 |
969 | IntegerTextField lenTF = new IntegerTextField();
970 | GridBagConstraints gbc_lenTF = new GridBagConstraints();
971 | gbc_lenTF.fill = GridBagConstraints.HORIZONTAL;
972 | gbc_lenTF.anchor = GridBagConstraints.CENTER;
973 | gbc_lenTF.insets = new Insets(0, 0, 0, 5);
974 | gbc_lenTF.gridx = 3;
975 | gbc_lenTF.gridy = guiMemNextId;
976 | gbc_lenTF.weightx = 1;
977 | gbc_lenTF.weighty = 0.1;
978 | vectorsPanel.add(lenTF.getComponent(), gbc_lenTF);
979 | vectors.put(addrTF, lenTF);
980 |
981 | JButton btnDel = new JButton("");
982 | btnDel.setBorder(null);
983 | btnDel.setContentAreaFilled(false);
984 | btnDel.setIcon(deleteIcon);
985 | GridBagConstraints gbc_btnDel = new GridBagConstraints();
986 | gbc_btnDel.fill = GridBagConstraints.HORIZONTAL;
987 | gbc_btnDel.anchor = GridBagConstraints.CENTER;
988 | gbc_btnDel.insets = new Insets(0, 0, 0, 5);
989 | gbc_btnDel.gridx = 0;
990 | gbc_btnDel.gridy = guiMemNextId++;
991 | gbc_btnDel.weighty = 0.1;
992 | vectorsPanel.add(btnDel, gbc_btnDel);
993 | delMemBtns.add(btnDel);
994 | btnDel.addActionListener(new ActionListener() {
995 | public void actionPerformed(ActionEvent actionEvent) {
996 | guiMemNextId--;
997 | vectorsPanel.remove(addrTF.getComponent());
998 | vectorsPanel.remove(lenTF.getComponent());
999 | vectorsPanel.remove(btnDel);
1000 | delMemBtns.remove(btnDel);
1001 | vectors.remove(addrTF, lenTF);
1002 | vectorsPanel.repaint();
1003 | vectorsPanel.revalidate();
1004 | }
1005 | });
1006 | vectorsPanel.repaint();
1007 | vectorsPanel.revalidate();
1008 | }
1009 | });
1010 |
1011 |
1012 | lbStatus = new JLabel("Status:");
1013 | lbStatus.setForeground(Color.BLUE);
1014 | lbStatus.setFont(sansSerif13);
1015 |
1016 | statusLabel = new JLabel(configuringString);
1017 | statusLabel.setFont(sansSerif13);
1018 |
1019 | statusLabelFound = new JLabel("");
1020 | statusLabelFound.setFont(sansSerif13);
1021 |
1022 | btnRun = new JButton("Run");
1023 | btnRun.setIcon(startIcon);
1024 | btnRun.setFont(sansSerif12);
1025 |
1026 | solutionTextArea = new JTextArea();
1027 | solutionTextArea.setFont(sansSerif12);
1028 | scrollSolutionTextArea = new JScrollPane(solutionTextArea);
1029 | solutionTextArea.setEditable(false);
1030 | scrollSolutionTextArea.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
1031 | scrollSolutionTextArea.setBorder(new LineBorder(Color.blue, 1));
1032 | scrollSolutionTextArea.setVisible(false);
1033 |
1034 | btnStop = new JButton("Stop");
1035 | btnStop.addActionListener(new ActionListener() {
1036 | public void actionPerformed(ActionEvent e) {
1037 | if (new File(tmpDir + "angr_options.json").exists()) {
1038 | setIsTerminated(true);
1039 | statusLabel.setText("[+] Stopping...");
1040 | statusLabelFound.setText("");
1041 | scrollSolutionTextArea.setVisible(false);
1042 | }
1043 | }
1044 | });
1045 | btnStop.setFont(sansSerif12);
1046 | btnStop.setIcon(stopIcon);
1047 |
1048 | btnReset = new JButton("Reset");
1049 | btnReset.setIcon(resetIcon);
1050 | btnReset.setFont(sansSerif12);
1051 | btnReset.addActionListener(new ActionListener() {
1052 | public void actionPerformed(ActionEvent e) {
1053 | resetState();
1054 | }
1055 | });
1056 |
1057 | GroupLayout gl_statusPanel = new GroupLayout(statusPanel);
1058 | gl_statusPanel.setHorizontalGroup(
1059 | gl_statusPanel.createParallelGroup(Alignment.LEADING)
1060 | .addGroup(gl_statusPanel.createSequentialGroup()
1061 | .addGap(10)
1062 | .addComponent(statusLabelFound, GroupLayout.DEFAULT_SIZE, 127, Short.MAX_VALUE)
1063 | .addGap(71)
1064 | .addComponent(scrollSolutionTextArea, GroupLayout.DEFAULT_SIZE, 378, Short.MAX_VALUE)
1065 | .addGap(10))
1066 | .addGroup(gl_statusPanel.createSequentialGroup()
1067 | .addGroup(gl_statusPanel.createParallelGroup(Alignment.TRAILING)
1068 | .addGroup(gl_statusPanel.createSequentialGroup()
1069 | .addGap(77)
1070 | .addComponent(btnRun, GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE)
1071 | .addGap(77)
1072 | .addComponent(btnStop, GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE)
1073 | .addGap(77)
1074 | .addComponent(btnReset, GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE)
1075 | .addGap(1))
1076 | .addGroup(gl_statusPanel.createSequentialGroup()
1077 | .addGap(10)
1078 | .addComponent(statusLabel, GroupLayout.DEFAULT_SIZE, 495, Short.MAX_VALUE)))
1079 | .addGap(91))
1080 | .addGroup(gl_statusPanel.createSequentialGroup()
1081 | .addContainerGap()
1082 | .addComponent(lbStatus, GroupLayout.PREFERRED_SIZE, 46, GroupLayout.PREFERRED_SIZE)
1083 | .addContainerGap(538, Short.MAX_VALUE))
1084 | );
1085 | gl_statusPanel.setVerticalGroup(
1086 | gl_statusPanel.createParallelGroup(Alignment.LEADING)
1087 | .addGroup(gl_statusPanel.createSequentialGroup()
1088 | .addGap(10)
1089 | .addGroup(gl_statusPanel.createParallelGroup(Alignment.BASELINE)
1090 | .addComponent(btnRun, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE)
1091 | .addComponent(btnStop, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE)
1092 | .addComponent(btnReset, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE))
1093 | .addPreferredGap(ComponentPlacement.RELATED)
1094 | .addComponent(lbStatus, GroupLayout.PREFERRED_SIZE, 13, GroupLayout.PREFERRED_SIZE)
1095 | .addPreferredGap(ComponentPlacement.RELATED)
1096 | .addComponent(statusLabel, GroupLayout.PREFERRED_SIZE, 17, GroupLayout.PREFERRED_SIZE)
1097 | .addGroup(gl_statusPanel.createParallelGroup(Alignment.LEADING)
1098 | .addGroup(gl_statusPanel.createSequentialGroup()
1099 | .addGap(5)
1100 | .addComponent(statusLabelFound, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE))
1101 | .addGroup(gl_statusPanel.createSequentialGroup()
1102 | .addPreferredGap(ComponentPlacement.RELATED)
1103 | .addComponent(scrollSolutionTextArea, GroupLayout.DEFAULT_SIZE, 36, Short.MAX_VALUE)))
1104 | .addContainerGap())
1105 | );
1106 | statusPanel.setLayout(gl_statusPanel);
1107 |
1108 | JPanel hookPanel = new JPanel();
1109 | TitledBorder borderHP = BorderFactory.createTitledBorder("Hook options");
1110 | borderHP.setTitleFont(sansSerif12);
1111 | hookPanel.setBorder(borderHP);
1112 |
1113 | GroupLayout gl_mainPanel = new GroupLayout(mainPanel);
1114 | gl_mainPanel.setHorizontalGroup(
1115 | gl_mainPanel.createParallelGroup(Alignment.TRAILING)
1116 | .addGroup(gl_mainPanel.createSequentialGroup()
1117 | .addGroup(gl_mainPanel.createParallelGroup(Alignment.LEADING)
1118 | .addGroup(gl_mainPanel.createSequentialGroup()
1119 | .addContainerGap()
1120 | .addComponent(statusPanel, GroupLayout.DEFAULT_SIZE, 550, Short.MAX_VALUE))
1121 | .addGroup(gl_mainPanel.createSequentialGroup()
1122 | .addGroup(gl_mainPanel.createParallelGroup(Alignment.LEADING)
1123 | .addGroup(gl_mainPanel.createSequentialGroup()
1124 | .addGap(10)
1125 | .addComponent(mainOptionsPanel, GroupLayout.DEFAULT_SIZE, 275, Short.MAX_VALUE))
1126 | .addGroup(gl_mainPanel.createSequentialGroup()
1127 | .addContainerGap()
1128 | .addComponent(argumentsPanel, GroupLayout.DEFAULT_SIZE, 275, Short.MAX_VALUE))
1129 | .addGroup(gl_mainPanel.createSequentialGroup()
1130 | .addContainerGap()
1131 | .addComponent(hookPanel, GroupLayout.DEFAULT_SIZE, 275, Short.MAX_VALUE)))
1132 | .addPreferredGap(ComponentPlacement.RELATED)
1133 | .addComponent(customOptionsPanel, GroupLayout.DEFAULT_SIZE, 269, Short.MAX_VALUE)))
1134 | .addGap(13))
1135 | );
1136 | gl_mainPanel.setVerticalGroup(
1137 | gl_mainPanel.createParallelGroup(Alignment.LEADING)
1138 | .addGroup(gl_mainPanel.createSequentialGroup()
1139 | .addGroup(gl_mainPanel.createParallelGroup(Alignment.LEADING)
1140 | .addGroup(gl_mainPanel.createSequentialGroup()
1141 | .addGap(10)
1142 | .addComponent(mainOptionsPanel, GroupLayout.DEFAULT_SIZE, 178, Short.MAX_VALUE)
1143 | .addGap(2)
1144 | .addComponent(argumentsPanel, GroupLayout.DEFAULT_SIZE, 81, Short.MAX_VALUE)
1145 | .addPreferredGap(ComponentPlacement.RELATED)
1146 | .addComponent(hookPanel, GroupLayout.DEFAULT_SIZE, 90, Short.MAX_VALUE))
1147 | .addGroup(gl_mainPanel.createSequentialGroup()
1148 | .addContainerGap()
1149 | .addComponent(customOptionsPanel, GroupLayout.DEFAULT_SIZE, 357, Short.MAX_VALUE)))
1150 | .addPreferredGap(ComponentPlacement.UNRELATED)
1151 | .addComponent(statusPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
1152 | .addGap(5))
1153 | );
1154 | mainPanel.setLayout(gl_mainPanel);
1155 |
1156 | JButton btnAddHook = new JButton("Add Hook");
1157 | btnAddHook.addActionListener(new ActionListener() {
1158 | public void actionPerformed(ActionEvent e) {
1159 | if (getHookWindowState()) {
1160 | hookHandler = new HookHandler(AngryGhidraProvider.this);
1161 | hookHandler.main();
1162 | setHookWindowState(false);
1163 | } else {
1164 | hookHandler.toFront();
1165 | }
1166 | }
1167 | });
1168 | btnAddHook.setFont(new Font("SansSerif", Font.PLAIN, 11));
1169 |
1170 | GroupLayout gl_hookPanel = new GroupLayout(hookPanel);
1171 | gl_hookPanel.setHorizontalGroup(
1172 | gl_hookPanel.createParallelGroup(Alignment.LEADING)
1173 | .addGroup(gl_hookPanel.createSequentialGroup()
1174 | .addContainerGap()
1175 | .addComponent(btnAddHook, GroupLayout.PREFERRED_SIZE, 105, Short.MAX_VALUE)
1176 | .addGap(43)
1177 | .addComponent(hookLablesPanel, GroupLayout.DEFAULT_SIZE, 105, Short.MAX_VALUE)
1178 | .addContainerGap())
1179 | );
1180 | gl_hookPanel.setVerticalGroup(
1181 | gl_hookPanel.createParallelGroup(Alignment.TRAILING)
1182 | .addGroup(gl_hookPanel.createSequentialGroup()
1183 | .addGroup(gl_hookPanel.createParallelGroup(Alignment.TRAILING)
1184 | .addGroup(Alignment.LEADING, gl_hookPanel.createSequentialGroup()
1185 | .addContainerGap()
1186 | .addComponent(btnAddHook))
1187 | .addGroup(gl_hookPanel.createSequentialGroup()
1188 | .addGap(10)
1189 | .addComponent(hookLablesPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))
1190 | .addGap(34))
1191 | );
1192 | hookPanel.setLayout(gl_hookPanel);
1193 |
1194 | GridBagLayout gbl_hookLablesPanel = new GridBagLayout();
1195 | gbl_hookLablesPanel.columnWidths = new int[] {0};
1196 | gbl_hookLablesPanel.rowHeights = new int[] {0};
1197 | gbl_hookLablesPanel.columnWeights = new double[] {Double.MIN_VALUE};
1198 | gbl_hookLablesPanel.rowWeights = new double[] {Double.MIN_VALUE};
1199 | hookLablesPanel.setLayout(gbl_hookLablesPanel);
1200 | btnRun.addActionListener(new ActionListener() {
1201 | public void actionPerformed(ActionEvent e) {
1202 | statusLabel.setText(configuringString);
1203 | statusLabelFound.setText("");
1204 | setIsTerminated(false);
1205 | angrProcessing.clearTraceList(false);
1206 | JSONObject angr_options = new JSONObject();
1207 | Boolean auto_load_libs = false;
1208 | if (chckbxAutoLoadLibs.isSelected()) {
1209 | auto_load_libs = true;
1210 | }
1211 | angr_options.put("auto_load_libs", auto_load_libs);
1212 | if (chckbxBlankState.isSelected()) {
1213 | if (!blankStateTF.getText().matches("0x[0-9A-Fa-f]+")) {
1214 | statusLabel.setForeground(Color.red);
1215 | statusLabel.setText("[–] Error: enter the correct blank state address value in hex format!");
1216 | return;
1217 | }
1218 | String blank_state = blankStateTF.getText();
1219 | angr_options.put("blank_state", blank_state);
1220 | }
1221 | if (!dstAddressTF.getText().matches("0x[0-9A-Fa-f]+")) {
1222 | statusLabel.setForeground(Color.red);
1223 | statusLabel.setText("[–] Error: enter the correct destination address in hex format!");
1224 | return;
1225 | }
1226 | String find_addr = dstAddressTF.getText();
1227 | angr_options.put("find_address", find_addr);
1228 | if (chckbxAvoidAddresses.isSelected()) {
1229 | if (!avoidTextArea.getText().replaceAll("\\s+", "").matches("[0x0-9a-fA-F, /,]+")) {
1230 | statusLabel.setForeground(Color.red);
1231 | statusLabel.setText("[–] Error: enter the correct avoid addresses in hex format separated by comma!");
1232 | return;
1233 | }
1234 | String avoid = avoidTextArea.getText().replaceAll("\\s+", "");
1235 | angr_options.put("avoid_address", avoid);
1236 | }
1237 | if (chckbxArg.isSelected()) {
1238 | if (!firstArgTF.getText().isEmpty()) {
1239 | JSONObject argDetails = new JSONObject();
1240 | int id = 1;
1241 | argDetails.put(String.valueOf(id++), firstArgTF.getText());
1242 | for (IntegerTextField itf : argsTF) {
1243 | String value = itf.getText();
1244 | if (!value.isEmpty()) {
1245 | argDetails.put(String.valueOf(id), value);
1246 | }
1247 | id++;
1248 | }
1249 | angr_options.put("arguments", argDetails);
1250 | }
1251 | }
1252 | if (!vectorAddressTF.getText().isEmpty() &&
1253 | !vectorLenTF.getText().isEmpty()) {
1254 | JSONObject vectorDetails = new JSONObject();
1255 | vectorDetails.put(vectorAddressTF.getText(), vectorLenTF.getText());
1256 | for (Entry entry : vectors.entrySet()) {
1257 | String addr = entry.getKey().getText();
1258 | String len = entry.getValue().getText();
1259 | if (!addr.isEmpty() && !len.isEmpty()) {
1260 | vectorDetails.put(addr, len);
1261 | }
1262 | }
1263 | angr_options.put("vectors", vectorDetails);
1264 | }
1265 | if (!memStoreAddrTF.getText().isEmpty() && !memStoreValueTF.getText().isEmpty()) {
1266 | JSONObject storeDetails = new JSONObject();
1267 | storeDetails.put(memStoreAddrTF.getText(), memStoreValueTF.getText());
1268 | for (Entry entry : memStore.entrySet()) {
1269 | String addr = entry.getKey().getText();
1270 | String val = entry.getValue().getText();
1271 | if (!addr.isEmpty() && !val.isEmpty()) {
1272 | storeDetails.put(addr, val);
1273 | }
1274 | }
1275 | angr_options.put("mem_store", storeDetails);
1276 | }
1277 | String reg1 = registerTF.getText();
1278 | String val1 = valueTF.getText();
1279 | if (symbolicVectorInputCheck(reg1, val1)) {
1280 | JSONObject regDetails = new JSONObject();
1281 | regDetails.put(reg1, val1);
1282 | for (Entry entry : presetRegs.entrySet()) {
1283 | String reg = entry.getKey().getText();
1284 | String val = entry.getValue().getText();
1285 | if (symbolicVectorInputCheck(reg, val)) {
1286 | regDetails.put(reg, val);
1287 | }
1288 | }
1289 | angr_options.put("regs_vals", regDetails);
1290 | }
1291 | if (!hooks.isEmpty()) {
1292 | JSONArray hookList = new JSONArray();
1293 | for (Entry entry: hooks.entrySet()) {
1294 | JSONObject hookDetails = new JSONObject();
1295 | String[] hookOptions = entry.getKey();
1296 | String hookAddress = hookOptions[0];
1297 | hookDetails.put("length", hookOptions[1]);
1298 | String[][] regs = entry.getValue();
1299 | for (int i = 0; i entry : vectors.entrySet()) {
1400 | IntegerTextField addrTF = entry.getKey();
1401 | IntegerTextField lenTF = entry.getValue();
1402 | vectorsPanel.remove(addrTF.getComponent());
1403 | vectorsPanel.remove(lenTF.getComponent());
1404 | }
1405 | for (JButton button : delMemBtns) {
1406 | vectorsPanel.remove(button);
1407 | }
1408 | vectors.clear();
1409 | delMemBtns.clear();
1410 | vectorsPanel.repaint();
1411 | vectorsPanel.revalidate();
1412 |
1413 | // Reset mem set contents
1414 | guiStoreNextId = 2;
1415 | for (Entry entry : memStore.entrySet()) {
1416 | IntegerTextField addrTF = entry.getKey();
1417 | IntegerTextField valTF = entry.getValue();
1418 | writeMemoryPanel.remove(addrTF.getComponent());
1419 | writeMemoryPanel.remove(valTF.getComponent());
1420 | }
1421 | for (JButton button : delStoreBtns) {
1422 | writeMemoryPanel.remove(button);
1423 | }
1424 | memStoreAddrTF.setText("");
1425 | memStoreValueTF.setText("");
1426 | memStore.clear();
1427 | delStoreBtns.clear();
1428 | writeMemoryPanel.repaint();
1429 | writeMemoryPanel.revalidate();
1430 |
1431 | // Reset preset registers
1432 | guiRegNextId = 2;
1433 | for (Entry entry : presetRegs.entrySet()) {
1434 | JTextField regTF = entry.getKey();
1435 | JTextField valTF = entry.getValue();
1436 | regPanel.remove(regTF);
1437 | regPanel.remove(valTF);
1438 | }
1439 | for (JButton button : delRegsBtns) {
1440 | regPanel.remove(button);
1441 | }
1442 | registerTF.setText("");
1443 | valueTF.setText("");
1444 | delRegsBtns.clear();
1445 | presetRegs.clear();
1446 | regPanel.repaint();
1447 | regPanel.revalidate();
1448 |
1449 | // Reset all hooks
1450 | if (hookHandler != null) {
1451 | hookHandler.requestClearHooks();
1452 | }
1453 | hooks.clear();
1454 | for (JButton button : delHookBtns) {
1455 | hookLablesPanel.remove(button);
1456 | }
1457 | for (JLabel label : lbHooks) {
1458 | hookLablesPanel.remove(label);
1459 | }
1460 | lbHooks.clear();
1461 | delHookBtns.clear();
1462 | hookLablesPanel.repaint();
1463 | hookLablesPanel.revalidate();
1464 | }
1465 |
1466 | public boolean symbolicVectorInputCheck(String reg, String value) {
1467 | return !reg.isEmpty() && !value.isEmpty() && (value.matches("0x[0-9A-Fa-f]+") ||
1468 | value.matches("[0-9]+") || value.contains("sv"));
1469 | }
1470 |
1471 | public JTextField getFindAddressTF() {
1472 | return dstAddressTF;
1473 | }
1474 |
1475 | public JTextField getBSAddressTF() {
1476 | return blankStateTF;
1477 | }
1478 |
1479 | public JTextArea getTextArea() {
1480 | return avoidTextArea;
1481 | }
1482 |
1483 | public JCheckBox getCBBlankState() {
1484 | return chckbxBlankState;
1485 | }
1486 |
1487 | public JCheckBox getCBAvoidAddresses() {
1488 | return chckbxAvoidAddresses;
1489 | }
1490 |
1491 | public JPanel getWriteMemoryPanel() {
1492 | return writeMemoryPanel;
1493 | }
1494 |
1495 | public JPanel getHookLablesPanel() {
1496 | return hookLablesPanel;
1497 | }
1498 |
1499 | public int getGuiStoreCounter() {
1500 | return guiStoreNextId;
1501 | }
1502 |
1503 | public void setGuiStoreCounter(int value) {
1504 | guiStoreNextId = value;
1505 | }
1506 |
1507 | public IntegerTextField getStoreAddressTF() {
1508 | return memStoreAddrTF;
1509 | }
1510 |
1511 | public IntegerTextField getStoreValueTF() {
1512 | return memStoreValueTF;
1513 | }
1514 |
1515 | public void putIntoMemStore(IntegerTextField tf1, IntegerTextField tf2) {
1516 | memStore.put(tf1, tf2);
1517 | }
1518 |
1519 | public void removeFromMemStore(IntegerTextField tf1, IntegerTextField tf2) {
1520 | memStore.remove(tf1, tf2);
1521 | }
1522 |
1523 | public void putIntoDelStoreBtns(JButton button) {
1524 | delStoreBtns.add(button);
1525 | }
1526 |
1527 | public void removeFromDelStoreBtns(JButton button) {
1528 | delStoreBtns.remove(button);
1529 | }
1530 |
1531 | public void putIntoDelHookBtns(JButton button) {
1532 | delHookBtns.add(button);
1533 | }
1534 |
1535 | public void removeFromDelHookBtns(JButton button) {
1536 | delHookBtns.remove(button);
1537 | }
1538 |
1539 | public ImageIcon getDeleteIcon() {
1540 | return deleteIcon;
1541 | }
1542 |
1543 | public ImageIcon getAddIcon() {
1544 | return addIcon;
1545 | }
1546 |
1547 | public void putIntoHooks(String[] options, String[][] regs) {
1548 | hooks.put(options, regs);
1549 | }
1550 |
1551 | public void removeFromHooks(String[] options, String[][] regs) {
1552 | hooks.remove(options, regs);
1553 | }
1554 |
1555 | public void putIntoLbHooks(JLabel label) {
1556 | lbHooks.add(label);
1557 | }
1558 |
1559 | public void removeFromLbHooks(JLabel label) {
1560 | lbHooks.remove(label);
1561 | }
1562 |
1563 | public Boolean getIsTerminated() {
1564 | return isTerminated;
1565 | }
1566 |
1567 | public void setIsTerminated(Boolean value) {
1568 | isTerminated = value;
1569 | }
1570 |
1571 | public JLabel getStatusLabel() {
1572 | return statusLabel;
1573 | }
1574 |
1575 | public JLabel getStatusLabelFound() {
1576 | return statusLabelFound;
1577 | }
1578 |
1579 | public JScrollPane getScrollSolutionTextArea() {
1580 | return scrollSolutionTextArea;
1581 | }
1582 |
1583 | public JTextArea getSolutionTextArea() {
1584 | return solutionTextArea;
1585 | }
1586 |
1587 | public void setProgram(Program program) {
1588 | if (program != null) {
1589 | thisProgram = program;
1590 | }
1591 | }
1592 |
1593 | public void setHookWindowState(boolean value) {
1594 | isHookWindowClosed = value;
1595 | }
1596 |
1597 | public boolean getHookWindowState() {
1598 | return isHookWindowClosed;
1599 | }
1600 |
1601 | @Override
1602 | public JComponent getComponent() {
1603 | return mainPanel;
1604 | }
1605 | }
1606 |
--------------------------------------------------------------------------------
/src/main/java/angryghidra/HookHandler.java:
--------------------------------------------------------------------------------
1 | package angryghidra;
2 |
3 | import java.awt.Dimension;
4 | import java.awt.EventQueue;
5 | import java.awt.Font;
6 | import java.awt.GridBagConstraints;
7 | import java.awt.GridBagLayout;
8 | import java.awt.Insets;
9 | import java.awt.event.ActionEvent;
10 | import java.awt.event.ActionListener;
11 | import java.awt.event.WindowAdapter;
12 | import java.awt.event.WindowEvent;
13 | import java.util.ArrayList;
14 | import java.util.HashMap;
15 | import java.util.Map.Entry;
16 | import javax.swing.GroupLayout;
17 | import javax.swing.GroupLayout.Alignment;
18 | import javax.swing.JButton;
19 | import javax.swing.JFrame;
20 | import javax.swing.JLabel;
21 | import javax.swing.JPanel;
22 | import javax.swing.JTextField;
23 | import javax.swing.LayoutStyle.ComponentPlacement;
24 | import javax.swing.WindowConstants;
25 | import javax.swing.border.Border;
26 | import docking.widgets.textfield.IntegerTextField;
27 | import resources.ResourceManager;
28 |
29 | public class HookHandler {
30 | private AngryGhidraProvider mProvider;
31 | private int hookNextId;
32 | private int hookRegNextId;
33 | private JFrame frame;
34 | private JPanel regPanel;
35 | private IntegerTextField addressTF;
36 | private JTextField hookRegTF;
37 | private JTextField hookValTF;
38 | private HashMap regsVals;
39 | private ArrayList delButtons;
40 | private IntegerTextField lengthTF;
41 |
42 | public HookHandler(AngryGhidraProvider provider) {
43 | mProvider = provider;
44 | }
45 |
46 | public void main() {
47 | EventQueue.invokeLater(new Runnable() {
48 | public void run() {
49 | try {
50 | showWindow();
51 | } catch (Exception e) {
52 | e.printStackTrace();
53 | }
54 | }
55 | });
56 | }
57 |
58 | private void showWindow() {
59 | setFields();
60 | initializeGui();
61 | frame.setVisible(true);
62 | }
63 |
64 | private void setFields() {
65 | hookNextId = 2;
66 | hookRegNextId = 2;
67 | delButtons = new ArrayList ();
68 | regsVals = new HashMap<>();
69 | }
70 |
71 | private void initializeGui() {
72 | frame = new JFrame();
73 | frame.getContentPane().setMinimumSize(new Dimension(500, 333));
74 | frame.setTitle("Add hook");
75 | frame.setMinimumSize(new Dimension(500, 333));
76 | frame.setLocationRelativeTo(null);
77 | frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
78 | frame.setIconImage(ResourceManager.loadImage("images/ico.png").getImage());
79 | frame.addWindowListener(new WindowAdapter() {
80 | @Override
81 | public void windowClosing(WindowEvent e) {
82 | mProvider.setHookWindowState(true);
83 | }
84 | });
85 |
86 | addressTF = new IntegerTextField();
87 | Border border = addressTF.getComponent().getBorder();
88 | addressTF.setHexMode();
89 | GridBagConstraints gbc_addressTF = new GridBagConstraints();
90 | gbc_addressTF.anchor = GridBagConstraints.CENTER;
91 | gbc_addressTF.fill = GridBagConstraints.HORIZONTAL;
92 | gbc_addressTF.gridx = 0;
93 | gbc_addressTF.gridy = 1;
94 |
95 | Font sansSerif = new Font("SansSerif", Font.PLAIN, 12);
96 | JPanel hookLablesPanel = mProvider.getHookLablesPanel();
97 | JButton btnCreate = new JButton("Add");
98 | btnCreate.setFont(sansSerif);
99 | btnCreate.addActionListener(new ActionListener() {
100 | public void actionPerformed(ActionEvent e) {
101 | if (!addressTF.getText().isEmpty() && !lengthTF.getText().isEmpty()) {
102 | String[] options = new String[2];
103 | options[0] = addressTF.getText();
104 | options[1] = lengthTF.getText();
105 | String[][] regs = new String[2][regsVals.size() + 1];
106 |
107 | String reg1 = hookRegTF.getText();
108 | String val1 = hookValTF.getText();
109 | int id = 0;
110 | if (mProvider.symbolicVectorInputCheck(reg1, val1)) {
111 | regs[0][id] = reg1;
112 | regs[1][id++] = val1;
113 | for (Entry entry : regsVals.entrySet()) {
114 | String reg = entry.getKey().getText();
115 | String val = entry.getValue().getText();
116 | if (mProvider.symbolicVectorInputCheck(reg, val)) {
117 | regs[0][id] = reg;
118 | regs[1][id] = val;
119 | }
120 | id++;
121 | }
122 | mProvider.putIntoHooks(options, regs);
123 | JLabel lbHook = new JLabel("Hook at " + addressTF.getText());
124 | lbHook.setFont(sansSerif);
125 | GridBagConstraints gbc_lbHook = new GridBagConstraints();
126 | gbc_lbHook.fill = GridBagConstraints.HORIZONTAL;
127 | gbc_lbHook.anchor = GridBagConstraints.CENTER;
128 | gbc_lbHook.gridwidth = 3;
129 | gbc_lbHook.gridx = 1;
130 | gbc_lbHook.insets = new Insets(0, 0, 0, 5);
131 | gbc_lbHook.gridy = hookNextId;
132 | gbc_lbHook.weightx = 1;
133 | gbc_lbHook.weighty = 0.1;
134 | hookLablesPanel.add(lbHook, gbc_lbHook);
135 | mProvider.putIntoLbHooks(lbHook);
136 |
137 | JButton btnDel = new JButton("");
138 | btnDel.setBorder(null);
139 | btnDel.setContentAreaFilled(false);
140 | btnDel.setIcon(mProvider.getDeleteIcon());
141 | GridBagConstraints gbc_btnDel = new GridBagConstraints();
142 | gbc_btnDel.insets = new Insets(0, 0, 0, 5);
143 | gbc_btnDel.fill = GridBagConstraints.HORIZONTAL;
144 | gbc_btnDel.anchor = GridBagConstraints.CENTER;
145 | gbc_btnDel.gridx = 0;
146 | gbc_btnDel.gridy = hookNextId++;
147 | gbc_btnDel.weighty = 0.1;
148 | hookLablesPanel.add(btnDel, gbc_btnDel);
149 | mProvider.putIntoDelHookBtns(btnDel);
150 | btnDel.addActionListener(new ActionListener() {
151 | public void actionPerformed(ActionEvent actionEvent) {
152 | hookNextId--;
153 | mProvider.removeFromHooks(options, regs);
154 | mProvider.removeFromDelHookBtns(btnDel);
155 | mProvider.removeFromLbHooks(lbHook);
156 | hookLablesPanel.remove(lbHook);
157 | hookLablesPanel.remove(btnDel);
158 | hookLablesPanel.repaint();
159 | hookLablesPanel.revalidate();
160 | }
161 | });
162 | hookLablesPanel.repaint();
163 | hookLablesPanel.revalidate();
164 | }
165 | }
166 | }
167 | });
168 | JLabel lbRegisters = new JLabel(mProvider.htmlString);
169 | lbRegisters.setFont(sansSerif);
170 |
171 | regPanel = new JPanel();
172 | GridBagLayout gbl_regPanel = new GridBagLayout();
173 | gbl_regPanel.columnWidths = new int[]{0, 0, 0, 0, 0, 0};
174 | gbl_regPanel.rowHeights = new int[]{0, 0, 0};
175 | gbl_regPanel.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
176 | gbl_regPanel.rowWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
177 | regPanel.setLayout(gbl_regPanel);
178 |
179 | JLabel lblReg = new JLabel("Register");
180 | lblReg.setFont(sansSerif);
181 | GridBagConstraints gbc_lblReg = new GridBagConstraints();
182 | gbc_lblReg.anchor = GridBagConstraints.SOUTH;
183 | gbc_lblReg.insets = new Insets(0, 0, 0, 5);
184 | gbc_lblReg.gridx = 1;
185 | gbc_lblReg.gridy = 0;
186 | gbc_lblReg.weightx = 1;
187 | regPanel.add(lblReg, gbc_lblReg);
188 |
189 | JLabel lblValue = new JLabel(" Value ");
190 | lblValue.setFont(sansSerif);
191 | GridBagConstraints gbc_lblValue = new GridBagConstraints();
192 | gbc_lblValue.anchor = GridBagConstraints.SOUTH;
193 | gbc_lblValue.insets = new Insets(0, 0, 0, 5);
194 | gbc_lblValue.gridx = 3;
195 | gbc_lblValue.gridy = 0;
196 | gbc_lblValue.weightx = 1;
197 | regPanel.add(lblValue, gbc_lblValue);
198 |
199 | JButton btnAddButton = new JButton("");
200 | GridBagConstraints gbc_btnAddButton = new GridBagConstraints();
201 | gbc_btnAddButton.anchor = GridBagConstraints.CENTER;
202 | gbc_btnAddButton.fill = GridBagConstraints.HORIZONTAL;
203 | gbc_btnAddButton.insets = new Insets(0, 0, 0, 5);
204 | gbc_btnAddButton.gridx = 0;
205 | gbc_btnAddButton.gridy = 1;
206 | gbc_btnAddButton.weighty = 0.1;
207 | regPanel.add(btnAddButton, gbc_btnAddButton);
208 | btnAddButton.setBorder(null);
209 | btnAddButton.setContentAreaFilled(false);
210 | btnAddButton.setIcon(mProvider.getAddIcon());
211 |
212 | hookRegTF = new JTextField();
213 | hookRegTF.setBorder(border);
214 | hookRegTF.setColumns(5);
215 | GridBagConstraints gbc_TFReg1 = new GridBagConstraints();
216 | gbc_TFReg1.anchor = GridBagConstraints.CENTER;
217 | gbc_TFReg1.fill = GridBagConstraints.HORIZONTAL;
218 | gbc_TFReg1.insets = new Insets(0, 0, 0, 5);
219 | gbc_TFReg1.gridx = 1;
220 | gbc_TFReg1.gridy = 1;
221 | gbc_TFReg1.weighty = 0.1;
222 | regPanel.add(hookRegTF, gbc_TFReg1);
223 | hookRegTF.setBorder(border);
224 |
225 | hookValTF = new JTextField();
226 | hookValTF.setBorder(border);
227 | hookValTF.setColumns(5);
228 | GridBagConstraints gbc_TFVal1 = new GridBagConstraints();
229 | gbc_TFVal1.insets = new Insets(0, 0, 0, 5);
230 | gbc_TFVal1.anchor = GridBagConstraints.CENTER;
231 | gbc_TFVal1.fill = GridBagConstraints.HORIZONTAL;
232 | gbc_TFVal1.gridx = 3;
233 | gbc_TFVal1.gridy = 1;
234 | gbc_TFVal1.weightx = 1;
235 | gbc_TFVal1.weighty = 0.1;
236 | regPanel.add(hookValTF, gbc_TFVal1);
237 |
238 | btnAddButton.addActionListener(new ActionListener() {
239 | public void actionPerformed(ActionEvent e) {
240 | JTextField regTF = new JTextField();
241 | regTF.setBorder(border);
242 | regTF.setColumns(5);
243 | GridBagConstraints gbc_TFReg = new GridBagConstraints();
244 | gbc_TFReg.fill = GridBagConstraints.HORIZONTAL;
245 | gbc_TFReg.anchor = GridBagConstraints.CENTER;
246 | gbc_TFReg.gridx = 1;
247 | gbc_TFReg.insets = new Insets(0, 0, 0, 5);
248 | gbc_TFReg.gridy = hookRegNextId;
249 | gbc_TFReg.weightx = 1;
250 | gbc_TFReg.weighty = 0.1;
251 | regPanel.add(regTF, gbc_TFReg);
252 |
253 | JTextField valTF = new JTextField();
254 | valTF.setColumns(5);
255 | valTF.setBorder(border);
256 | GridBagConstraints gbc_TFVal = new GridBagConstraints();
257 | gbc_TFVal.fill = GridBagConstraints.HORIZONTAL;
258 | gbc_TFVal.anchor = GridBagConstraints.CENTER;
259 | gbc_TFVal.insets = new Insets(0, 0, 0, 5);
260 | gbc_TFVal.gridx = 3;
261 | gbc_TFVal.gridy = hookRegNextId;
262 | gbc_TFVal.weightx = 1;
263 | gbc_TFVal.weighty = 0.1;
264 | regPanel.add(valTF, gbc_TFVal);
265 | regsVals.put(regTF, valTF);
266 |
267 | JButton btnDel = new JButton("");
268 | btnDel.setBorder(null);
269 | btnDel.setContentAreaFilled(false);
270 | btnDel.setIcon(mProvider.getDeleteIcon());
271 | GridBagConstraints gbc_btnDel = new GridBagConstraints();
272 | gbc_btnDel.insets = new Insets(0, 0, 0, 5);
273 | gbc_btnDel.fill = GridBagConstraints.HORIZONTAL;
274 | gbc_btnDel.anchor = GridBagConstraints.CENTER;
275 | gbc_btnDel.gridx = 0;
276 | gbc_btnDel.gridy = hookRegNextId++;
277 | gbc_btnDel.weighty = 0.1;
278 | regPanel.add(btnDel, gbc_btnDel);
279 | delButtons.add(btnDel);
280 | btnDel.addActionListener(new ActionListener() {
281 | public void actionPerformed(ActionEvent actionEvent) {
282 | hookRegNextId--;
283 | delButtons.remove(btnDel);
284 | regsVals.remove(regTF, valTF);
285 | regPanel.remove(regTF);
286 | regPanel.remove(valTF);
287 | regPanel.remove(btnDel);
288 | regPanel.repaint();
289 | regPanel.revalidate();
290 | frame.setSize(frame.getWidth(), frame.getHeight() - 25);
291 | }
292 | });
293 | regPanel.repaint();
294 | regPanel.revalidate();
295 | frame.setSize(frame.getWidth(), frame.getHeight() + 25);
296 | }
297 | });
298 |
299 | JPanel AddrPanel = new JPanel();
300 | GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
301 | groupLayout.setHorizontalGroup(
302 | groupLayout.createParallelGroup(Alignment.TRAILING)
303 | .addGroup(groupLayout.createSequentialGroup()
304 | .addGap(18)
305 | .addComponent(AddrPanel, GroupLayout.DEFAULT_SIZE, 129, Short.MAX_VALUE)
306 | .addGap(39)
307 | .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
308 | .addComponent(regPanel, GroupLayout.DEFAULT_SIZE, 238, Short.MAX_VALUE)
309 | .addComponent(lbRegisters, GroupLayout.DEFAULT_SIZE, 238, Short.MAX_VALUE))
310 | .addContainerGap())
311 | .addGroup(groupLayout.createSequentialGroup()
312 | .addGap(129)
313 | .addComponent(btnCreate, GroupLayout.DEFAULT_SIZE, 184, Short.MAX_VALUE)
314 | .addGap(121))
315 | );
316 | groupLayout.setVerticalGroup(
317 | groupLayout.createParallelGroup(Alignment.LEADING)
318 | .addGroup(groupLayout.createSequentialGroup()
319 | .addGap(20)
320 | .addGroup(groupLayout.createParallelGroup(Alignment.LEADING, false)
321 | .addGroup(groupLayout.createSequentialGroup()
322 | .addComponent(lbRegisters, GroupLayout.PREFERRED_SIZE, 47, GroupLayout.PREFERRED_SIZE)
323 | .addPreferredGap(ComponentPlacement.UNRELATED)
324 | .addComponent(regPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
325 | .addComponent(AddrPanel, 0, 0, Short.MAX_VALUE))
326 | .addPreferredGap(ComponentPlacement.RELATED, 130, Short.MAX_VALUE)
327 | .addComponent(btnCreate)
328 | .addGap(27))
329 | );
330 | GridBagLayout gbl_AddrPanel = new GridBagLayout();
331 | gbl_AddrPanel.columnWidths = new int[]{0, 0};
332 | gbl_AddrPanel.rowHeights = new int[]{0, 0, 0, 0, 0};
333 | gbl_AddrPanel.columnWeights = new double[]{1.0, Double.MIN_VALUE};
334 | gbl_AddrPanel.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
335 | AddrPanel.setLayout(gbl_AddrPanel);
336 |
337 | JLabel lbAddress = new JLabel("Hook address:");
338 | lbAddress.setFont(sansSerif);
339 | GridBagConstraints gbc_lbAddress = new GridBagConstraints();
340 | gbc_lbAddress.anchor = GridBagConstraints.SOUTH;
341 | gbc_lbAddress.insets = new Insets(0, 0, 5, 5);
342 | gbc_lbAddress.gridx = 0;
343 | gbc_lbAddress.gridy = 0;
344 | AddrPanel.add(lbAddress, gbc_lbAddress);
345 |
346 | addressTF = new IntegerTextField();
347 | addressTF.setHexMode();
348 | GridBagConstraints gbc_AddrPanel = new GridBagConstraints();
349 | gbc_AddrPanel.fill = GridBagConstraints.HORIZONTAL;
350 | gbc_AddrPanel.gridx = 0;
351 | gbc_AddrPanel.gridy = 1;
352 | AddrPanel.add(addressTF.getComponent(), gbc_AddrPanel);
353 |
354 | JLabel lblHookLength = new JLabel("Hook length:");
355 | lblHookLength.setFont(sansSerif);
356 | GridBagConstraints gbc_lblHookLength = new GridBagConstraints();
357 | gbc_lblHookLength.anchor = GridBagConstraints.SOUTH;
358 | gbc_lblHookLength.insets = new Insets(0, 0, 5, 5);
359 | gbc_lblHookLength.gridx = 0;
360 | gbc_lblHookLength.gridy = 2;
361 | AddrPanel.add(lblHookLength, gbc_lblHookLength);
362 |
363 | lengthTF = new IntegerTextField();
364 | lengthTF.setDecimalMode();
365 | GridBagConstraints gbc_lengthTF = new GridBagConstraints();
366 | gbc_lengthTF.fill = GridBagConstraints.HORIZONTAL;
367 | gbc_lengthTF.gridx = 0;
368 | gbc_lengthTF.gridy = 3;
369 | AddrPanel.add(lengthTF.getComponent(), gbc_lengthTF);
370 | frame.getContentPane().setLayout(groupLayout);
371 | }
372 |
373 | public void requestClearHooks() {
374 | hookNextId = 2;
375 | hookRegNextId = 2;
376 | if (regPanel == null) {
377 | return;
378 | }
379 | if (delButtons != null){
380 | for (JButton button : delButtons) {
381 | regPanel.remove(button);
382 | }
383 | delButtons.clear();
384 | }
385 | if (regsVals != null){
386 | for (Entry entry : regsVals.entrySet()) {
387 | regPanel.remove(entry.getKey());
388 | regPanel.remove(entry.getValue());
389 | }
390 | regsVals.clear();
391 | }
392 | regPanel.repaint();
393 | regPanel.revalidate();
394 | }
395 |
396 | public void toFront() {
397 | frame.toFront();
398 | }
399 | }
400 |
--------------------------------------------------------------------------------
/src/main/java/angryghidra/LocalColorizingService.java:
--------------------------------------------------------------------------------
1 | package angryghidra;
2 |
3 | import java.awt.Color;
4 | import ghidra.framework.plugintool.PluginTool;
5 | import ghidra.program.model.address.Address;
6 | import ghidra.program.model.listing.Program;
7 | import ghidra.app.plugin.core.colorizer.ColorizingService;
8 |
9 | public class LocalColorizingService {
10 | private ColorizingService mCService;
11 | private Program mProgram;
12 |
13 | public LocalColorizingService(PluginTool tool, Program program) {
14 | mCService = tool.getService(ColorizingService.class);
15 | mProgram = program;
16 | }
17 |
18 | public void resetColor(Address address) {
19 | int TransactionID = mProgram.startTransaction("resetColor");
20 | mCService.clearBackgroundColor(address, address);
21 | mProgram.endTransaction(TransactionID, true);
22 | }
23 |
24 | public void setColor(Address address, Color color) {
25 | int TransactionID = mProgram.startTransaction("setColor");
26 | mCService.setBackgroundColor(address, address, color);
27 | mProgram.endTransaction(TransactionID, true);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/angryghidra/UserAddressStorage.java:
--------------------------------------------------------------------------------
1 | package angryghidra;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import ghidra.program.model.address.Address;
6 |
7 | public class UserAddressStorage {
8 | private Address currentDestAddr;
9 | private Address currentBlankStateAddr;
10 | private List currentAvoidAddresses;
11 |
12 | public UserAddressStorage() {
13 | currentDestAddr = null;
14 | currentBlankStateAddr = null;
15 | currentAvoidAddresses = new ArrayList ();
16 | }
17 |
18 | public Address getDestinationAddress() {
19 | return currentDestAddr;
20 | }
21 |
22 | public Address getBlankStateAddress() {
23 | return currentBlankStateAddr;
24 | }
25 |
26 | public List getAvoidAddresses() {
27 | return currentAvoidAddresses;
28 | }
29 |
30 | public Address getAvoidAddress(int index) {
31 | return currentAvoidAddresses.get(index);
32 | }
33 |
34 | public void setDestinationAddress(Address address) {
35 | currentDestAddr = address;
36 | }
37 |
38 | public void setBlankStateAddress(Address address) {
39 | currentBlankStateAddr = address;
40 | }
41 |
42 | public void setAvoidAddresses(List addresses) {
43 | currentAvoidAddresses = addresses;
44 | }
45 |
46 | public void addAvoidAddress(Address address) {
47 | currentAvoidAddresses.add(address);
48 | }
49 |
50 | public void removeAvoidAddress(Address address) {
51 | currentAvoidAddresses.remove(address);
52 | }
53 |
54 | public void removeAvoidAddress(int index) {
55 | currentAvoidAddresses.remove(index);
56 | }
57 |
58 | public void clearAvoidAddresses() {
59 | currentAvoidAddresses.clear();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/resources/images/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/src/main/resources/images/add.png
--------------------------------------------------------------------------------
/src/main/resources/images/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/src/main/resources/images/delete.png
--------------------------------------------------------------------------------
/src/main/resources/images/flag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/src/main/resources/images/flag.png
--------------------------------------------------------------------------------
/src/main/resources/images/ico.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/src/main/resources/images/ico.png
--------------------------------------------------------------------------------
/src/main/resources/images/reset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/src/main/resources/images/reset.png
--------------------------------------------------------------------------------
/src/main/resources/images/stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nalen98/AngryGhidra/0e6dc9c695de654367fbc0d9cd123a86791bff4d/src/main/resources/images/stop.png
--------------------------------------------------------------------------------