首先项目里的java文件,以及项目引用到的第三方jar或aar包里面的class,统统都编译成classes.dex放在apk包的根目录,项目的资源目录和AndroidManifest.xml被处理生成资源目录和resource.arsc以及AndroidManifest.xml文件放到apk包根目录。

apk包安装到android后,apk包被复制到/data/app目录,应用程序每次启动后就会加载这个apk,访问里面的资源。而为了加快执行,apk包根目录的classes.dex会已经arch优化成odex,放在/data/dalvik_cache目录。应用程序加载的执行代码就是这个odex。apk包的lib目录下的所有文件(主要是so第三方c库)都会从apk包复制到/data/lib。

当我们对一个普通的apk包分析时,res目录下的xml和根目录下的AndroidManifest.xml都在打包时被处理过,不能直接阅读。这些xml文件都是可执行的脚本描述。而执行文件classes.dex则是我们希望反编译汇编代码进行分析的。apktool这个工具的主要逆向功能就是,将res目录下的xml和AndroidManifest.xml文件还原释放出来,以及将classes.dex反汇编成smali。

android系统自带有反汇编工具,/usr/xbin/dexdump。这个工具可以直接从odex反汇编出smali描述出来。

下面常用的反编译工具和各种文件之间的转换。

这里有4种工具,

oat2dex,将odex或oat转换出dex。

d2j工具套,虚拟机机器指令和可执行包之间的assemble和disassemble,以及Davlik虚拟机可执行文件dex和java虚拟机执行包之间的转换。dex可以反汇编出smali,而class可以反汇编出j。

代码逆向工具,smali2java就是将smali翻译出java文件,DJ JavaDecomplier就是将class或java虚拟机指令反向出java文件。这两个工具都不能很好地对控制逻辑(条件控制,循环控制,跳转)进行翻译。smali2java面对稍复杂一点的控制逻辑就不工作,它的翻译函数异常没有结果。而DJ JavaDecomplier面对稍复杂一点的控制逻辑,它的逆向代码与其它语言的逆向工具的逆向代码一样,天书一样多的跳标签,不是人类阅读的。

注,这里说Java有跳转,是指catch,熟悉c++,oc反汇编都明白,在异常处理代码就是在做跳转。而在java机器指令或smali指令中,异常也是有专门的跳转指令和标签。

下面是我对百度加固baiduprotect的StubApplication.smali进行人工逆向的java代码

 .method private static loadX86Library()V
.locals .prologue
.line
const/ v24, 0x0 .line
.local v24, "packageName":Ljava/lang/String;
const/ v4, 0x0 .line
.local v4, "apkPath":Ljava/lang/String;
invoke-static {}, Lcom/baidu/protect/StubApplication;->is64BitEnv()Z move-result v15 .line
.local v15, "is_x86_64":Z
:try_start_0
new-instance v5, Ljava/io/BufferedReader; new-instance v30, Ljava/io/InputStreamReader; .line
new-instance v31, Ljava/io/FileInputStream; const-string v32, "/proc/self/maps" invoke-direct/range {v31 .. v32}, Ljava/io/FileInputStream;-><init>(Ljava/lang/String;)V invoke-direct/range {v30 .. v31}, Ljava/io/InputStreamReader;-><init>(Ljava/io/InputStream;)V .line
move-object/from16 v0, v30 invoke-direct {v5, v0}, Ljava/io/BufferedReader;-><init>(Ljava/io/Reader;)V .line
.local v5, "br":Ljava/io/BufferedReader;
invoke-virtual {v5}, Ljava/io/BufferedReader;->readLine()Ljava/lang/String; move-result-object v19 .local v19, "line":Ljava/lang/String;
:goto_0
if-nez v19, :cond_3 .line
:goto_1
invoke-virtual {v5}, Ljava/io/BufferedReader;->close()V
:try_end_0
.catch Ljava/io/IOException; {:try_start_0 .. :try_end_0} :catch_0 .line
.end local v5 # "br":Ljava/io/BufferedReader;
.end local v19 # "line":Ljava/lang/String;
:goto_2
if-eqz v15, :cond_a .line
const-string v28, "libbaiduprotect_x86_64.so" .line
.local v28, "soname":Ljava/lang/String;
:goto_3
if-eqz v4, :cond_2 if-eqz v24, :cond_2 .line
const-wide/ v12, 0x0 .line
.local v12, "fileModified":J
const-wide/ v22, 0x0 .line
.local v22, "newFileModified":J
invoke-static/range {v24 .. v24}, Lcom/baidu/protect/StubApplication;->getDataFolder(Ljava/lang/String;)Ljava/lang/String; move-result-object v7 .line
.local v7, "dataFolder":Ljava/lang/String;
new-instance v30, Ljava/lang/StringBuilder; invoke-static {v7}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String; move-result-object v31 invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V move-object/from16 v0, v30 move-object/from16 v1, v24 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v30 const-string v31, "/.x86lib/" invoke-virtual/range {v30 .. v31}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v30 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v18 .line
.local v18, "libTargetFolder":Ljava/lang/String;
new-instance v30, Ljava/lang/StringBuilder; invoke-static/range {v18 .. v18}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String; move-result-object v31 invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V move-object/from16 v0, v30 move-object/from16 v1, v28 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v30 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v17 .line
.local v17, "libPath":Ljava/lang/String;
new-instance v9, Ljava/io/File; move-object/from16 v0, v18 invoke-direct {v9, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V .line
.local v9, "f":Ljava/io/File;
invoke-virtual {v9}, Ljava/io/File;->exists()Z move-result v30 if-nez v30, :cond_0 .line
invoke-virtual {v9}, Ljava/io/File;->mkdir()Z .line
:cond_0
:try_start_1
new-instance v30, Ljava/lang/StringBuilder; const-string v31, "assets/" invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V move-object/from16 v0, v30 move-object/from16 v1, v28 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v30 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v27 .line
.local v27, "soEntryName":Ljava/lang/String;
new-instance v21, Ljava/util/zip/ZipInputStream; new-instance v30, Ljava/io/FileInputStream; move-object/from16 v0, v30 invoke-direct {v0, v4}, Ljava/io/FileInputStream;-><init>(Ljava/lang/String;)V move-object/from16 v0, v21 move-object/from16 v1, v30 invoke-direct {v0, v1}, Ljava/util/zip/ZipInputStream;-><init>(Ljava/io/InputStream;)V .line
.local v21, "localZipInputStream":Ljava/util/zip/ZipInputStream;
:goto_4
invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->getNextEntry()Ljava/util/zip/ZipEntry; move-result-object v20 .line
.local v20, "localZipEntry":Ljava/util/zip/ZipEntry;
if-nez v20, :cond_b .line
:cond_1
:goto_5
invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->close()V
:try_end_1
.catch Ljava/io/IOException; {:try_start_1 .. :try_end_1} :catch_1 .line
.end local v20 # "localZipEntry":Ljava/util/zip/ZipEntry;
.end local v21 # "localZipInputStream":Ljava/util/zip/ZipInputStream;
.end local v27 # "soEntryName":Ljava/lang/String;
:goto_6
invoke-static/range {v17 .. v17}, Ljava/lang/System;->load(Ljava/lang/String;)V .line
.end local v7 # "dataFolder":Ljava/lang/String;
.end local v9 # "f":Ljava/io/File;
.end local v12 # "fileModified":J
.end local v17 # "libPath":Ljava/lang/String;
.end local v18 # "libTargetFolder":Ljava/lang/String;
.end local v22 # "newFileModified":J
:cond_2
return-void .line
.end local v28 # "soname":Ljava/lang/String;
.restart local v5 # "br":Ljava/io/BufferedReader;
.restart local v19 # "line":Ljava/lang/String;
:cond_3
:try_start_2
const-string v30, ".apk" move-object/from16 v0, v19 move-object/from16 v1, v30 invoke-virtual {v0, v1}, Ljava/lang/String;->endsWith(Ljava/lang/String;)Z move-result v30 if-eqz v30, :cond_5 .line
sget-object v30, Ljava/lang/System;->out:Ljava/io/PrintStream; new-instance v31, Ljava/lang/StringBuilder; const-string v32, "Wigan:line=" invoke-direct/range {v31 .. v32}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V move-object/from16 v0, v31 move-object/from16 v1, v19 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v31 invoke-virtual/range {v31 .. v31}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v31 invoke-virtual/range {v30 .. v31}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V .line
const-string v30, " " move-object/from16 v0, v19 move-object/from16 v1, v30 invoke-virtual {v0, v1}, Ljava/lang/String;->split(Ljava/lang/String;)[Ljava/lang/String; move-result-object v26 .line
.local v26, "s":[Ljava/lang/String;
move-object/from16 v0, v26 array-length v0, v0 move/from16 v30, v0 add-int/lit8 v30, v30, -0x1 aget-object v25, v26, v30 .line
.local v25, "path":Ljava/lang/String;
const-string v30, "/mnt/asec/" move-object/from16 v0, v25 move-object/from16 v1, v30 invoke-virtual {v0, v1}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z move-result v30 if-nez v30, :cond_4 const-string v30, "/data/app/" move-object/from16 v0, v25 move-object/from16 v1, v30 invoke-virtual {v0, v1}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z move-result v30 if-eqz v30, :cond_6 .line
:cond_4
const/ v30, 0xa move-object/from16 v0, v25 move/from16 v1, v30 invoke-virtual {v0, v1}, Ljava/lang/String;->substring(I)Ljava/lang/String; move-result-object v3 .line
.local v3, "apkName":Ljava/lang/String;
:goto_7
const/ v30, 0x2d move/from16 v0, v30 invoke-virtual {v3, v0}, Ljava/lang/String;->lastIndexOf(I)I move-result v16 .line
.local v16, "lastIndex":I
const/ v30, -0x1 move/from16 v0, v16 move/from16 v1, v30 if-ne v0, v1, :cond_8 .line
.end local v3 # "apkName":Ljava/lang/String;
.end local v16 # "lastIndex":I
.end local v25 # "path":Ljava/lang/String;
.end local v26 # "s":[Ljava/lang/String;
:cond_5
invoke-virtual {v5}, Ljava/io/BufferedReader;->readLine()Ljava/lang/String; move-result-object v19 goto/ :goto_0 .line
.restart local v25 # "path":Ljava/lang/String;
.restart local v26 # "s":[Ljava/lang/String;
:cond_6
const-string v30, "/app/" move-object/from16 v0, v25 move-object/from16 v1, v30 invoke-virtual {v0, v1}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z move-result v30 if-eqz v30, :cond_7 .line
const/ v30, 0x5 move-object/from16 v0, v25 move/from16 v1, v30 invoke-virtual {v0, v1}, Ljava/lang/String;->substring(I)Ljava/lang/String; move-result-object v3 .line
.restart local v3 # "apkName":Ljava/lang/String;
goto :goto_7 .line
.end local v3 # "apkName":Ljava/lang/String;
:cond_7
const-string v30, "/mnt/asec2/[2]" move-object/from16 v0, v25 move-object/from16 v1, v30 invoke-virtual {v0, v1}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z move-result v30 if-eqz v30, :cond_5 .line
const/ v30, 0xe move-object/from16 v0, v25 move/from16 v1, v30 invoke-virtual {v0, v1}, Ljava/lang/String;->substring(I)Ljava/lang/String; move-result-object v3 .restart local v3 # "apkName":Ljava/lang/String;
goto :goto_7 .line
.restart local v16 # "lastIndex":I
:cond_8
const/ v30, 0x0 move/from16 v0, v30 move/from16 v1, v16 invoke-virtual {v3, v0, v1}, Ljava/lang/String;->substring(II)Ljava/lang/String; move-result-object v29 .line
.local v29, "tmpPackageName":Ljava/lang/String;
move-object/from16 v24, v29 .line
if-eqz v15, :cond_9 .line
const/ v30, 0x2f move/from16 v0, v30 invoke-virtual {v3, v0}, Ljava/lang/String;->lastIndexOf(I)I move-result v16 .line
const/ v30, -0x1 move/from16 v0, v16 move/from16 v1, v30 if-eq v0, v1, :cond_5 .line
const/ v30, 0x0 move/from16 v0, v30 move/from16 v1, v16 invoke-virtual {v3, v0, v1}, Ljava/lang/String;->substring(II)Ljava/lang/String; move-result-object v2 .line
.local v2, "apkInstallName":Ljava/lang/String;
new-instance v9, Ljava/io/File; new-instance v30, Ljava/lang/StringBuilder; const-string v31, "/data/app/" invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V move-object/from16 v0, v30 invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v30 const-string v31, "/lib/x86_64/libbaiduprotect.so" invoke-virtual/range {v30 .. v31}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v30 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v30 move-object/from16 v0, v30 invoke-direct {v9, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V .line
.restart local v9 # "f":Ljava/io/File;
invoke-virtual {v9}, Ljava/io/File;->exists()Z move-result v30 if-eqz v30, :cond_5 .line
move-object/from16 v24, v29 .line
new-instance v30, Ljava/lang/StringBuilder; const-string v31, "/data/app/" invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V move-object/from16 v0, v30 invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v30 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v4 .line
goto/ :goto_1 .line
.end local v2 # "apkInstallName":Ljava/lang/String;
.end local v9 # "f":Ljava/io/File;
:cond_9
new-instance v9, Ljava/io/File; new-instance v30, Ljava/lang/StringBuilder; const-string v31, "/data/data/" invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V move-object/from16 v0, v30 move-object/from16 v1, v29 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v30 const-string v31, "/lib/libbaiduprotect.so" invoke-virtual/range {v30 .. v31}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v30 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v30 move-object/from16 v0, v30 invoke-direct {v9, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V .line
.restart local v9 # "f":Ljava/io/File;
invoke-virtual {v9}, Ljava/io/File;->exists()Z
:try_end_2
.catch Ljava/io/IOException; {:try_start_2 .. :try_end_2} :catch_0 move-result v30 if-eqz v30, :cond_5 .line
move-object/from16 v24, v29 .line
move-object/from16 v4, v25 .line
goto/ :goto_1 .line
.end local v3 # "apkName":Ljava/lang/String;
.end local v5 # "br":Ljava/io/BufferedReader;
.end local v9 # "f":Ljava/io/File;
.end local v16 # "lastIndex":I
.end local v19 # "line":Ljava/lang/String;
.end local v25 # "path":Ljava/lang/String;
.end local v26 # "s":[Ljava/lang/String;
.end local v29 # "tmpPackageName":Ljava/lang/String;
:catch_0
move-exception v8 .line
.local v8, "e":Ljava/io/IOException;
invoke-virtual {v8}, Ljava/io/IOException;->printStackTrace()V goto/ :goto_2 .line
.end local v8 # "e":Ljava/io/IOException;
:cond_a
const-string v28, "libbaiduprotect_x86.so" .restart local v28 # "soname":Ljava/lang/String;
goto/ :goto_3 .line
.restart local v7 # "dataFolder":Ljava/lang/String;
.restart local v9 # "f":Ljava/io/File;
.restart local v12 # "fileModified":J
.restart local v17 # "libPath":Ljava/lang/String;
.restart local v18 # "libTargetFolder":Ljava/lang/String;
.restart local v20 # "localZipEntry":Ljava/util/zip/ZipEntry;
.restart local v21 # "localZipInputStream":Ljava/util/zip/ZipInputStream;
.restart local v22 # "newFileModified":J
.restart local v27 # "soEntryName":Ljava/lang/String;
:cond_b
:try_start_3
invoke-virtual/range {v20 .. v20}, Ljava/util/zip/ZipEntry;->getName()Ljava/lang/String; move-result-object v30 move-object/from16 v0, v30 move-object/from16 v1, v27 invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z move-result v30 if-eqz v30, :cond_f .line
invoke-virtual/range {v20 .. v20}, Ljava/util/zip/ZipEntry;->getTime()J move-result-wide v22 .line
new-instance v10, Ljava/io/File; move-object/from16 v0, v17 invoke-direct {v10, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V
:try_end_3
.catch Ljava/io/IOException; {:try_start_3 .. :try_end_3} :catch_1 .line
.end local v9 # "f":Ljava/io/File;
.local v10, "f":Ljava/io/File;
:try_start_4
invoke-virtual {v10}, Ljava/io/File;->exists()Z move-result v30 if-eqz v30, :cond_d .line
invoke-virtual {v10}, Ljava/io/File;->lastModified()J move-result-wide v12 .line
cmp-long v30, v12, v22 if-nez v30, :cond_c .line
invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->closeEntry()V move-object v9, v10 .line
.end local v10 # "f":Ljava/io/File;
.restart local v9 # "f":Ljava/io/File;
goto/ :goto_5 .line
.end local v9 # "f":Ljava/io/File;
.restart local v10 # "f":Ljava/io/File;
:cond_c
invoke-virtual {v10}, Ljava/io/File;->delete()Z .line
:cond_d
new-instance v11, Ljava/io/FileOutputStream; move-object/from16 v0, v17 invoke-direct {v11, v0}, Ljava/io/FileOutputStream;-><init>(Ljava/lang/String;)V .line
.local v11, "fo":Ljava/io/FileOutputStream;
const/ v30, 0x400 move/from16 v0, v30 new-array v6, v0, [B .line
.local v6, "buffer":[B
:goto_8
move-object/from16 v0, v21 invoke-virtual {v0, v6}, Ljava/util/zip/ZipInputStream;->read([B)I move-result v14 .line
.local v14, "i":I
const/ v30, -0x1 move/from16 v0, v30 if-ne v14, v0, :cond_e .line
invoke-virtual {v11}, Ljava/io/FileOutputStream;->flush()V .line
invoke-virtual {v11}, Ljava/io/FileOutputStream;->close()V .line
invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->closeEntry()V .line
new-instance v9, Ljava/io/File; move-object/from16 v0, v17 invoke-direct {v9, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V
:try_end_4
.catch Ljava/io/IOException; {:try_start_4 .. :try_end_4} :catch_2 .line
.end local v10 # "f":Ljava/io/File;
.restart local v9 # "f":Ljava/io/File;
:try_start_5
invoke-virtual {v9}, Ljava/io/File;->exists()Z move-result v30 if-eqz v30, :cond_1 .line
move-wide/from16 v0, v22 invoke-virtual {v9, v0, v1}, Ljava/io/File;->setLastModified(J)Z
:try_end_5
.catch Ljava/io/IOException; {:try_start_5 .. :try_end_5} :catch_1 goto/ :goto_5 .line
.end local v6 # "buffer":[B
.end local v11 # "fo":Ljava/io/FileOutputStream;
.end local v14 # "i":I
.end local v20 # "localZipEntry":Ljava/util/zip/ZipEntry;
.end local v21 # "localZipInputStream":Ljava/util/zip/ZipInputStream;
.end local v27 # "soEntryName":Ljava/lang/String;
:catch_1
move-exception v8 .line
.restart local v8 # "e":Ljava/io/IOException;
:goto_9
invoke-virtual {v8}, Ljava/io/IOException;->printStackTrace()V goto/ :goto_6 .line
.end local v8 # "e":Ljava/io/IOException;
.end local v9 # "f":Ljava/io/File;
.restart local v6 # "buffer":[B
.restart local v10 # "f":Ljava/io/File;
.restart local v11 # "fo":Ljava/io/FileOutputStream;
.restart local v14 # "i":I
.restart local v20 # "localZipEntry":Ljava/util/zip/ZipEntry;
.restart local v21 # "localZipInputStream":Ljava/util/zip/ZipInputStream;
.restart local v27 # "soEntryName":Ljava/lang/String;
:cond_e
const/ v30, 0x0 :try_start_6
move/from16 v0, v30 invoke-virtual {v11, v6, v0, v14}, Ljava/io/FileOutputStream;->write([BII)V
:try_end_6
.catch Ljava/io/IOException; {:try_start_6 .. :try_end_6} :catch_2 goto :goto_8 .line
.end local v6 # "buffer":[B
.end local v11 # "fo":Ljava/io/FileOutputStream;
.end local v14 # "i":I
:catch_2
move-exception v8 move-object v9, v10 .end local v10 # "f":Ljava/io/File;
.restart local v9 # "f":Ljava/io/File;
goto :goto_9 .line
:cond_f
:try_start_7
invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->closeEntry()V
:try_end_7
.catch Ljava/io/IOException; {:try_start_7 .. :try_end_7} :catch_1 goto/ :goto_4
.end method

smali指令文件

     private static void loadX86Library() {
// :( Parsing error. Please contact me.
}

smali2java逆向出的结果

 private static void loadX86Library()
{
boolean flag;
Object obj;
Object obj1;
Object obj2;
Object obj3;
Object obj5;
Object obj6;
obj2 = null;
obj1 = null;
obj5 = null;
obj6 = null;
flag = is64BitEnv();
obj3 = obj5;
obj = obj1;
BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/self/maps")));
obj3 = obj5;
obj = obj1;
String s = bufferedreader.readLine();
goto _L1
_L29:
obj3 = obj1;
obj = obj2;
bufferedreader.close();
obj = obj2;
_L17:
int i;
Object obj4;
String s1;
if(flag)
obj2 = "libbaiduprotect_x86_64.so";
else
obj2 = "libbaiduprotect_x86.so";
if(obj1 == null || obj == null) goto _L3; else goto _L2
_L2:
obj = (new StringBuilder(String.valueOf(getDataFolder(((String) (obj)))))).append(((String) (obj))).append("/.x86lib/").toString();
obj3 = (new StringBuilder(String.valueOf(obj))).append(((String) (obj2))).toString();
obj = new File(((String) (obj)));
if(!((File) (obj)).exists())
((File) (obj)).mkdir();
obj2 = (new StringBuilder("assets/")).append(((String) (obj2))).toString();
obj = new ZipInputStream(new FileInputStream(((String) (obj1))));
_L25:
obj1 = ((ZipInputStream) (obj)).getNextEntry();
if(obj1 != null) goto _L5; else goto _L4
_L4:
((ZipInputStream) (obj)).close();
_L22:
System.load(((String) (obj3)));
_L3:
return;
_L27:
obj1 = obj2;
obj3 = obj5;
obj = obj2;
if(!s.endsWith(".apk")) goto _L7; else goto _L6
_L6:
obj3 = obj5;
obj = obj2;
System.out.println((new StringBuilder("Wigan:line=")).append(s).toString());
obj3 = obj5;
obj = obj2;
obj1 = s.split(" ");
obj3 = obj5;
obj = obj2;
s1 = obj1[obj1.length - 1];
obj3 = obj5;
obj = obj2;
if(s1.startsWith("/mnt/asec/")) goto _L9; else goto _L8
_L8:
obj3 = obj5;
obj = obj2;
if(!s1.startsWith("/data/app/")) goto _L10; else goto _L9
_L9:
obj3 = obj5;
obj = obj2;
s = s1.substring(10);
_L13:
obj3 = obj5;
obj = obj2;
i = s.lastIndexOf('-');
if(i != -1) goto _L12; else goto _L11
_L11:
obj1 = obj2;
_L7:
obj3 = obj5;
obj = obj1;
s = bufferedreader.readLine();
obj2 = obj1;
continue; /* Loop/switch isn't completed */
_L10:
obj3 = obj5;
obj = obj2;
if(!s1.startsWith("/app/"))
break MISSING_BLOCK_LABEL_464;
obj3 = obj5;
obj = obj2;
s = s1.substring(5);
goto _L13
obj1 = obj2;
obj3 = obj5;
obj = obj2;
if(!s1.startsWith("/mnt/asec2/[2]")) goto _L7; else goto _L14
_L14:
obj3 = obj5;
obj = obj2;
s = s1.substring(14);
goto _L13
_L12:
obj3 = obj5;
obj = obj2;
obj2 = s.substring(0, i);
obj4 = obj2;
if(!flag)
break MISSING_BLOCK_LABEL_650;
obj3 = obj5;
obj = obj4;
i = s.lastIndexOf('/');
obj1 = obj4;
if(i == -1) goto _L7; else goto _L15
_L15:
obj3 = obj5;
obj = obj4;
s1 = s.substring(0, i);
obj1 = obj4;
obj3 = obj5;
obj = obj4;
if(!(new File((new StringBuilder("/data/app/")).append(s1).append("/lib/x86_64/libbaiduprotect.so").toString())).exists()) goto _L7; else goto _L16
_L16:
obj3 = obj5;
obj = obj2;
boolean flag1;
try
{
obj1 = (new StringBuilder("/data/app/")).append(s).toString();
continue; /* Loop/switch isn't completed */
}
// Misplaced declaration of an exception variable
catch(Object obj1)
{
((IOException) (obj1)).printStackTrace();
obj1 = obj3;
}
goto _L17
obj3 = obj5;
obj = obj4;
flag1 = (new File((new StringBuilder("/data/data/")).append(((String) (obj2))).append("/lib/libbaiduprotect.so").toString())).exists();
obj1 = obj4;
if(!flag1) goto _L7; else goto _L18
_L18:
obj1 = s1;
continue; /* Loop/switch isn't completed */
_L5:
long l;
if(!((ZipEntry) (obj1)).getName().equals(obj2))
break MISSING_BLOCK_LABEL_891;
l = ((ZipEntry) (obj1)).getTime();
obj1 = new File(((String) (obj3)));
label0:
{
if(!((File) (obj1)).exists())
break MISSING_BLOCK_LABEL_789;
if(((File) (obj1)).lastModified() != l)
break label0;
((ZipInputStream) (obj)).closeEntry();
}
goto _L4
((File) (obj1)).delete();
byte abyte0[];
obj1 = new FileOutputStream(((String) (obj3)));
abyte0 = new byte[1024];
_L23:
i = ((ZipInputStream) (obj)).read(abyte0);
if(i != -1) goto _L20; else goto _L19
_L19:
((FileOutputStream) (obj1)).flush();
((FileOutputStream) (obj1)).close();
((ZipInputStream) (obj)).closeEntry();
obj1 = new File(((String) (obj3)));
if(!((File) (obj1)).exists()) goto _L4; else goto _L21
_L21:
((File) (obj1)).setLastModified(l);
goto _L4
obj;
_L24:
((IOException) (obj)).printStackTrace();
goto _L22
_L20:
((FileOutputStream) (obj1)).write(abyte0, 0, i);
goto _L23
obj;
goto _L24
((ZipInputStream) (obj)).closeEntry();
goto _L25
_L1:
if(s != null) goto _L27; else goto _L26
_L26:
obj1 = obj6;
if(true) goto _L29; else goto _L28
_L28:
}

DJ Java Decomplier逆向出来的结果

baiduprotect`StubApplication.loadX86Library 手工逆向的结果

这个函数逻辑是:

1. 描述内存映射区间,找出加载的apk包名。

2. 在/data/app,/mnt/asec,或/mnt/asec2[2]目录下找出安装的apk,(所谓的安装就是将apk复制到固定目录下)。

3. 用压缩包方式打开apk包,找里面的assets/libbaiduprotect_${arch}.so库文件。

4. 将找到的so库文件释放到/data/data/${appname}/.${arch}目录下。

5. 更新这个so库文件的修改时间。

6. 加载这个so库文件。

虽然在/data/lib/${appname}目录已经有一个libbaiduprotect.so,但那只是个晃。加载完真正的so后,就会将apk包内的assest/baiduprotect1.jar释放到/data/data/${appname}/.1/1.jar,再将其转换成classes.dex。这两个文件都是以加密的方式,放在存储设备上的。这才是被保护的app的正体,并且baiduprotect不会直接去加载这个dex,而是在内存中解密后,用libdvm.so的jni去进行内存加载。所以你不能通过映射区间找出其映射的位置,如果你想dump它的内存映像,就会被baiduprotect发现终止app。

最新文章

  1. Html标签列表【转】
  2. Nancy之Pipelines三兄弟(Before After OnError)
  3. echarts引入及应用
  4. 【转】MyEclipse2015安装SVN插件
  5. finder怎么才能找到library
  6. http://jingyan.baidu.com/article/d169e186aa8728436611d8f3.html
  7. (转)Android之自定义适配器
  8. UVa 294 (因数的个数) Divisors
  9. Hibernate中get方法和load方法的区别
  10. C#使用itextsharp生成PDF文件
  11. HTML标签的offset、client、 scroll和currentStyle属性
  12. Oracle 12C 新特性之表分区或子分区的在线迁移
  13. python简明教程代码
  14. elasticsearch中 refresh 和flush区别(转)
  15. input,select默认颜色修改
  16. Linux之清理linux内存cache
  17. [antd-design-pro] mock 数据(post,request不一致)Sorry, we need js to run correctly!
  18. Ubuntu16.04 LTS软件中心闪退及修改阿里源
  19. docker使用自定义镜像zabbix服务
  20. c语言四则运算

热门文章

  1. 16.Nginx HTTPS实践
  2. Java 中的 final、finally、finalize 有什么不同?
  3. HashMap - 类注释
  4. 关于ArcGIS的OBJECTID生成策略拙见
  5. Android自定义控件:图形报表的实现(折线图、曲线图、动态曲线图)(View与SurfaceView分别实现图表控件)
  6. 数据存储之关系型数据库存储---MySQL存储
  7. EffectiveJava-1
  8. Netty连接处理那些事
  9. 使用Typescript重构axios(十六)——请求和响应数据配置化
  10. python学习之【第四篇】:Python中的列表及其所具有的方法