Skip to content

Commit 32f6239

Browse files
committed
add(ui), fix(exporter), misc: Add actual UI, fix exporter not knowing of overloads, and a buch of other bug fixes and stuff
1 parent 3bcd7b8 commit 32f6239

19 files changed

+1670
-501
lines changed

BromaIDA.py

Lines changed: 76 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
VERSION = "5.7.0"
1+
# flake8-in-file-ignores: noqa: E402
2+
VERSION = "6.0.0"
23
__AUTHOR__ = "SpaghettDev"
34

45
PLUGIN_NAME = "BromaIDA"
@@ -8,93 +9,109 @@
89
from idaapi import (
910
msg as ida_msg, register_action, unregister_action,
1011
plugin_t as ida_plugin_t, action_desc_t as ida_action_desc_t,
11-
PLUGIN_PROC, PLUGIN_HIDE, PLUGIN_KEEP
12+
PLUGIN_PROC, PLUGIN_KEEP
1213
)
13-
from ida_kernwin import ask_file, ASKBTN_BTN1, ASKBTN_BTN2
14+
from ida_kernwin import ask_file
1415
from idautils import Names
1516

1617
from broma_ida.utils import (
17-
popup, stop, get_platform, get_platform_printable
18+
stop, get_ida_path, get_platform, get_platform_printable, path_exists
1819
)
1920
from broma_ida.broma.importer import BromaImporter
2021
from broma_ida.broma.exporter import BromaExporter
2122
from broma_ida.ida_ctx_entry import IDACtxEntry
2223

24+
from broma_ida.data.data_manager import DataManager
2325

24-
def bida_main():
25-
"""BromaIDA main entrypoint"""
26-
import_export_prompt = popup(
27-
"Import", "Export", "",
28-
"Import or Export Broma file?\n"
29-
)
26+
from broma_ida.ui.simple_popup import SimplePopup
27+
from broma_ida.ui.main_form import MainForm
3028

31-
if import_export_prompt == ASKBTN_BTN1:
32-
filePath: str = ask_file(False, "GeometryDash.bro", "bro")
3329

34-
if filePath is None or (filePath and not filePath.endswith(".bro")):
35-
popup("Ok", "Ok", None, "Please select a valid file!")
36-
stop()
30+
def on_import(form: MainForm, code: int = 0):
31+
form.Close(1)
3732

38-
platform = get_platform()
39-
broma_importer = BromaImporter(platform)
33+
file_path: str = ask_file(False, "GeometryDash.bro", "bro")
4034

41-
try:
42-
with open(filePath, "r") as f:
43-
broma_importer.parse_file_stream(f)
44-
except FileNotFoundError:
45-
popup("Ok", "Ok", None, "File doesn't exist? Please try again.")
46-
stop()
35+
if not path_exists(file_path, ".bro"):
36+
SimplePopup("Please select a valid file!", "Cancel").show()
37+
stop()
4738

48-
broma_importer.import_into_idb()
39+
platform = get_platform()
40+
broma_importer = BromaImporter(platform, file_path)
41+
broma_importer.parse_file()
42+
broma_importer.import_into_idb()
4943

50-
print("[+] BromaIDA: Finished importing bindings from Broma file")
51-
popup(
52-
"Ok", "Ok", None,
53-
"Finished importing "
54-
f"{get_platform_printable(platform)} "
55-
"bindings from Broma file."
56-
)
44+
print("[+] BromaIDA: Finished importing bindings from Broma file")
45+
SimplePopup(
46+
"Finished importing "
47+
f"{get_platform_printable(platform)} "
48+
"bindings from Broma file.",
49+
"OK"
50+
).show()
5751

58-
elif import_export_prompt == ASKBTN_BTN2:
59-
platform = get_platform()
52+
DataManager().close()
6053

61-
if platform.startswith("android"):
62-
popup(
63-
"Ok", "Ok", None,
64-
"Cannot export bindings from Android binary!"
65-
)
66-
stop()
6754

68-
# for_saving is not True because we need to read the file first
69-
# which may not even exist if the saving prompt is used
70-
# (since you can select files that don't exist within said prompt)
71-
filePath = ask_file(False, "GeometryDash.bro", "bro")
55+
def on_export(form: MainForm, code: int = 0):
56+
form.Close(1)
7257

73-
if filePath is None or (filePath and not filePath.endswith(".bro")):
74-
popup("Ok", "Ok", None, "Please select a valid file!")
75-
stop()
58+
platform = get_platform()
7659

77-
broma_exporter = BromaExporter(platform, filePath)
60+
if platform.startswith("android"):
61+
SimplePopup(
62+
"Cannot export bindings from Android binary!", "Cancel"
63+
).show()
64+
stop()
7865

79-
broma_exporter.import_from_idb(Names())
80-
broma_exporter.export()
66+
# for_saving is not True because we need to read the file first
67+
# which may not even exist if the saving prompt is used
68+
# (since you can select files that don't exist within said prompt)
69+
file_path: str = ask_file(False, "GeometryDash.bro", "bro")
8170

82-
print(
83-
"[+] BromaIDA: Finished exporting "
84-
f"{broma_exporter.num_exports} bindings."
85-
)
86-
popup("Ok", "Ok", None, "Finished exporting bindings to Broma file.")
71+
if not path_exists(file_path, ".bro"):
72+
SimplePopup("Please select a valid file!", "Cancel").show()
73+
stop()
74+
75+
broma_exporter = BromaExporter(platform, file_path)
76+
77+
broma_exporter.import_from_idb(Names())
78+
broma_exporter.export()
79+
80+
print(
81+
"[+] BromaIDA: Finished exporting "
82+
f"{broma_exporter.num_exports} bindings, "
83+
f"{broma_exporter.num_ret_exports} return types and "
84+
f"{broma_exporter.num_args_names_exports} argument names."
85+
)
86+
SimplePopup("Finished exporting bindings to Broma file.", "OK").show()
87+
88+
DataManager().close()
89+
90+
91+
def bida_main():
92+
"""BromaIDA main entrypoint"""
93+
DataManager().init(get_ida_path("plugins") / "broma_ida" / "shelf")
94+
95+
form_code = MainForm(
96+
VERSION,
97+
get_platform_printable(get_platform()),
98+
on_import,
99+
on_export
100+
).show()
101+
102+
# cancel
103+
if form_code == 0:
104+
DataManager().close()
87105

88106

89107
class BromaIDAPlugin(ida_plugin_t):
90108
"""BromaIDA Plugin"""
91-
flags = PLUGIN_PROC | PLUGIN_HIDE
109+
flags = PLUGIN_PROC
92110
comment = "Broma support for IDA."
93111
help = f"{PLUGIN_HOTKEY} to start the importing/exporting."
94112
wanted_name = PLUGIN_NAME
95-
wanted_hotkey = PLUGIN_HOTKEY
96113

97-
ACTION_BTIDA = "btida:run_btida"
114+
ACTION_BTIDA = "bida:run_bida"
98115
ACTION_DESC = "Launches the BromaIDA plugin."
99116

100117
def init(self):
@@ -111,7 +128,8 @@ def term(self):
111128
ida_msg(f"{PLUGIN_NAME} v{VERSION} unloaded\n")
112129

113130
def run(self, arg):
114-
"""Ran on "File -> Script File" (shocker) (broken for me :D)"""
131+
"""Ran on "File -> Script File" (shocker)
132+
(does not work because this plugin has multiple py files)"""
115133
bida_main()
116134

117135
def _register_action(self):

README.md

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,51 +10,89 @@ Parses a Broma file and exports the bindings into a Broma file/imports the bindi
1010

1111
- IDA 7.0 or higher
1212
- IDAPython
13-
- Python v3.0.0+ (tested with v3.11.9)
13+
- Python v3.10.0+ (tested with v3.11.9)
1414
- PyBroma
1515
- If you want to be able to import types:
1616
- IDAClang
17-
- MSVC STL headers if reversing Windows binary, GCC STL headers for the other platforms
17+
- STL Headers (see [Importing Types Requirements](#importing-types-requirements))
1818

1919
## Features
2020

21-
- Import method names, return type and arguments
22-
- Export method addresses
23-
- Import types (see [Importing Types Requirements](#importing-types-requirements))
24-
- On Android binaries, fixes IDA completely messing up the arguments of functions for no reason
21+
- Importing
22+
- Import function names
23+
- Import types (see [Importing Types Requirements](#importing-types-requirements)). If enabled, will do the following:
24+
- Import Broma classes members, virtual functions, etc...
25+
- Import function return types
26+
- Import function arguments types and names
27+
- On Android binaries, fixes IDA completely messing up the arguments of functions for no reason
28+
- Exporting
29+
- Export function addresses for any platform
30+
- Export function return types (if enabled, see [BromaIDA Settings](#bromaida-settings))
31+
- Export function arguments' names (if enabled, see [BromaIDA Settings](#bromaida-settings))
2532

2633
## Installation
2734

2835
1. Get python, then `git clone https://github.com/CallocGD/PyBroma --recursive`, `cd PyBroma` then finally `python .\setup.py install` to install PyBroma (blame CallocGD for breaking `pip install https://github.com/CallocGD/PyBroma/archive/refs/heads/main.zip`)
29-
1. Download the release/zip file
30-
2. Copy `BromaIDA.py` and the `broma_ida` folder into `IDA_DIRECTORY/plugins`
36+
2. Download the release/zip file
37+
3. Copy `BromaIDA.py` and the `broma_ida` folder into `IDA_DIRECTORY/plugins`
3138

3239
## Usage
3340

34-
1. `Ctrl-Shift-B` to start importing/exporting
35-
2. Browse and select the broma file (must have Extras.bro in the same directory if you want to import types)
41+
1. `Ctrl-Shift-B`, or from the Top Bar (Edit -> Plugins -> BromaIDA) to start importing/exporting
42+
2. Browse and select the Broma file
3643
3. Let the script handle the rest and enjoy free/exported bindings
3744

3845
## Importing Types Requirements
3946

40-
To import types, you must have IDAClang and the headers for the target platform. Currently only tested with Windows and Android.
41-
1. Open the target binary in IDA
42-
2. In the top bar, select Options > Compiler, Source Parser: Clang. And in Include Directories, replace with the location of the header files
43-
1. For Windows binary
44-
1. Get MSVC Headers by installing MSVC using [Visual Studio Installer](https://visualstudio.microsoft.com/downloads)
45-
2. Set the Include Directories to `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include`
46-
2. For Android binaries (Android 64 and 32 bit)
47-
1. First get gcc-arm-none-linux-gnueabihf (i did so by using scoop; `scoop install extras/gcc-arm-none-linux-gnueabihf`)
48-
2. Then, in the Include Directories, set it to `C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\arm-none-linux-gnueabihf\include\c++\13.3.1;C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\arm-none-linux-gnueabihf\include\c++\13.3.1\arm-none-linux-gnueabihf;C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\arm-none-linux-gnueabihf\libc\usr\include;C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\lib\gcc\arm-none-linux-gnueabihf\13.3.1\include` (be sure to replace YOUR_NAME with your windows username)
49-
3. Or use MSVC headers, but be sure to click "Yes" when prompted to use Custom GNU STL!
50-
3. For MacOS (Intel and M1 Mac) and iOS binaries
51-
1. First get gcc (i did so by using scoop; `scoop install gcc`)
52-
2. Then, in the Include Directories, set it to `C:\Users\YOUR_NAME\scoop\apps\gcc\current\include\c++\13.2.0;C:\Users\YOUR_NAME\scoop\apps\gcc\current\include\c++\13.2.0\x86_64-w64-mingw32;C:\Users\YOUR_NAME\scoop\apps\gcc\current\x86_64-w64-mingw32\include` (be sure to replace YOUR_NAME with your windows username)
53-
3. Or use MSVC headers, but again, be sure to click "Yes" when prompted to use Custom GNU STL.
54-
3. Click on OK
55-
56-
Start the script and when prompted to import types, click yes, then the types will automatically be imported for you.
47+
- To import types:
48+
- You must have IDAClang.
49+
- You must have the STL headers for the target platform (MSVC headers for Windows binary, GCC headers for the others). You can however use MSVC headers on binaries that aren't Windows (_but not the other way around_).
50+
- Extras.bro **_must_** be in the same directory as the imported Broma file
51+
52+
- Get your STL Headers path (on Windows)
53+
- For Windows binary (or if not using custom GNU STL)
54+
1. Get MSVC Headers by installing MSVC using the [Visual Studio Installer](https://visualstudio.microsoft.com/downloads)
55+
2. Your header path should be `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include`
56+
- For Android binaries (Android 64 and 32 bit)
57+
1. First get gcc-arm-none-linux-gnueabihf (i did so by using scoop; `scoop install extras/gcc-arm-none-linux-gnueabihf`)
58+
2. Your header path should be `C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\arm-none-linux-gnueabihf\include\c++\13.3.1;C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\arm-none-linux-gnueabihf\include\c++\13.3.1\arm-none-linux-gnueabihf;C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\arm-none-linux-gnueabihf\libc\usr\include;C:\Users\YOUR_NAME\scoop\apps\gcc-arm-none-linux-gnueabihf\current\lib\gcc\arm-none-linux-gnueabihf\13.3.1\include` (be sure to replace YOUR_NAME with your windows username)
59+
- For MacOS (Intel and M1 Mac) and iOS binaries
60+
1. First get gcc (i did so by using scoop; `scoop install gcc`)
61+
2. Your header path should be `C:\Users\YOUR_NAME\scoop\apps\gcc\current\include\c++\13.2.0;C:\Users\YOUR_NAME\scoop\apps\gcc\current\include\c++\13.2.0\x86_64-w64-mingw32;C:\Users\YOUR_NAME\scoop\apps\gcc\current\x86_64-w64-mingw32\include` (be sure to replace YOUR_NAME with your windows username)
62+
63+
1. Launch the BromaIDA plugin using Ctrl-Shift-B, or from the Top Bar (Edit -> Plugins -> BromaIDA)
64+
2. Click on the Settings button
65+
3. Follow the steps above to get and get your STL Headers path (be sure to check "Import Types")
66+
- Once you get your STL Header path, paste it in the correct folder input. ("MSVC STL Directory" for MSVC, ...)
67+
- If you **_aren't_** using custom GNU STL, be sure to **uncheck** "Use Custom [Android/Mac] GNU STL".
68+
- If you **_are_** using custom GNU STL, be sure to **check** "Use Custom [Android/Mac] GNU STL", otherwise you won't be able to select the custom GNU STL path.
69+
4. Exit out of the settings window
70+
71+
Start the script and the plugin will handle everything :)
72+
73+
## BromaIDA Settings
74+
75+
Can be accessed through the main popup by clicking on the "Settings" button.
76+
This replaces the old "ask everything everytime" method.
77+
78+
Here you will find some options you can set, such as importing types, settings default parser parameters, etc...
79+
The options you chose will be saved into a [shelf](https://docs.python.org/3/library/shelve.html) stored in the `IDA_DIRECTORY/plugins/broma_ida` folder.
80+
81+
![BromaIDA Settings](assets/settings.png)
82+
83+
## Utilities
84+
85+
This is section is meant for people who want to contribute.
86+
87+
In the `utils` folder, you can find some utilities that can help in contributing.
88+
89+
- Currently has:
90+
- `tasks.json`: To be put in `/BromaIDA/.vscode`, adds 2 tasks for VSCode. "Install Plugin" will copy `BromaIDA.py` and the `broma_ida` to the `IDA_DIRECTORY/plugins` directory; And "Launch IDA v8.3" which will launch IDA (shocker). Just be sure to replace IDA's directory with your IDA installation directory.
5791

5892
## Thanks
5993

60-
Special thanks to [CallocGD](https://github.com/CallocGD)'s [PyBroma](https://github.com/CallocGD/PyBroma) which is used to import bindings from Broma.
94+
- Special thanks to:
95+
- The [IDAPython API](https://hex-rays.com/products/ida/support/idapython_docs): Used for everything.
96+
- [CallocGD](https://github.com/CallocGD)'s [PyBroma](https://github.com/CallocGD/PyBroma): Used to parse imported Broma files.
97+
- @sleepyut: Issuing 3 trillion bug reports. Also for suggesting a bunch of features. (they also made BromaBJ)
98+
- [AngelDev06](https://github.com/AngelDev06): Contributing features.

assets/bida.gif

378 KB
Loading

assets/settings.png

24.8 KB
Loading

0 commit comments

Comments
 (0)