获取此 .so 文件中使用的算法

逆向工程 拆卸 部件
2021-06-20 20:28:40

我一直在尝试对 BLE“Smartlock”进行逆向工程,以使用 Python 而不是它附带的应用程序打开它。

我在拆卸他们提供的 SDK、识别 BLE 数据包、标头等方面取得了很大进展,但现在我被卡住了。它在 Java 库中包含一个 .so 文件,该文件负责对从锁发送和发送到锁的数据进行编码和解码。它接受两个参数并返回加密或解密的数据:

// .java - The data as a byte array and a single byte to somehow encrypt it all
public static native byte[] decodeWithEncryptByte(byte[] dataByteArray, byte encryptByte);

也许它甚至是一个众所周知/有名字的算法,但我完全被困住了。任何提示都会有所帮助,即使是人类可读的伪代码!

decodeWithEncriptByte部分如下:

.text:00000a20 <Java_com_scaf_android_client_CodecUtils_decodeWithEncrypt>:
.text:00000a20 55                               push   %ebp
.text:00000a21 57                               push   %edi
.text:00000a22 56                               push   %esi
.text:00000a23 53                               push   %ebx
.text:00000a24 e8 97 fb ff ff                   call   0x000005c0
.text:00000a29 81 c3 b7 25 00 00                add    $0x25b7,%ebx
.text:00000a2f 8d 64 24 c4                      lea    -0x3c(%esp),%esp
.text:00000a33 8b 74 24 50                      mov    0x50(%esp),%esi
.text:00000a37 0f b6 44 24 5c                   movzbl 0x5c(%esp),%eax
.text:00000a3c 8b 4c 24 58                      mov    0x58(%esp),%ecx
.text:00000a40 88 44 24 2f                      mov    %al,0x2f(%esp)
.text:00000a44 8b 06                            mov    (%esi),%eax
.text:00000a46 89 4c 24 04                      mov    %ecx,0x4(%esp)
.text:00000a4a c7 44 24 08 00 00 00 00          movl   $0x0,0x8(%esp)
.text:00000a52 89 34 24                         mov    %esi,(%esp)
.text:00000a55 ff 90 e0 02 00 00                call   *0x2e0(%eax)
.text:00000a5b 8b 7c 24 58                      mov    0x58(%esp),%edi
.text:00000a5f 89 44 24 20                      mov    %eax,0x20(%esp)
.text:00000a63 8b 06                            mov    (%esi),%eax
.text:00000a65 89 7c 24 04                      mov    %edi,0x4(%esp)
.text:00000a69 89 34 24                         mov    %esi,(%esp)
.text:00000a6c ff 90 ac 02 00 00                call   *0x2ac(%eax)
.text:00000a72 89 c5                            mov    %eax,%ebp
.text:00000a74 8b 06                            mov    (%esi),%eax
.text:00000a76 89 6c 24 04                      mov    %ebp,0x4(%esp)
.text:00000a7a 89 34 24                         mov    %esi,(%esp)
.text:00000a7d ff 90 c0 02 00 00                call   *0x2c0(%eax)
.text:00000a83 8b 4c 24 20                      mov    0x20(%esp),%ecx
.text:00000a87 89 c7                            mov    %eax,%edi
.text:00000a89 8b 06                            mov    (%esi),%eax
.text:00000a8b 89 4c 24 10                      mov    %ecx,0x10(%esp)
.text:00000a8f 89 6c 24 0c                      mov    %ebp,0xc(%esp)
.text:00000a93 c7 44 24 08 00 00 00 00          movl   $0x0,0x8(%esp)
.text:00000a9b 89 7c 24 04                      mov    %edi,0x4(%esp)
.text:00000a9f 89 34 24                         mov    %esi,(%esp)
.text:00000aa2 ff 90 40 03 00 00                call   *0x340(%eax)
.text:00000aa8 8b 06                            mov    (%esi),%eax
.text:00000aaa c7 44 24 08 00 00 00 00          movl   $0x0,0x8(%esp)
.text:00000ab2 89 7c 24 04                      mov    %edi,0x4(%esp)
.text:00000ab6 89 34 24                         mov    %esi,(%esp)
.text:00000ab9 ff 90 e0 02 00 00                call   *0x2e0(%eax)
.text:00000abf 89 44 24 24                      mov    %eax,0x24(%esp)
.text:00000ac3 8b 06                            mov    (%esi),%eax
.text:00000ac5 89 7c 24 04                      mov    %edi,0x4(%esp)
.text:00000ac9 89 34 24                         mov    %esi,(%esp)
.text:00000acc ff 90 ac 02 00 00                call   *0x2ac(%eax)
.text:00000ad2 89 44 24 28                      mov    %eax,0x28(%esp)
.text:00000ad6 85 c0                            test   %eax,%eax
.text:00000ad8 7e 3f                            jle    0x00000b19
.text:00000ada 8b 7c 24 24                      mov    0x24(%esp),%edi
.text:00000ade 89 c1                            mov    %eax,%ecx
.text:00000ae0 89 74 24 50                      mov    %esi,0x50(%esp)
.text:00000ae4 0f b6 e8                         movzbl %al,%ebp
.text:00000ae7 0f b6 74 24 2f                   movzbl 0x2f(%esp),%esi
.text:00000aec 89 f8                            mov    %edi,%eax
.text:00000aee 01 cf                            add    %ecx,%edi
.text:00000af0 8b 8b fc ff ff ff                mov    -0x4(%ebx),%ecx
.text:00000af6 8d 76 00                         lea    0x0(%esi),%esi
.text:00000af9 8d bc 27 00 00 00 00             lea    0x0(%edi,%eiz,1),%edi
.text:00000b00 89 f2                            mov    %esi,%edx
.text:00000b02 83 c0 01                         add    $0x1,%eax
.text:00000b05 32 50 ff                         xor    -0x1(%eax),%dl
.text:00000b08 88 50 ff                         mov    %dl,-0x1(%eax)
.text:00000b0b 32 14 29                         xor    (%ecx,%ebp,1),%dl
.text:00000b0e 88 50 ff                         mov    %dl,-0x1(%eax)
.text:00000b11 39 f8                            cmp    %edi,%eax
.text:00000b13 75 eb                            jne    0x00000b00
.text:00000b15 8b 74 24 50                      mov    0x50(%esp),%esi
.text:00000b19 8b 7c 24 28                      mov    0x28(%esp),%edi
.text:00000b1d 8b 06                            mov    (%esi),%eax
.text:00000b1f 89 34 24                         mov    %esi,(%esp)
.text:00000b22 89 7c 24 04                      mov    %edi,0x4(%esp)
.text:00000b26 ff 90 c0 02 00 00                call   *0x2c0(%eax)
.text:00000b2c 8b 4c 24 24                      mov    0x24(%esp),%ecx
.text:00000b30 8b 16                            mov    (%esi),%edx
.text:00000b32 89 7c 24 0c                      mov    %edi,0xc(%esp)
.text:00000b36 89 4c 24 10                      mov    %ecx,0x10(%esp)
.text:00000b3a 89 44 24 04                      mov    %eax,0x4(%esp)
.text:00000b3e 89 34 24                         mov    %esi,(%esp)
.text:00000b41 c7 44 24 08 00 00 00 00          movl   $0x0,0x8(%esp)
.text:00000b49 89 44 24 24                      mov    %eax,0x24(%esp)
.text:00000b4d ff 92 40 03 00 00                call   *0x340(%edx)
.text:00000b53 8b 44 24 20                      mov    0x20(%esp),%eax
.text:00000b57 8b 16                            mov    (%esi),%edx
.text:00000b59 89 34 24                         mov    %esi,(%esp)
.text:00000b5c 89 44 24 08                      mov    %eax,0x8(%esp)
.text:00000b60 8b 44 24 58                      mov    0x58(%esp),%eax
.text:00000b64 c7 44 24 0c 00 00 00 00          movl   $0x0,0xc(%esp)
.text:00000b6c 89 44 24 04                      mov    %eax,0x4(%esp)
.text:00000b70 ff 92 00 03 00 00                call   *0x300(%edx)
.text:00000b76 8b 44 24 24                      mov    0x24(%esp),%eax
.text:00000b7a 8d 64 24 3c                      lea    0x3c(%esp),%esp
.text:00000b7e 5b                               pop    %ebx
.text:00000b7f 5e                               pop    %esi
.text:00000b80 5f                               pop    %edi
.text:00000b81 5d                               pop    %ebp
.text:00000b82 c3                               ret    
.text:00000b83 8d b6 00 00 00 00                lea    0x0(%esi),%esi
.text:00000b89 8d bc 27 00 00 00 00             lea    0x0(%edi,%eiz,1),%edi

同样,编码过程可能非常相似。

我已经使用在线反汇编程序来分析程序集,如果有人知道这里发生了什么,那么打开的文件也可以在那里找到!

非常感谢任何帮助

编辑:该文件在此处可用:https : //github.com/ttlock/Android_SDK_Demo/blob/master/app/libs/ttlock-release-3.0.7.aar

要查看有问题的具体文件,您只需要下载它并解压缩它,里面是一个以jni/同一事物的不同架构命名的文件夹

该设备是一个 TTLock,我希望对其进行逆向工程以使其完全开源,以便人们可以为锁创建自定义网关,允许它在本地工作(当前网关仅支持 Web 操作...并为此致电中国)。我这里有 5 个 TTLocks,虽然它们是很好的锁,但当互联网关闭时它们不能在 LAN 上工作,这真是令人失望。

2个回答

dscrc_table声明了一个 256 字节的表,解密循环是一个单行:

  for( int i = 0; i < vNewByteArrayLen; ++i )
    vNewByteArrayElts[i] ^= a4KeyByte ^ dscrc_table[vNewByteArrayLen];

在 GitHub 上查看我的要点

编辑:这东西真的是用来保护你的门不被未经授权的人打开的吗?把它扔掉!

罗尔夫给出了一个很好的答案,将他的要点与您在 ghidra 中编辑的文件上的几分钟 ghidra 进行比较,确实给出了几乎相同的伪代码

看着 JniEnv 它被定义为

struct {
const struct func* Funcs;
jwhatever GetSomeJava(jsomething foo, jotherthing blah) {
return funcs->GetSomeJava(…...);
}
229 function ptrs like this 
}

所以创建一个带有 230 个 PVIODS 的假结构并将参数 1 重新输入为 JniEnv* ghidra 使 *代码(blah + foo )作为 Env->xn dscrc 是一个达拉斯半导体 crc 查找表

这是来自 ghidra 的伪代码

/* WARNING: Function: __i686.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */

undefined4
Java_com_scaf_android_client_CodecUtils_decodeWithEncrypt
          (JniEnv *Env,int param_2,byte *dallasarray,byte key)

{
  byte bVar1;
  int local_EAX_53;
  int local_EAX_76;
  int local_EAX_93;
  byte *local_EAX_153;
  uint uVar2;
  int i;
  byte *pbVar3;
  undefined4 uVar4;
  
  local_EAX_53 = (**(code **)((int)Env->field_0x0 + 0x2e0))(Env,dallasarray,0);
  local_EAX_76 = (**(code **)((int)Env->field_0x0 + 0x2ac))(Env,dallasarray);
  local_EAX_93 = (**(code **)((int)Env->field_0x0 + 0x2c0))(Env,local_EAX_76);
  (**(code **)((int)Env->field_0x0 + 0x340))(Env,local_EAX_93,0,local_EAX_76,local_EAX_53);
  local_EAX_153 = (byte *)(**(code **)((int)Env->field_0x0 + 0x2e0))(Env,local_EAX_93,0);
  uVar2 = (**(code **)((int)Env->field_0x0 + 0x2ac))(Env,local_EAX_93);
  if (0 < (int)uVar2) {
    i = (int)local_EAX_153;
    do {
      pbVar3 = (byte *)(i + 1);
      bVar1 = *(byte *)i;
      *(byte *)i = key ^ bVar1;
      *(byte *)i = key ^ bVar1 ^ dscrc_table[uVar2 & 0xff];
      i = (int)pbVar3;
    } while (pbVar3 != local_EAX_153 + uVar2);
  }
  uVar4 = (**(code **)((int)Env->field_0x0 + 0x2c0))(Env,uVar2);
  (**(code **)((int)Env->field_0x0 + 0x340))(Env,uVar4,0,uVar2,local_EAX_153);
  (**(code **)((int)Env->field_0x0 + 0x300))(Env,dallasarray,local_EAX_53,0);
  return uVar4;
}

从这个 ghidra 扩展JniAnalyzer导入数据类型,伪 代码 变得更好

F:\>mkdir jniana

F:\>cd jniana

F:\jniana>f:\git\bin\git.exe clone https://github.com/Ayrx/JNIAnalyzer.git

Cloning into 'JNIAnalyzer'...
remote: Enumerating objects: 347, done.
Rremote: Total 347 (delta 0), reused 0 (delta 0), pack-reused 347                                                       Recei
Receiving objects: 100% (347/347), 14.27 MiB | 102.00 KiB/s, done.
Resolving deltas: 100% (92/92), done.

F:\jniana>dir /b /s *.gdt
F:\jniana\JNIAnalyzer\JNIAnalyzer\data\jni_all.gdt

F:\jniana>f:\ghidra912\ghidraRun.bat

click the small black arrow in Data Type Manager 
Open File Archieve 
Navigate to this gdt and load it 

Select the Function in decompiler and Edit Function Signature 
Retype the First Argument to JniEnv* and see the differnece 
as below 

为第一个参数 JniEnv * param1 添加正确类型后的伪代码

jbyteArray
Java_com_scaf_android_client_CodecUtils_decodeWithEncrypt
          (JNIEnv *Env,int Unused,jbyteArray param_3,byte param_4)

{
  byte bVar1;
  jbyte *buf;
  jsize len;
  jbyteArray array;
  byte *buf_00;
  uint len_00;
  byte *pbVar2;
  byte *pbVar3;
  
  buf = (*(*Env)->GetByteArrayElements)((JNIEnv *)Env,param_3,(jboolean *)0x0);
  len = (*(*Env)->GetArrayLength)((JNIEnv *)Env,(jarray)param_3);
  array = (*(*Env)->NewByteArray)((JNIEnv *)Env,len);
  (*(*Env)->SetByteArrayRegion)((JNIEnv *)Env,array,0,len,buf);
  buf_00 = (byte *)(*(*Env)->GetByteArrayElements)((JNIEnv *)Env,array,(jboolean *)0x0);
  len_00 = (*(*Env)->GetArrayLength)((JNIEnv *)Env,(jarray)array);
  if (0 < (int)len_00) {
    pbVar2 = buf_00;
    do {
      pbVar3 = pbVar2 + 1;
      bVar1 = *pbVar2;
      *pbVar2 = param_4 ^ bVar1;
      *pbVar2 = param_4 ^ bVar1 ^ dscrc_table[len_00 & 0xff];
      pbVar2 = pbVar3;
    } while (pbVar3 != buf_00 + len_00);
  }
  array = (*(*Env)->NewByteArray)((JNIEnv *)Env,len_00);
  (*(*Env)->SetByteArrayRegion)((JNIEnv *)Env,array,0,len_00,(jbyte *)buf_00);
  (*(*Env)->ReleaseByteArrayElements)((JNIEnv *)Env,param_3,buf,0);
  return array;
}