作者:yueji0j1anke
首发于公号:剑客古月的安全屋
字数:1720
阅读时间: 5min
声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。合法渗透,本文章内容纯属虚构,如遇巧合,纯属意外
目录
-
前言
-
前置知识
-
PMSHook
-
IO重定向
-
总结
0x01 前言
本来在整理校验签名对抗的实战部分,突然发现存在一部分底层汇编以及操作需要详细讲解,加入进去显然太过冗杂,遂干脆新开辟一个专题。
本期依旧偏向逆向,有兴趣的师傅可以看看
0x02 前置知识
校验签名对抗现有方案
防重打包以及绕过一向是app攻防的重点。红极一时的过签工具很多->MT,NP,再配合现在诸多的dex内存dump工具,可以无视诸多壳成功重打包运行。
其中最核心的技术就是PMSHook与IO重定向
下面就来着重讲讲这两种技术
0x03 PMSHook
其主要利用反射和动态代理技术去修改apk中dex文件的signature,依靠PMS获取的攻击者构造后的正确签名信息signature,完成apk的签名检验
以下是一个testdemo,可以通过PM获取包的很多信息
public class MainActivity extends AppCompatActivity {
private byte[] signatureFromAPI() {
try {
PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
Log.i("签名数量:", info.signatures.length + "");
return info.signatures[0].toByteArray();
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(e);
}
}
}
包括PM命令,实则也是通过类似的接口实现命令的调用
那getPackageManager()如何从MainActivity获取的呢
通过ContextWrapper子类接口获取实现->而Context本身便是Activity的产物,具体接口就是hook住android.app.ActivityThread
这里实现一个简单的testdemo
public class ServiceManagerWraper {
public final static String ZJ = "ZJ595";
public static void hookPMS(Context context, String signed, String appPkgName, int hashCode) {
try {
// 获取全局的ActivityThread对象
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method currentActivityThreadMethod =
activityThreadClass.getDeclaredMethod("currentActivityThread");
Object currentActivityThread = currentActivityThreadMethod.invoke(null);
// 获取ActivityThread里面原始的sPackageManager
Field sPackageManagerField = activityThreadClass.getDeclaredField("sPackageManager");
sPackageManagerField.setAccessible(true);
Object sPackageManager = sPackageManagerField.get(currentActivityThread);
// 准备好代{过}{滤}理对象, 用来替换原始的对象
Class<?> iPackageManagerInterface = Class.forName("android.content.pm.IPackageManager");
Object proxy = Proxy.newProxyInstance(
iPackageManagerInterface.getClassLoader(),
new Class<?>[]{iPackageManagerInterface},
new PmsHookBinderInvocationHandler(sPackageManager, signed, appPkgName, 0));
// 1. 替换掉ActivityThread里面的 sPackageManager 字段
sPackageManagerField.set(currentActivityThread, proxy);
// 2. 替换 ApplicationPackageManager里面的 mPM对象
PackageManager pm = context.getPackageManager();
Field mPmField = pm.getClass().getDeclaredField("mPM");
mPmField.setAccessible(true);
mPmField.set(pm, proxy);
} catch (Exception e) {
Log.d(ZJ, "hook pms error:" + Log.getStackTraceString(e));
}
}
public static void hookPMS(Context context) {
String Sign = "原包的签名信息";
hookPMS(context, Sign, "com.zj.hookpms", 0);
}
}
public class PmsHookBinderInvocationHandler implements InvocationHandler{
//应用正确的签名信息
private String SIGN;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.i(SHARK, method.getName());
//查看是否是getPackageInfo方法
if("getPackageInfo".equals(method.getName())){
String pkgName = (String)args[0];
Integer flag = (Integer)args[1];
//是否是获取我们需要hook apk的签名
if(flag == PackageManager.GET_SIGNATURES && appPkgName.equals(pkgName)){
//将构造方法中传进来的新的签名覆盖掉原来的签名
Signature sign = new Signature(SIGN);
PackageInfo info = (PackageInfo) method.invoke(base, args);
info.signatures[0] = sign;
return info;
}
}
return method.invoke(base, args);
}
}
那对于mt管理器,它会对packageinfo内置过滤信息进行处理
对应的过滤代码是这一段
主要功能是通过伪造签名(Fake Signature)*和*修改系统的内存缓存,劫持PackageInfo
类中签名信息的获取过程,从而在应用程序内部伪装某个包(packageName
)的签名数据。
对应只需在此处修改包名与原包签名,即可完成PM绕过
编译,找dex文件
找到dex文件后,移入apk文件内部
查看AndoridManifest.xml文件是否拥有自己的application
比如说这里存在,就不用去使用我们的Application
有的话直接插入代码
寻找MainApplication.smali
插入代码
.method static <clinit>()V .registers 1 .line 37 new-instance v0, Lcom/example/nativelib/KillerApplication; # type@0013 invoke-direct {v0}, Lcom/example/nativelib/KillerApplication;-><init>()V # method@001c .line 38 return-void .end method
完成PMS校验绕过
0x04 IO重定向
什么是IO重定向呢
简而言之,就是本来该读取a应用的信息,你替换成b,类似于pwn中的execve(),从而实现
路径替换 签名绕过 检测绕过
在新来的mt一键过签名校验中,具体代码如下
获取app原包,放入对应origin.apk实现路径重定向
随后传到
hookApkPath(apkFile.getAbsolutePath(), repFile.getAbsolutePath());
该方法进行安卓底层的hook
具体来说,就是hook底层几个打开文件的命令操作接口
具体实操如下:
编译一下,把testapp的so文件和dex文件拿出来,放入至你要绕过的apk,从而实现IO重定向(记得做个继承)
这个lsposed模块的dex文件也要拿过来,
该文件也得放入hook apk中
找到对应Application随后反编译即可
0x05 总结
直接用一键过签工具很方便,but了解原理也是很重要的一部分,以后安全开发也可以根据学习这个写出一些框架应用
原文始发于微信公众号(剑客古月的安全屋):app攻防-校验签名对抗&IO重定向&PM篇
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论