首先项目里的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。

android逆向总结的更多相关文章

  1. [转]Android逆向之动态调试总结

    一.在SO中关键函数上下断点 刚学逆向调试时.大多都满足于在SO中某关键函数上下断点.然后通过操作应用程序,去触发这个断点,然后进行调试 详细的步骤可以参见非虫大大的<Android软件安全与逆 ...

  2. android逆向学习小结--CrackMe_1

    断断续续的总算的把android开发和逆向的这两本书看完了,虽然没有java,和android开发的基础,但总体感觉起来还是比较能接收的,毕竟都是触类旁通的.当然要深入的话还需要对这门语言的细节特性和 ...

  3. Android逆向之so的半自动化逆向

    因为工作需要,转型干android逆向,有几个月了.不过对于so的逆向,任然停留在,难难难的阶段,虽然上次自己还是逆向了一个15k左右的小so文件,但是,那个基本是靠,一步一步跟代码,查看堆栈信息来自 ...

  4. Android逆向破解表单注册程序

    Android逆向破解表单注册程序 Android开发 ADT: android studio(as) 程序界面如下,注册码为6位随机数字,注册成功时弹出通知注册成功,注册失败时弹出通知注册失败. 布 ...

  5. Android逆向破解表单登录程序

    Android逆向破解表单登录程序 Android开发 ADT: android studio(as) 程序界面如下,登录成功时弹出通知登录成功,登录失败时弹出通知登录失败. 布局代码 <?xm ...

  6. Android逆向之静态分析

    想必打过CTF的小伙伴多多少少都触过Android逆向,所以斗哥将给大家整一期关于Android逆向的静态分析与动态分析.本期先带来Android逆向的静态分析,包括逆向工具使用.文件说明.例题解析等 ...

  7. Android 逆向实战篇(加密数据包破解)

    1. 实战背景由于工作需要,要爬取某款App的数据,App的具体名称此处不便透露,避免他们发现并修改加密逻辑我就得重新破解了. 爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长, ...

  8. 【转】Android逆向入门流程

    原文:https://www.jianshu.com/p/71fb7ccc05ff 0.写在前面 本文是笔者自学笔记,以破解某目标apk的方式进行学习,中间辅以原理性知识,方便面试需求. 参考文章的原 ...

  9. Android逆向之smali

    Android逆向之smali 头信息 smail文件前三行 .class <访问权限> [关键修饰字] <类名>; .super <父类名>; .source & ...

  10. Android逆向学习资料

    Android逆向基础之Dalvik虚拟机: https://lyxw.github.io/archivers/Android%E9%80%86%E5%90%91%E5%9F%BA%E7%A1%80% ...

随机推荐

  1. CSAPP:逆向工程【缓冲区溢出攻击】

    逆向工程[缓冲区溢出攻击] 任务描述 掌握函数调用时的栈帧结构,利用输入缓冲区的溢出漏洞,将攻击代码嵌入当前程序的栈帧中,使程序执行我们所期望的过程. 主要方法 溢出的字符将覆盖栈帧上的数据,会覆盖程 ...

  2. NServiceBus+RabbitMQ开发分布式应用

    前言      NServiceBus提供了8种传输管道组件,分别是Learning.MSMQ.Azure Service Bus.Azure Service Bus (Legacy).Azure S ...

  3. 利用requests和BeautifulSoup爬取菜鸟教程的代码与图片并保存为markdown格式

    还是设计模式的开卷考试,我想要多准备一点资料,于是写了个爬虫爬取代码与图片,有巧妙地进行格式化进一步处理,最终变为了markdown的格式 import requests from bs4 impor ...

  4. MySQL 分页查询优化——延迟关联优化

    目录 1.   InnoDB表的索引的几个概念 2.   覆盖索引和回表 3.   分页查询 4.   延迟关联优化 写在前面 下面的介绍均是在选用MySQL数据库和Innodb引擎的基础开展.我们先 ...

  5. 面试必问:ACID/CAP

    转载: https://www.jdon.com/artichect/acid-cap.html ACID和CAP的详尽比较 事务机制ACID和CAP理论是数据管理和分布式系统中两个重要的概念,很不巧 ...

  6. 基于mysql-8.0.16-winx64的主从搭建

    1.主服务器的my.ini文件内容:[mysqld]# 主库和从库需要不一致server-id=1log-bin=mysql-bin# 同步的数据库binlog-do-db=master-slave# ...

  7. Smali语言基础语法

    1.Smali语言基础语法-数据类型与描述符 smali中有两类数据类型:基本类型和引用类型.引用类型是指数组和对象,其它都是基础类型. 基本类型以及每种类型的描述符: Java类型 类型描述符 说明 ...

  8. Java接口统一样式返回模板

    Java接口统一样式返回模板 背景 在进行接口开发时,一般需要一个固定的返回样式,成功和失败的时候,都按照这种格式来进行统一的返回,这样,在与其他人进行接口之间的联调时不会显得很杂乱无章.而这种固定的 ...

  9. SpringBoot系列教程之Bean之指定初始化顺序的若干姿势

    上一篇博文介绍了@Order注解的常见错误理解,它并不能指定 bean 的加载顺序,那么问题来了,如果我需要指定 bean 的加载顺序,那应该怎么办呢? 本文将介绍几种可行的方式来控制 bean 之间 ...

  10. Mysql 性能优化及问题

    MySQL max_allowed_packet设置及问题 查看 max_allowed_packet show VARIABLES like '%max_allowed_packet%'; 以下内容 ...