Skip to content

Commit eb5b8ff

Browse files
author
Justine Osborne
committedJan 9, 2013
updates to README for a bit of explanation on writing a custom Jython
plugin
1 parent b30b715 commit eb5b8ff

File tree

3 files changed

+193
-48
lines changed

3 files changed

+193
-48
lines changed
 

‎AndroidSSLBypass/defaults.prop

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
adb.location=/home/freeze/android-sdks/platform-tools/adb
1+
adb.location=D:/tools/android-sdk/platform-tools/adb.exe
2+

‎AndroidSSLBypass/plugins/TestJythonPlugin.py

+24-23
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,31 @@ def __init__(self):
1111
def setupEvents(self):
1212
self.output("Python: setupEvents")
1313
self.createBreakpointRequest("android.util.Log.i")
14-
self.createBreakpointRequest("android.util.Log.d")
15-
self.createBreakpointRequest("android.util.Log.v")
16-
self.createBreakpointRequest("android.util.Log.e")
17-
self.createBreakpointRequest("android.util.Log.w")
18-
14+
self.createBreakpointRequest("android.util.Log.d")
15+
self.createBreakpointRequest("android.util.Log.v")
16+
self.createBreakpointRequest("android.util.Log.e")
17+
self.createBreakpointRequest("android.util.Log.w")
18+
1919
def handleEvent(self, event):
20-
# http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdi/com/sun/jdi/event/BreakpointEvent.html
21-
vm = event.virtualMachine();
22-
thread = event.thread()
23-
fr0 = thread.frames()[0]
24-
location = fr0.location()
25-
method = location.method()
26-
name = method.name()
27-
dalvikUtils = DalvikUtils(vm,thread)
28-
args = method.variables()
20+
# http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdi/com/sun/jdi/event/BreakpointEvent.html
21+
vm = event.virtualMachine();
22+
thread = event.thread()
23+
fr0 = thread.frames()[0]
24+
location = fr0.location()
25+
method = location.method()
26+
name = method.name()
27+
dalvikUtils = DalvikUtils(vm,thread)
28+
args = method.variables()
29+
30+
self.output("="*20)
31+
self.output("EVENT: \n\t%s\n" % ( event.toString()))
32+
vals = []
33+
self.output("VARIABLES:\n")
2934

30-
self.output("="*20)
31-
self.output("EVENT: \n\t%s\n" % ( event.toString()))
32-
vals = []
33-
self.output("VARIABLES:\n")
34-
for arg in args:
35-
val = fr0.getValue(arg)
36-
self.output("\t%s = %s\n" % (arg,val))
37-
vals.append(val)
35+
for arg in args:
36+
val = fr0.getValue(arg)
37+
self.output("\t%s = %s\n" % (arg,val))
38+
vals.append(val)
3839

39-
self.output("="*20)
40+
self.output("="*20)
4041
self.resumeEventSet()

‎README.md

+167-24
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ Basic Usage
5656

5757
Type ?list for a list of commands
5858

59+
* ADB location can also be set in the defaults.prop file in the root dir
60+
5961
* List devices:
6062

6163
ads>> ld
@@ -100,18 +102,19 @@ Basic Usage
100102
* Load plugins:
101103

102104
ads>> lp plugins
103-
attempting to load plugins from: plugins ....
104-
loaded Java plugins:
105-
com.isecpartners.android.jdwp.plugin.SSLBypassJDIPlugin
106-
com.isecpartners.android.jdwp.plugin.JythonConsoleJDIPlugin
107-
com.isecpartners.android.jdwp.plugin.TraceMethodsJDIPlugin
108-
com.isecpartners.android.jdwp.plugin.TestJDIPlugin
109-
loaded Jython plugins:
110-
TestJythonPlugin
105+
attempting to load plugins from: plugins ....
106+
loaded Java plugins:
107+
com.isecpartners.android.jdwp.plugin.SSLBypassJDIPlugin
108+
com.isecpartners.android.jdwp.plugin.JythonConsoleJDIPlugin
109+
com.isecpartners.android.jdwp.plugin.TraceMethodsJDIPlugin
110+
com.isecpartners.android.jdwp.plugin.TestJDIPlugin
111+
loaded Jython plugins:
112+
TestJythonPlugin
111113

112114
* Initialize plugin:
113-
ads>> ip com.isecpartners.android.jdwp.plugin.SSLBypassJDIPlugin
114-
ads>> ip TestJythonPlugin
115+
116+
ads>> ip com.isecpartners.android.jdwp.plugin.SSLBypassJDIPlugin
117+
ads>> ip TestJythonPlugin
115118

116119

117120
After the plugin has been successfully initialized, do the action in the app that causes an SSL connection to be made. Breakpoints should be hit and handled via the initialized plugins.
@@ -143,37 +146,177 @@ without closing the app.
143146
Building
144147
==================
145148

146-
* Modify the properties in build.properties corresponding to locations of ddmlib and tools.jar on your filesystem
149+
* Modify the properties in build.properties corresponding to locations of ddmlib
147150

148151
* ddmlib is found in the Android SDK at: android-sdk\tools\lib\ddmlib.jar
149152

150-
* tools.jar is found in the JDK libs, for example: C:/Program Files (x86)/Java/jdk1.7.0_05/lib/tools.jar
153+
* Ensure that tools.jar can be found by setting JAVA_HOME to point to the JDK root directory
154+
155+
* tools.jar is found in the JDK lib dir, for example: C:/Program Files (x86)/Java/jdk1.7.0_05/lib/tools.jar
151156

152157
* Run the ant build file: build.xml
153158

154159
Testing
155160
===================
156161

157-
* Run tests using the emulator
162+
* Run tests using the emulator
158163

159-
* Install AndroidSSLBypassHelperApp
164+
* Install AndroidSSLBypassHelperApp
160165

161-
* Install SSLTestApp
166+
* Install SSLTestApp
162167

163-
* Setup proxy
168+
* Setup proxy
164169

165-
* Right now SSLTestApp points to the host as seen from the emulator (10.0.2.2)
170+
* Right now SSLTestApp points to the host as seen from the emulator (10.0.2.2)
166171

167-
* This is hardcoded for now, a better test app will be included in the future
168-
169-
* Follow the basic usage instructions for running SSLBypassJDIPlugin
172+
* This is hardcoded for now, a better test app will be included in the future
173+
174+
* Follow the basic usage instructions for running SSLBypassJDIPlugin
170175

171-
Writing new plugins
172-
===================
173176

174-
*TODO
177+
Custom Jython Plugin Overview
178+
=====================
179+
180+
This tool is rather poorly named "android-ssl-bypass" in that bypassing SSL is far from all it does. It was initally presented at conference where bypassing ssl was its main purpose. However, it was created to be an extensible debugging tool that can be used for a variety of debugging tasks. It might be more aptly named something like "android-debug-shell", and probably will be changed to that at some point. This aims to provide a basic guide for creating your own simple debugging plugins for the tool using Jython. The plugins can be written in Java as well, but Jython is the easiest method for extensibility.
181+
182+
The power of Jython is that it lets us easily use and Java classes in the classpath. So we can import the Java Class AbstractJDIPlugin and create a Python class which extends it in order to create a plugin that can be loaded by the tool. In the future when the APIs are more solid there will be real documentation, but for now there is only source code :). Some jargon:
183+
184+
* Event (http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdi/com/sun/jdi/event/Event.html)
185+
186+
* Interface which represents an event request to the virtual machine. An event can be one of the following:
187+
AccessWatchpointEvent, BreakpointEvent, ClassPrepareEvent, ClassUnloadEvent, ExceptionEvent, LocatableEvent, MethodEntryEvent, MethodExitEvent, ModificationWatchpointEvent, StepEvent, ThreadDeathEvent, ThreadStartEvent, VMDeathEvent, VMDisconnectEvent, VMStartEvent, WatchpointEvent
188+
189+
* EventRequest (http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdi/com/sun/jdi/request/EventRequest.html)
190+
191+
* Respresents a request for notification for an event
192+
193+
194+
So first we import some Java classes from the tool that we will need to use:
195+
196+
from com.isecpartners.android.jdwp.pluginservice import AbstractJDIPlugin
197+
from com.isecpartners.android.jdwp import DalvikUtils
198+
import com.sun.jdi.event.Event
199+
200+
We can now create a class which extends the AbstractJDIPlugin using the following:
201+
202+
class TestJythonPlugin(AbstractJDIPlugin):
203+
204+
def __init__(self):
205+
AbstractJDIPlugin.__init__(self,"TestJythonPlugin")
206+
self.output("Python: initalized TestJythonPlugin")
207+
208+
A plugin must implement the abstract methods setupEvents() and handleEvent(Event). In the setupEvents method, the plugins creates and registers EventRequest objects using the convience methods provided by the Abstract JDIPlugin API, such as createBreakpointRequest(String locationString).
209+
210+
def setupEvents(self):
211+
self.output("Python: setupEvents")
212+
self.createBreakpointRequest("android.util.Log.i")
213+
self.createBreakpointRequest("android.util.Log.d")
214+
self.createBreakpointRequest("android.util.Log.v")
215+
self.createBreakpointRequest("android.util.Log.e")
216+
self.createBreakpointRequest("android.util.Log.w")
217+
218+
Now in the handleEvents(Event e) method we handle the events we just registered for. The tool works in a last in wins manner as far as two plugins trying to register for the same event (overall this feature is still in heavy dev so prepare for some bugs here when trying to load multiple plugins at once). Now we can do stuff with the Event object which is received by the function. In this case we know we are dealing with a BreakpointEvent (http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdi/com/sun/jdi/event/BreakpointEvent.html) because that is all we registered. We can use the methods of the event to extract the current thread, frame, location, and method. From that we can obtain the local variables and much more.
219+
220+
def handleEvent(self, event):
221+
vm = event.virtualMachine();
222+
thread = event.thread()
223+
fr0 = thread.frames()[0]
224+
location = fr0.location()
225+
method = location.method()
226+
name = method.name()
227+
dalvikUtils = DalvikUtils(vm,thread)
228+
args = method.variables()
229+
230+
self.output("="*20)
231+
self.output("EVENT: \n\t%s\n" % ( event.toString()))
232+
vals = []
233+
self.output("VARIABLES:\n")
234+
for arg in args:
235+
val = fr0.getValue(arg)
236+
self.output("\t%s = %s\n" % (arg,val))
237+
vals.append(val)
238+
239+
self.output("="*20)
240+
241+
Then we can choose to resume the event set which causes all threads to resume and the application continues execution.
242+
243+
self.resumeEventSet()
244+
245+
The plugin can then be used by attaching to the process, loading the plugins from the directory in which the Jython plugin is located, and initalizing the plugin. The following is an example debugging session from the example plugin in plugins/TestJythonPlugin:
246+
247+
====================
248+
Welcome to ANDROID DEBUG SHELL
249+
Type ?list for list of commands
250+
====================
251+
252+
ads>> ld
253+
Devices:
254+
emulator-5554 : nexus7 [emulator-5554]
255+
256+
ads>> sd emulator-5554
257+
Selected Device:
258+
emulator-5554
259+
ads>> apps
260+
Clients on: emulator-5554
261+
com.android.quicksearchbox : 8600
262+
com.android.browser : 8601
263+
com.android.exchange : 8602
264+
com.android.mms : 8603
265+
com.android.deskclock : 8604
266+
com.android.providers.calendar : 8605
267+
com.android.calendar : 8606
268+
com.android.contacts : 8607
269+
system_process : 8608
270+
com.android.email : 8609
271+
android.process.acore : 8610
272+
com.android.phone : 8611
273+
com.android.systemui : 8612
274+
com.android.launcher : 8613
275+
com.android.settings : 8614
276+
com.android.inputmethod.latin : 8615
277+
android.process.media : 8616
278+
279+
ads>> a 8601
280+
successfully attached to localhost:8601
281+
ads>> lp plugins
282+
attempting to load plugins from: plugins ....
283+
loaded Java plugins:
284+
com.isecpartners.android.jdwp.plugin.SSLBypassJDIPlugin
285+
com.isecpartners.android.jdwp.plugin.JythonConsoleJDIPlugin
286+
com.isecpartners.android.jdwp.plugin.TraceMethodsJDIPlugin
287+
com.isecpartners.android.jdwp.plugin.TestJDIPlugin
288+
loaded Jython plugins:
289+
TestJythonPlugin
290+
291+
ads>> ip TestJythonPlugin
292+
Python: setupEvents
293+
attempting to initalize plugin: TestJythonPlugin
294+
plugin initialized: TestJythonPlugin
295+
ads>> ====================
296+
EVENT:
297+
BreakpointEvent@android.util.Log:159 in thread <1> main
298+
299+
VARIABLES:
300+
301+
tag in android.util.Log.i(java.lang.String, java.lang.String)@android.util.Log:159 = "Choreographer"
302+
303+
msg in android.util.Log.i(java.lang.String, java.lang.String)@android.util.Log:159 = "Skipped 103 frames! The application may
304+
be doing too much work on its main thread."
305+
306+
====================
307+
====================
308+
EVENT:
309+
BreakpointEvent@android.util.Log:159 in thread <1> main
310+
311+
VARIABLES:
312+
313+
tag in android.util.Log.i(java.lang.String, java.lang.String)@android.util.Log:159 = "Choreographer"
314+
315+
msg in android.util.Log.i(java.lang.String, java.lang.String)@android.util.Log:159 = "Skipped 110 frames! The application may
316+
be doing too much work on its main thread."
317+
175318

176-
FAQ
319+
FAQ
177320
==================
178321

179322
Q: Why is it so slow the first time I run the plugin?

0 commit comments

Comments
 (0)
Please sign in to comment.