首先项目里的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. go-json类

    package main import ( "encoding/json" "fmt" ) /* { "company":"itc ...

  2. Kubernetes WebSSH终端窗口自适应Resize

    追求完美不服输的我,一直在与各种问题斗争的路上痛并快乐着 上一篇文章Django实现WebSSH操作Kubernetes Pod最后留了个问题没有解决,那就是terminal内容窗口的大小没有办法调整 ...

  3. 为什么要用dubbo,dubbo是什么,为什么要和zk结合使用?

    目录 为什么要用dubbo dubbo是什么 dubbo架构 dubbo和zk关系 为什么要用dubbo? 随着互联网的发展,网站的应用规模不断扩大,常规的垂直架构已经无法应,分布式服务架构势在必行, ...

  4. 设计模式C++描述----19.命令(Command)模式

    一. 举例说明 我们知道,在多线程程序中,多个用户都给系统发 Read 和 Write 命令.这里有几点需要说明: 1. 首先明确一点,所有的这些 Read 和 Write 命令都是调用一个库函数. ...

  5. Oauth 2.0学习

    OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版. 本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为R ...

  6. ansible剧本之playbook操作

    ansible 剧本 yaml介绍: 是一个编程语言 文件后缀名 yaml yml 数据对应格式: 字典: key: value 列表: [] - ansible-playbook命令格式 执行顺序: ...

  7. Java中 实体类 VO、 PO、DO、DTO、 BO、 QO、DAO、POJO的概念

    PO(persistant object) 持久对象 在 o/r 映射的时候出现的概念,如果没有 o/r 映射,没有这个概念存在了.通常对应数据模型 ( 数据库 ), 本身还有部分业务逻辑的处理.可以 ...

  8. 解决node.js使用fs读取文件出错

      今天配接口,使用fs模块读取json出现了错误'no such file or directory',然后经查终于解决,特此记录. 使用nodejs的fs模块读取文件时习惯用相对路径,但是运行的时 ...

  9. Vue入坑第一篇

    写在前面的话:文章是个人学习过程中的总结,为方便以后回头在学习.文章中会参考官方文档和其他的一些文章,示例均为亲自编写和实践,若有写的不对的地方欢迎大家和我一起交流. 一.前言 本篇作为vue入门的一 ...

  10. MySQL的统计信息学习总结

    统计信息概念 MySQL统计信息是指数据库通过采样.统计出来的表.索引的相关信息,例如,表的记录数.聚集索引page个数.字段的Cardinality.....MySQL在生成执行计划时,需要根据索引 ...