Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__pycache__/
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,6 @@ It is also important that attaching a debugger will create a new debugger instan

## Demo
![demo](idacode/images/preview.gif)

## Contributors
* [mrexodia](https://github.com/mrexodia)
50 changes: 6 additions & 44 deletions ida/idacode.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,9 @@
import socket, sys, os, threading, inspect, asyncio
import tornado, debugpy
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
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()

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

def create_socket_handler():
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}")
server.listen(address=settings.HOST, port=settings.PORT)

def start_server():
setup_patches()
create_socket_handler()
tornado.ioloop.IOLoop.current().start()

class IDACode(idaapi.plugin_t):
def __init__(self):
self.flags = idaapi.PLUGIN_UNL
self.comment = "IDACode"
self.help = "IDACode"
self.wanted_name = "Start IDACode"
self.wanted_hotkey = ""

def init(self):
return idaapi.PLUGIN_OK

def run(self, args):
thread = threading.Thread(target=start_server)
thread.daemon = True
thread.start()

def term(self):
pass
import idacode_utils.plugin as plugin

def PLUGIN_ENTRY():
return IDACode()
return plugin.IDACode()
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(message)
print(f"[IDACode] {message}")
api.breakpoint()
73 changes: 73 additions & 0 deletions ida/idacode_utils/plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import socket, sys, os, threading, inspect, asyncio, subprocess
try:
import tornado, debugpy
except ImportError:
print("[IDACode] Dependencies missing, run: python3 -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"
initialized = False

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

def create_socket_handler():
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}")
server.listen(address=settings.HOST, port=settings.PORT)

def start_server():
setup_patches()
create_socket_handler()
tornado.ioloop.IOLoop.current().start()

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}"
return (settings_version, ida_version)

class IDACode(idaapi.plugin_t):
def __init__(self):
self.flags = idaapi.PLUGIN_UNL
self.comment = "IDACode"
self.help = "IDACode"
self.wanted_name = "IDACode"
self.wanted_hotkey = ""

def init(self):
global initialized
if not initialized:
initialized = True
if os.path.isfile(settings.PYTHON):
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}")
return idaapi.PLUGIN_SKIP
else:
print(f"[IDACode] settings.PYTHON ({settings.PYTHON}) does not exist, aborting load")
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 loaded, use Edit -> Plugins -> IDACode to start the server")
return idaapi.PLUGIN_OK

def run(self, args):
thread = threading.Thread(target=start_server)
thread.daemon = True
thread.start()

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

class SocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print("IDACode client connected")
print("[IDACode] client connected")

def on_message(self, message):
message = json.loads(message.decode("utf8"))

if message["event"] == "set_workspace":
path = message["path"]
hooks.set_script_folder(path)
print(f"Set workspace folder to {path}")
print(f"[IDACode] Set workspace folder to {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"Executing {script}")
print(f"[IDACode] Executing {script}")
idaapi.execute_sync(
lambda: idaapi.IDAPython_ExecScript(script, env),
idaapi.MFF_WRITE
)
else:
print(f"Invalid event {message['event']}")
print(f"[IDACode] Invalid event {message['event']}")

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

## 0.1.1

- Added logging support
- Added logging support

### 0.1.2

- Enhanced UX
- Added configuration checks
7 changes: 6 additions & 1 deletion idacode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,9 @@ IDACode doesn't support host to VM communication unless the VM uses a shared vol

### 0.1.1

- Added logging support
- Added logging support

### 0.1.2

- Enhanced UX
- Added configuration checks
10 changes: 5 additions & 5 deletions 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.1",
"version": "0.1.2",
"publisher": "Layle",
"license": "SEE LICENSE IN LICENSE.md",
"preview": true,
Expand Down Expand Up @@ -38,19 +38,19 @@
"commands": [
{
"command": "idacode.connectToIDA",
"title": "Connect to IDA"
"title": "IDACode: Connect to IDA"
},
{
"command": "idacode.attachToIDA",
"title": "Attach a debugger to IDA"
"title": "IDACode: Attach a debugger to IDA"
},
{
"command": "idacode.connectAndAttachToIDA",
"title": "Connect and attach a debugger to IDA"
"title": "IDACode: Connect and attach a debugger to IDA"
},
{
"command": "idacode.executeScript",
"title": "Execute script in IDA"
"title": "IDACode: Execute script in IDA"
}
],
"configuration": {
Expand Down
Binary file modified images/commands.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.