reverse-engineering-assistant 2.9.1__tar.gz → 2.9.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/PKG-INFO +76 -35
  2. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/README.md +71 -34
  3. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/pyproject.toml +6 -2
  4. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/__init__.py +91 -0
  5. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant/api_server_tools/connection.py +3 -0
  6. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/llm_tools.py +134 -0
  7. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/re_tool_box/__init__.py +6 -0
  8. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/re_tool_box/bookmarks.py +65 -0
  9. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/re_tool_box/comment.py +65 -0
  10. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/re_tool_box/cross_reference.py +69 -0
  11. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/re_tool_box/cursor.py +45 -0
  12. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/re_tool_box/data.py +154 -0
  13. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/re_tool_box/decompilation.py +204 -0
  14. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/re_tool_box/symbols.py +209 -0
  15. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/api_server_tools/re_tools.py +17 -0
  16. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/assistant.py +503 -0
  17. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant/assistant_api_server.py +66 -15
  18. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/chat_client.py +292 -0
  19. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/crash_dump.py +112 -0
  20. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/model.py +72 -0
  21. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaBookmark_pb2.py +35 -0
  22. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaBookmark_pb2.pyi +33 -0
  23. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaBookmark_pb2_grpc.py +145 -0
  24. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaChat_pb2.py +39 -0
  25. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaChat_pb2.pyi +55 -0
  26. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaChat_pb2_grpc.py +235 -0
  27. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaComment_pb2.py +31 -0
  28. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaComment_pb2.pyi +19 -0
  29. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaComment_pb2_grpc.py +102 -0
  30. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaData_pb2.py +47 -0
  31. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaData_pb2.pyi +94 -0
  32. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaData_pb2_grpc.py +231 -0
  33. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaGetCursor_pb2.py +31 -0
  34. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaGetCursor_pb2.pyi +21 -0
  35. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaGetCursor_pb2_grpc.py +102 -0
  36. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaGetDecompilation_pb2.py +44 -0
  37. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaGetDecompilation_pb2.pyi +83 -0
  38. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaGetDecompilation_pb2_grpc.py +231 -0
  39. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaGetSymbols_pb2.py +47 -0
  40. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaGetSymbols_pb2.pyi +70 -0
  41. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaGetSymbols_pb2_grpc.py +260 -0
  42. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaHandshake_pb2.py +31 -0
  43. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaHandshake_pb2.pyi +21 -0
  44. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaHandshake_pb2_grpc.py +102 -0
  45. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaHeartbeat_pb2.py +31 -0
  46. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaHeartbeat_pb2.pyi +23 -0
  47. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaHeartbeat_pb2_grpc.py +102 -0
  48. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaReferences_pb2.py +31 -0
  49. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaReferences_pb2.pyi +20 -0
  50. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaReferences_pb2_grpc.py +102 -0
  51. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaVariable_pb2.py +27 -0
  52. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaVariable_pb2.pyi +17 -0
  53. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/RevaVariable_pb2_grpc.py +29 -0
  54. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant/protocol/__init__.py +0 -0
  55. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant.egg-info/PKG-INFO +76 -35
  56. reverse_engineering_assistant-2.9.4/reverse_engineering_assistant.egg-info/SOURCES.txt +64 -0
  57. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant.egg-info/requires.txt +4 -0
  58. reverse_engineering_assistant-2.9.1/reverse_engineering_assistant/api_server_tools/__init__.py +0 -16
  59. reverse_engineering_assistant-2.9.1/reverse_engineering_assistant/api_server_tools/llm_tools.py +0 -111
  60. reverse_engineering_assistant-2.9.1/reverse_engineering_assistant/api_server_tools/re_tools.py +0 -354
  61. reverse_engineering_assistant-2.9.1/reverse_engineering_assistant/assistant.py +0 -453
  62. reverse_engineering_assistant-2.9.1/reverse_engineering_assistant/chat_client.py +0 -179
  63. reverse_engineering_assistant-2.9.1/reverse_engineering_assistant/configuration.py +0 -151
  64. reverse_engineering_assistant-2.9.1/reverse_engineering_assistant/model.py +0 -109
  65. reverse_engineering_assistant-2.9.1/reverse_engineering_assistant.egg-info/SOURCES.txt +0 -22
  66. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant/.gitignore +0 -0
  67. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant/__init__.py +0 -0
  68. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant/documents.py +0 -0
  69. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant/reva_exceptions.py +0 -0
  70. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant/tool.py +0 -0
  71. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant.egg-info/dependency_links.txt +0 -0
  72. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant.egg-info/entry_points.txt +0 -0
  73. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/reverse_engineering_assistant.egg-info/top_level.txt +0 -0
  74. {reverse_engineering_assistant-2.9.1 → reverse_engineering_assistant-2.9.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: reverse-engineering-assistant
3
- Version: 2.9.1
3
+ Version: 2.9.4
4
4
  Summary: An AI assistant for reverse engineering tasks
5
5
  Author: サイバーカイダ (cyberkaida)
6
6
  Classifier: License :: OSI Approved :: Apache Software License
@@ -11,6 +11,9 @@ Description-Content-Type: text/markdown
11
11
  Requires-Dist: langchain
12
12
  Requires-Dist: langchain-core
13
13
  Requires-Dist: langchain-openai
14
+ Requires-Dist: langchain-community
15
+ Requires-Dist: langchain-experimental
16
+ Requires-Dist: langgraph
14
17
  Requires-Dist: prompt_toolkit
15
18
  Requires-Dist: sentence_transformers
16
19
  Requires-Dist: PyYAML
@@ -18,6 +21,7 @@ Requires-Dist: pydantic
18
21
  Requires-Dist: rich
19
22
  Requires-Dist: grpcio
20
23
  Requires-Dist: protobuf
24
+ Requires-Dist: flask
21
25
 
22
26
  # ReVA - Reverse Engineering Assistant
23
27
 
@@ -46,13 +50,14 @@ information from the tools, but when there is no information it can still respon
46
50
  questions from its training.
47
51
 
48
52
  You can ask questions like:
53
+ - What are the interesting strings in this program?
49
54
  - Does this program use encryption? Write a markdown report on the encryption and where it is used.
50
55
  - Draw a class diagram using plantuml syntax.
51
56
  - Start from main, examine the program in detail. Rename variables as you go and provide a summary of the program.
52
57
  - Explain the purpose of the `__mod_init` segment.
53
58
  - What does `mmap` return?
54
59
  - What does the function at address 0x80000 do?
55
- - This is a CTF problem. Start at main, examine the program in detail and write a pwntools script to get the flag.
60
+ - This is a CTF problem. Write a pwntools script to get the flag.
56
61
 
57
62
  An important part of reverse engineering is the process. Many other tools simply ask a single question of the LLM,
58
63
  this means it is difficult to determine _why_ a thing happened. In ReVa we break all actions down into small parts
@@ -68,33 +73,40 @@ Built in support is provided for:
68
73
  - [OpenAI](https://platform.openai.com/overview) for online inference and easy setup (Needs an OpenAI API key)
69
74
  - [Ollama](https://ollama.ai) and any model it supports for local on-device inference or connecting to a self hosted remote inference server.
70
75
 
76
+ See [Configuration](#configuration) for more information about settings for the providers.
77
+
71
78
  Adding additional inference servers is easy if it is supported by langchain.
72
79
 
73
80
  ## Configuration
74
81
 
75
- > This is currently being moved to the Ghidra GUI
76
- > See Edit -> Tool Options -> ReVa in the Codebrowser Tool
82
+ Configuration for ReVa is in the CodeBrowser Tool options.
83
+ Open a program and go to Edit -> Tool Options -> ReVa.
84
+
85
+ There are options for:
86
+ - Selecting a provider (OpenAI or Ollama, others coming soon!)
87
+ - Enabling "Follow", this will move the Ghidra view to the location of
88
+ things ReVa is examining or changing.
89
+ - Enabling "Auto-allow", ReVa will log her actions for the user to accept
90
+ in the "ReVa Actions Log" window.
91
+
92
+ There are sections for the providers.
93
+
94
+ ### OpenAI
77
95
 
78
- Configuration for the reverse engineering assistant is stored at
79
- `~/.config/reverse-engineering-assistant/config.yaml`. If this
80
- is not present on first start, a default configuration using
81
- OpenAI for inference and the `OPENAI_API_TOKEN` environment
82
- variable will be used.
96
+ By default, the OpenAI key is loaded from the environment variable `OPENAI_API_KEY`. You can also set your key inside Ghidra. Setting the key back to the `OPENAI_API_KEY` value will clear the key from the Ghidra configuration and load it from the environment.
83
97
 
84
- The most important setting is the `type` top level setting.
85
- This controls what inference service you use. These are the
86
- same as the configuration keys, for example to use Ollama,
87
- set type to `ollama` and configure the settings in the `ollama:`
88
- section.
98
+ You can also select the model. By default `gpt-4o` is selected. This model works best with the tools and the prompt provided by ReVa.
89
99
 
90
- The configuration also contains the prompts used for the models.
91
- If you use Ollama or OpenAI these will be processed to fit the
92
- model specific prompt pattern (placing the system prompt in the
93
- correct tags, etc).
100
+ `gpt-4` also works well, but is slow and needs more prompting by the user to explore a binary.
94
101
 
95
- For `llama-cpp` and `text-generation-webui` these may need to be
96
- configured for your specific model. For this reason Ollama is
97
- preferred for self hosting.
102
+ ### Ollama
103
+
104
+ Ollama is a local inference server. The default server is set to localhost, with the default Ollama port. You can change this to a remote server if you want to perform inference on a remote machine. This is useful for organisations that self host.
105
+
106
+ You can also select a model. The model must alread be loaded on the server. Good performance has been seen with:
107
+ - `mixtral`
108
+ - `llama3`
109
+ - `phi`
98
110
 
99
111
  ## Workflow
100
112
 
@@ -112,24 +124,41 @@ If you have more than one Ghidra open, you can select the right one with
112
124
  `reva-chat --project ${project-name}`, if it is not set, `reva-chat` will
113
125
  ask you which project you want to connect to.
114
126
 
115
- ## Installation
127
+ ## Protocol Build
116
128
 
117
- First install the python component, I like to use `pipx`. It is best to make
118
- sure that `reva-server` and `reva-chat` are on your path.
119
- The Ghidra extension will need to start `reva-server`, and you will need to
120
- run `reva-chat`.
129
+ To communicate between `reva-server` and the extension, [gRPC](https://grpc.io) is used. You can read more about that (here)[./DEVELOPER.md]. Building the source files from those protocol definitions is driven from the [Makefile](/Makefile). To build the protocol source code files, run this command in the project's root:
121
130
 
122
- To install the particular extension for your disassembler see:
123
- - [Ghidra Support](#ghidra-support)
131
+ ```sh
132
+ make protocol
133
+ ```
124
134
 
125
- The chat can be started with:
135
+ ## Python Project (reva-server and reva-chat) Installation
136
+
137
+ First install the python component, I like to use `pipx`. Install it with something like:
126
138
 
127
139
  ```sh
128
- reva-chat
140
+ pip install pipx
129
141
  ```
130
142
 
131
- > You can also configure the path to `reva-server` in `Edit -> Tool Options -> ReVa`
132
- > if it is not on your path. But you really should put it on your path!
143
+ In the `reverse-engineering-assistant` folder, run:
144
+
145
+ ```sh
146
+ pipx install .
147
+ ```
148
+
149
+ After installing the python project, pipx may warn you that you need to add a folder to your PATH environment variable. Make sure that the folder (now containing `reva-server` and `reva-chat`) are in your PATH variable. pipx can do it for you with this command:
150
+
151
+ ```sh
152
+ pipx ensurepath
153
+ ```
154
+
155
+ The extension will need to start `reva-server`, and you will need to run `reva-chat`. In case you do not want to add them to your PATH, see the [Configuration](#configuration) section for how to set the path to the executables.
156
+
157
+ Once the `reva-server` has been started by the extension the chat can be started with:
158
+
159
+ ```sh
160
+ reva-chat
161
+ ```
133
162
 
134
163
  # Ghidra Support
135
164
 
@@ -139,12 +168,16 @@ reva-chat
139
168
 
140
169
  Follow the instructions in the [ghidra-assistant](ghidra-assistant/README.md) plugin.
141
170
 
142
- After installation, enable the `ReVaPlugin` extension in the CodeBrowser tool (Open a file and click: File -> Configure -> Miscellaneous).
171
+ After installation, enable the `ReVa Plugin` extension in the CodeBrowser tool (Open a file and click: File -> Configure -> Miscellaneous).
143
172
 
144
173
  If you want ReVa enabled by default, click File -> Save Tool to save the configuration.
145
174
 
146
175
  If everything is working correctly you will see a ReVa menu on your menu bar.
147
176
 
177
+ ## Configuration
178
+
179
+ You can modify the plugin configuration in `Edit -> Tool Options -> ReVa`.
180
+
148
181
  ## Undo
149
182
 
150
183
  Whenever ReVa performs an action it will create an undo point for each action. If ReVa renames 5 variables, this will be
@@ -152,9 +185,17 @@ one undo.
152
185
 
153
186
  ## Menus
154
187
 
155
- > These are being added in the next release
188
+ ReVa adds an option to the CodeBrowser Tool's Window menu.
189
+ Select Window -> ReVa Action Log to open the ReVa Action Log window.
190
+
191
+ This window shows actions ReVa has performed and would like to perform.
192
+ You can accept or reject a change by double clicking the ✅ or ❌ icon. You can also go to the location the action will be performed by double clicking the address.
193
+
194
+ If you reject an action, ReVa will be told and she will move on.
195
+
196
+ You can also enable "Auto-allow" in the ReVa options. This will automatically accept all actions ReVa wants to perform.
156
197
 
157
- ReVa adds some elements to the Ghidra UI. You can either ask ReVa to do something in the chat window,
198
+ ReVa also adds some elements to the Ghidra UI. You can either ask ReVa to do something in the chat window,
158
199
  "Examine the variable usage in `main` in detail, rename the variables with more descriptive names.",
159
200
  or use the menu system.
160
201
 
@@ -25,13 +25,14 @@ information from the tools, but when there is no information it can still respon
25
25
  questions from its training.
26
26
 
27
27
  You can ask questions like:
28
+ - What are the interesting strings in this program?
28
29
  - Does this program use encryption? Write a markdown report on the encryption and where it is used.
29
30
  - Draw a class diagram using plantuml syntax.
30
31
  - Start from main, examine the program in detail. Rename variables as you go and provide a summary of the program.
31
32
  - Explain the purpose of the `__mod_init` segment.
32
33
  - What does `mmap` return?
33
34
  - What does the function at address 0x80000 do?
34
- - This is a CTF problem. Start at main, examine the program in detail and write a pwntools script to get the flag.
35
+ - This is a CTF problem. Write a pwntools script to get the flag.
35
36
 
36
37
  An important part of reverse engineering is the process. Many other tools simply ask a single question of the LLM,
37
38
  this means it is difficult to determine _why_ a thing happened. In ReVa we break all actions down into small parts
@@ -47,33 +48,40 @@ Built in support is provided for:
47
48
  - [OpenAI](https://platform.openai.com/overview) for online inference and easy setup (Needs an OpenAI API key)
48
49
  - [Ollama](https://ollama.ai) and any model it supports for local on-device inference or connecting to a self hosted remote inference server.
49
50
 
51
+ See [Configuration](#configuration) for more information about settings for the providers.
52
+
50
53
  Adding additional inference servers is easy if it is supported by langchain.
51
54
 
52
55
  ## Configuration
53
56
 
54
- > This is currently being moved to the Ghidra GUI
55
- > See Edit -> Tool Options -> ReVa in the Codebrowser Tool
57
+ Configuration for ReVa is in the CodeBrowser Tool options.
58
+ Open a program and go to Edit -> Tool Options -> ReVa.
59
+
60
+ There are options for:
61
+ - Selecting a provider (OpenAI or Ollama, others coming soon!)
62
+ - Enabling "Follow", this will move the Ghidra view to the location of
63
+ things ReVa is examining or changing.
64
+ - Enabling "Auto-allow", ReVa will log her actions for the user to accept
65
+ in the "ReVa Actions Log" window.
66
+
67
+ There are sections for the providers.
68
+
69
+ ### OpenAI
56
70
 
57
- Configuration for the reverse engineering assistant is stored at
58
- `~/.config/reverse-engineering-assistant/config.yaml`. If this
59
- is not present on first start, a default configuration using
60
- OpenAI for inference and the `OPENAI_API_TOKEN` environment
61
- variable will be used.
71
+ By default, the OpenAI key is loaded from the environment variable `OPENAI_API_KEY`. You can also set your key inside Ghidra. Setting the key back to the `OPENAI_API_KEY` value will clear the key from the Ghidra configuration and load it from the environment.
62
72
 
63
- The most important setting is the `type` top level setting.
64
- This controls what inference service you use. These are the
65
- same as the configuration keys, for example to use Ollama,
66
- set type to `ollama` and configure the settings in the `ollama:`
67
- section.
73
+ You can also select the model. By default `gpt-4o` is selected. This model works best with the tools and the prompt provided by ReVa.
68
74
 
69
- The configuration also contains the prompts used for the models.
70
- If you use Ollama or OpenAI these will be processed to fit the
71
- model specific prompt pattern (placing the system prompt in the
72
- correct tags, etc).
75
+ `gpt-4` also works well, but is slow and needs more prompting by the user to explore a binary.
73
76
 
74
- For `llama-cpp` and `text-generation-webui` these may need to be
75
- configured for your specific model. For this reason Ollama is
76
- preferred for self hosting.
77
+ ### Ollama
78
+
79
+ Ollama is a local inference server. The default server is set to localhost, with the default Ollama port. You can change this to a remote server if you want to perform inference on a remote machine. This is useful for organisations that self host.
80
+
81
+ You can also select a model. The model must alread be loaded on the server. Good performance has been seen with:
82
+ - `mixtral`
83
+ - `llama3`
84
+ - `phi`
77
85
 
78
86
  ## Workflow
79
87
 
@@ -91,24 +99,41 @@ If you have more than one Ghidra open, you can select the right one with
91
99
  `reva-chat --project ${project-name}`, if it is not set, `reva-chat` will
92
100
  ask you which project you want to connect to.
93
101
 
94
- ## Installation
102
+ ## Protocol Build
95
103
 
96
- First install the python component, I like to use `pipx`. It is best to make
97
- sure that `reva-server` and `reva-chat` are on your path.
98
- The Ghidra extension will need to start `reva-server`, and you will need to
99
- run `reva-chat`.
104
+ To communicate between `reva-server` and the extension, [gRPC](https://grpc.io) is used. You can read more about that (here)[./DEVELOPER.md]. Building the source files from those protocol definitions is driven from the [Makefile](/Makefile). To build the protocol source code files, run this command in the project's root:
100
105
 
101
- To install the particular extension for your disassembler see:
102
- - [Ghidra Support](#ghidra-support)
106
+ ```sh
107
+ make protocol
108
+ ```
103
109
 
104
- The chat can be started with:
110
+ ## Python Project (reva-server and reva-chat) Installation
111
+
112
+ First install the python component, I like to use `pipx`. Install it with something like:
105
113
 
106
114
  ```sh
107
- reva-chat
115
+ pip install pipx
108
116
  ```
109
117
 
110
- > You can also configure the path to `reva-server` in `Edit -> Tool Options -> ReVa`
111
- > if it is not on your path. But you really should put it on your path!
118
+ In the `reverse-engineering-assistant` folder, run:
119
+
120
+ ```sh
121
+ pipx install .
122
+ ```
123
+
124
+ After installing the python project, pipx may warn you that you need to add a folder to your PATH environment variable. Make sure that the folder (now containing `reva-server` and `reva-chat`) are in your PATH variable. pipx can do it for you with this command:
125
+
126
+ ```sh
127
+ pipx ensurepath
128
+ ```
129
+
130
+ The extension will need to start `reva-server`, and you will need to run `reva-chat`. In case you do not want to add them to your PATH, see the [Configuration](#configuration) section for how to set the path to the executables.
131
+
132
+ Once the `reva-server` has been started by the extension the chat can be started with:
133
+
134
+ ```sh
135
+ reva-chat
136
+ ```
112
137
 
113
138
  # Ghidra Support
114
139
 
@@ -118,12 +143,16 @@ reva-chat
118
143
 
119
144
  Follow the instructions in the [ghidra-assistant](ghidra-assistant/README.md) plugin.
120
145
 
121
- After installation, enable the `ReVaPlugin` extension in the CodeBrowser tool (Open a file and click: File -> Configure -> Miscellaneous).
146
+ After installation, enable the `ReVa Plugin` extension in the CodeBrowser tool (Open a file and click: File -> Configure -> Miscellaneous).
122
147
 
123
148
  If you want ReVa enabled by default, click File -> Save Tool to save the configuration.
124
149
 
125
150
  If everything is working correctly you will see a ReVa menu on your menu bar.
126
151
 
152
+ ## Configuration
153
+
154
+ You can modify the plugin configuration in `Edit -> Tool Options -> ReVa`.
155
+
127
156
  ## Undo
128
157
 
129
158
  Whenever ReVa performs an action it will create an undo point for each action. If ReVa renames 5 variables, this will be
@@ -131,9 +160,17 @@ one undo.
131
160
 
132
161
  ## Menus
133
162
 
134
- > These are being added in the next release
163
+ ReVa adds an option to the CodeBrowser Tool's Window menu.
164
+ Select Window -> ReVa Action Log to open the ReVa Action Log window.
165
+
166
+ This window shows actions ReVa has performed and would like to perform.
167
+ You can accept or reject a change by double clicking the ✅ or ❌ icon. You can also go to the location the action will be performed by double clicking the address.
168
+
169
+ If you reject an action, ReVa will be told and she will move on.
170
+
171
+ You can also enable "Auto-allow" in the ReVa options. This will automatically accept all actions ReVa wants to perform.
135
172
 
136
- ReVa adds some elements to the Ghidra UI. You can either ask ReVa to do something in the chat window,
173
+ ReVa also adds some elements to the Ghidra UI. You can either ask ReVa to do something in the chat window,
137
174
  "Examine the variable usage in `main` in detail, rename the variables with more descriptive names.",
138
175
  or use the menu system.
139
176
 
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "reverse-engineering-assistant"
7
7
  readme = "README.md"
8
- version = "2.9.1"
8
+ version = "2.9.4"
9
9
  authors = [
10
10
  {name="サイバーカイダ (cyberkaida)"},
11
11
  ]
@@ -20,6 +20,9 @@ dependencies = [
20
20
  "langchain",
21
21
  "langchain-core",
22
22
  "langchain-openai",
23
+ "langchain-community",
24
+ "langchain-experimental",
25
+ "langgraph",
23
26
  "prompt_toolkit",
24
27
  "sentence_transformers",
25
28
  "PyYAML",
@@ -27,8 +30,9 @@ dependencies = [
27
30
  "rich",
28
31
  "grpcio",
29
32
  "protobuf",
33
+ "flask",
30
34
  ]
31
35
 
32
36
  [project.scripts]
33
37
  reva-server = "reverse_engineering_assistant.assistant_api_server:main"
34
- reva-chat = "reverse_engineering_assistant.chat_client:main"
38
+ reva-chat = "reverse_engineering_assistant.chat_client:main"
@@ -0,0 +1,91 @@
1
+
2
+
3
+ from typing import List
4
+ from reverse_engineering_assistant.reva_exceptions import RevaToolException
5
+ from reverse_engineering_assistant.tool import AssistantProject
6
+ from reverse_engineering_assistant.assistant import RevaTool
7
+ from reverse_engineering_assistant.model import RevaModel
8
+ from reverse_engineering_assistant.api_server_tools.connection import get_channel
9
+ from typing import Optional, Tuple
10
+ import logging
11
+
12
+
13
+ class RevaMessageHandler(object):
14
+ handles_type = None
15
+
16
+ _global_message_handlers: List[RevaMessageHandler] = []
17
+
18
+ __all__ = ['register_message_handler']
19
+
20
+ def register_message_handler(cls: RevaMessageHandler):
21
+ _global_message_handlers.append(cls)
22
+ return cls
23
+
24
+
25
+ class RevaRemoteTool(RevaTool):
26
+ logger: logging.Logger
27
+
28
+ def __init__(self, project: AssistantProject, llm: RevaModel) -> None:
29
+ self.logger = logging.getLogger(f"reverse_engineering_assistant.RevaRemoteTool.{self.__class__.__name__}")
30
+ self.logger.addHandler(logging.FileHandler(project.project_path / "reva.log"))
31
+ super().__init__(project, llm)
32
+
33
+ @property
34
+ def channel(self):
35
+ return get_channel()
36
+
37
+ def resolve_to_address_and_symbol(self, thing: str) -> Tuple[str, Optional[str]]:
38
+ """
39
+ Resolve a string to an address and symbol.
40
+ If it is an address it can be a namespaced address or a plain hex address.
41
+
42
+ This helps reduce hallucinations and catch issues with symbols and namespaces early.
43
+
44
+ Returns a tuple of (address, symbol).
45
+ """
46
+ self.logger.debug(f"Resolving {thing} to address and symbol")
47
+ assert thing is not None
48
+ address: Optional[str] = None
49
+ symbol: Optional[str] = None
50
+ try:
51
+ # This is a plain address in the main namespace
52
+ address = hex(int(thing, 16))
53
+ self.logger.debug(f"Resolved {thing} to address: {address}")
54
+ except ValueError:
55
+ # This could also be a Ghidra namespaced address, so let's check that too!
56
+ if "::" in thing:
57
+ last_part = thing.split("::")[-1]
58
+ try:
59
+ hex(int(last_part, 16))
60
+ # If the last part of the address is a hex number, then we can assume it is an address
61
+ address = thing
62
+ except ValueError:
63
+ # Otherwise, it is a symbol
64
+ symbol = thing
65
+ else:
66
+ # This is a symbol
67
+ symbol = thing
68
+
69
+ # We can check if it is a symbol
70
+ from ..protocol import RevaGetSymbols_pb2_grpc, RevaGetSymbols_pb2
71
+ stub = RevaGetSymbols_pb2_grpc.RevaToolSymbolServiceStub(self.channel)
72
+ request = RevaGetSymbols_pb2.RevaSymbolRequest()
73
+ if address:
74
+ request.address = address
75
+ if symbol:
76
+ request.name = symbol
77
+
78
+ self.logger.debug(f"Getting symbol for {thing} request: {request}")
79
+ response = stub.GetSymbol(request)
80
+ self.logger.debug(f"Got symbol for {thing} response: {response}")
81
+
82
+ if response.name:
83
+ symbol = response.name
84
+ if response.address:
85
+ address = response.address
86
+
87
+ if address is None and symbol is None:
88
+ raise RevaToolException(message=f"Could not resolve {thing} to an address or symbol. Double check your symbol or address is correct.")
89
+ self.logger.debug(f"Resolved {thing} to address: {address}, symbol: {symbol}")
90
+ assert address is not None
91
+ return address, symbol
@@ -11,6 +11,9 @@ from functools import cache
11
11
  _channel: Optional[Channel] = None
12
12
  @cache
13
13
  def get_channel() -> Channel:
14
+ """
15
+ Get the global gRPC channel to the extension.
16
+ """
14
17
  global _channel
15
18
  if not _channel:
16
19
  raise ValueError("Channel not set")
@@ -0,0 +1,134 @@
1
+
2
+
3
+ from ast import Call
4
+ import queue
5
+ import threading
6
+ from typing import Callable, Dict, Optional
7
+ from uuid import uuid4
8
+ from venv import logger
9
+
10
+ from ..protocol.RevaChat_pb2_grpc import RevaChatServiceServicer
11
+ from ..protocol.RevaChat_pb2 import RevaChatMessageResponse
12
+
13
+ from functools import cache
14
+ from ..assistant import ReverseEngineeringAssistant
15
+
16
+ import logging
17
+ module_logger = logging.getLogger("reva-server")
18
+
19
+ from langchain_core.callbacks.base import BaseCallbackHandler
20
+ from langchain_core.agents import AgentAction, AgentFinish
21
+
22
+ from reverse_engineering_assistant.model import RevaModel
23
+ from reverse_engineering_assistant.model import get_llm_ollama, get_llm_openai
24
+
25
+ class RevaChat(RevaChatServiceServicer):
26
+ logger = logging.getLogger("reva-server.RevaChat")
27
+
28
+ def _model_from_request(self, request) -> RevaModel:
29
+ """
30
+ Given a request, return the model associated with the request.
31
+ """
32
+ if request.ollama.model:
33
+ return get_llm_ollama(base_url=request.ollama.url, model=request.ollama.model)
34
+ if request.openai.model:
35
+ return get_llm_openai(model=request.openai.model, api_key=request.openai.token)
36
+ raise ValueError("No model specified in request. Please file a bug.")
37
+
38
+ def chat(self, request, context):
39
+ self.logger.info(f"Received request: {request}")
40
+ assistant = ReverseEngineeringAssistant(
41
+ request.project,
42
+ model=self._model_from_request(request)
43
+ )
44
+ self.logger.info(f"Assistant: {assistant}")
45
+ llm_response = assistant.query(request.message)
46
+ self.logger.info(f"LLM Response: {llm_response}")
47
+ response = RevaChatMessageResponse()
48
+ response.message = llm_response
49
+ return response
50
+
51
+ def chatResponseStream(self, request, context):
52
+ """
53
+ Given a request, return a stream of responses including
54
+ thoughts and a final message from the LLM.
55
+ """
56
+ self.logger.info(f"Received request: {request}")
57
+
58
+ response_queue: queue.Queue = queue.Queue()
59
+
60
+ def callback(message: str):
61
+ # Called for intermediate thoughts
62
+ response = RevaChatMessageResponse()
63
+ response.thought = message
64
+ response_queue.put(response)
65
+
66
+ assistant = ReverseEngineeringAssistant(
67
+ request.project,
68
+ model=self._model_from_request(request),
69
+ logging_callbacks=[callback],
70
+ )
71
+ self.logger.info(f"Assistant: {assistant}")
72
+
73
+ def run_query(query: str):
74
+ llm_response = assistant.query(query)
75
+ self.logger.info(f"LLM Response: {llm_response}")
76
+ response = RevaChatMessageResponse()
77
+ response.message = llm_response
78
+ response_queue.put(response)
79
+
80
+ t = threading.Thread(target=run_query, args=[request.message])
81
+ t.start()
82
+
83
+ done = False
84
+ while not done:
85
+ response = response_queue.get()
86
+ # We stop when we get a message and not thoughts
87
+ if response.message and not response.thought:
88
+ done = True
89
+ yield response
90
+ t.join()
91
+
92
+ def chatStream(self, request_iterator, context):
93
+ assistant: Optional[ReverseEngineeringAssistant] = None
94
+ response_queue: queue.Queue = queue.Queue()
95
+
96
+ def callback(message: str):
97
+ # Called for intermediate thoughts
98
+ response = RevaChatMessageResponse()
99
+ response.thought = message
100
+ response_queue.put(response)
101
+
102
+ for request in request_iterator:
103
+ if not assistant:
104
+ assistant = ReverseEngineeringAssistant(
105
+ request.project,
106
+ model=self._model_from_request(request),
107
+ logging_callbacks=[callback],
108
+ )
109
+ self.logger.info(f"Received request: {request}")
110
+ def run_query(query: str):
111
+ assert assistant is not None
112
+ self.logger.info(f"Asking assistant: {query}")
113
+ llm_response = assistant.query(query)
114
+ self.logger.info(f"LLM Response: {llm_response}")
115
+ response = RevaChatMessageResponse()
116
+ response.message = llm_response
117
+ response_queue.put(response)
118
+
119
+ t = threading.Thread(target=run_query, args=[request.message])
120
+ t.start()
121
+
122
+ done = False
123
+ while not done:
124
+ response = response_queue.get()
125
+ # We stop when we get a message and not thoughts
126
+ if response.message and not response.thought:
127
+ done = True
128
+ yield response
129
+ t.join()
130
+
131
+ def shutdown(self, request, context):
132
+ self.logger.warning("Shutting down")
133
+ import sys
134
+ sys.exit(0)
@@ -0,0 +1,6 @@
1
+ """
2
+ To make sure your tool is loaded, you should import it here.
3
+ `assistant_api_server.py` imports everything from `re_tools.py`,
4
+ and `re_tools.py` imports everything from here.
5
+ """
6
+