Skip to content

Commit cb277a5

Browse files
committed
ending upload binary
1 parent 49d739a commit cb277a5

9 files changed

Lines changed: 202 additions & 115 deletions

File tree

features/configuration/config.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ def __init__(self):
88
self.host = ""
99
self.current_analysis = None
1010
self.is_configured = None
11+
self.binary_id = None
12+
self.analysis_id = None
1113
self._load_config()
1214

1315

@@ -34,11 +36,23 @@ def _load_config(self):
3436
"type" : "string",\
3537
"default" : "False",\
3638
"description" : "Configuration Status"}')
39+
settings.register_setting("revengai.binary_id",
40+
'{"title" : "Binary ID",\
41+
"type" : "string",\
42+
"default" : "",\
43+
"description" : "Current Binary ID"}')
44+
settings.register_setting("revengai.analysis_id",
45+
'{"title" : "Analysis ID",\
46+
"type" : "string",\
47+
"default" : "",\
48+
"description" : "Current Analysis ID"}')
3749

3850
self.host = settings.get_string("revengai.host", None)
3951
self.api_key = settings.get_string("revengai.api_key", None)
4052
self.current_analysis = settings.get_string("revengai.current_analysis", None)
4153
self.is_configured = settings.get_string("revengai.is_configured", None)
54+
self.binary_id = settings.get_integer("revengai.binary_id", None)
55+
self.analysis_id = settings.get_integer("revengai.analysis_id", None)
4256

4357
re_conf["apikey"] = self.api_key
4458
re_conf["host"] = self.host
@@ -71,3 +85,17 @@ def clear_config(self):
7185
self.current_analysis = None
7286
self.is_configured = False
7387
self.save_config()
88+
89+
def set_binary_id(self, binary_id: str):
90+
"""Set the binary ID and store it in settings."""
91+
self.binary_id = binary_id
92+
settings = Settings()
93+
settings.set_integer("revengai.binary_id", self.binary_id)
94+
return
95+
96+
def set_analysis_id(self, analysis_id: str):
97+
"""Set the analysis ID and store it in settings."""
98+
self.analysis_id = analysis_id
99+
settings = Settings()
100+
settings.set_integer("revengai.analysis_id", self.analysis_id)
101+
return

features/configuration/config_dialog.py

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,10 @@
11
from PySide6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel,
22
QLineEdit, QPushButton, QMessageBox, QProgressDialog, QProgressBar)
3-
from PySide6.QtCore import Qt, QThread, Signal
3+
from PySide6.QtCore import Qt
44
from PySide6.QtGui import QPixmap
55
from binaryninja import log_info, log_error, log_warn
66
import os
7-
8-
class ConfigSaveThread(QThread):
9-
finished = Signal(bool, str)
10-
11-
def __init__(self, config, api_key, host):
12-
super().__init__()
13-
self.config = config
14-
self.api_key = api_key
15-
self.host = host
16-
17-
def run(self):
18-
try:
19-
self.config.api_key = self.api_key
20-
self.config.host = self.host
21-
success = self.config.save_config()
22-
23-
if not success:
24-
self.finished.emit(False, "API key not valid or host not reachable.")
25-
else:
26-
self.finished.emit(True, "")
27-
28-
except Exception as e:
29-
self.finished.emit(False, str(e))
7+
from .config_save_thread import ConfigSaveThread
308

319
class ConfigDialog(QDialog):
3210
def __init__(self, config):
@@ -152,18 +130,18 @@ def save_config(self):
152130
self.progress.findChild(QProgressBar).setMinimumWidth(250)
153131
self.progress.findChild(QProgressBar).setMinimumHeight(20)
154132
self.progress.setStyleSheet("""
155-
QProgressBar {
156-
border: 1px solid #cccccc;
157-
border-radius: 4px;
158-
text-align: center;
159-
background-color: #f0f0f0;
160-
min-width: 250px;
161-
min-height: 20px;
162-
}
163-
QProgressBar::chunk {
164-
background-color: #007bff;
165-
border-radius: 3px;
166-
}
133+
QProgressBar {
134+
border: 1px solid #cccccc;
135+
border-radius: 4px;
136+
text-align: center;
137+
background-color: #f0f0f0;
138+
min-width: 250px;
139+
min-height: 20px;
140+
}
141+
QProgressBar::chunk {
142+
background-color: #007bff;
143+
border-radius: 3px;
144+
}
167145
""")
168146

169147
self.save_thread = ConfigSaveThread(self.config, api_key, host)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from PySide6.QtCore import QThread, Signal
2+
3+
class ConfigSaveThread(QThread):
4+
finished = Signal(bool, str)
5+
6+
def __init__(self, config, api_key, host):
7+
super().__init__()
8+
self.config = config
9+
self.api_key = api_key
10+
self.host = host
11+
12+
def run(self):
13+
try:
14+
self.config.api_key = self.api_key
15+
self.config.host = self.host
16+
success = self.config.save_config()
17+
18+
if not success:
19+
self.finished.emit(False, "API key not valid or host not reachable.")
20+
else:
21+
self.finished.emit(True, "")
22+
23+
except Exception as e:
24+
self.finished.emit(False, str(e))

features/upload/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def __init__(self, config=None):
88
super().__init__(config)
99
self.uploader = BinaryUploader(config)
1010
log_info("RevEng.AI | Process Feature initialized")
11-
11+
1212
def register(self):
1313
PluginCommand.register(
1414
"RevEng.AI\\Process Binary",
@@ -17,8 +17,8 @@ def register(self):
1717
self.is_valid
1818
)
1919
log_info("RevEng.AI | Process Feature registered")
20-
20+
2121
def show_upload_dialog(self, bv):
22+
log_info("RevEng.AI | Opening process dialog")
2223
dialog = UploadDialog(self.config, self.uploader, bv)
23-
if dialog.exec() == UploadDialog.Accepted:
24-
self.uploader.upload_binary(bv, dialog.get_upload_options())
24+
dialog.exec()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from PySide6.QtCore import QThread, Signal
2+
from binaryninja import log_error
3+
4+
class ModelLoadThread(QThread):
5+
finished = Signal(list) # Signal emitting the loaded models
6+
error = Signal(str) # Signal for error handling
7+
8+
def __init__(self, uploader, bv):
9+
super().__init__()
10+
self.uploader = uploader
11+
self.bv = bv
12+
13+
def run(self):
14+
try:
15+
models = self.uploader.get_models(self.bv)
16+
self.finished.emit(models)
17+
except Exception as e:
18+
log_error(f"RevEng.AI | Failed to load models: {str(e)}")
19+
self.error.emit(str(e))

features/upload/upload.py

Lines changed: 86 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,105 @@
1-
from binaryninja import BinaryView, log_info, log_error
2-
from reait.api import RE_models
1+
from binaryninja import BinaryView, log_info, log_error, log_debug, SymbolType, BinaryViewType
2+
from reait.api import RE_models, RE_upload, RE_analysis_lookup, RE_analyse
3+
import json
34

45
class BinaryUploader:
56
def __init__(self, config):
67
self.config = config
78

89

9-
def get_models(self):
10+
def get_models(self, bv: BinaryView):
1011
try:
12+
guess_model_platform = ""
13+
if bv.view_type == "PE":
14+
guess_model_platform = "windows"
15+
elif bv.view_type == "ELF":
16+
guess_model_platform = "linux"
17+
elif bv.view_type == "MACHO":
18+
guess_model_platform = "macos"
19+
20+
guess_model_arch = ""
21+
if bv.arch.name == "x86":
22+
guess_model_arch = "x86-32"
23+
elif bv.arch.name == "x86_64":
24+
guess_model_arch = "x86"
25+
else:
26+
guess_model_arch = bv.arch.name
27+
28+
log_info(f"RevEng.AI | Architecture: {bv.arch.name} | File type: {bv.view_type}")
1129
models = RE_models().json()
12-
return set([model["model_name"] for model in models["models"]])
30+
models = list([model["model_name"] for model in models["models"]])
31+
32+
guess_model = f"{guess_model_arch}-{guess_model_platform}"
33+
log_info(f"RevEng.AI | Guess model: {guess_model}")
34+
for i, model in enumerate(models):
35+
if guess_model in model:
36+
log_info(f"RevEng.AI | Found model: {model}")
37+
models.insert(0, models.pop(i))
38+
break
39+
log_info(f"RevEng.AI | Models: {models}")
40+
return models
1341
except Exception as e:
14-
log_error(f"Failed to get models: {str(e)}")
15-
return set()
42+
log_error(f"RevEng.AI | Failed to get models: {str(e)}")
43+
return []
1644

1745

1846
def upload_binary(self, bv: BinaryView, options: dict):
1947
try:
20-
log_info(f"Uploading binary {bv.file.filename} with options: {options}")
21-
log_info(f"Options: {options}")
22-
log_info(f"Binary size: {bv.file}")
23-
self.config.save_config()
48+
log_info(f"RevEng.AI | Uploading binary {bv.file.filename}.")
49+
50+
upload = RE_upload(bv.file.filename).json()
51+
52+
if not upload.get("success", False):
53+
log_error(f"RevEng.AI | Failed to upload binary {bv.file.filename}.")
54+
return False
55+
56+
log_info(f"RevEng.AI | Binary {bv.file.filename} uploaded successfully.")
57+
58+
sha_256_hash = upload["sha_256_hash"]
59+
log_info(f"RevEng.AI | SHA-256 hash: {sha_256_hash}")
2460

25-
# TODO: Implement actual upload logic here
26-
# This will involve:
27-
# 1. Getting the binary data from bv
28-
# 2. Use the RE_upload_binary function to upload the binary
29-
# 3. Handling the response
61+
# Convert symbols to a list of dictionaries with hex strings
62+
symbols = []
63+
log_info(f"RevEng.AI | Image Base: {bv.image_base:x}")
64+
for key, value in bv.symbols.items():
65+
if value[0].type == SymbolType.FunctionSymbol:
66+
func = bv.get_function_at(value[0].address)
67+
symbols.append({
68+
"name": func.name,
69+
"start": func.start,
70+
"end": func.start + func.total_bytes,
71+
})
72+
log_info(f"RevEng.AI | Name: {key} | Start: {func.start:x} | End: {func.start + func.total_bytes:x} | Size: {func.total_bytes}")
73+
74+
# Log all analysis parameters
75+
log_info("RevEng.AI | Analysis parameters:")
76+
log_info(f"RevEng.AI | - File path: {bv.file.filename}")
77+
log_info(f"RevEng.AI | - Binary scope: {'PRIVATE' if options['is_private'] else 'PUBLIC'}")
78+
log_info(f"RevEng.AI | - Debug info path: {options.get('debug_info', None)}")
79+
log_info(f"RevEng.AI | - Model name: {options['model']}")
80+
log_info(f"RevEng.AI | - Tags: {options.get('tags', [])}")
81+
log_info(f"RevEng.AI | - Number of symbols: {len(symbols)}")
82+
83+
analysis = RE_analyse(
84+
fpath=bv.file.filename,
85+
binary_scope= "PRIVATE" if options["is_private"] else "PUBLIC",
86+
model_name=options["model"],
87+
tags=options["tags"],
88+
symbols=symbols
89+
).json()
90+
91+
log_info(f"RevEng.AI | Analysis response: {analysis}")
92+
93+
binary_id = analysis["binary_id"]
94+
analysis_info = RE_analysis_lookup(str(binary_id)).json()
95+
96+
log_info(f"RevEng.AI | Analysis info: {analysis_info}")
3097

31-
log_info(f"Binary {bv.file.filename} uploaded successfully with options: {options}")
98+
self.config.set_binary_id(binary_id)
99+
self.config.set_analysis_id(analysis_info["analysis_id"])
100+
32101
return True
33102

34103
except Exception as e:
35-
log_error(f"Failed to upload binary: {str(e)}")
104+
log_error(f"RevEng.AI | Failed to upload binary: {str(e)}")
36105
return False
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from PySide6.QtCore import QThread, Signal
2+
3+
class UploadBinaryThread(QThread):
4+
finished = Signal(bool, str) # Signal for success/failure and error message
5+
6+
def __init__(self, uploader, bv, options):
7+
super().__init__()
8+
self.uploader = uploader
9+
self.bv = bv
10+
self.options = options
11+
12+
def run(self):
13+
try:
14+
success = self.uploader.upload_binary(self.bv, self.options)
15+
if success:
16+
self.finished.emit(True, "")
17+
else:
18+
self.finished.emit(False, "Duplicate binary or host not reachable.")
19+
except Exception as e:
20+
self.finished.emit(False, str(e))

0 commit comments

Comments
 (0)