├── .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 | ![AngryGhidra Plugin](./images/AngryPluginDemo.gif) 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 | ![AngryGhidraView](./images/View.png) 31 | 32 | Apply patched bytes to write them into the memory of angr project: 33 | 34 | ![ApplyPatchedBytes](./images/ApplyPatchedBytes.png) 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 --------------------------------------------------------------------------------