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代码
1 .method private static loadX86Library()V 2 .locals 33 3 4 .prologue 5 .line 128 6 const/16 v24, 0x0 7 8 .line 129 9 .local v24, "packageName":Ljava/lang/String; 10 const/4 v4, 0x0 11 12 .line 131 13 .local v4, "apkPath":Ljava/lang/String; 14 invoke-static {}, Lcom/baidu/protect/StubApplication;->is64BitEnv()Z 15 16 move-result v15 17 18 .line 134 19 .local v15, "is_x86_64":Z 20 :try_start_0 21 new-instance v5, Ljava/io/BufferedReader; 22 23 new-instance v30, Ljava/io/InputStreamReader; 24 25 .line 135 26 new-instance v31, Ljava/io/FileInputStream; 27 28 const-string v32, "/proc/self/maps" 29 30 invoke-direct/range {v31 .. v32}, Ljava/io/FileInputStream;-><init>(Ljava/lang/String;)V 31 32 invoke-direct/range {v30 .. v31}, Ljava/io/InputStreamReader;-><init>(Ljava/io/InputStream;)V 33 34 .line 134 35 move-object/from16 v0, v30 36 37 invoke-direct {v5, v0}, Ljava/io/BufferedReader;-><init>(Ljava/io/Reader;)V 38 39 .line 136 40 .local v5, "br":Ljava/io/BufferedReader; 41 invoke-virtual {v5}, Ljava/io/BufferedReader;->readLine()Ljava/lang/String; 42 43 move-result-object v19 44 45 .local v19, "line":Ljava/lang/String; 46 :goto_0 47 if-nez v19, :cond_3 48 49 .line 186 50 :goto_1 51 invoke-virtual {v5}, Ljava/io/BufferedReader;->close()V 52 :try_end_0 53 .catch Ljava/io/IOException; {:try_start_0 .. :try_end_0} :catch_0 54 55 .line 192 56 .end local v5 # "br":Ljava/io/BufferedReader; 57 .end local v19 # "line":Ljava/lang/String; 58 :goto_2 59 if-eqz v15, :cond_a 60 61 .line 193 62 const-string v28, "libbaiduprotect_x86_64.so" 63 64 .line 200 65 .local v28, "soname":Ljava/lang/String; 66 :goto_3 67 if-eqz v4, :cond_2 68 69 if-eqz v24, :cond_2 70 71 .line 201 72 const-wide/16 v12, 0x0 73 74 .line 202 75 .local v12, "fileModified":J 76 const-wide/16 v22, 0x0 77 78 .line 203 79 .local v22, "newFileModified":J 80 invoke-static/range {v24 .. v24}, Lcom/baidu/protect/StubApplication;->getDataFolder(Ljava/lang/String;)Ljava/lang/String; 81 82 move-result-object v7 83 84 .line 205 85 .local v7, "dataFolder":Ljava/lang/String; 86 new-instance v30, Ljava/lang/StringBuilder; 87 88 invoke-static {v7}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String; 89 90 move-result-object v31 91 92 invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V 93 94 move-object/from16 v0, v30 95 96 move-object/from16 v1, v24 97 98 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 99 100 move-result-object v30 101 102 const-string v31, "/.x86lib/" 103 104 invoke-virtual/range {v30 .. v31}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 105 106 move-result-object v30 107 108 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; 109 110 move-result-object v18 111 112 .line 206 113 .local v18, "libTargetFolder":Ljava/lang/String; 114 new-instance v30, Ljava/lang/StringBuilder; 115 116 invoke-static/range {v18 .. v18}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String; 117 118 move-result-object v31 119 120 invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V 121 122 move-object/from16 v0, v30 123 124 move-object/from16 v1, v28 125 126 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 127 128 move-result-object v30 129 130 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; 131 132 move-result-object v17 133 134 .line 207 135 .local v17, "libPath":Ljava/lang/String; 136 new-instance v9, Ljava/io/File; 137 138 move-object/from16 v0, v18 139 140 invoke-direct {v9, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V 141 142 .line 208 143 .local v9, "f":Ljava/io/File; 144 invoke-virtual {v9}, Ljava/io/File;->exists()Z 145 146 move-result v30 147 148 if-nez v30, :cond_0 149 150 .line 209 151 invoke-virtual {v9}, Ljava/io/File;->mkdir()Z 152 153 .line 212 154 :cond_0 155 :try_start_1 156 new-instance v30, Ljava/lang/StringBuilder; 157 158 const-string v31, "assets/" 159 160 invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V 161 162 move-object/from16 v0, v30 163 164 move-object/from16 v1, v28 165 166 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 167 168 move-result-object v30 169 170 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; 171 172 move-result-object v27 173 174 .line 213 175 .local v27, "soEntryName":Ljava/lang/String; 176 new-instance v21, Ljava/util/zip/ZipInputStream; 177 178 new-instance v30, Ljava/io/FileInputStream; 179 180 move-object/from16 v0, v30 181 182 invoke-direct {v0, v4}, Ljava/io/FileInputStream;-><init>(Ljava/lang/String;)V 183 184 move-object/from16 v0, v21 185 186 move-object/from16 v1, v30 187 188 invoke-direct {v0, v1}, Ljava/util/zip/ZipInputStream;-><init>(Ljava/io/InputStream;)V 189 190 .line 215 191 .local v21, "localZipInputStream":Ljava/util/zip/ZipInputStream; 192 :goto_4 193 invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->getNextEntry()Ljava/util/zip/ZipEntry; 194 195 move-result-object v20 196 197 .line 216 198 .local v20, "localZipEntry":Ljava/util/zip/ZipEntry; 199 if-nez v20, :cond_b 200 201 .line 258 202 :cond_1 203 :goto_5 204 invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->close()V 205 :try_end_1 206 .catch Ljava/io/IOException; {:try_start_1 .. :try_end_1} :catch_1 207 208 .line 264 209 .end local v20 # "localZipEntry":Ljava/util/zip/ZipEntry; 210 .end local v21 # "localZipInputStream":Ljava/util/zip/ZipInputStream; 211 .end local v27 # "soEntryName":Ljava/lang/String; 212 :goto_6 213 invoke-static/range {v17 .. v17}, Ljava/lang/System;->load(Ljava/lang/String;)V 214 215 .line 266 216 .end local v7 # "dataFolder":Ljava/lang/String; 217 .end local v9 # "f":Ljava/io/File; 218 .end local v12 # "fileModified":J 219 .end local v17 # "libPath":Ljava/lang/String; 220 .end local v18 # "libTargetFolder":Ljava/lang/String; 221 .end local v22 # "newFileModified":J 222 :cond_2 223 return-void 224 225 .line 138 226 .end local v28 # "soname":Ljava/lang/String; 227 .restart local v5 # "br":Ljava/io/BufferedReader; 228 .restart local v19 # "line":Ljava/lang/String; 229 :cond_3 230 :try_start_2 231 const-string v30, ".apk" 232 233 move-object/from16 v0, v19 234 235 move-object/from16 v1, v30 236 237 invoke-virtual {v0, v1}, Ljava/lang/String;->endsWith(Ljava/lang/String;)Z 238 239 move-result v30 240 241 if-eqz v30, :cond_5 242 243 .line 139 244 sget-object v30, Ljava/lang/System;->out:Ljava/io/PrintStream; 245 246 new-instance v31, Ljava/lang/StringBuilder; 247 248 const-string v32, "Wigan:line=" 249 250 invoke-direct/range {v31 .. v32}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V 251 252 move-object/from16 v0, v31 253 254 move-object/from16 v1, v19 255 256 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 257 258 move-result-object v31 259 260 invoke-virtual/range {v31 .. v31}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; 261 262 move-result-object v31 263 264 invoke-virtual/range {v30 .. v31}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V 265 266 .line 140 267 const-string v30, " " 268 269 move-object/from16 v0, v19 270 271 move-object/from16 v1, v30 272 273 invoke-virtual {v0, v1}, Ljava/lang/String;->split(Ljava/lang/String;)[Ljava/lang/String; 274 275 move-result-object v26 276 277 .line 141 278 .local v26, "s":[Ljava/lang/String; 279 move-object/from16 v0, v26 280 281 array-length v0, v0 282 283 move/from16 v30, v0 284 285 add-int/lit8 v30, v30, -0x1 286 287 aget-object v25, v26, v30 288 289 .line 144 290 .local v25, "path":Ljava/lang/String; 291 const-string v30, "/mnt/asec/" 292 293 move-object/from16 v0, v25 294 295 move-object/from16 v1, v30 296 297 invoke-virtual {v0, v1}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z 298 299 move-result v30 300 301 if-nez v30, :cond_4 302 303 const-string v30, "/data/app/" 304 305 move-object/from16 v0, v25 306 307 move-object/from16 v1, v30 308 309 invoke-virtual {v0, v1}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z 310 311 move-result v30 312 313 if-eqz v30, :cond_6 314 315 .line 145 316 :cond_4 317 const/16 v30, 0xa 318 319 move-object/from16 v0, v25 320 321 move/from16 v1, v30 322 323 invoke-virtual {v0, v1}, Ljava/lang/String;->substring(I)Ljava/lang/String; 324 325 move-result-object v3 326 327 .line 156 328 .local v3, "apkName":Ljava/lang/String; 329 :goto_7 330 const/16 v30, 0x2d 331 332 move/from16 v0, v30 333 334 invoke-virtual {v3, v0}, Ljava/lang/String;->lastIndexOf(I)I 335 336 move-result v16 337 338 .line 157 339 .local v16, "lastIndex":I 340 const/16 v30, -0x1 341 342 move/from16 v0, v16 343 344 move/from16 v1, v30 345 346 if-ne v0, v1, :cond_8 347 348 .line 136 349 .end local v3 # "apkName":Ljava/lang/String; 350 .end local v16 # "lastIndex":I 351 .end local v25 # "path":Ljava/lang/String; 352 .end local v26 # "s":[Ljava/lang/String; 353 :cond_5 354 invoke-virtual {v5}, Ljava/io/BufferedReader;->readLine()Ljava/lang/String; 355 356 move-result-object v19 357 358 goto/16 :goto_0 359 360 .line 147 361 .restart local v25 # "path":Ljava/lang/String; 362 .restart local v26 # "s":[Ljava/lang/String; 363 :cond_6 364 const-string v30, "/app/" 365 366 move-object/from16 v0, v25 367 368 move-object/from16 v1, v30 369 370 invoke-virtual {v0, v1}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z 371 372 move-result v30 373 374 if-eqz v30, :cond_7 375 376 .line 148 377 const/16 v30, 0x5 378 379 move-object/from16 v0, v25 380 381 move/from16 v1, v30 382 383 invoke-virtual {v0, v1}, Ljava/lang/String;->substring(I)Ljava/lang/String; 384 385 move-result-object v3 386 387 .line 149 388 .restart local v3 # "apkName":Ljava/lang/String; 389 goto :goto_7 390 391 .line 150 392 .end local v3 # "apkName":Ljava/lang/String; 393 :cond_7 394 const-string v30, "/mnt/asec2/[2]" 395 396 move-object/from16 v0, v25 397 398 move-object/from16 v1, v30 399 400 invoke-virtual {v0, v1}, Ljava/lang/String;->startsWith(Ljava/lang/String;)Z 401 402 move-result v30 403 404 if-eqz v30, :cond_5 405 406 .line 151 407 const/16 v30, 0xe 408 409 move-object/from16 v0, v25 410 411 move/from16 v1, v30 412 413 invoke-virtual {v0, v1}, Ljava/lang/String;->substring(I)Ljava/lang/String; 414 415 move-result-object v3 416 417 .restart local v3 # "apkName":Ljava/lang/String; 418 goto :goto_7 419 420 .line 160 421 .restart local v16 # "lastIndex":I 422 :cond_8 423 const/16 v30, 0x0 424 425 move/from16 v0, v30 426 427 move/from16 v1, v16 428 429 invoke-virtual {v3, v0, v1}, Ljava/lang/String;->substring(II)Ljava/lang/String; 430 431 move-result-object v29 432 433 .line 161 434 .local v29, "tmpPackageName":Ljava/lang/String; 435 move-object/from16 v24, v29 436 437 .line 162 438 if-eqz v15, :cond_9 439 440 .line 163 441 const/16 v30, 0x2f 442 443 move/from16 v0, v30 444 445 invoke-virtual {v3, v0}, Ljava/lang/String;->lastIndexOf(I)I 446 447 move-result v16 448 449 .line 164 450 const/16 v30, -0x1 451 452 move/from16 v0, v16 453 454 move/from16 v1, v30 455 456 if-eq v0, v1, :cond_5 457 458 .line 167 459 const/16 v30, 0x0 460 461 move/from16 v0, v30 462 463 move/from16 v1, v16 464 465 invoke-virtual {v3, v0, v1}, Ljava/lang/String;->substring(II)Ljava/lang/String; 466 467 move-result-object v2 468 469 .line 169 470 .local v2, "apkInstallName":Ljava/lang/String; 471 new-instance v9, Ljava/io/File; 472 473 new-instance v30, Ljava/lang/StringBuilder; 474 475 const-string v31, "/data/app/" 476 477 invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V 478 479 move-object/from16 v0, v30 480 481 invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 482 483 move-result-object v30 484 485 const-string v31, "/lib/x86_64/libbaiduprotect.so" 486 487 invoke-virtual/range {v30 .. v31}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 488 489 move-result-object v30 490 491 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; 492 493 move-result-object v30 494 495 move-object/from16 v0, v30 496 497 invoke-direct {v9, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V 498 499 .line 170 500 .restart local v9 # "f":Ljava/io/File; 501 invoke-virtual {v9}, Ljava/io/File;->exists()Z 502 503 move-result v30 504 505 if-eqz v30, :cond_5 506 507 .line 171 508 move-object/from16 v24, v29 509 510 .line 172 511 new-instance v30, Ljava/lang/StringBuilder; 512 513 const-string v31, "/data/app/" 514 515 invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V 516 517 move-object/from16 v0, v30 518 519 invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 520 521 move-result-object v30 522 523 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; 524 525 move-result-object v4 526 527 .line 173 528 goto/16 :goto_1 529 530 .line 177 531 .end local v2 # "apkInstallName":Ljava/lang/String; 532 .end local v9 # "f":Ljava/io/File; 533 :cond_9 534 new-instance v9, Ljava/io/File; 535 536 new-instance v30, Ljava/lang/StringBuilder; 537 538 const-string v31, "/data/data/" 539 540 invoke-direct/range {v30 .. v31}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V 541 542 move-object/from16 v0, v30 543 544 move-object/from16 v1, v29 545 546 invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 547 548 move-result-object v30 549 550 const-string v31, "/lib/libbaiduprotect.so" 551 552 invoke-virtual/range {v30 .. v31}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 553 554 move-result-object v30 555 556 invoke-virtual/range {v30 .. v30}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; 557 558 move-result-object v30 559 560 move-object/from16 v0, v30 561 562 invoke-direct {v9, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V 563 564 .line 178 565 .restart local v9 # "f":Ljava/io/File; 566 invoke-virtual {v9}, Ljava/io/File;->exists()Z 567 :try_end_2 568 .catch Ljava/io/IOException; {:try_start_2 .. :try_end_2} :catch_0 569 570 move-result v30 571 572 if-eqz v30, :cond_5 573 574 .line 179 575 move-object/from16 v24, v29 576 577 .line 180 578 move-object/from16 v4, v25 579 580 .line 181 581 goto/16 :goto_1 582 583 .line 187 584 .end local v3 # "apkName":Ljava/lang/String; 585 .end local v5 # "br":Ljava/io/BufferedReader; 586 .end local v9 # "f":Ljava/io/File; 587 .end local v16 # "lastIndex":I 588 .end local v19 # "line":Ljava/lang/String; 589 .end local v25 # "path":Ljava/lang/String; 590 .end local v26 # "s":[Ljava/lang/String; 591 .end local v29 # "tmpPackageName":Ljava/lang/String; 592 :catch_0 593 move-exception v8 594 595 .line 188 596 .local v8, "e":Ljava/io/IOException; 597 invoke-virtual {v8}, Ljava/io/IOException;->printStackTrace()V 598 599 goto/16 :goto_2 600 601 .line 196 602 .end local v8 # "e":Ljava/io/IOException; 603 :cond_a 604 const-string v28, "libbaiduprotect_x86.so" 605 606 .restart local v28 # "soname":Ljava/lang/String; 607 goto/16 :goto_3 608 609 .line 219 610 .restart local v7 # "dataFolder":Ljava/lang/String; 611 .restart local v9 # "f":Ljava/io/File; 612 .restart local v12 # "fileModified":J 613 .restart local v17 # "libPath":Ljava/lang/String; 614 .restart local v18 # "libTargetFolder":Ljava/lang/String; 615 .restart local v20 # "localZipEntry":Ljava/util/zip/ZipEntry; 616 .restart local v21 # "localZipInputStream":Ljava/util/zip/ZipInputStream; 617 .restart local v22 # "newFileModified":J 618 .restart local v27 # "soEntryName":Ljava/lang/String; 619 :cond_b 620 :try_start_3 621 invoke-virtual/range {v20 .. v20}, Ljava/util/zip/ZipEntry;->getName()Ljava/lang/String; 622 623 move-result-object v30 624 625 move-object/from16 v0, v30 626 627 move-object/from16 v1, v27 628 629 invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z 630 631 move-result v30 632 633 if-eqz v30, :cond_f 634 635 .line 220 636 invoke-virtual/range {v20 .. v20}, Ljava/util/zip/ZipEntry;->getTime()J 637 638 move-result-wide v22 639 640 .line 221 641 new-instance v10, Ljava/io/File; 642 643 move-object/from16 v0, v17 644 645 invoke-direct {v10, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V 646 :try_end_3 647 .catch Ljava/io/IOException; {:try_start_3 .. :try_end_3} :catch_1 648 649 .line 222 650 .end local v9 # "f":Ljava/io/File; 651 .local v10, "f":Ljava/io/File; 652 :try_start_4 653 invoke-virtual {v10}, Ljava/io/File;->exists()Z 654 655 move-result v30 656 657 if-eqz v30, :cond_d 658 659 .line 223 660 invoke-virtual {v10}, Ljava/io/File;->lastModified()J 661 662 move-result-wide v12 663 664 .line 224 665 cmp-long v30, v12, v22 666 667 if-nez v30, :cond_c 668 669 .line 226 670 invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->closeEntry()V 671 672 move-object v9, v10 673 674 .line 227 675 .end local v10 # "f":Ljava/io/File; 676 .restart local v9 # "f":Ljava/io/File; 677 goto/16 :goto_5 678 679 .line 229 680 .end local v9 # "f":Ljava/io/File; 681 .restart local v10 # "f":Ljava/io/File; 682 :cond_c 683 invoke-virtual {v10}, Ljava/io/File;->delete()Z 684 685 .line 233 686 :cond_d 687 new-instance v11, Ljava/io/FileOutputStream; 688 689 move-object/from16 v0, v17 690 691 invoke-direct {v11, v0}, Ljava/io/FileOutputStream;-><init>(Ljava/lang/String;)V 692 693 .line 234 694 .local v11, "fo":Ljava/io/FileOutputStream; 695 const/16 v30, 0x400 696 697 move/from16 v0, v30 698 699 new-array v6, v0, [B 700 701 .line 236 702 .local v6, "buffer":[B 703 :goto_8 704 move-object/from16 v0, v21 705 706 invoke-virtual {v0, v6}, Ljava/util/zip/ZipInputStream;->read([B)I 707 708 move-result v14 709 710 .line 237 711 .local v14, "i":I 712 const/16 v30, -0x1 713 714 move/from16 v0, v30 715 716 if-ne v14, v0, :cond_e 717 718 .line 242 719 invoke-virtual {v11}, Ljava/io/FileOutputStream;->flush()V 720 721 .line 243 722 invoke-virtual {v11}, Ljava/io/FileOutputStream;->close()V 723 724 .line 244 725 invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->closeEntry()V 726 727 .line 247 728 new-instance v9, Ljava/io/File; 729 730 move-object/from16 v0, v17 731 732 invoke-direct {v9, v0}, Ljava/io/File;-><init>(Ljava/lang/String;)V 733 :try_end_4 734 .catch Ljava/io/IOException; {:try_start_4 .. :try_end_4} :catch_2 735 736 .line 248 737 .end local v10 # "f":Ljava/io/File; 738 .restart local v9 # "f":Ljava/io/File; 739 :try_start_5 740 invoke-virtual {v9}, Ljava/io/File;->exists()Z 741 742 move-result v30 743 744 if-eqz v30, :cond_1 745 746 .line 249 747 move-wide/from16 v0, v22 748 749 invoke-virtual {v9, v0, v1}, Ljava/io/File;->setLastModified(J)Z 750 :try_end_5 751 .catch Ljava/io/IOException; {:try_start_5 .. :try_end_5} :catch_1 752 753 goto/16 :goto_5 754 755 .line 259 756 .end local v6 # "buffer":[B 757 .end local v11 # "fo":Ljava/io/FileOutputStream; 758 .end local v14 # "i":I 759 .end local v20 # "localZipEntry":Ljava/util/zip/ZipEntry; 760 .end local v21 # "localZipInputStream":Ljava/util/zip/ZipInputStream; 761 .end local v27 # "soEntryName":Ljava/lang/String; 762 :catch_1 763 move-exception v8 764 765 .line 260 766 .restart local v8 # "e":Ljava/io/IOException; 767 :goto_9 768 invoke-virtual {v8}, Ljava/io/IOException;->printStackTrace()V 769 770 goto/16 :goto_6 771 772 .line 240 773 .end local v8 # "e":Ljava/io/IOException; 774 .end local v9 # "f":Ljava/io/File; 775 .restart local v6 # "buffer":[B 776 .restart local v10 # "f":Ljava/io/File; 777 .restart local v11 # "fo":Ljava/io/FileOutputStream; 778 .restart local v14 # "i":I 779 .restart local v20 # "localZipEntry":Ljava/util/zip/ZipEntry; 780 .restart local v21 # "localZipInputStream":Ljava/util/zip/ZipInputStream; 781 .restart local v27 # "soEntryName":Ljava/lang/String; 782 :cond_e 783 const/16 v30, 0x0 784 785 :try_start_6 786 move/from16 v0, v30 787 788 invoke-virtual {v11, v6, v0, v14}, Ljava/io/FileOutputStream;->write([BII)V 789 :try_end_6 790 .catch Ljava/io/IOException; {:try_start_6 .. :try_end_6} :catch_2 791 792 goto :goto_8 793 794 .line 259 795 .end local v6 # "buffer":[B 796 .end local v11 # "fo":Ljava/io/FileOutputStream; 797 .end local v14 # "i":I 798 :catch_2 799 move-exception v8 800 801 move-object v9, v10 802 803 .end local v10 # "f":Ljava/io/File; 804 .restart local v9 # "f":Ljava/io/File; 805 goto :goto_9 806 807 .line 255 808 :cond_f 809 :try_start_7 810 invoke-virtual/range {v21 .. v21}, Ljava/util/zip/ZipInputStream;->closeEntry()V 811 :try_end_7 812 .catch Ljava/io/IOException; {:try_start_7 .. :try_end_7} :catch_1 813 814 goto/16 :goto_4 815 .end method
1 private static void loadX86Library() { 2 // :( Parsing error. Please contact me. 3 }
1 private static void loadX86Library() 2 { 3 boolean flag; 4 Object obj; 5 Object obj1; 6 Object obj2; 7 Object obj3; 8 Object obj5; 9 Object obj6; 10 obj2 = null; 11 obj1 = null; 12 obj5 = null; 13 obj6 = null; 14 flag = is64BitEnv(); 15 obj3 = obj5; 16 obj = obj1; 17 BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/self/maps"))); 18 obj3 = obj5; 19 obj = obj1; 20 String s = bufferedreader.readLine(); 21 goto _L1 22 _L29: 23 obj3 = obj1; 24 obj = obj2; 25 bufferedreader.close(); 26 obj = obj2; 27 _L17: 28 int i; 29 Object obj4; 30 String s1; 31 if(flag) 32 obj2 = "libbaiduprotect_x86_64.so"; 33 else 34 obj2 = "libbaiduprotect_x86.so"; 35 if(obj1 == null || obj == null) goto _L3; else goto _L2 36 _L2: 37 obj = (new StringBuilder(String.valueOf(getDataFolder(((String) (obj)))))).append(((String) (obj))).append("/.x86lib/").toString(); 38 obj3 = (new StringBuilder(String.valueOf(obj))).append(((String) (obj2))).toString(); 39 obj = new File(((String) (obj))); 40 if(!((File) (obj)).exists()) 41 ((File) (obj)).mkdir(); 42 obj2 = (new StringBuilder("assets/")).append(((String) (obj2))).toString(); 43 obj = new ZipInputStream(new FileInputStream(((String) (obj1)))); 44 _L25: 45 obj1 = ((ZipInputStream) (obj)).getNextEntry(); 46 if(obj1 != null) goto _L5; else goto _L4 47 _L4: 48 ((ZipInputStream) (obj)).close(); 49 _L22: 50 System.load(((String) (obj3))); 51 _L3: 52 return; 53 _L27: 54 obj1 = obj2; 55 obj3 = obj5; 56 obj = obj2; 57 if(!s.endsWith(".apk")) goto _L7; else goto _L6 58 _L6: 59 obj3 = obj5; 60 obj = obj2; 61 System.out.println((new StringBuilder("Wigan:line=")).append(s).toString()); 62 obj3 = obj5; 63 obj = obj2; 64 obj1 = s.split(" "); 65 obj3 = obj5; 66 obj = obj2; 67 s1 = obj1[obj1.length - 1]; 68 obj3 = obj5; 69 obj = obj2; 70 if(s1.startsWith("/mnt/asec/")) goto _L9; else goto _L8 71 _L8: 72 obj3 = obj5; 73 obj = obj2; 74 if(!s1.startsWith("/data/app/")) goto _L10; else goto _L9 75 _L9: 76 obj3 = obj5; 77 obj = obj2; 78 s = s1.substring(10); 79 _L13: 80 obj3 = obj5; 81 obj = obj2; 82 i = s.lastIndexOf('-'); 83 if(i != -1) goto _L12; else goto _L11 84 _L11: 85 obj1 = obj2; 86 _L7: 87 obj3 = obj5; 88 obj = obj1; 89 s = bufferedreader.readLine(); 90 obj2 = obj1; 91 continue; /* Loop/switch isn't completed */ 92 _L10: 93 obj3 = obj5; 94 obj = obj2; 95 if(!s1.startsWith("/app/")) 96 break MISSING_BLOCK_LABEL_464; 97 obj3 = obj5; 98 obj = obj2; 99 s = s1.substring(5); 100 goto _L13 101 obj1 = obj2; 102 obj3 = obj5; 103 obj = obj2; 104 if(!s1.startsWith("/mnt/asec2/[2]")) goto _L7; else goto _L14 105 _L14: 106 obj3 = obj5; 107 obj = obj2; 108 s = s1.substring(14); 109 goto _L13 110 _L12: 111 obj3 = obj5; 112 obj = obj2; 113 obj2 = s.substring(0, i); 114 obj4 = obj2; 115 if(!flag) 116 break MISSING_BLOCK_LABEL_650; 117 obj3 = obj5; 118 obj = obj4; 119 i = s.lastIndexOf('/'); 120 obj1 = obj4; 121 if(i == -1) goto _L7; else goto _L15 122 _L15: 123 obj3 = obj5; 124 obj = obj4; 125 s1 = s.substring(0, i); 126 obj1 = obj4; 127 obj3 = obj5; 128 obj = obj4; 129 if(!(new File((new StringBuilder("/data/app/")).append(s1).append("/lib/x86_64/libbaiduprotect.so").toString())).exists()) goto _L7; else goto _L16 130 _L16: 131 obj3 = obj5; 132 obj = obj2; 133 boolean flag1; 134 try 135 { 136 obj1 = (new StringBuilder("/data/app/")).append(s).toString(); 137 continue; /* Loop/switch isn't completed */ 138 } 139 // Misplaced declaration of an exception variable 140 catch(Object obj1) 141 { 142 ((IOException) (obj1)).printStackTrace(); 143 obj1 = obj3; 144 } 145 goto _L17 146 obj3 = obj5; 147 obj = obj4; 148 flag1 = (new File((new StringBuilder("/data/data/")).append(((String) (obj2))).append("/lib/libbaiduprotect.so").toString())).exists(); 149 obj1 = obj4; 150 if(!flag1) goto _L7; else goto _L18 151 _L18: 152 obj1 = s1; 153 continue; /* Loop/switch isn't completed */ 154 _L5: 155 long l; 156 if(!((ZipEntry) (obj1)).getName().equals(obj2)) 157 break MISSING_BLOCK_LABEL_891; 158 l = ((ZipEntry) (obj1)).getTime(); 159 obj1 = new File(((String) (obj3))); 160 label0: 161 { 162 if(!((File) (obj1)).exists()) 163 break MISSING_BLOCK_LABEL_789; 164 if(((File) (obj1)).lastModified() != l) 165 break label0; 166 ((ZipInputStream) (obj)).closeEntry(); 167 } 168 goto _L4 169 ((File) (obj1)).delete(); 170 byte abyte0[]; 171 obj1 = new FileOutputStream(((String) (obj3))); 172 abyte0 = new byte[1024]; 173 _L23: 174 i = ((ZipInputStream) (obj)).read(abyte0); 175 if(i != -1) goto _L20; else goto _L19 176 _L19: 177 ((FileOutputStream) (obj1)).flush(); 178 ((FileOutputStream) (obj1)).close(); 179 ((ZipInputStream) (obj)).closeEntry(); 180 obj1 = new File(((String) (obj3))); 181 if(!((File) (obj1)).exists()) goto _L4; else goto _L21 182 _L21: 183 ((File) (obj1)).setLastModified(l); 184 goto _L4 185 obj; 186 _L24: 187 ((IOException) (obj)).printStackTrace(); 188 goto _L22 189 _L20: 190 ((FileOutputStream) (obj1)).write(abyte0, 0, i); 191 goto _L23 192 obj; 193 goto _L24 194 ((ZipInputStream) (obj)).closeEntry(); 195 goto _L25 196 _L1: 197 if(s != null) goto _L27; else goto _L26 198 _L26: 199 obj1 = obj6; 200 if(true) goto _L29; else goto _L28 201 _L28: 202 }
这个函数逻辑是:
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。