一、目标
不管是通过rpc调用签名还是模拟执行,都有一个小小的问题,那就是没有在真机环境下直接调用so来算签名来的快。
所以我们今天的目标是尝试在Android系统下直接调用目标App的so文件来做签名。
二、步骤
先从一个假想的例子说起
extern "C" JNIEXPORT jstring JNICALL Java_com_fenfei_loadso_MainActivity_stringFromJNI( JNIEnv* env, jobject obj) { jclass cls = env->GetObjectClass(obj); jmethodID mid = env->GetMethodID(cls, "getPackageManager", "()Landroid/content/pm/PackageManager;"); mid = env->GetMethodID(cls, "getPackageName", "()Ljava/lang/String;");// jstring packageName = (jstring) env->CallObjectMethod(obj, mid); const char* str; str = env->GetStringUTFChars(packageName, NULL); env->ReleaseStringUTFChars(packageName, str); std::string strRc = "ok"; if( strcmp(str,"com.fenfei.demo") != 0){ strRc = "OMG"; } return env->NewStringUTF(strRc.c_str()); }
这个so在它的 stringFromJNI 的函数中获取了当前包名,判断是自己的包名就返回 OK,如果不是就返回 OMG
我们直接load这so,调用它的 stringFromJNI 函数,毫不意外,它的返回值是 OMG。
SandHook的使用
那么要让它返回正确的 OK,有如下几种方法:
- getPackageName函数恰好是可以重写的,那么重写 MainActivity 类的 getPackageName 函数直接返回 "com.fenfei.demo"
- Hook Native层 strcmp 函数,把比较的返回值改写成成功
- Hook Java层 getPackageName 函数,来返回 "com.fenfei.demo"
今天我们使用最后一种方法,Hook Java层 getPackageName。
本次用的Hook库是 github.com/ganyao114/S…
导入SandHook库
在 app/build.gradle 中增加 implementation 'com.swift.sandhook:hooklib:4.2.1'
增加MyApp类,初始化SandHook
import android.app.Application; public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); try { SandHook.addHookClass( MainActivityHooker.class); } catch (HookErrorException e) { e.printStackTrace(); } } }
记得在 AndroidManifest.xml 中增加 android:name=".MyApp"
增加MainActivityHooker类,Hook getPackageName函数
@HookClass(ContextWrapper.class) public class MainActivityHooker { @HookMethodBackup("getPackageName") static Method onGetPackageNameBackup; @HookMethod("getPackageName") public static String onGetPackageName(@ThisObject ContextWrapper thiz) throws Throwable { String strPkg = (String)SandHook.callOriginByBackup(onGetPackageNameBackup, thiz); if (thiz.getClass().equals(MainActivity.class)){ Log.e("MainActivityHooker", thiz + "hooked getPackageName success rc= com.fenfei.demo"); return "com.fenfei.demo"; }else{ return strPkg; } } }
好了,这次so就以为自己还是运行在com.fenfei.demo之下正常的返回 OK 了
三、总结
借鸡生蛋要了解鸡的心理,让它以为还在自己家,它可能东看看西看看,这时候千万要小心把周围都模拟出来。然后它才会乖乖的下蛋。
本篇教程是开胃菜,也是基础。下一篇才是真正的实战。
TIP: 本文的目的只有一个就是学习更多的逆向技巧和思路,如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担,和本文以及作者没关系,本文涉及到的代码项目可以去 奋飞的朋友们 知识星球自取,欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: fenfei331 讨论下。
关注微信公众号 奋飞安全 ,最新技术干货实时推送