├── .gitignore
├── README.md
├── build-linux.sh
├── build-windows.cmd
├── create-eclipse-project-linux.sh
├── create-eclipse-project-windows.cmd
├── out
├── AndroidCryptoHookPlugin-1.0.0.jar
└── AndroidCryptoHookPlugin-1.0.1.jar
├── scripts
├── build.xml
└── generateEclipseProjectFilesForPlugin.py
└── src
└── com
└── pnf
└── andhook
├── AndroidCryptoHook.java
├── AndroidCryptoHookPlugin.java
├── HandlerManager.java
├── IHandler.java
├── ThreadStore.java
└── handlers
├── AbstractHandler.java
├── Handler_doFinal_Ba.java
├── Handler_doFinal_BaI.java
└── Handler_update_BaIIBa.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .project
2 | .classpath
3 | bin/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AndroidCryptoHookPlugin
2 |
3 | This plugin uses the JEB debugger API to monitor the use of cryptographic primitives in a running Android application, specifically the methods in the `Cipher` abstract class. This plugin is intended as proof-of-concept code show-casing what can be done with the `IDebuggerUnit` et al. set of interfaces.
4 |
5 | Note that this plugin can be used with any client, such as the official UI RCP client, or a headless client.
6 |
7 | How to use as a stand-alone Jar plugin:
8 |
9 | - Navigate to the `build/` folder
10 | - Build the plugin using Ant: `ant -file build-andhook.xml -Dversion=1.0.0 clean build package`
11 | - Copy to your JEB `coreplugins/` folder and start JEB
12 |
13 | How to use in a development environment, via the RCP desktop client:
14 |
15 | - Set the plugin's *.class files folder and class name in the Development tab of the Options dialog
16 | - Restart JEB
17 | - Open an APK
18 | - Start a debugging session, then run the plugin (via *File, Engines* menu.)
19 |
--------------------------------------------------------------------------------
/build-linux.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | ant -f scripts/build.xml -DpluginClassname=com.pnf.andhook.AndroidCryptoHookPlugin -DpluginFilename=AndroidCryptoHookPlugin -DpluginVersion=1.0.1
--------------------------------------------------------------------------------
/build-windows.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | ant -f scripts\build.xml -DpluginClassname=com.pnf.andhook.AndroidCryptoHookPlugin -DpluginFilename=AndroidCryptoHookPlugin -DpluginVersion=1.0.1
--------------------------------------------------------------------------------
/create-eclipse-project-linux.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | python scripts/generateEclipseProjectFilesForPlugin.py $1
--------------------------------------------------------------------------------
/create-eclipse-project-windows.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | python scripts\generateEclipseProjectFilesForPlugin.py %1
3 |
--------------------------------------------------------------------------------
/out/AndroidCryptoHookPlugin-1.0.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pnfsoftware/jeb-andhook/8db6b1ae63b9b198d55df7c807e7bced579cc879/out/AndroidCryptoHookPlugin-1.0.0.jar
--------------------------------------------------------------------------------
/out/AndroidCryptoHookPlugin-1.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pnfsoftware/jeb-andhook/8db6b1ae63b9b198d55df7c807e7bced579cc879/out/AndroidCryptoHookPlugin-1.0.1.jar
--------------------------------------------------------------------------------
/scripts/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/scripts/generateEclipseProjectFilesForPlugin.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | tplProject = '''
5 |
6 | %s
7 |
8 |
9 |
10 |
11 |
12 | org.eclipse.jdt.core.javabuilder
13 |
14 |
15 |
16 |
17 |
18 | org.eclipse.jdt.core.javanature
19 |
20 |
21 | '''
22 |
23 | tplClasspath = '''
24 |
25 |
26 |
27 | %s
28 |
29 |
30 | '''
31 |
32 | if __name__ == '__main__':
33 | prjname = os.path.split(os.path.abspath(os.path.dirname(sys.argv[0]) + '/..'))[-1]
34 | print('Project name: %s' % prjname)
35 |
36 | internal = len(sys.argv) > 1 and sys.argv[1] == '-i'
37 |
38 | if 'JEB_HOME' not in os.environ:
39 | print('Set an environment variable JEB_HOME pointing to your JEB folder')
40 | sys.exit(-1)
41 |
42 | jebhome = os.environ['JEB_HOME']
43 | jebcorepath = os.path.join(jebhome, 'bin/app/jeb.jar')
44 | if not os.path.isfile(jebcorepath):
45 | print('Based on your value of JEB_HOME, jeb.jar was expected at this location, but it was not found: %s' % jebcorepath)
46 | sys.exit(-1)
47 | jebdocpath = os.path.join(jebhome, 'doc/apidoc.zip')
48 |
49 | _Project = tplProject % prjname
50 | with open('.project', 'w') as f:
51 | f.write(_Project)
52 | print('Generated: Eclipse .project file')
53 |
54 | jeblibentry = '''
55 |
56 | ''' % (jebcorepath, jebdocpath)
57 | if internal:
58 | # FOR INTERNAL USE
59 | jeblibentry = ''
60 | _Classpath = tplClasspath % jeblibentry
61 | with open('.classpath', 'w') as f:
62 | f.write(_Classpath)
63 | print('Generated: Eclipse .classpath file')
--------------------------------------------------------------------------------
/src/com/pnf/andhook/AndroidCryptoHook.java:
--------------------------------------------------------------------------------
1 | package com.pnf.andhook;
2 |
3 | import com.pnf.andhook.handlers.Handler_doFinal_Ba;
4 | import com.pnf.andhook.handlers.Handler_doFinal_BaI;
5 | import com.pnf.andhook.handlers.Handler_update_BaIIBa;
6 | import com.pnfsoftware.jeb.core.events.J;
7 | import com.pnfsoftware.jeb.core.events.JebEvent;
8 | import com.pnfsoftware.jeb.core.units.code.android.IDexUnit;
9 | import com.pnfsoftware.jeb.core.units.code.debug.DebuggerEventType;
10 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerEventData;
11 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerUnit;
12 | import com.pnfsoftware.jeb.util.events.IEvent;
13 | import com.pnfsoftware.jeb.util.events.IEventListener;
14 | import com.pnfsoftware.jeb.util.logging.GlobalLog;
15 | import com.pnfsoftware.jeb.util.logging.ILogger;
16 |
17 | /**
18 | * Hook set-up, tear-down and debugger listener.
19 | *
20 | * @author Nicolas Falliere
21 | *
22 | */
23 | public class AndroidCryptoHook {
24 | private static final ILogger logger = GlobalLog.getLogger(AndroidCryptoHook.class);
25 |
26 | IDexUnit dex;
27 | IDebuggerUnit dbg;
28 | IEventListener dbgListener;
29 | HandlerManager hm;
30 |
31 | AndroidCryptoHook(IDexUnit dex, IDebuggerUnit dbg) {
32 | this.dex = dex;
33 | this.dbg = dbg;
34 | }
35 |
36 | synchronized boolean stop() {
37 | if(dbgListener != null) {
38 | dbg.removeListener(dbgListener);
39 | dbgListener = null;
40 | }
41 | hm.unregisterAll();
42 | return true;
43 | }
44 |
45 | synchronized boolean start() {
46 | // our listener will be called first
47 | dbg.insertListener(0, dbgListener = new IEventListener() {
48 | @Override
49 | public void onEvent(IEvent e) {
50 | onDebuggerEvent(e);
51 | }
52 | });
53 |
54 | hm = new HandlerManager(dbg, dex);
55 |
56 | // sample hooks for 3 key encryption methods in the Cipher abstract class
57 | // TODO: more methods, other classes/libs, hook native libs via the native debugger
58 | hm.register(new Handler_doFinal_Ba());
59 | hm.register(new Handler_doFinal_BaI());
60 | hm.register(new Handler_update_BaIIBa());
61 |
62 | return true;
63 | }
64 |
65 | synchronized void onDebuggerEvent(IEvent e) {
66 | if(e.getSource() != dbg) {
67 | return;
68 | }
69 |
70 | if(!(e.getType() == J.DbgTargetEvent && e.getData() instanceof IDebuggerEventData)) {
71 | return;
72 | }
73 |
74 | IDebuggerEventData data = (IDebuggerEventData)e.getData();
75 | String address = data.getAddress();
76 | if(address == null) {
77 | return;
78 | }
79 |
80 | if(data.getType() == DebuggerEventType.BREAKPOINT) {
81 | logger.debug("METHOD ENTRY: %s", address);
82 | IHandler h = hm.getByAddress(address);
83 | if(h != null) {
84 | h.onEnter(dbg, data);
85 | dbg.run();
86 | ((JebEvent)e).setStopPropagation(true);
87 | }
88 | }
89 | else if(data.getType() == DebuggerEventType.BREAKPOINT_FUNCTION_EXIT) {
90 | logger.debug("METHOD EXIT: %s", address);
91 | IHandler h = hm.getByAddress(address);
92 | if(h != null) {
93 | h.onExit(dbg, data);
94 | dbg.run();
95 | ((JebEvent)e).setStopPropagation(true);
96 | }
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/com/pnf/andhook/AndroidCryptoHookPlugin.java:
--------------------------------------------------------------------------------
1 | package com.pnf.andhook;
2 |
3 | import java.util.Map;
4 |
5 | import javax.crypto.Cipher;
6 |
7 | import com.pnfsoftware.jeb.core.AbstractEnginesPlugin;
8 | import com.pnfsoftware.jeb.core.IEnginesContext;
9 | import com.pnfsoftware.jeb.core.IPluginInformation;
10 | import com.pnfsoftware.jeb.core.IRuntimeProject;
11 | import com.pnfsoftware.jeb.core.PluginInformation;
12 | import com.pnfsoftware.jeb.core.RuntimeProjectUtil;
13 | import com.pnfsoftware.jeb.core.Version;
14 | import com.pnfsoftware.jeb.core.units.code.android.IDexUnit;
15 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerUnit;
16 | import com.pnfsoftware.jeb.core.util.DebuggerHelper;
17 | import com.pnfsoftware.jeb.util.collect.Lists;
18 | import com.pnfsoftware.jeb.util.logging.GlobalLog;
19 | import com.pnfsoftware.jeb.util.logging.ILogger;
20 |
21 | /**
22 | * This plugin uses the JEB debugger API to monitor the use of cryptographic primitives in a running
23 | * Android application, specifically the methods in the {@link Cipher} abstract class. This plugin
24 | * is intended as proof-of-concept code show-casing what can be done with the {@link IDebuggerUnit}
25 | * et al. set of interfaces.
26 | *
27 | * Note that this plugin can be used with any client, such as the official UI RCP client, or a
28 | * headless client.
29 | *
30 | * How to use as a stand-alone Jar plugin:
31 | *
32 | * - Navigate to the build/ folder
33 | * - Build the plugin using Ant:
34 | *
ant -file build-andhook.xml -Dversion=1.0.0 clean build package
35 | * - Copy to your JEB coreplugins/ folder and start JEB
36 | *
37 | *
38 | * How to use in a development environment, via the RCP desktop client:
39 | *
40 | * - Set the plugin's *.class files folder and class name in the Development tab of the Options
41 | * dialog
42 | * - (Instructions here: JEB Dev Tutorial Part 1)
44 | *
45 | * - Restart JEB
46 | *
47 | *
48 | * Then: open an APK; start a debugging session; run the plugin (eg, in UI: File, Engines menu.)
49 | *
50 | * @author Nicolas Falliere
51 | *
52 | */
53 | public class AndroidCryptoHookPlugin extends AbstractEnginesPlugin {
54 | private static final ILogger logger = GlobalLog.getLogger(AndroidCryptoHookPlugin.class);
55 |
56 | @Override
57 | public IPluginInformation getPluginInformation() {
58 | return new PluginInformation("Android Crypto-Hook Plugin",
59 | "Hook cryptographic primitives during an Android app debugging sesssion", "PNF Software",
60 | Version.create(1, 0, 2), Version.create(3, 0, 9), null);
61 | }
62 |
63 | private AndroidCryptoHook manager;
64 |
65 | @Override
66 | public void execute(IEnginesContext engctx, Map executionOptions) {
67 | IRuntimeProject prj = engctx.getProject(0);
68 | if(prj == null) {
69 | logger.warn("No project found");
70 | return;
71 | }
72 |
73 | IDexUnit dex = Lists.getFirst(RuntimeProjectUtil.findUnitsByType(prj, IDexUnit.class, false));
74 | if(dex == null) {
75 | logger.warn("No DEX unit found");
76 | return;
77 | }
78 |
79 | IDebuggerUnit dbg = DebuggerHelper.getDebuggerForUnit(prj, dex);
80 | if(dbg == null) {
81 | logger.warn("No debugger found for DEX file");
82 | return;
83 | }
84 |
85 | if(!dbg.isAttached()) {
86 | logger.warn("The debugger is not attached");
87 | return;
88 | }
89 |
90 | if(manager == null) {
91 | logger.info("Hooking cryptographic primitives...");
92 | manager = new AndroidCryptoHook(dex, dbg);
93 | manager.start();
94 | }
95 | else {
96 | logger.info("Un-hooking cryptographic primitives...");
97 | manager.stop();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/com/pnf/andhook/HandlerManager.java:
--------------------------------------------------------------------------------
1 | package com.pnf.andhook;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | import com.pnfsoftware.jeb.core.units.code.android.IDexUnit;
7 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerBreakpoint;
8 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerUnit;
9 |
10 | /**
11 | * Handler manager fo hook objects.
12 | *
13 | * @author Nicolas Falliere
14 | *
15 | */
16 | public class HandlerManager {
17 | IDebuggerUnit dbg;
18 | IDexUnit dex;
19 | Map hmap = new HashMap<>();
20 |
21 | public HandlerManager(IDebuggerUnit dbg, IDexUnit dex) {
22 | this.dbg = dbg;
23 | this.dex = dex;
24 | }
25 |
26 | public void register(IHandler handler) {
27 | String addr = handler.getAddress();
28 | IDebuggerBreakpoint bp = dbg.setBreakpoint(addr, dex);
29 | if(bp != null) {
30 | hmap.put(handler, bp);
31 | }
32 | }
33 |
34 | public IHandler getByAddress(String address) {
35 | for(IHandler h: hmap.keySet()) {
36 | if(address.startsWith(h.getAddress())) {
37 | return h;
38 | }
39 | }
40 | return null;
41 | }
42 |
43 | public boolean unregister(IHandler handler) {
44 | IDebuggerBreakpoint bp = hmap.get(handler);
45 | if(bp == null) {
46 | return false;
47 | }
48 |
49 | dbg.clearBreakpoint(bp);
50 | hmap.remove(handler);
51 | return true;
52 | }
53 |
54 | public void unregisterAll() {
55 | for(IHandler h: hmap.keySet()) {
56 | IDebuggerBreakpoint bp = hmap.get(h);
57 | dbg.clearBreakpoint(bp);
58 | }
59 | hmap.clear();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/com/pnf/andhook/IHandler.java:
--------------------------------------------------------------------------------
1 | package com.pnf.andhook;
2 |
3 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerEventData;
4 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerUnit;
5 |
6 | /**
7 | * Definition of a hook object.
8 | *
9 | * @author Nicolas Falliere
10 | *
11 | */
12 | public interface IHandler {
13 |
14 | /**
15 | * Get the hookd method address.
16 | *
17 | * @return
18 | */
19 | String getAddress();
20 |
21 | /**
22 | * Hook routine called on method enter.
23 | *
24 | * @param dbg
25 | * @param data
26 | */
27 | void onEnter(IDebuggerUnit dbg, IDebuggerEventData data);
28 |
29 | /**
30 | * Hook routine called on method exit.
31 | *
32 | * @param dbg
33 | * @param data
34 | */
35 | void onExit(IDebuggerUnit dbg, IDebuggerEventData data);
36 | }
37 |
--------------------------------------------------------------------------------
/src/com/pnf/andhook/ThreadStore.java:
--------------------------------------------------------------------------------
1 | package com.pnf.andhook;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * Simple thread local storage, implemented as a map-to-map structure.
8 | *
9 | * @author Nicolas Falliere
10 | *
11 | */
12 | public class ThreadStore {
13 | private Map> tls = new HashMap<>();
14 |
15 | public void put(long tid, String name, Object object) {
16 | Map m = tls.get(tid);
17 | if(m == null) {
18 | m = new HashMap();
19 | tls.put(tid, m);
20 | }
21 | m.put(name, object);
22 | }
23 |
24 | @SuppressWarnings("unchecked")
25 | public T get(long tid, String name, Class c) {
26 | Map m = tls.get(tid);
27 | if(m == null) {
28 | return null;
29 | }
30 |
31 | Object o = m.get(name);
32 | if(o == null) {
33 | return null;
34 | }
35 |
36 | //if(!c.isAssignableFrom(o.getClass())) {
37 | // return null;
38 | //}
39 | return (T)o;
40 | }
41 |
42 | public void clean(long tid) {
43 | tls.remove((Long)tid);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/com/pnf/andhook/handlers/AbstractHandler.java:
--------------------------------------------------------------------------------
1 | package com.pnf.andhook.handlers;
2 |
3 | import java.util.List;
4 |
5 | import com.pnf.andhook.IHandler;
6 | import com.pnf.andhook.ThreadStore;
7 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerVariable;
8 | import com.pnfsoftware.jeb.core.units.code.debug.ITypedValue;
9 | import com.pnfsoftware.jeb.core.units.code.debug.impl.ValueArray;
10 | import com.pnfsoftware.jeb.core.units.code.debug.impl.ValueByte;
11 | import com.pnfsoftware.jeb.core.units.code.debug.impl.ValueInteger;
12 | import com.pnfsoftware.jeb.util.format.Formatter;
13 | import com.pnfsoftware.jeb.util.logging.GlobalLog;
14 | import com.pnfsoftware.jeb.util.logging.ILogger;
15 |
16 | /**
17 | * Base class for hook objects.
18 | *
19 | * @author Nicolas Falliere
20 | *
21 | */
22 | public abstract class AbstractHandler implements IHandler {
23 | protected static final ILogger logger = GlobalLog.getLogger(AbstractHandler.class);
24 |
25 | protected ThreadStore tls = new ThreadStore();
26 |
27 | protected void logData(byte[] in, byte[] out) {
28 | StringBuilder sb = new StringBuilder();
29 | sb.append(String.format("[CRYPTO] %s\n", getAddress()));
30 | if(in != null) {
31 | sb.append(String.format(">>>>\n%s", Formatter.formatBinaryBlock(in)));
32 | }
33 | if(out != null) {
34 | sb.append(String.format("<<<<\n%s", Formatter.formatBinaryBlock(out)));
35 | }
36 | logger.info(sb.toString());
37 | }
38 |
39 | public static int readInt(ITypedValue v) {
40 | if(!(v instanceof ValueInteger)) {
41 | throw new IllegalArgumentException();
42 | }
43 |
44 | return ((ValueInteger)v).getValue();
45 | }
46 |
47 | public static byte[] readByteArray(ITypedValue v) {
48 | // read all
49 | return readByteArray(v, 0, -1);
50 | }
51 |
52 | public static byte[] readByteArray(ITypedValue v, int offset, int size) {
53 | if(!(v instanceof ValueArray)) {
54 | throw new IllegalArgumentException();
55 | }
56 | ValueArray o = (ValueArray)v;
57 |
58 | List extends IDebuggerVariable> byteVariables = o.getValue();
59 |
60 | int cnt = size < 0 ? byteVariables.size(): size;
61 | byte[] in = new byte[cnt];
62 |
63 | int i = 0;
64 | for(IDebuggerVariable byteVar: byteVariables.subList(offset, offset + cnt)) {
65 | in[i] = ((ValueByte)byteVar.getTypedValue()).getValue();
66 | i++;
67 | }
68 | return in;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/com/pnf/andhook/handlers/Handler_doFinal_Ba.java:
--------------------------------------------------------------------------------
1 | package com.pnf.andhook.handlers;
2 |
3 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerEventData;
4 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerThreadStackFrame;
5 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerUnit;
6 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerVariable;
7 |
8 | /**
9 | * Hook for Cipher method: byte[] doFinal(byte[] input)
.
10 | *
11 | * @author Nicolas Falliere
12 | *
13 | */
14 | public class Handler_doFinal_Ba extends AbstractHandler {
15 |
16 | @Override
17 | public String getAddress() {
18 | return "Ljavax/crypto/Cipher;->doFinal([B)[B";
19 | }
20 |
21 | @Override
22 | public void onEnter(IDebuggerUnit dbg, IDebuggerEventData data) {
23 | long tid = data.getThreadId();
24 |
25 | IDebuggerThreadStackFrame f0 = dbg.getThreadById(tid).getFrame(0);
26 | IDebuggerVariable p1 = f0.getInternalParameter(1, "[B");
27 | byte[] in = readByteArray(p1.getTypedValue());
28 | tls.put(tid, "in", in);
29 | }
30 |
31 | @Override
32 | public void onExit(IDebuggerUnit dbg, IDebuggerEventData data) {
33 | long tid = data.getThreadId();
34 |
35 | if(data.getReturnValue() == null) {
36 | logger.error("Cannot get return value");
37 | return;
38 | }
39 |
40 | byte[] out = readByteArray(data.getReturnValue());
41 | byte[] in = tls.get(tid, "in", byte[].class);
42 | logData(in, out);
43 |
44 | tls.clean(tid);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/com/pnf/andhook/handlers/Handler_doFinal_BaI.java:
--------------------------------------------------------------------------------
1 | package com.pnf.andhook.handlers;
2 |
3 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerEventData;
4 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerThreadStackFrame;
5 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerUnit;
6 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerVariable;
7 |
8 | /**
9 | * Hook for Cipher method: int doFinal (byte[] output, int outputOffset)
.
10 | *
11 | * @author Nicolas Falliere
12 | *
13 | */
14 | public class Handler_doFinal_BaI extends AbstractHandler {
15 |
16 | @Override
17 | public String getAddress() {
18 | return "Ljavax/crypto/Cipher;->doFinal([BI)I";
19 | }
20 |
21 | @Override
22 | public void onEnter(IDebuggerUnit dbg, IDebuggerEventData data) {
23 | long tid = data.getThreadId();
24 |
25 | IDebuggerThreadStackFrame f0 = dbg.getThreadById(tid).getFrame(0);
26 | IDebuggerVariable p1 = f0.getInternalParameter(1, "[B");
27 | IDebuggerVariable p2 = f0.getInternalParameter(2, "I");
28 |
29 | int outputOffset = readInt(p2.getTypedValue());
30 |
31 | tls.put(tid, "output", p1);
32 | tls.put(tid, "outputOffset", outputOffset);
33 | }
34 |
35 | @Override
36 | public void onExit(IDebuggerUnit dbg, IDebuggerEventData data) {
37 | long tid = data.getThreadId();
38 |
39 | if(data.getReturnValue() == null) {
40 | logger.error("Cannot get return value");
41 | return;
42 | }
43 | int outputSize = readInt(data.getReturnValue());
44 |
45 | IDebuggerVariable p1 = tls.get(tid, "output", IDebuggerVariable.class);
46 | int outputOffset = tls.get(tid, "outputOffset", Integer.class);
47 |
48 | byte[] output = readByteArray(p1.getTypedValue(), outputOffset, outputSize);
49 |
50 | logData(null, output);
51 |
52 | tls.clean(tid);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/com/pnf/andhook/handlers/Handler_update_BaIIBa.java:
--------------------------------------------------------------------------------
1 | package com.pnf.andhook.handlers;
2 |
3 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerEventData;
4 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerThreadStackFrame;
5 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerUnit;
6 | import com.pnfsoftware.jeb.core.units.code.debug.IDebuggerVariable;
7 |
8 | /**
9 | * Hook for Cipher method:
10 | * int update(byte[] input, int inputOffset, int inputLen, byte[] output)
.
11 | *
12 | * @author Nicolas Falliere
13 | *
14 | */
15 | public class Handler_update_BaIIBa extends AbstractHandler {
16 |
17 | @Override
18 | public String getAddress() {
19 | return "Ljavax/crypto/Cipher;->update([BII[B)I";
20 | }
21 |
22 | @Override
23 | public void onEnter(IDebuggerUnit dbg, IDebuggerEventData data) {
24 | long tid = data.getThreadId();
25 |
26 | IDebuggerThreadStackFrame f0 = dbg.getThreadById(tid).getFrame(0);
27 | IDebuggerVariable p1 = f0.getInternalParameter(1, "[B");
28 | IDebuggerVariable p2 = f0.getInternalParameter(2, "I");
29 | IDebuggerVariable p3 = f0.getInternalParameter(3, "I");
30 | IDebuggerVariable p4 = f0.getInternalParameter(4, "[B");
31 |
32 | int _inputOffset = readInt(p2.getTypedValue());
33 | int _inputLen = readInt(p3.getTypedValue());
34 | byte[] in = readByteArray(p1.getTypedValue(), _inputOffset, _inputLen);
35 | tls.put(tid, "in", in);
36 |
37 | tls.put(tid, "p_out", p4);
38 | }
39 |
40 | @Override
41 | public void onExit(IDebuggerUnit dbg, IDebuggerEventData data) {
42 | long tid = data.getThreadId();
43 |
44 | if(data.getReturnValue() == null) {
45 | logger.error("Cannot get return value");
46 | return;
47 | }
48 | int outLen = readInt(data.getReturnValue());
49 |
50 | IDebuggerVariable p4 = tls.get(tid, "p_out", IDebuggerVariable.class);
51 | byte[] out = readByteArray(p4.getTypedValue(), 0, outLen);
52 |
53 | byte[] in = tls.get(tid, "in", byte[].class);
54 | logData(in, out);
55 |
56 | tls.clean(tid);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------