Skip to content

Commit

Permalink
Merge pull request #8 from MeitarR/python2-support
Browse files Browse the repository at this point in the history
Python2 support
  • Loading branch information
ioncodes authored Jun 18, 2020
2 parents 2210042 + 58dff97 commit f0e64b0
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 27 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# IDACode
IDACode makes it easy to execute and debug Python 3 scripts in your IDA environment without leaving Visual Studio Code. The VS Code extension can be found on the [marketplace](https://marketplace.visualstudio.com/items?itemName=Layle.idacode).
IDACode makes it easy to execute and debug Python scripts in your IDA environment without leaving Visual Studio Code. The VS Code extension can be found on the [marketplace](https://marketplace.visualstudio.com/items?itemName=Layle.idacode).
IDACode is still in a very early state and bugs are to be expected. Please open a new issue if you encounter any issues.

## Features
Expand All @@ -8,14 +8,14 @@ IDACode is still in a very early state and bugs are to be expected. Please open
* **Compatibility**: IDACode does not require you to modify your scripts in a specific way. All scripts can be executed from within IDA without changes.
* **Modularity**: IDACode does not make extensive use of safe wrappers for thread synchronization, this allows you to import any module from any path at any given time. Instead IDACode synchronizes the script execution thread with IDAs main thread to avoid performance and unexpected issues.

IDACode only supports Python 3. If there's a need for Python 2 compatibility please vote [here](https://github.com/ioncodes/idacode/issues/3).
IDACode supports both Python 2 and Python 3!

## Setup
To set up the dependencies for the IDA plugin run:

```sh
# make sure to use the correct Python version
python3 -m pip install --user debugpy tornado
python -m pip install --user debugpy tornado
```

Either clone this repository or download a release package from [here](https://github.com/ioncodes/idacode/releases). `ida.zip` reflects the contents of the `ida` folder in this repository. Copy all files into IDAs plugin directory.
Expand Down Expand Up @@ -51,7 +51,7 @@ Ensure that the workspace folder is the folder that your main scripts are locate
Once you are connected you are able to select `Execute script in IDA`.

## Debugging
IDACode uses VS Code's remote debugger to connect to IDA. All VS Code features are supported. However, you have to specify the scripts entrypoint by using Python 3 builtin functionality: `breakpoint`. This instruction tells the debugger to pause execution, if there's no debugger present it will just ignore the function. When executing `breakpoint` in IDA, IDACode gives you additional features such as logging and conditionals which are not present in the normal builtin function. Here's an example:
IDACode uses VS Code's remote debugger to connect to IDA. All VS Code features are supported. However, you have to specify the scripts entrypoint by using Python builtin functionality: `breakpoint`. This instruction tells the debugger to pause execution, if there's no debugger present it will just ignore the function. When executing `breakpoint` in IDA, IDACode gives you additional features such as logging and conditionals which are not present in the normal builtin function. Here's an example:

```py
name = idc.get_segm_name(segment)
Expand All @@ -65,4 +65,5 @@ It is also important that attaching a debugger will create a new debugger instan
![demo](idacode/images/preview.gif)

## Contributors
* [mrexodia](https://github.com/mrexodia)
* [mrexodia](https://github.com/mrexodia)
* [MeitarR](https://github.com/MeitarR)
3 changes: 0 additions & 3 deletions ida/idacode.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import sys
if sys.version_info < (3, 3):
print("[IDACode] Python 2.7 is not (yet) supported, vote at https://github.com/ioncodes/idacode/issues/3")
sys.exit()

import idacode_utils.plugin as plugin

Expand Down
Empty file added ida/idacode_utils/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion ida/idacode_utils/dbg.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ def bp(*args):
break
if condition:
if message:
print(f"[IDACode] {message}")
print("[IDACode] {message}".format(message=message))
api.breakpoint()
22 changes: 12 additions & 10 deletions ida/idacode_utils/plugin.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
import socket, sys, os, threading, inspect, asyncio, subprocess
import socket, sys, os, threading, inspect, subprocess
try:
import tornado, debugpy
except ImportError:
print("[IDACode] Dependencies missing, run: python3 -m pip install --user debugpy tornado")
print("[IDACode] Dependencies missing, run: python -m pip install --user debugpy tornado")
sys.exit()
import idaapi
import idacode_utils.dbg as dbg
import idacode_utils.hooks as hooks
import idacode_utils.settings as settings
from idacode_utils.socket_handler import SocketHandler

VERSION = "0.1.2"
VERSION = "0.1.3"
initialized = False

def setup_patches():
hooks.install()
sys.executable = settings.PYTHON

def create_socket_handler():
asyncio.set_event_loop(asyncio.new_event_loop())
if sys.version_info >= (3, 4):
import asyncio
asyncio.set_event_loop(asyncio.new_event_loop())
app = tornado.web.Application([
(r"/ws", SocketHandler),
])
server = tornado.httpserver.HTTPServer(app)
print(f"[IDACode] Listening on {settings.HOST}:{settings.PORT}")
print("[IDACode] Listening on {address}:{port}".format(address=settings.HOST, port=settings.PORT))
server.listen(address=settings.HOST, port=settings.PORT)

def start_server():
Expand All @@ -34,7 +36,7 @@ def start_server():
def get_python_versions():
settings_version = subprocess.check_output([settings.PYTHON, "-c", "import sys; print(sys.version + sys.platform)"])
settings_version = settings_version.decode("utf-8", "ignore").strip()
ida_version = f"{sys.version}{sys.platform}"
ida_version = "{}{}".format(sys.version, sys.platform)
return (settings_version, ida_version)

class IDACode(idaapi.plugin_t):
Expand All @@ -53,14 +55,14 @@ def init(self):
settings_version, ida_version = get_python_versions()
if settings_version != ida_version:
print("[IDACode] settings.PYTHON version mismatch, aborting load:")
print(f"[IDACode] IDA interpreter: {ida_version}")
print(f"[IDACode] settings.PYTHON: {settings_version}")
print("[IDACode] IDA interpreter: {}".format(ida_version))
print("[IDACode] settings.PYTHON: {}".format(settings_version))
return idaapi.PLUGIN_SKIP
else:
print(f"[IDACode] settings.PYTHON ({settings.PYTHON}) does not exist, aborting load")
print("[IDACode] settings.PYTHON ({}) does not exist, aborting load".format(settings.PYTHON))
print("[IDACode] To fix this issue, modify idacode_utils/settings.py to point to the python executable")
return idaapi.PLUGIN_SKIP
print(f"[IDACode] Plugin version {VERSION}")
print("[IDACode] Plugin version {}".format(VERSION))
print("[IDACode] Plugin loaded, use Edit -> Plugins -> IDACode to start the server")
return idaapi.PLUGIN_OK

Expand Down
10 changes: 5 additions & 5 deletions ida/idacode_utils/socket_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ def start_debug_server():
if settings.LOGGING:
tmp_path = tempfile.gettempdir()
debugpy.log_to(tmp_path)
print(f"[IDACode] Logging to {tmp_path} with pattern debugpy.*.log")
print("[IDACode] Logging to {} with pattern debugpy.*.log".format(tmp_path))
debugpy.listen((settings.HOST, settings.DEBUG_PORT))
print(f"[IDACode] IDACode debug server listening on {settings.HOST}:{settings.DEBUG_PORT}")
print("[IDACode] IDACode debug server listening on {address}:{port}".format(address=settings.HOST, port=settings.DEBUG_PORT))

class SocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
Expand All @@ -30,7 +30,7 @@ def on_message(self, message):
if message["event"] == "set_workspace":
path = message["path"]
hooks.set_script_folder(path)
print(f"[IDACode] Set workspace folder to {path}")
print("[IDACode] Set workspace folder to {}".format(path))
elif message["event"] == "attach_debugger":
start_debug_server()
self.write_message({
Expand All @@ -39,13 +39,13 @@ def on_message(self, message):
elif message["event"] == "execute_script":
script = message["path"]
env = create_env()
print(f"[IDACode] Executing {script}")
print("[IDACode] Executing {}".format(script))
idaapi.execute_sync(
lambda: idaapi.IDAPython_ExecScript(script, env),
idaapi.MFF_WRITE
)
else:
print(f"[IDACode] Invalid event {message['event']}")
print("[IDACode] Invalid event {}".format(message['event']))

def on_close(self):
print("[IDACode] Client disconnected")
6 changes: 5 additions & 1 deletion idacode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@
### 0.1.2

- Enhanced UX
- Added configuration checks
- Added configuration checks

### 0.1.3

- Added support for Python 2
6 changes: 5 additions & 1 deletion idacode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@ IDACode doesn't support host to VM communication unless the VM uses a shared vol
### 0.1.2

- Enhanced UX
- Added configuration checks
- Added configuration checks

### 0.1.3

- Added support for Python 2
2 changes: 1 addition & 1 deletion idacode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "IDACode",
"description": "Run and debug your IDA scripts from VS Code",
"icon": "images/icon.png",
"version": "0.1.2",
"version": "0.1.3",
"publisher": "Layle",
"license": "SEE LICENSE IN LICENSE.md",
"preview": true,
Expand Down

0 comments on commit f0e64b0

Please sign in to comment.