一尘不染

NDK应用程序签名检查

java

我在应用程序中有一些安全密钥。我想安全地存储它。我喜欢将其存储在本地共享库中(可能是从某些代码生成的)。之后,我希望它通过一种将检查原始APK签名的方法返回。因此,除了受信任的应用程序之外,没有人可以使用此文件。我知道,ndk库也可以反编译,但这要比Java
.class文件更难于对本机代码进行逆向工程。

题:

  1. 有没有办法从本机代码(c / c ++)中获取原始apk的签名?
  2. 如何确保从受信任的应用程序调用该库?

阅读 218

收藏
2020-12-03

共1个答案

一尘不染

我将在这里回答您的第一个问题:

应用程序的签名存储在APK的DEX(Dalvik可执行文件)文件中。DEX文件具有以下结构:

  1. 标头
  2. 数据部分 (包含字符串,代码指令,字段等)
  3. *方法标识符,类标识符等的 *数组

因此,这是DEX文件头的开头:

  1. DEX_FILE_MAGIC 常数 -ubyte [8]
  2. *您的应用程序的 *Adler-32校验和 (DEX_FILE_MAGIC和校验和本身除外)-uint
  3. *应用程序的 *SHA-1签名 (DEX_FILE_MAGIC,校验和和哈希本身除外)-ubyte [20]

因此,要确定apk的签名,您应该从偏移量32开始计算DEX文件的SHA-1签名。

要从本地代码访问apk的DEX文件,您可以读取过程内存,该内存存储在/ proc / self / maps中:

FILE *fp;
fp = fopen("/proc/self/maps", "r");

proc / $ ID / maps文件中的每一行都具有以下结构:

  1. 地址
  2. 权限
  3. 抵消
  4. 设备
  5. 索引节点
  6. 路径名

在这里,您可以找到对proc / $ ID / maps文件结构的更好描述:了解Linux / proc / id /
maps

要检测DEX文件在进程内存中的位置,您应该在proc / self / maps文件的每一行中检出“
pathname”列。当找到与DEX文件对应的行时,您应该获得DEX文件区域的开始和结束地址:

while (fgets(line, 2048, fp) != NULL) {
    // search for '.dex'
    if (strstr(line, ".dex") != NULL) {
        // get starting and ending addresses of the DEX file region

因此,当您具有apk字节码的起始地址和结束地址时,便可以计算apk的签名。

2020-12-03