android逆向总结
首先项目里的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逆向出来的结果
这个函数逻辑是:
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。
android逆向总结的更多相关文章
- [转]Android逆向之动态调试总结
一.在SO中关键函数上下断点 刚学逆向调试时.大多都满足于在SO中某关键函数上下断点.然后通过操作应用程序,去触发这个断点,然后进行调试 详细的步骤可以参见非虫大大的<Android软件安全与逆 ...
- android逆向学习小结--CrackMe_1
断断续续的总算的把android开发和逆向的这两本书看完了,虽然没有java,和android开发的基础,但总体感觉起来还是比较能接收的,毕竟都是触类旁通的.当然要深入的话还需要对这门语言的细节特性和 ...
- Android逆向之so的半自动化逆向
因为工作需要,转型干android逆向,有几个月了.不过对于so的逆向,任然停留在,难难难的阶段,虽然上次自己还是逆向了一个15k左右的小so文件,但是,那个基本是靠,一步一步跟代码,查看堆栈信息来自 ...
- Android逆向破解表单注册程序
Android逆向破解表单注册程序 Android开发 ADT: android studio(as) 程序界面如下,注册码为6位随机数字,注册成功时弹出通知注册成功,注册失败时弹出通知注册失败. 布 ...
- Android逆向破解表单登录程序
Android逆向破解表单登录程序 Android开发 ADT: android studio(as) 程序界面如下,登录成功时弹出通知登录成功,登录失败时弹出通知登录失败. 布局代码 <?xm ...
- Android逆向之静态分析
想必打过CTF的小伙伴多多少少都触过Android逆向,所以斗哥将给大家整一期关于Android逆向的静态分析与动态分析.本期先带来Android逆向的静态分析,包括逆向工具使用.文件说明.例题解析等 ...
- Android 逆向实战篇(加密数据包破解)
1. 实战背景由于工作需要,要爬取某款App的数据,App的具体名称此处不便透露,避免他们发现并修改加密逻辑我就得重新破解了. 爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长, ...
- 【转】Android逆向入门流程
原文:https://www.jianshu.com/p/71fb7ccc05ff 0.写在前面 本文是笔者自学笔记,以破解某目标apk的方式进行学习,中间辅以原理性知识,方便面试需求. 参考文章的原 ...
- Android逆向之smali
Android逆向之smali 头信息 smail文件前三行 .class <访问权限> [关键修饰字] <类名>; .super <父类名>; .source & ...
- Android逆向学习资料
Android逆向基础之Dalvik虚拟机: https://lyxw.github.io/archivers/Android%E9%80%86%E5%90%91%E5%9F%BA%E7%A1%80% ...
随机推荐
- std::multimap
标准库还定义了一个 multimap 容器,它与 map 类似,所不同的是它允许重复键. 成员函数 insert() make_pair() 辅助函数来完成此任务. find(k) 返回指向第一个与键 ...
- PowerShell渗透--Empire(二)
权限提升 Bypass UAC usemodule powershell/privesc/bypassuac 设置listener execute list查看 usemodule powershel ...
- echarts折线图动态改变数据时的一个bug
echarts折线图中当增加dataZoom,修改start大于0的时候,会出现折线混乱,变成竖直的线,绘制有问题. 解决方法,在dataZoom中增加filterMode: 'empty' http ...
- Sentinel Getting Started And Integration of Spring Cloud Alibaba Tutorials
原文链接:Sentinel Getting Started And Integration of Spring Cloud Alibaba Tutorials Sentinel Getting Sta ...
- vue-cli3 搭建 vue 项目
vue-cli3 搭建 vue 项目 项目是在mac的环境下配置的 win的同学请移步[https://www.cnblogs.com/zhaomeizi/p/8483597.html] 安装 nod ...
- 百万年薪python之路 -- 面向对象之:类空间问题以及类之间的关系
面向对象之:类空间问题以及类之间的关系 1.从空间角度研究类 1.何处添加对象属性 class A: def __init__(self,name): self.name = name def fun ...
- Veins(车载通信仿真框架)入门教程
Veins入门教程——教你如何下手研究 目录 Veins入门教程——教你如何下手研究 目录 废话少说! 讲解omnetpp.ini!(挑关键的) 讲解RSUExampleScnario.ned! 注意 ...
- APP打包设置程序版本号
正确设置方式是: 注意,以下修改不会起作用<manifestxmlns:android="http://schemas.android.com/apk/res/android" ...
- 怎样通过excel录入来批量造数据
背景: 自动化测试除了验证系统功能外,还能够为测试人员根据测试要求造数据实现测试需要!但是一般的自动化测试,都是在编写脚本的时候,写死在程序里的.所以本文是为了在满足系统操作流程的基础上,根据测试的要 ...
- Scrapy 之settings配置
BOT_NAME 默认: 'scrapybot' 当您使用 startproject 命令创建项目时其也被自动赋值. ROBOTSTXT_OBEY = False 是否遵守rebotes.txt协议 ...