首页
社区
课程
招聘
[原创]安卓改机技术揭秘(二) 高级攻防技巧
发表于: 2016-10-2 00:28 32806

[原创]安卓改机技术揭秘(二) 高级攻防技巧

2016-10-2 00:28
32806

接下来讲一下APP的高级攻防技巧。
估计厂商也认识到了APP在JAVA环境下运行收集到的信息被篡改的几率很大,所以很多厂商把目光标准了JNI层。
JNI层的运算是独立于JAVA层以外的、更底层的运算,也就是说,你用XPOSED安装了一个JAVA层的钩子修改了机器的重要信息A,但从JNI层读取信息A的时候,并不会触发你的钩子,所以返回值是系统真实值。
那么JNI层的数据如何修改呢?如何进入JNI层?进入JNI层后如何使用钩子?

这里我提供两个思路 两个思路都有完整的JAVA+JNI层的HOOK功能和框架 而且两种方案都有自己的优缺点,靠你自己取舍。
1 Cydia Substrate
具体可以参考
http://www.cydiasubstrate.com/
http://www.cydiasubstrate.com/inject/dalvik/ (java层支持)
http://www.cydiasubstrate.com/inject/android/ (JNI/Native层支持)
cydia框架的优势很明显,同时支持jni和java层的HOOK功能,缺点也很明显,兼容性不好,官网上标注最高支持安卓4.3版,但实际中测试发现一些第三方的ROM会出现一些莫名其妙的问题,而据说有人用安卓4.4也可以完美运行。所以是否使用CYDIA框架,要根据你目前的硬件情况来选择,如果你的手机ROM可以运行CYDIA,我更推荐使用这种完整的集成方案
所以是否使用CYDIA框架,要根据你目前的硬件情况来选择,如果你的手机ROM可以运行CYDIA,我更推荐使用这种同时支持两个环境完整的集成方案。
使用cydia开发 搭建框架我这里不多重复了,可以登录官网查看文档。

public class Main
{
	public static int nTest=0;
	static void initialize()
	{
		//函数入口
		//do something........
	}
}


根据cydia和xposed的框架原理来看,cydia的开发成本会更高一些。
在你第一次使用这个框架时,编译后会出现很多莫名其妙的问题,如果你之前在c/c++语言上有过比较深的基础并且做过hook的相关项目,这些莫名其妙的问题解决起来会很轻松.
其中有三个点需要注意:
① cydia中的所有变量都是全局变量,例如,你在App A中个修改了nTest,那么会同步到其他App进程所有对Main.nTest的引用上。
② cydia中因为无法直接获得当前App的信息,你需要使用一个聪明的方式获得你想要东西作为你是否要HOOK目标进程的判断依据。
③ cydia引入了hookClassLoad方法,这个和xposed中的设计理念是不同的,详细资料看文档。
例如你可以用cydia hook捕获到Activity的OnCreate创建过程

Class<?> resources = android.app.Activity.class;
Method method_name=HTool.GetDeclaredMethodFromClass(resources,"onCreate",Bundle.class);
if (method_name != null) {
	final MS.MethodPointer old = new MS.MethodPointer();
	MS.hookMethod(resources, method_name, new MS.MethodHook() {
		@Override
		public Object invoked(Object obj, Object... args) throws Throwable {
			Object result_old = old.invoke(obj, args);
			Log.i(CreateTag,"onCreate PackName:"+PackName);
			return result_old;
		}
	}, old);
}



也可以使用cydia jni hook拦截getprop的返回值

int (*old__system_property_read)(int pi, char *name, char *value);
int new__system_property_read(int pi, char *name, char *value)
{
    int result=old__system_property_read(pi,name,value);
    return result;
}
//程序入口
MSInitialize
{
	MSImageRef image = MSGetImageByName("/system/lib/libc.so");
	if (image != NULL)
	{
		void *hook__system_property_read=MSFindSymbol(image,"__system_property_read");
		if(hook__system_property_read) MSHookFunction(hook__system_property_read,(void*)&new__system_property_read,(void **)&old__system_property_read);
		else LOGE("error find __system_property_read ");
	}
}


上面的例子HOOK了native层的__system_property_read方法,重定向到new__system_property_read。该方法是执行命令getprop的关键过程,配置好代码可以修改getprop的所有返回值

2 Xposed+Libc_hook.so
下面说第二种方案,如果你的安卓系统不能安装cydia 但同时又需要jni层的HOOK 那么我推荐你使用下面这套方案,实现成本相对第一种要复杂一些,但是跟着我所写的步骤,一定能得到你所要的功能。
在不能安装cydia的情况下如何进入jni层HOOK呢?很简单,找到关键so库文件,以病毒修改elf的方式,加载自己的注入代码,把自己的hook.so注入到该进程中即可
首先找到一个注入点,这里我推荐libc.so 因为基本上每个进程都要用到libc,更重要的是 libc的加载时机足够早。
① abd pull /system/lib/libc.so 先把手机上的libc.so到本地 然后使用ida打开
② 打开Function Window窗口找到dlopen函数的地址 0xEAD0

③ 打开Program Segmentation窗口找到.init_array的地址 0x57480

④ 按ALT+B搜索80个0 此地址随意 本例中找到地址为 0x51F00

⑤ 按照上面的三个数字 对应带入下面的代码中 使用vs2015 c#编译通过
⑥ 运行时 把libc.so放在exe同目录下可得到libc_ok.so
使用上面的程序生成的libc_ok.so覆盖回/system/lib/libc.so即可
以后每当程序运行,都会自动加载/system/lib/libckis.so库文件 可以尽情的HOOK了!

class Program
{
	static int dlopenAddr = 0xEAD0; //opendl地址
	static int InitArrayAddr = 0x57480-0x1000; //此处IDA的地址总是比UE中的多0x1000
	static int asmAddr = 0x51F00; //代码插入位置
	
	static byte[] asm = { 0xFF,0x40,0x2D,0xE9,0x18,0x00,0x9F,0xE5,0x00,0x10,0xA0,0xE3,0x00,0x00,0x8F,0xE0,
							0x01,0xF7,0xFF,0xEB,0xFF,0x40,0xBD,0xE8,0x08,0x00,0x9F,0xE5,0x00,0x00,0x8F,0xE0,
							0x10,0xFF,0x2F,0xE1,0x9C,0x68,0x03,0x00,0x09,0xBF,0x01,0x00,0x00,0x00,0x00,0x00};
	static int StrAddr = asmAddr + 0x40;
	static void Main(string[] args)
	{
		BinaryReader br = null;
		try
		{
			br = new BinaryReader(new FileStream("libc.so", FileMode.Open));
		}
		catch (IOException e)
		{
			Console.WriteLine(e.Message + "Cannot open file.");
			return;
		}
		int length = Convert.ToInt32(br.BaseStream.Length);
		byte[] data = br.ReadBytes(length);
		br.Close();
		byte[] LibCkisSo = System.Text.Encoding.ASCII.GetBytes("libckis.so");
		Array.ConstrainedCopy(LibCkisSo, 0, data, StrAddr, LibCkisSo.Length);
		int JmpReturnAddr = System.BitConverter.ToInt32(data, InitArrayAddr);
		byte[] byAsmAddr = System.BitConverter.GetBytes(asmAddr);
		Array.ConstrainedCopy(byAsmAddr, 0, data, InitArrayAddr, byAsmAddr.Length);
		byte[] JmpOffset = System.BitConverter.GetBytes(JmpReturnAddr - asmAddr - 0x24);
		Array.ConstrainedCopy(JmpOffset, 0, asm, 0x28, JmpOffset.Length);
		byte[] StrOffset = System.BitConverter.GetBytes(StrAddr - asmAddr - 0x14);
		Array.ConstrainedCopy(StrOffset, 0, asm, 0x24, StrOffset.Length);
		byte[] DlopenOffset = System.BitConverter.GetBytes((dlopenAddr - asmAddr - 0x18) / 4);
		Array.ConstrainedCopy(DlopenOffset, 0, asm, 0x10, StrOffset.Length - 1);
		Array.ConstrainedCopy(asm, 0, data, asmAddr, asm.Length);
		BinaryWriter bw = new BinaryWriter(new FileStream("libc_ok.so", FileMode.Create));
		bw.Write(data);
		bw.Close();
	}
}



上面着重讲解了cydia框架的使用以及手动注入jni层的方法,这种方法从原理上,可以100%的过目前的所有的检测,这是单一xposed框架做不到的。


欢迎讨论 QQ 586593


[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 3
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  一位没有留下痕迹的看雪读者   +1.00 2019/03/23 膜拜大佬
最新回复 (60)
雪    币: 2596
活跃值: (3589)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
谢谢分享
2016-10-2 00:32
0
雪    币: 76
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2016-10-2 11:45
0
雪    币: 214
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享,学习一下思路
2016-10-2 18:24
0
雪    币: 44229
活跃值: (19960)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
5
今天的看雪公众号,己把一 、二这2篇 文章发出去了。
再次感谢分享!
2016-10-2 18:34
0
雪    币: 241
活跃值: (226)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
老板 , 有稿费没?
2016-10-3 01:58
0
雪    币: 44229
活跃值: (19960)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
7
对被选中的文章,将给予kx币的奖励。
此帖精华或优秀,将由版主适时来设置。
2016-10-3 09:53
0
雪    币: 147
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
没明白第二种方式的hook代码怎么写
2016-10-4 06:06
0
雪    币: 198
活跃值: (581)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
9
似懂非懂的~先mark一下~感谢感谢~~
2016-10-8 09:30
0
雪    币: 102
活跃值: (1845)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
mark
2016-10-8 10:48
0
雪    币: 41
活跃值: (823)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
感谢分享!
2016-10-8 10:48
0
雪    币: 10171
活跃值: (5047)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
感谢分享~
2016-10-8 11:29
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
感谢分享,学习了!
2016-10-9 18:02
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
感谢分享
2016-10-9 18:09
0
雪    币: 163
活跃值: (1538)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
15
想问一下,如果JNI层调用的是JAVA的类来进行获取,在JAVA层HOOK不到吗?
2016-10-11 09:59
0
雪    币: 241
活跃值: (226)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
16
那要看你使用的框架原理 XPOSED我不太确定 cydia是肯定能HOOK到的
2016-10-11 12:00
0
雪    币: 163
活跃值: (1538)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
17
我是觉的XPOSED应该也是OK的。毕竟走的都是虚拟机。
2016-10-11 13:47
0
雪    币: 163
活跃值: (1538)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
18
libc_and_libc_ok.rar
我按照做法:
static int dlopenAddr = 0xD028; //opendl地址
static int InitArrayAddr = 0x00049E20 - 0x1000; //此处IDA的地址总是比UE中的多0x1000
static int asmAddr = 0x4A400; //代码插入位置

得到libc_ok.so,拉进IDA,发现汇编在0x4B400.如下,是正确的吗?

.data:0004B400
.data:0004B400                         ; =============== S U B R O U T I N E =======================================
.data:0004B400
.data:0004B400
.data:0004B400                         sub_4B400
.data:0004B400 FF 40 2D E9                             STMFD           SP!, {R0-R7,LR}
.data:0004B404 18 00 9F E5                             LDR             R0, =(aLibckis_so - 0x4B414)
.data:0004B408 00 10 A0 E3                             MOV             R1, #0
.data:0004B40C 00 00 8F E0                             ADD             R0, PC, R0 ; "libckis.so"
.data:0004B410 04 0B FF EB                             BL              loc_E028
.data:0004B414 FF 40 BD E8                             LDMFD           SP!, {R0-R7,LR}
.data:0004B418 08 00 9F E5                             LDR             R0, =(loc_F2F8+1 - 0x4B424)
.data:0004B41C 00 00 8F E0                             ADD             R0, PC, R0 ; loc_F2F8
.data:0004B420 10 FF 2F E1                             BX              R0
.data:0004B420                         ; End of function sub_4B400
.data:0004B420
.data:0004B420                         ; ---------------------------------------------------------------------------
.data:0004B424 2C 00 00 00             off_4B424       DCD aLibckis_so - 0x4B414
.data:0004B424                                                                 ; DATA XREF: sub_4B400+4r
.data:0004B424                                                                 ; "libckis.so"
.data:0004B428 D5 3E FC FF             off_4B428       DCD loc_F2F8+1 - 0x4B424
.data:0004B428                                                                 ; DATA XREF: sub_4B400+18r
.data:0004B42C 00                                      DCB    0
.data:0004B42D 00                                      DCB    0
.data:0004B42E 00                                      DCB    0
.data:0004B42F 00                                      DCB    0
.data:0004B430 00                                      DCB    0
.data:0004B431 00                                      DCB    0
.data:0004B432 00                                      DCB    0
.data:0004B433 00                                      DCB    0
.data:0004B434 00                                      DCB    0
.data:0004B435 00                                      DCB    0
.data:0004B436 00                                      DCB    0
.data:0004B437 00                                      DCB    0
.data:0004B438 00                                      DCB    0
.data:0004B439 00                                      DCB    0
.data:0004B43A 00                                      DCB    0
.data:0004B43B 00                                      DCB    0
.data:0004B43C 00                                      DCB    0
.data:0004B43D 00                                      DCB    0
.data:0004B43E 00                                      DCB    0
.data:0004B43F 00                                      DCB    0
.data:0004B440 6C 69 62 63 6B 69 73 2E+aLibckis_so     DCB "libckis.so",0      ; DATA XREF: sub_4B400+Co
.data:0004B440 73 6F 00                                                        ; .data:off_4B424o
.data:0004B44B 00                                      DCB    0
.data:0004B44C 00                                      DCB    0
.data:0004B44D 00                                      DCB    0
.data:0004B44E 00                                      DCB    0
.data:0004B44F 00                                      DCB    0
.data:0004B450 00                                      DCB    0
.data:0004B451 00                                      DCB    0
.data:0004B452 00                                      DCB    0
.data:0004B453 00                                      DCB    0
.data:0004B454 00                                      DCB    0
.data:0004B455 00                                      DCB    0
.data:0004B456 00                                      DCB    0
上传的附件:
2016-10-11 14:00
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
JNI层都要处理那些API 能指点一下吗?
2016-10-14 07:18
0
雪    币: 241
活跃值: (226)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
20
ida下按f5 dlopen("libckis.so",0)就对了

里面的几个值需要你从新抓
2016-10-14 09:09
0
雪    币: 241
活跃值: (226)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
21
看你要干嘛
2016-10-14 09:11
0
雪    币: 128
活跃值: (447)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
感谢分享
2016-10-14 10:21
0
雪    币: 163
活跃值: (1538)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
23
我生成的libc_ok.so,值就是重新抓的。
但貌似结果不对。
2016-10-14 11:10
0
雪    币: 241
活跃值: (226)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
24
libc发给我看看 要原版和改之后的都发一下 qq 586593

估计得晚点上线
2016-10-14 12:35
0
雪    币: 191
活跃值: (195)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
25
楼主好人谢谢分享,第二种办法太太。。。。。省略一万个太酷炫了
2016-10-14 17:51
0
游客
登录 | 注册 方可回帖
返回
//