├── .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 | *

37 | *

38 | * How to use in a development environment, via the RCP desktop client: 39 | *

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