vmp入门
记录学习的过程
vmp壳的应用。从效果上面看,是把java的函数,加密成了native的函数,在实现函数加密保护时,主要是对相同参数并且相同返回值的函数加密成native的。所以会一般是两种情况,一个是直接对onCreate函数进行vmp保护,或者是抽象出一个统一参数和返回值的函数。然后对这个函数进行vmp保护。
native的函数都是需要动态注册的。所以我们先改造aosp源码。打印下注册了函数,以及函数的地址,方便我们后续进行调试跟踪,下面修改art_method.cc
12345678910111213141516const void* ArtMethod::RegisterNative(const void* native_method, bool is_fast) { CHECK(IsNative()) << PrettyMethod(); CHECK(!IsFastNative()) << PrettyMethod(); CHECK(native_method != nullptr) << PrettyMethod(); ...
fart的理解和分析过程
文章内的fart的源码素材均来自看雪搞研网课。安卓源码为8.1
学习了一段时间fart然后整理一下以便哪天忘记了翻翻
fart是一个art环境下基于主动调用的自动化脱壳方案。在定制的fart环境中,只需要运行需要脱壳的apk即可自动脱壳,将脱壳后的dex文件dump在/sdcard/fart/app包名的目录下,那么这个流程是如何实现的呢。
内部的一些原理作者有发过帖子详细进行过讲解,所以这里先是跟着作者的思想进行一步步的深入。先贴上地址
1、[FART:ART环境下基于主动调用的自动化脱壳方案][https://bbs.pediy.com/thread-252630.htm]
2、[FART正餐前甜点:ART下几个通用简单高效的dump内存中dex方法][https://bbs.pediy.com/thread-254028.htm]
3、[拨云见日:安卓APP脱壳的本质以及如何快速发现ART下的脱壳点][https://bbs.pediy.com/thread-254555.htm]
阅读几篇文章后,我简单整理一下收获
ActivityThread.main()是一个app开始 ...
AndroidNativeEmu和unidbg对抗ollvm的字符串混淆
AndroidNativeEmu和unidbg都是对unicorn进行了一定程度封装的开源项目,让我们可以很方便的调用jni函数,以及对没有实现的函数进行hook实现处理。并且让我们可以实现so里面模拟调用java函数。下面首先使用AndroidNativeEmu来对抗ollvm的字符串混淆。对so进行修复。让我们可以更加便捷的进行静态分析。
在实现之前,先总结下原理。
ollvm的字符串混淆,我们使用ida的时候。看到的结果如下。
这里相当于是一个解密函数。通过这个函数将会还原成正常的字符串。然后我们看看在哪里调用到了这个解密函数
可以看到是在.init_array中使用解密函数对字符串进行还原。也就是说。当我们执行完.init_array后。就会将正常的字符串写入内存中。这时我们就得到了真正的字符串了。所以根据这个情况。
第一步,我们需要监控内存的读写,然后运行.init_array。这样发生的内存写入时,基本可以确定是字符串还原函数在写入恢复的字符串。
写之前我们先看看unicorn的内存写入的相关注释
12345678/* Callback function ...
unicorn初学
unicorn相当于是一个cpu的模拟器,可以用来执行so中的代码段,一般不要直接使用apk中的so文件,直接使用是需要修复上下文的,这样会比较复杂。最好是直接从内存中直接dump一个so出来。然后就可以直接执行so里面的代码段。然后看一个例子ollvm9.apk
样品下载地址: https://pan.baidu.com/s/1ynsGvKAUbmvodvjG0mlLVg 密码: wu45
解密案例:https://github.com/dqzg12300/unicornDemo
首先用jadx打开这个apk。看看里面的按钮的功能
然后看到这里主要用到了UUIDCheckSum这个函数来进行加密
解压这个apk。用ida打开libnative-lib.so找到UUIDCheckSum函数。发现这个函数是ollvm混淆的。然后找入参的使用,发现了一个关键函数。
然后我们想要用unicorn来执行这个函数。首先找到函数的起始和终止位置,这个函数我找到是start:0xfcb4 end:0xff2c
直接使用我们这个ida查看的so文件是不行了。最好是在真机执行时从内存中dum ...
ollvm自定义string加密pass
先贴上测试好的结果: https://github.com/dqzg12300/kOLLVM.git
想要写一个字符串加密的pass,第一步就是先实现一遍c++的算法流程,然后再看一看生成的IR文件,然后再写对应的加密pass,下面看一个自己实现的简单c++字符串加密。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849#include <stdio.h>#include <cstring>#include <string>int main(int argc, char** argv) { //加密 std::string str1="hello world!!!"; //这里是随机的key,先写固定,真实实现的时候再每个字节使用一个随机key int randkey=11; //加密复杂度 int kstr_size=10; int enclen ...
llvm的pass
llvm中的pass例子llvm中最重要的部分就是pass,llvm主要就是通过pass来对代码进行优化工作。然后先看怎么使用pass。官方有默认注册很多种pass。所有pass都是在llvm/lib/Transforms目录下,可以通过opt来使用pass,先看官方例子最简单的pass,路径是llvm/lib/Transforms/Hello/Hello.cpp
123456789101112131415161718192021222324252627#include "llvm/ADT/Statistic.h"#include "llvm/IR/Function.h"#include "llvm/Pass.h"#include "llvm/Support/raw_ostream.h"using namespace llvm;#define DEBUG_TYPE "hello"STATISTIC(HelloCounter, "Counts number of function ...
llvm简单的使用
学习记录
llvm是一款跨平台的编译器,我们可以用它来优化编译代码,让代码执行的更加高效,而ollvm是将代码进行编译混淆,增加代码的不可读性。它的官方网站是http://llvm.org/
llvm中有一个中间语言是LLVM IR,这里看一段官方的说明
1The LLVM Core libraries provide a modern source- and target-independent optimizer, along with code generation support for many popular CPUs (as well as some less common ones!) These libraries are built around a well specified code representation known as the LLVM intermediate representation ("LLVM IR"). The LLVM Core libraries are well documented, and it is p ...
使用frida hook解释器Interpreter
学习的记录
准备hook一下Interpreter解释器的所有执行函数。先看下art/runtime/interpreter/interpreter.cc这个主要文件
123456enum InterpreterImplKind { kSwitchImplKind, // Switch-based interpreter implementation. kMterpImplKind // Assembly interpreter};static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind;
然后在中间看到了这个枚举,就是说我当前这个8.1的有两种解释器,一个是switch的,另一个是Assembly汇编的,然后看到当前选择的是汇编解释器,继续看下面如果是汇编解释器就怎么处理,代码太长,只截取中间关键的部分了。
123456789101112131415161718192021222324252627282930if (kInterpr ...
使用frida来hook artmethod的RegisterNative
继续学习记录
之前找到了最终有调用到ArtMethod的RegisterNative来进行绑定。现在使用frida来hook打印一下注册的函数名和地址。先用ida找到我们之前找到的ArtMethod下的RegisterNative
找到了导出函数符号_ZN3art9ArtMethod14RegisterNativeEPKvb
然后这里只有ArtMethod的指针,要获取完整的函数名。要使用ArtMethod的函数PrettyMethod。
导出函数符号为 _ZN3art9ArtMethod12PrettyMethodEb
然后frida的代码就是先hook到RegisterNative,然后调用PrettyMethod来获取函数名
123456789101112131415161718192021222324252627function hook_native_register(){ var module= Process.getModuleByName("libart.so"); var ArtMethodRegisterNative=m ...
jni函数动态注册分析
动态注册jni函数时的流程学习过程的记录,以下代码参考自aosp8.1
jni函数绑定主要是有两种方式。静态注册和动态注册的jni函数
静态注册的jni函数有两次绑定,在类加载时会绑定一次,在jni函数第一次被调用时,art会对jni函数的地址进行查询并绑定
动态注册的jni函数也有两次绑定,在类加载时绑定一次,第二次由开发人员的代码主动绑定。
DexClassLoader是安卓的一种类加载器,然后用他的loadClass函数来进行类加载处理,而DexClassLoader中没有看到loadClass函数。通过在父类中寻找。最终发现loadClass在ClassLoad类中。继承关系如下
DexClassLoader–>BaseDexClassLoader–>ClassLoader
然后开始看看loadClass的实现
123public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false);}
...
ios的砸壳和基础工具
一、砸壳1、dumpdecrypted这种砸壳方式我在ios11的机子上测试没能解密成功,然后ios10一点问题都没有。可能是我太渣了吧。新手还请用ios10来尝试
首先从github上下载了编译出来dumpdecrypted,这个基本没啥问题的。
接着我们用到了两个路径,一个是沙盒到路径,还有一个是运行的路径
运行想要砸壳的应用,然后ps -e|grep Application找到要砸壳的应用,将路径保存出来
然后我们需要找到沙盒到路径,简单的办法就是使用cycript注入之后,再查询出来。
ios11的是
1[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]
1file:///var/mobile/Containers/Data/Application/3B94D3F0-2CFB-4E0E-A0A2-03F960B2BA60/Docume ...
类对象的内存布局
类对象的存储结构首先看下一个空的对象占用的内存大小
123456class Student{};int main(){ Student stu; printf("stu size:%lu\n",sizeof(stu));}
下面是结果,说明一个对象的内存占用至少是1个字节
1@"stu size:1\r\n"
然后再看看增加成员变量的结构体的内存占用
12345678class Student{private: int arg;};int main(){ Student stu; printf("stu size:%lu\n",sizeof(stu));}
结果是int的大小
1@"stu size:4\r\n"
如果再增加一个char变量,结果就有区别了
123456789class Student{private: int arg; char sex;} ...