APK防护——Anti_Virtual App的思路和实现
作者:HAI_i
原文来自:https://bbs.ichunqiu.com/thread-42982-1-1.html
0×00 前言
Virtual App是一个很强大的存在,破坏了Android 系统本身的隔离措施,可以进行免root hook和其他黑科技操作,你可以用这个做很多在原来APP里做不到事情,于此同时Virtual App的安全威胁也不言而喻。可以去看看这篇文章。VirtualApp技术黑产利用研究报告。
当然还有其他东西,可以去各大论坛进行深度挖掘。
我们这次的重点是放在Anti_Virtual App上。
1.内容
1.1 第一种思路和实现
1.2 第二种思路和实现
我也不知道用什么来命名,感觉要是把思路直接写在标题里之后不好展开。不啰嗦了正文开始。
0×01 第一种思路和实现
1.思路
1.1 思路是从哪来的?
我们要防止App在VirtualAPP上运行就要通过Virtual启动App时的一些特征来逆向分析,VirtualAPP是开源的我们也可以结合源码来进行分析。
1.2 思路挖掘
Android应用隔离是基于Linux系统的多用户机制实现的,即每个应用在安装时被分配了不同的Linux用户uid/gid。而在VirtualApp中,client应用(通过VirtualApp安装的应用)与host应用(即VirtualApp本身)是具有相同用户uid的。
这个是在Virtual资料里的介绍,这里有一个值得关注的地方就是,client应用和host应用具有相同的uid。
我们来进行一个测试。
这个是我们运行在正常环境下的。
用grep过滤一下。
然后我们运行在虚拟机下用grep过滤一下。
有一个前提就是,Android 系统中的UID是在app安装的时候进行分配的,之后是不会进行更改的。而且为了可以进行沙箱和隔离,每一个APP分配到的UID是不同的,而且不同的UID仅仅拥有一个进程。这是Linux的多用户系统被阉割下成为了现在的状态,当然也提高了APP的安全性。相同的UID具有共享的特性。
就这个不同的点,我们进行测试的实现。
2. 实现
实现的方法直接使用NDK来进行开发,或者使用java也可以。
实现思路就是我在app里调用ps |grep,拿到返回行数,简单粗暴易懂,可能会有bug,针对一般情况。轻踩。
我们需要做的第一步就是,获取到APP的UID对应的UNAME。
我这里使用的是封装方法。
struct passwd *pwd;
pwd = getpwuid(getuid());
char *find=pwd->pw_name;
这样可以直接拿到UNAME
然后我们使用字符串拼接,将命令结合,我是不是太啰嗦了。。。
char cmd[20]="ps | grep ";
LOGD("%s",cmd);
strcat(cmd,find);
LOGD("%s",cmd);
使用popen进行命令的运行
int getEnd(char * cmd)
{
FILE *pp = popen(cmd, "r"); //建立管道
if (!pp) {
LOGD("error");
}
int i=0;
char tmp[1024]; //设置一个合适的长度,以存储每一行输出
while (fgets(tmp, sizeof(tmp), pp) != NULL) {
if (tmp[strlen(tmp) - 1] == '\n') {
tmp[strlen(tmp) - 1] = '\0'; //去除换行符
i++;
}
LOGD("%s",tmp);
}
LOGD("i:%d",i);
return i;
}
最后进行调用判断。整合一下最后的结果。
struct passwd *pwd;
pwd = getpwuid(getuid());
char *find=pwd->pw_name;
LOGD("%s",find);
char cmd[20]="ps | grep ";
LOGD("%s",cmd);
strcat(cmd,find);
LOGD("%s",cmd);
int i =getEnd(cmd);
if (i>4)
{
LOGD("This is VA!");
kill(0, SIGKILL);
}
3.测试
3.1 正常环境
3.2 VirtualApp环境测试
0×02 第二种思路和实现
1.思路
Virtual App有一个特点,就是在运行app的时候,如果存在so文件的话,会将so文件拷贝到自己的目录下,那么是不是可以对so文件路劲进行读取,然后进行判断,就可以区分开Virtual App和正常运行环境呢。
这个实现要对/proc/PID/maps这个文件进行分析。实现起来可能有点复杂。去git上看看有没有开源项目。
最后锁定了一个目标。https://github.com/ysrc/AntiVirtualApp
2.实现
2.1 实现思路总结
(1)拿到PID
(2)拿到/proc/PID/maps
(3) 拿到包名
(4)拿到SO路径
(5)分析比对
2.2 拿到PID
拿到当前进程的PID的方法很多。这里有一个很简单的方法就是
int pid=getpid();
当然还有另外一种就是通过对java层进行反射拿到pid,两种都是实现了的。
反射三步走,轻松拿到,这里对返回值的掌控还没有到轻车熟路的程度,但是这样子的反射还是可以拿到的。
//反射拿到pid
jclass Process=env->FindClass("android/os/Process");
jmethodID myPid=env->GetStaticMethodID(Process,"myPid","()I");
LOGD("%d",(int)env->CallStaticIntMethod(Process,myPid));
return (int)env->CallStaticIntMethod(Process,myPid);
2.3 拿到/proc/PID/maps
这里通过文件拼接读取就可以拿到文件指针了。
char data[256];
char s[64] = {0};
int pid=getpid();
sprintf(s, "/proc/%d/maps", pid);
FILE *fd = fopen(s, "r");
if (fd==NULL)
{
LOGD("The file is field");
} else
{
LOGD("ok");
}
2.4 拿到包名。
包名可以通过/proc/PID/cmdline这个文件来拿到
我们还是进行相同的操作。然后对文件进行处理,最后拿到了我们的包名。
char *buffer = (char *) malloc(1024);
memset(buffer, 0, 1024);
char path_t[256] = {0};
int pid = getpid();
sprintf(path_t, "/proc/%d/cmdline", pid);
int fd = open(path_t, O_RDONLY);
if (fd > 0) {
int read_count = (int) read(fd, buffer, 1024);
close(fd);
if (read_count > 0) {
return buffer;
}
}
free(buffer);
return NULL;
进行一个测试:
2.5拿到SO路径
对我们拿到的maps进行处理。
char path[128] = {0};
char uid[10] = {0};
char * filter="libnative-lib.so";
while (fgets(data, 256, fd)) {
int len = (int) strlen(data);
if (len <= 0) {
continue;
}
data[--len] = '\0';
if (sscanf(data, "%*llx-%*llx %s %*s %*s %*s %s", uid, path) != 2) {
continue;
}
LOGD("%s",data);
if (strcmp(uid, "r-xp") == 0 && endsWith(path, filter)) { LOGD("getSoPath1:%s",path);
break;
}
}
进行测试
现在so也拿到了。
2.6 分析比对
比对的原理是so加载的地方大多只有三个,通过这三个加上包名进行比对,然后就可以发现VirtualApp下运行的App的so包地址已经更改为VirtualApp的地址,原因很有可能就是因为隔离的特性不能越界访问。
size_t len = strlen(p);
int i=0;
if (strstr(path,p) != NULL) {
if (startsWith(path, SO_APP_LIB)) {
if (strncmp(path + SO_APP_LIB_LEN, p, len)) {
i++;
}
} else if (startsWith(path, SO_DATA_APP)) {
if (strncmp(path + SO_DATA_APP_LEN, p, len)) {
i++;
}
} else if (startsWith(path, SO_DATA_DATA)) {
if (strncmp(path + SO_DATA_DATA_LEN, p, len)) {
i++;
}
}
}
2.7 最后进行一个结果测试
在正常的环境下运行
在VirtualApp下运行
0×03 总结
如果还想进一步深入的话,可以推荐看一下VirtualApp的源码,这样可能对各个方面理解会有很大的帮助。
以上
有问题大家可以留言哦~也欢迎大家到春秋论坛中来玩耍呢!>>>点击跳转
APK防护——Anti_Virtual App的思路和实现的更多相关文章
- 我的Android进阶之旅------>解决如下错误failed to copy 'Settings2.apk' to '/system/app//Settings2.apk': Read-only
push apk的时候报错 ouyangpeng@oyp-ubuntu:~/apk升级$ adb push Settings2.apk /system/app/ failed to copy 'Set ...
- Flutter - You need to use a different version code for your APK or Android App Bundle because you already have one with version code 1.
前两天提交了一个版本Google Play,结果今天收到拒绝的邮件,说App内购有问题. 于是把设置里面的支付宝和微信打赏功能关闭,又打了一个aab. 然后上传到Google Play,结果提示 Yo ...
- Android Apk加固的初步实现思路(dex整体加固)
一.前 言 Android Apk加固的发展已经有一段时间了,相对来说本篇博客要记录的Android加壳的实现思路是4年的东西了,已经被老鸟玩烂了,Android加固的安全厂商也不会采用这么粗犷的方式 ...
- 手机APP测试思路及测试要点
一 手机APP测试基本思路: 测试计划--测试方案--测试用例--执行: 很多小公司都没有具体的需求,项目时间也比较紧,而且流程也不是很严谨,在这样的情况之下,作为测试的我们,该怎样去对项目进行用例 ...
- 浏览器唤起APP的思路(本文转载)
在做 h5 页面中,会遇到这样一个需求,有一个立即打开的按钮,如果本地安装了我们的 app,那么点击就直接唤起本地 app,如果没有安装,则跳转到下载. 首先想到的是两个问题:一是如何唤起本地 app ...
- 学习app开发思路
1.首先在学习之前进行一次或者是整体或者是部分的检测,当第一次检测就通过,则可以认为是熟练掌握的东西(可以在后期对其进行验证是否是熟练)2.后面的学习过程,对回答的正确与否以及从第一次开始学习到目前为 ...
- 解决 genymotion 安装apk报错 app contains ARM native code and your Genymotion device cannot run ARM instructions
1.某些APP安装在模拟器时提示“ this probably means that the app contains ARM native code and your Genymotion devi ...
- Windows下adb push 总是提示Failed to copy "XX.apk" to 'system/app':Read-only file system
一般情况看到这种提示我们会想到需要root权限,然后敲上adb remount,但是当我们执行过adb remount后,提示成功,但执行push命令依旧无法完成push. 那么此时我们的做法应该是重 ...
- 批量执行app自动化测试思路设计图
随机推荐
- java导出excel模板数据
Java导出excel数据模板,这里直接贴代码开发,流程性的走下去就是步骤: String[] colName=new String[]{"期间","科目代码" ...
- (转)Word插入图片显示不全怎么办
https://jingyan.baidu.com/article/e73e26c0c0081c24adb6a73d.html 现在告诉大家解决办法. 方法一: A.单击选中图片,然后在“开始”选项卡 ...
- Nginx 工作原理
Nginx 工作原理 Nginx由内核和模块组成. Nginx本身做的工作实际很少,当它接到一个HTTP请求时,它仅仅是通过查找配置文件将此次请求映射到一个location block,而此locat ...
- ie7ajax 跨域 no transport 解决办法
客户端js <script src="jquery-1.8.0.min.js"></script> <script src="JavaScr ...
- pytorch入门之安装和配置
pytorch是一种python接口的深度学习框架,其他的框架还有caffe,tensorflow等等. 1,pytorch目前支持linux和OSX两种系统.支持的Python版本有2.7,3.5, ...
- Servlet中获取Spring管理的bean
描述: 在Servlet中调用Spring管理的接口,可以使Dao/Service/ServiceImpl. 前提是在调用的bean中有注解: @Repository("beanName&q ...
- python--第十三天总结(html ,css 语法)
概述 HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可以让浏览器 ...
- JAVA企业级应用TOMCAT实战
1. Tomcat简介 原文链接:https://blog.oldboyedu.com/java-tomcat/ Tomcat是Apache软件基金会(Apache Software Foundati ...
- CentOS7配置samba服务
Step1:安装samba相关软件 [root@node-1 ~]# yum -y install samba samba-client Step2:创建共享目录 [root@node-1 ~]# m ...
- 【python原理解析】gc原理初步解析
python的gc是会用到:引用计数.标记-清除和分代收集,首先说明一下什么是引用计数 可以通过sys模块中的getrefcount()方法获取某个对象的引用计数 python本身的数据类型有基础类型 ...