首页
论坛
课程
招聘
[原创]Android svc获取设备信息
2020-12-25 19:05 6671

[原创]Android svc获取设备信息

2020-12-25 19:05
6671

前言:

现在市面上改机的软件很多,大部分都是通过Hook的方式去修改Java层的一些参数和变量,或者直接反射的方式去set成伪造数据。
如果通过正常的获取设备信息的API去获取的时候就很容易是假的

 

这时候我们可以通过读取文件的方式去获取设备信息,还需要加CRC对底层函数进行判断,很是麻烦
因为底层的IO函数一旦被Hook,比如openat函数,就算读取文件的方式去可能获取的设备也可能是被mock的。

这时候有没有一种相对稳定的方式去获取最真实的设备信息呢?

通过syscall 直接调用svc指令的方式让Linux切换到内核态,执行完毕以后去直接拿返回结果即可
(systcall是Linux内核的入口,切换到内核态以后,无法被Hook)

方案:

实现也很简单,提供两种方式:

  • 1,直接调用libc.so里面的syscall
  • 2,内联汇编,将Libc.so syscall里面的代码抠出来
    本质区别不大

实现:

  • 方式1:
    直接调用syscall

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    std::string FileUtils::getFileText(char *path,int BuffSize) {
     
      char buffer[BuffSize];
      memset(buffer, 0, BuffSize);
      std::string str;
      //int fd = open(path, O_RDONLY);
      long fd = syscall(__NR_open, path, O_RDONLY);
     
      //失败 -1;成功:>0 读出的字节数  =0文件读完了
      while (syscall(__NR_read,fd, buffer, 1) != 0) {
          //LOG(ERROR) << "读取文件内容  " <<buffer;
          str.append(buffer);
      }
      syscall(__NR_close,fd);
      return str;
    }
  • 方式2
    通过内联汇编的方式调用Svc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::string FileUtils::getRawFileText(char *path,int BuffSize) {
 
    char buffer[BuffSize];
    memset(buffer, 0, BuffSize);
    std::string str;
    //int fd = open(path, O_RDONLY);
    long fd = raw_syscall(__NR_open, path, O_RDONLY);
 
    //失败 -1;成功:>0 读出的字节数  =0文件读完了
    while (read(fd, buffer, 1) != 0) {
        //LOG(ERROR) << "读取文件内容  " <<buffer;
        str.append(buffer);
    }
    syscall(__NR_close,fd);
    return str;
}

重点看一下raw_syscall

 

内联汇编代码主要分32和64

  • 32位实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    .text
    .global raw_syscall
    .type raw_syscall,%function
 
raw_syscall:
        MOV             R12, SP
        STMFD           SP!, {R4-R7}
        MOV             R7, R0
        MOV             R0, R1
        MOV             R1, R2
        MOV             R2, R3
        LDMIA           R12, {R3-R6}
        SVC             0
        LDMFD           SP!, {R4-R7}
        mov             pc, lr
  • 64位实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    .text
    .global raw_syscall
    .type raw_syscall,@function
 
raw_syscall:
        MOV             X8, X0
        MOV             X0, X1
        MOV             X1, X2
        MOV             X2, X3
        MOV             X3, X4
        MOV             X4, X5
        MOV             X5, X6
        SVC             0
        RET

cmake里添加

1
enable_language(C ASM)

编译即可

 

比如获取网卡设备信息

1
2
LOG(ERROR) << "读取文件内容  " <<
            FileUtils::getFileText("/sys/class/net/p2p0/address",20);

<br/>
<br/>
<br/>

这种方式一定是安全的么?

答案是否定的

 

目前主流的两种方法

  • 可以通过Ptrace进行svc拦截,在使用前需要将Ptrace方法堵住
    (因为Ptrace作为Linux的调试函数,是可以调试svc指令的,很多游戏辅助也都是这么搞得)
    方法也很多,可以像一般壳子的方式提前占坑,或者读取调试状态,去判断是否被调试 都是不错的办法。
  • 使用一些特殊的虚拟机,比如GS虚拟机之类的。
    底层原理相当于在安卓上面实现一个新的安卓,这个很复杂,用到了Google开源的一些东西
    比如gVisor(Google的gVisor则是linux上实现linux),需要重新实现一遍安卓内核 ,所以就算svc指令也可以去拦截。

<br>
<br>
帖子根据个人经验梳理,如有不足,及时告知。


2021 KCTF 秋季赛 防守篇-征题倒计时(11月14日截止)!

最后于 2020-12-25 23:05 被珍惜Any编辑 ,原因: 格式修改
收藏
点赞5
打赏
分享
最新回复 (21)
雪    币: 250
活跃值: 活跃值 (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
神话大大 活跃值 2020-12-25 19:13
2
1
大佬nb
雪    币: 5
活跃值: 活跃值 (85)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
peter_puff 活跃值 2020-12-25 19:16
3
0
大佬nb
雪    币: 187
活跃值: 活跃值 (2002)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
蟑螂一号 活跃值 1 2020-12-25 20:28
4
1
你这个>=Android10估计也会歇菜吧
雪    币: 479
活跃值: 活跃值 (676)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2020-12-25 21:20
5
0

嘿嘿

雪    币: 677
活跃值: 活跃值 (2888)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
珍惜Any 活跃值 2020-12-25 21:24
6
0
sudami 嘿嘿
雪    币: 677
活跃值: 活跃值 (2888)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
珍惜Any 活跃值 2020-12-25 21:25
7
0
蟑螂一号 你这个>=Android10估计也会歇菜吧
不会呦
雪    币: 611
活跃值: 活跃值 (575)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mb_foyotena 活跃值 2020-12-25 21:39
8
0
虽然是老手段了,但还是支持一下
雪    币: 611
活跃值: 活跃值 (575)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mb_foyotena 活跃值 2020-12-25 21:40
9
0
穿透还以为可以越权获取呢,可以就nb了
雪    币: 59
活跃值: 活跃值 (408)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
iceway 活跃值 2020-12-25 22:43
10
0
标题起的太奇怪了,什么穿透,我以为是虚拟机穿透,就是调用个syscall。。。
雪    币: 677
活跃值: 活跃值 (2888)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
珍惜Any 活跃值 2020-12-25 23:05
11
0
iceway 标题起的太奇怪了,什么穿透,我以为是虚拟机穿透,就是调用个syscall。。。
雪    币: 948
活跃值: 活跃值 (470)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
seandong 活跃值 2020-12-26 01:41
12
0
这不是很常规的做法吗
雪    币: 257
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_oagkgfne 活跃值 2020-12-26 23:09
13
0
https://bbs.pediy.com/thread-264142.htm 大佬 这个可以搞吗
雪    币: 804
活跃值: 活跃值 (473)
能力值: (RANK:400 )
在线值:
发帖
回帖
粉丝
莫灰灰 活跃值 9 2020-12-28 10:43
14
0
这招在iOS上其实挺好用的;Android上的话,有些黑产用自编译内核,在内核层进行的过滤,这招就有局限了。
雪    币: 677
活跃值: 活跃值 (2888)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
珍惜Any 活跃值 2020-12-28 14:25
15
0
莫灰灰 这招在iOS上其实挺好用的;Android上的话,有些黑产用自编译内核,在内核层进行的过滤,这招就有局限了。
确实
雪    币: 190
活跃值: 活跃值 (399)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
FIGHTING安 活跃值 1 2020-12-28 16:29
16
0
这种方式兼容性是个大问题。会有各种莫名奇妙的Crash。
雪    币: 9
活跃值: 活跃值 (218)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Qira 活跃值 2020-12-29 16:07
17
0
以前测试arm64的时候,发现华为,小米,google 的系统调用号不一样,不知道这块怎么兼容
雪    币: 2078
活跃值: 活跃值 (1166)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 2021-1-13 16:16
18
0
Qira 以前测试arm64的时候,发现华为,小米,google 的系统调用号不一样,不知道这块怎么兼容
采集全 调用号
雪    币: 251
活跃值: 活跃值 (266)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
327135569 活跃值 2021-3-23 22:43
19
0
除了刷内核, 写LKM, ptrace, 另外拿ida扫一下 svc, swi 啥的通通 hook 掉也是个办法.
雪    币: 677
活跃值: 活跃值 (2888)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
珍惜Any 活跃值 2021-3-24 10:36
20
0
327135569 除了刷内核, 写LKM, ptrace, 另外拿ida扫一下 svc, swi 啥的通通 hook 掉也是个办法.
确实是一种办法如果可以ptrace上去,也可以进行拦截的。
雪    币: 1358
活跃值: 活跃值 (629)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Amun 活跃值 2021-3-25 15:41
21
0
能介绍一下 GS虚拟机 是怎么拦截 syscall 的吗?gVisor 是 Ptrace 或 kvm,Android上kvm行不通,但这虚拟机的进程里也是 TracerPid:0
雪    币: 677
活跃值: 活跃值 (2888)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
珍惜Any 活跃值 2021-3-27 15:10
22
0
Amun 能介绍一下 GS虚拟机 是怎么拦截 syscall 的吗?gVisor 是 Ptrace 或 kvm,Android上kvm行不通,但这虚拟机的进程里也是 TracerPid:0
就是ptrace
游客
登录 | 注册 方可回帖
返回