unicorn_learning4

  1. 目标
  2. 注册java类和方法

unicorn_starting

模拟Jni与Java交互

目标

hook这个函数,其中存在调用java类和java函数

image-20221231150501748

尝试将上一次的代码进行修改后直接执行,观察结果

image-20221231153507375

注册java类和方法

结果发现不能找到java这个类,下面已经给出申明,直接复制即可

class com_sec_udemo_MainActivity(metaclass=JavaClassDef, jvm_name="com/sec/udemo/MainActivity"):
    def __init__(self):
        pass
# 添加自定义java类
emulator.java_classloader.add_class(com_sec_udemo_MainActivity)

执行后发现又要声明相关方法:

image-20221231154406776

声明方法:

@java_method_def(name='getSaltFromJava',signature='(Ljava/lang/String;)Ljava/lang/String;',
                     args_list=['jstring'],native=False) # 这里native=False申明此方法非native方法
def getSaltFromJava(self,mu,data):
        pass

这个函数在java中的功能如下:

image-20221231142325743

这里我们作出拼接返回即可

执行后再次报错

image-20221231155418523

这里我们缺少jobject对象,这里我们手动创建一下,然后传入进去

obj = com_sec_udemo_MainActivity()
sign = emulator.call_symbol(libnat_mod,'Java_com_sec_udemo_MainActivity_sign_1lv3',
        emulator.java_vm.jni_env.address_ptr,obj,'123')
print(sign)

然后这里又有相加时出现错误

image-20221231160243373

这里我们调试一下,data的内容:

image-20221231160423365

一看是java string类型,类型展开发现value中value就是python的str类型

image-20221231160549317

修改后成功出结果:

image-20221231160712892

完整代码:

from unicorn import *
import logging
import sys
from androidemu.java.helpers.native_method import native_method
from UnicornTraceDebugger import udbg
from androidemu.emulator import Emulator
from androidemu.utils import memory_helpers
from androidemu.java.java_classloader import JavaClassDef
from androidemu.java.java_method_def import java_method_def

# 配置logging
logging.basicConfig(
    stream=sys.stdout,
    level=logging.DEBUG,
    format="%(asctime)s %(levelname)7s %(name)34s | %(message)s"
                    )
# 用于打印调试信息
logger = logging.getLogger(__name__)

class com_sec_udemo_MainActivity(metaclass=JavaClassDef, jvm_name="com/sec/udemo/MainActivity"):
    def __init__(self):
        pass
    @java_method_def(name='getSaltFromJava',signature='(Ljava/lang/String;)Ljava/lang/String;',
                     args_list=['jstring'],native=False)
    def getSaltFromJava(self,mu,data):
        print('hello')
        return data.value.value + 'salt..'

# 根据执行失败的库函数,进行hook,直接本地写函数实现相关库函数功能,首先导入修饰器
@native_method
def __aeabi_memclr(mu,addr,size):
    mu.mem_write(addr,bytes(size))
    print('__aeabi_memclr_ptr (addr:%x,size:%d)' % (addr,size))

@native_method
def __aeabi_memcpy(mu,dist,source,size):
    data = mu.mem_read(source,size)
    mu.mem_write(dist,bytes(data))
    print('__aeabi_memcpy (dist:%x,source:%x)' % (dist,source))

@native_method
def sprintf(mu,buffer,format,arg1,arg2):
    format1 = memory_helpers.read_utf8(mu,format)
    data1 = memory_helpers.read_utf8(mu,arg1)
    res = format1 % (data1,arg2)
    mu.mem_write(buffer,bytes((res+'\x00').encode('utf-8')))
    print('sprintf (%s)' % (format))

# 创建模拟器
emulator = Emulator()

# 添加hook 此处必须在导入so文件之前就hook,因为此hook的本质就是hook got表的内容
# 在导入so文件之前hook才生效,导入之后没法hook
emulator.modules.add_symbol_hook('__aeabi_memclr', emulator.hooker.write_function(__aeabi_memclr) + 1)
emulator.modules.add_symbol_hook('__aeabi_memcpy', emulator.hooker.write_function(__aeabi_memcpy) + 1)
emulator.modules.add_symbol_hook('sprintf', emulator.hooker.write_function(sprintf) + 1)

# 添加自定义java类
emulator.java_classloader.add_class(com_sec_udemo_MainActivity)

# 加载相关so文件
# do_init 参数为false,即不执行初始化函数,因为unicorn不能实现相关初始化操作,
# 这可能会涉及更多库的调用
emulator.load_library('./lib/libc.so',do_init=False)
libnat_mod = emulator.load_library('./lib/libnative-lib.so',do_init=False)

# 执行报错时打印调试信息,跟踪报错与定位发生报错的相关地址
dbg = udbg.UnicornDebugger(emulator.mu,udbg.UDBG_MODE_ALL)


# 开始执行想要执行的jni函数
try:
    # 根据so模块调用指定的函数,后面都是函数的参数
    # 参数1: JNIEnv
    # 参数2: 是java类的对象,这里填0即可
    # 参数3: 是函数输入字符串
    obj = com_sec_udemo_MainActivity()
    sign = emulator.call_symbol(libnat_mod,'Java_com_sec_udemo_MainActivity_sign_1lv3',
                         emulator.java_vm.jni_env.address_ptr,obj,'123')
    print(sign)
except UcError as e:
    # 打印调用栈
    tracks = dbg.get_tracks()
    # 这里打印调用地址即可,打印后100条
    for addr in tracks[-100:-1]:
        print(hex(addr - 0xcbc66000))
    print(e)



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 jaytp@qq.com

×

喜欢就点赞,疼爱就打赏