GithubHelp home page GithubHelp logo

youlor / unpacker Goto Github PK

View Code? Open in Web Editor NEW
606.0 15.0 216.0 4.65 MB

基于ART主动调用的脱壳机

Makefile 0.14% C++ 41.52% Assembly 18.81% C 0.44% Python 0.10% Shell 0.01% Java 33.89% HTML 4.57% AIDL 0.53%
unpacker

unpacker's Introduction

Youpk

又一款基于ART的主动调用的脱壳机

原理

Youpk是一款针对Dex整体加固+各式各样的Dex抽取的脱壳机

基本流程如下:

  1. 从内存中dump DEX
  2. 构造完整调用链, 主动调用所有方法并dump CodeItem
  3. 合并 DEX, CodeItem

从内存中dump DEX

DEX文件在art虚拟机中使用DexFile对象表示, 而ClassLinker中引用了这些对象, 因此可以采用从ClassLinker中遍历DexFile对象并dump的方式来获取.

//unpacker.cc
std::list<const DexFile*> Unpacker::getDexFiles() {
  std::list<const DexFile*> dex_files;
  Thread* const self = Thread::Current();
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  ReaderMutexLock mu(self, *class_linker->DexLock());
  const std::list<ClassLinker::DexCacheData>& dex_caches = class_linker->GetDexCachesData();
  for (auto it = dex_caches.begin(); it != dex_caches.end(); ++it) {
    ClassLinker::DexCacheData data = *it;
    const DexFile* dex_file = data.dex_file;
    dex_files.push_back(dex_file);
  }
  return dex_files;
}

另外, 为了避免dex做任何形式的优化影响dump下来的dex文件, 在dex2oat中设置 CompilerFilter 为仅验证

//dex2oat.cc
compiler_options_->SetCompilerFilter(CompilerFilter::kVerifyAtRuntime);

构造完整调用链, 主动调用所有方法

  1. 创建脱壳线程

    //unpacker.java
    public static void unpack() {
        if (Unpacker.unpackerThread != null) {
            return;
        }
    
        //开启线程调用
        Unpacker.unpackerThread = new Thread() {
            @Override public void run() {
                while (true) {
                    try {
                        Thread.sleep(UNPACK_INTERVAL);
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (shouldUnpack()) {
                        Unpacker.unpackNative();
                    }   
                }
            }
        };
        Unpacker.unpackerThread.start();
    }
  2. 在脱壳线程中遍历DexFile的所有ClassDef

    //unpacker.cc
    for (; class_idx < dex_file->NumClassDefs(); class_idx++) {
  3. 解析并初始化Class

    //unpacker.cc
    mirror::Class* klass = class_linker->ResolveType(*dex_file, dex_file->GetClassDef(class_idx).class_idx_, h_dex_cache, h_class_loader);
    StackHandleScope<1> hs2(self);
    Handle<mirror::Class> h_class(hs2.NewHandle(klass));
    bool suc = class_linker->EnsureInitialized(self, h_class, true, true);
  4. 主动调用Class的所有Method, 并修改ArtMethod::Invoke使其强制走switch型解释器

    //unpacker.cc
    uint32_t args_size = (uint32_t)ArtMethod::NumArgRegisters(method->GetShorty());
    if (!method->IsStatic()) {
        args_size += 1;
    }
    
    JValue result;
    std::vector<uint32_t> args(args_size, 0);
    if (!method->IsStatic()) {
        mirror::Object* thiz = klass->AllocObject(self);
        args[0] = StackReference<mirror::Object>::FromMirrorPtr(thiz).AsVRegValue();  
    }
    method->Invoke(self, args.data(), args_size, &result, method->GetShorty());
    
    //art_method.cc
    if (UNLIKELY(!runtime->IsStarted() || Dbg::IsForcedInterpreterNeededForCalling(self, this) 
    || (Unpacker::isFakeInvoke(self, this) && !this->IsNative()))) {
    if (IsStatic()) {
    art::interpreter::EnterInterpreterFromInvoke(
    self, this, nullptr, args, result, /*stay_in_interpreter*/ true);
    } else {
    mirror::Object* receiver =
    reinterpret_cast<StackReference<mirror::Object>*>(&args[0])->AsMirrorPtr();
    art::interpreter::EnterInterpreterFromInvoke(
    self, this, receiver, args + 1, result, /*stay_in_interpreter*/ true);
    }
    }
    
    //interpreter.cc
    static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImplKind;
  5. 在解释器中插桩, 在每条指令执行前设置回调

    //interpreter_switch_impl.cc
    // Code to run before each dex instruction.
      #define PREAMBLE()                                                                 \
      do {                                                                               \
        inst_count++;                                                                    \
        bool dumped = Unpacker::beforeInstructionExecute(self, shadow_frame.GetMethod(), \
                                                         dex_pc, inst_count);            \
        if (dumped) {                                                                    \
          return JValue();                                                               \
        }                                                                                \
        if (UNLIKELY(instrumentation->HasDexPcListeners())) {                            \
          instrumentation->DexPcMovedEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),  shadow_frame.GetMethod(), dex_pc);            						   										   \
        }                                                                                \
      } while (false)
  6. 在回调中做针对性的CodeItem的dump, 这里仅仅是简单的示例了直接dump, 实际上, 针对某些厂商的抽取, 可以真正的执行几条指令等待CodeItem解密后再dump

    //unpacker.cc
    bool Unpacker::beforeInstructionExecute(Thread *self, ArtMethod *method, uint32_t dex_pc, int inst_count) {
      if (Unpacker::isFakeInvoke(self, method)) {
      	Unpacker::dumpMethod(method);
        return true;
      }
      return false;
    }

合并 DEX, CodeItem

将dump下来的CodeItem填充到DEX的相应位置中即可. 主要是基于google dx工具修改.

参考链接

FUPK3: https://bbs.pediy.com/thread-246117.htm

FART: https://bbs.pediy.com/thread-252630.htm

刷机

  1. 仅支持pixel 1代
  2. 重启至bootloader: adb reboot bootloader
  3. 解压 Youpk_sailfish.zip 并双击 flash-all.bat

编译

脱壳机源码编译

  1. 下载android-7.1.2_r33完整源码
  2. 替换unpacker/android-7.1.2_r33
  3. 编译

修复工具编译

  1. IDEA导入dexfixer项目
  2. main class为 com.android.dx.unpacker.DexFixer

使用方法

  1. 该工具仅仅用来学习交流, 请勿用于非法用途, 否则后果自付!

  2. 配置待脱壳的app包名, 准确来讲是进程名称

    adb shell "echo cn.youlor.mydemo >> /data/local/tmp/unpacker.config"
  3. 如果apk没有整体加固, 未避免installd调用dex2oat优化, 需要在安装之前执行第2步

  4. 启动apk等待脱壳 每隔10秒将自动重新脱壳(已完全dump的dex将被忽略), 当日志打印unpack end时脱壳完成

  5. pull出dump文件, dump文件路径为 /data/data/包名/unpacker

    adb pull /data/data/cn.youlor.mydemo/unpacker
  6. 调用修复工具 dexfixer.jar, 两个参数, 第一个为dump文件目录(必须为有效路径), 第二个为重组后的DEX目录(不存在将会创建)

    java -jar dexfixer.jar /path/to/unpacker /path/to/output

适用场景

  1. 整体加固
  2. 抽取:

常见问题

  1. dump中途退出或卡死,重新启动进程,再次等待脱壳即可
  2. 当前仅支持被壳保护的dex, 不支持App动态加载的dex/jar

unpacker's People

Contributors

westinyang avatar youlor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

unpacker's Issues

A little question...

Hello my friend! Nice to communicate with you.Recently I am studying your youpk and I think it's really interesting and talented.But unfortunately,I also met some problems and I can't resolve it even tried every google and baidu.The following step is what I operated:
1.download the aosp source code of android-7.1.2_r33.
2.insert youpk modified code.
3.make aosp then get boot.img and system.img in out directory.
4.fastboot flash boot boot.img & fastboot flash system system.img.
5.fastboot reboot
But then I got the following error from android studio logcat window and the device stuck at android logo interface:
1970-03-01 04:31:24.984 18392-18392/? A/art: art/runtime/indirect_reference_table.cc:175] Internal Error: non-empty local reference table
1970-03-01 04:31:24.984 18392-18392/? A/art: art/runtime/indirect_reference_table.cc:175] local reference table dump:
1970-03-01 04:31:24.984 18392-18392/? A/art: art/runtime/indirect_reference_table.cc:175] Last 1 entries (of 1):
1970-03-01 04:31:24.984 18392-18392/? A/art: art/runtime/indirect_reference_table.cc:175] 0: 0x12c011c0 java.lang.Class<cn.youlor.Unpacker>
1970-03-01 04:31:24.984 18392-18392/? A/art: art/runtime/indirect_reference_table.cc:175] Summary:
1970-03-01 04:31:24.984 18392-18392/? A/art: art/runtime/indirect_reference_table.cc:175] 1 of java.lang.Class
1970-03-01 04:31:24.984 18392-18392/? A/art: art/runtime/indirect_reference_table.cc:175]
1970-03-01 04:31:25.045 18392-18392/? A/art: art/runtime/runtime.cc:423] Runtime aborting...
1970-03-01 04:31:25.045 18392-18392/? A/art: art/runtime/runtime.cc:423] Aborting thread:
1970-03-01 04:31:25.045 18392-18392/? A/art: art/runtime/runtime.cc:423] "main" prio=5 tid=1 Runnable
1970-03-01 04:31:25.045 18392-18392/? A/art: art/runtime/runtime.cc:423] | group="" sCount=0 dsCount=0 obj=0x12c310d0 self=0xe8a85400
1970-03-01 04:31:25.045 18392-18392/? A/art: art/runtime/runtime.cc:423] | sysTid=18392 nice=0 cgrp=default sched=0/0 handle=0xeb701534
1970-03-01 04:31:25.045 18392-18392/? A/art: art/runtime/runtime.cc:423] | state=R schedstat=( 3247957383 216235988 288 ) utm=209 stm=115 core=1 HZ=100
1970-03-01 04:31:25.045 18392-18392/? A/art: art/runtime/runtime.cc:423] | stack=0xff543000-0xff545000 stackSize=8MB
1970-03-01 04:31:25.045 18392-18392/? A/art: art/runtime/runtime.cc:423] | held mutexes= "abort lock" "mutator lock"(shared held)
I really don't know how to resolve it.I will appreciate it very much if you can help me.Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.