安卓逆向-用Frida写代码进行脱壳

常用Frida的API

function_address = Module.findExportByName(libname, function);
Interceptor.attach(address, func);
Interceptor.attach(address,
 onEnter: function (args) {
 },
 onLeave: function (retval) {
 }
)
File 模块 写文件流程
 new File(filepath, mode)
 write(data)
 flush()
 close()
file = new File("yuanrenxue.dex", "wb")
//data 是字符串或者 arrayBuffer // readByteArray() 返回的arrayBuffer
file.write(data)
file.flush()
file.close()
//把内存里的值转成字符串
Memory.readUtf8String()
//把内存里的值转换成整型
Memory.readInt()
//以begin为起始位置,从内存中读length长度的数据出来 返回ArrayBuffer类型
Memory.readByteArray(begin, length)
//把地址转换成NativePointer类型 frida里操作内存地址需要先转成NativePointer类型!!!
ptr()
JS api
#把其它进制转换成10进制
parseInt(num, radix)

复习dex文件格式

https://www.jianshu.com/p/f7f0a712ddfe

在这里插入图片描述
在这里插入图片描述

复习脱壳原理:

 复习:加固壳是如何运行起来的?
 1. -->APP启动
 2. -->壳dex先加载起来
 3. -->壳负责把源dex文件读出来
 4. -->壳把源dex文件解密
 5. -->把解密后的dex加载进内存 源dex运行起来

 源dex文件最终会加载进内存
 Hook加载Dex的函数(OpenMemory),把Dex从内存中dump出来
 Hook DexFile::OpenMemory()
 DexFile::OpenMemory(const uint8_t* base,size_t size,const std::string& location,
 uint32_t location_checksum,MemMap* mem_map,//nullptrconst OatDexFile* oat_dex_file,
 std::string* error_msg)

Frida代码脱壳

从手机端获取要hook的函数的so文件

在这里插入图片描述

用IDA打开得到OpenMemory的导出名

在这里插入图片描述

利用Frida的API进行导出(进行app重启非常重要device.resume(pid))
import frida, sys

def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)
package = 'com.iCitySuzhou.suzhou001'
jscode = """
var openMemory_address = Module.findExportByName("libart.so","_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_")

Interceptor.attach(openMemory_address,{
    onEnter:function(args){
        console.log("start")
        // dex文件的起始位置
        var dex_begin_address = args[1]

        // dex文件的前8个字节是magic字段,打印magic会显示"dex 035"这三个字符,可以验证是否为dex文件
        console.log("magic:"+Memory.readUtf8String(dex_begin_address))

        // 把地址转换成整形,再加32,因为dex文件的第32个字节处存放的是dex文件的大小
        var address = parseInt(dex_begin_address,16) + 32

        // 把address地址指向的内存读取出来,该值就是dex的文件大小
        // ptr(address)转换的原因是frida只接受NativePointer类型的指针
        var dex_size = Memory.readInt(ptr(address))
        console.log("dex_size:"+dex_size)

        // frida写文件,把内存中的数据写到本地
        var timestamp = new Date().getTime();
        var file = new File("/data/data/%s/"+timestamp+".dex",'wb')
        
        // Memory.readByteArray(begin,length)把内存里的数据读出来,从begin开始读,取length的长度
        file.write(Memory.readByteArray(dex_begin_address,dex_size))
        file.flush()
        file.close()

        send("dex begin address:"+parseInt(dex_begin_address,16))
        send("dex file size :"+dex_size)
    },
    onLeave: function (retval) {
        if (retval.toInt32() > 0) {
        }
    }
})
"""% (package)

# 定位jar包
device= frida.get_usb_device()
pid = device.spawn(['com.iCitySuzhou.suzhou001'])
process = device.attach(pid)
# 传入上面的js代码创造脚本
script = process.create_script(jscode)
# 接受信息打印信息模块
script.on('message', on_message)
print('[*] Running')
script.load()
# 重启的方法非常重要!为了能hook到,重启一遍这样是最好不过的了
device.resume(pid)
sys.stdin.read()

这样既可成功把引力波的壳脱出来

熟悉安卓虚拟机加载dex文件的流程(进阶)

https://www.jianshu.com/p/f81242ad8cb7

猜你喜欢

转载自blog.csdn.net/m0_50685012/article/details/114456047
今日推荐