Col-E / Recaf

The modern Java bytecode editor
https://recaf.coley.software
MIT License
6.04k stars 467 forks source link

Recaf as a Java Agent #31

Closed Col-E closed 6 years ago

Col-E commented 6 years ago

It would be REALLY neat if recaf could be applied to a jvm as an agent and the edits would be applied via the instrumentation API.

It'd be sorta like JavaSnoop.

So this would probably pass some arguments to the main method, which would replace the file menu with a "refresh classes" button or something similar. It would still behave largely the same as before with the file tree, as that can just be retrieved via the class path / agent launch args.

Since it would have access to all the libraries I'd imagine there should be some sorta option to limit what is accessible so some operations of recaf aren't slowed to a halt.

andylizi commented 6 years ago

Awesome idea!

Col-E commented 6 years ago

Current progress:

image image

First pic is recaf launched normally. UI isn't finished up, but the idea is you select a VM and it will auto-attach to it (spawning a new recaf instance)*. I tested this on Luyten, a front-end for the Procyon decompiler. As seen in the second picture it works, the new recaf window is associated with the same process as luyten, but for some reason the UI stops properly rendering. It still functions correctly, but the UI just fails to properly invalidate / redraw.

This seems to just be an issue with swing. I tested it on Minecraft and it ran just fine. Example when I get a little more cleaned up.

Col-E commented 6 years ago

Pushed what I got so far in https://github.com/Col-E/Recaf/commit/ea8f632d555af987e7beaa6ec1b7b0b7f3893ff0. The ability to save edits in agent-mode is not implemented yet, but everything else seems to work!

The issue with moving forward on this is the ability to save only changed classes. I can't think of a clean and simple way to do this.

Col-E commented 6 years ago

As of 7d9b37ee089a642eda13cb3e2df8614d8d5fba49 saving only modified classes works! It only updates classes if you edit the method code though (add / remove opcodes). Due to the way the ASM tree API is structured I still don't think I'll easily be able to listen to subtle changes like changing an invokevirtual's owner. I'll add a way to manually register classes until I can figure something out.

Edit: Manual marking in 55743ac9c2d644c429d23720f3838b8a0ffcd10b

Edit 2: Current thoughts are replacing ALL references to ASM nodes with custom extensions with getter/setters that keep track of changes. This would resolve the issue without being overly ugly. This will also potentially allow the creation of an "undo" feature.

Col-E commented 6 years ago

I noticed when attaching to jvm's with older ASM libs already loaded things still worked, but the version check threw an exception in ClassNode so in 20192d736e8ab25ef4c6b16e24bccbbf079bacb5 agent-mode will detect the loaded version and use it. If no version of ASM is in the JVM it'll just load the one recaf comes with, V6.

Also I tried the custom extension idea with 137219196b48e0ffa3cff1033c9bccd3fa2e709f (I reverted everything and misspelled truly) and that seems like a really inefficient solution. I guess I'll settle with what we got now (Detection of new opcodes and manual marking)

Col-E commented 6 years ago

Gonna close this as its now supported and works as defined by the original post. Only difference is the file tree updates classes automatically in 1.0