首页
社区
课程
招聘
[原创]细品sec2023安卓赛题
发表于: 2023-8-31 17:25 23374

[原创]细品sec2023安卓赛题

2023-8-31 17:25
23374

在今年三月份的时候,我参加了腾讯游戏安全技术竞赛,到现在差不多快过去半年了,当时做这道安卓初赛题目时,也是卡在开头就毫无头绪了,而后看到看雪上的三位大佬|_|sher师傅,juice4fun师傅fallw1nd师傅都分享了他们做这道题目时的解题过程,也是让我重拾了做出这道安卓初赛题的信心,因为需要分心在学习和其他事情上,所以从三月份到七月份也是陆陆续续复现了五个月,一路上走走停停

终于在八月份,我难能可贵的获得了整整一个月的充裕时间,这也让我可以好好去钻研这道对我来说难度极大的安卓题目了,解题的过程中基本上把我能想到的安卓逆向工具用了个遍,每当我在解题的过程中遇到瓶颈时,我总会把这三位大佬的writeup打开来反复观摩研究思考为什么要这样做,怎么做效果会更好

直到注册机写完之后纵观整个解题过程,真的是学到了很多

il2CppDumper是分析unity游戏的基础,能有好的开头全靠站在巨人的肩膀上

运行时解密so文件,让我首次尝试去手工修复dump下来的so

libsec2023.so中的反调试让我学会使用在安卓手机中断下硬件断点的工具rwProcMem33,也开始第一次编译安卓内核,经历了两三个不眠之夜

第一眼见到CSEL-BR和CSET-BR结构的花指令让我毫无头绪,也让我开始思考frida-stalker与unicorn的区别所在,最终我选择使用frida-stalker辅助分析,IDApython批量去花的方法,效果很好

BlackObfuscator混淆让我想起了被ollvm的控制流平坦化支配的恐惧,一筹莫展之际,这个月最新的工具Jeb5.1竟然能完美去除BlackObfuscator混淆,着实让我惊喜不已

在探索vm的过程,我也慢慢的摸索出了vm题型的解题方法,或许未来遇到vm我也能游刃有余了

前言写的有点长了,也算是我在这半年对于这道安卓题的感悟吧哈哈,虽然是安卓方向初赛题,但是对我整个安卓逆向的学习过程意义非凡,这篇文章我也写的尽可能的详细,前后的思维也尽量避免跳跃,每一步的操作基本上都是有据可依的,为之后也同样想要复现这道题目的朋友尽一点绵薄之力

题目可以在腾讯游戏安全竞赛官网下载 下载链接

看雪这里也上传了一份到附件里了

我在github里面也存了一份上去 下载链接

首先我们通过jadx反编译mouse_pre.aligned.signed.apk,通过查看AndroidManifest.xml可以知道下列关键信息

解压该apk,通过查看lib文件夹内的内容,我们发现了libil2cpp.so

image-20230407124030376

我们使用Il2CppDumper尝试解密global-metadata.dat,但是却失败了

image-20230407124010267

看了一下global-metadata.dat是没有加密的

image-20230407160715829

接下来我们用ida反编译libil2cpp.so,发现被加密了

image-20230407142822706

接下来我准备用frida来把解密后的libil2cpp.so从内存中dump下来

但是当我用frida将代码注入进去后,apk提示hack detect,然后就退出了

之后我不用frida注入这个apk,但是后台依旧运行着frida-server,apk依然弹出hack detect后退出

通过这一点我大致可以判断它的检测方式有这两种可能

我们一个一个去验证一下

首先我们把后台运行的frida-server名称改成fs试试

修改完后依旧弹出hack detect

那我们再去试一试修改frida-server的端口

端口修改之后用frida注入也不弹窗了

现在我们可以用frida把解密后的libil2cpp.sodump下来,脚本如下

在使用frida运行脚本之前需要注意去做一下端口转发

随后进行frida注入

image-20230407160451904

直接把dump下来的libil2cpp.so放到Il2CppDumper中,成功获取符号

image-20230407230411862

对于dump下来的so文件,所有的段(segment)和节(section)的偏移都是在虚拟空间中的偏移(即映射到进程空间的虚拟地址偏移),但静态分析工具分析so时所使用的偏移仍然为在实际文件中的偏移(即相对于文件开头的字节偏移量),错误的偏移导致静态分析工具如IDA等无法分析dump下来的so

所以我们需要将segmentsection在实际文件中的偏移替换为在虚拟空间中的偏移,这些偏移由program header tablesecion header table内的成员指出

我们将libil2cpp.solibil2cpp.so_0x712a997000_0x13cc000.so一并拖入010 editor中,两个文件相互对比进行修复

010editor中复制一个成员的值到另一个成员中,只需要在软件界面的Template Results中单击想要复制的值按下Ctrl+Shift+C,然后单击需要替换的值,按下Ctrl+Shift+V即可完成替换

段(segment) 的位置和大小由程序头表(Program Header Table)中的这四个成员决定

libil2cpp.so_0x712a997000_0x13cc000.so中我们将program_header_table中每一个elementp_vaddr_VIRTUAL_ADDRESS的值复制到p_offset_FROM_FILE_BEGIN,p_memsz_SEGMENT_RAM_LENGTH的值复制到p_filesz_SEGMENT_FILE_LENGTH

节头表(secion header table)的位置在最后一个段(segment)之后,我们可以从ELF文件的Execution View直观看出
图片描述

由下图所示,libil2cpp.so_0x712a997000_0x13cc000.sosection_header_table在实际文件中的偏移为0x11AB778,我们需要将其修改为在虚拟空间中的偏移,这个值为0x13CB778,计算过程如下,此处所涉及计算的成员的值是在program_header_table的最后一个element,即program_table_entry64_program_table_element[10]

Section Header Table和Program Header Table并不是一定要位于文件开头和结尾的,其位置由ELF Header指出

决定section_header_table起始地址的成员为elf_header->e_shoff_SECTION_HEADER_OFFSET_IN_FILE,位置如下图所示,在修改完成后,按下F5重新运行模板ELF.bt
图片描述

在我们修正 节头表(secion header table) 的偏移后,节头表所在的区域是没有内容的,如下图所示,所以需要从libil2cpp.so中复制节(section)的内容到dump下来的so中
图片描述

我们在libil2cpp.so点击struct section_header_table并按下Ctrl+Shift+C,然后回到libil2cpp.so_0x712a997000_0x13cc000.so中,选中section_header_table然后按下Ctrl+Shift+V,按下F5重新运行模板ELF.bt
图片描述

可以发现修补了节(section)的内容之后,section的名称依旧是乱码

这是什么原因呢?

ELF文件中的每个section都是有名字的,比如.data.text.rodata,每个名字都是一个字符串,既然是字符串就需要一个字符串池来保存,而这个字符串池也是一个section,或者说准备一个section用来维护一个字符串池,这个字符串池保存了其他section以及它自己的名字。这个特殊的section叫做.shstrtab,所有section的头部是连续存放在一起的,类似一个数组,e_shstrndx变量是.shstrtab在这个数组中的下标。

首先我们要明白section的名称是如何通过索引找到的,在libil2cpp.so_0x712a997000_0x13cc000.so中,找到elf_header->e_shtrndx_STRING_TABLE_INDEX,这个的值为26(0x1A),说明了section_header_table->section_table_element[26]存储了所有section的名称
图片描述
section_header_table->section_table_element[26]s_offset的值决定了section的名称将从1199370h去索引

图片描述

我们可以在dump前后的libil2cpp.so都跳转到这个地址去看看,在010editor中进行地址跳转只需右键该值选择Goto Address即可
图片描述
section的所有名称都在这个地方
图片描述
之后我们要将section的符号名称从原来的so复制到dump下来的so里面,位置就是我们之前分析出来的section_table_element[26]s_offset所指向的物理内存地址,即选中libil2cpp.so0x1199370h0x1199470h按下Ctrl+Shift+C,然后将光标移动到libil2cpp.so_0x712a997000_0x13cc000.so119A370h处,按下Ctrl+Shift+V

节(section) 的位置和大小由节头表(secion_header_table)中这两个成员决定

修正 节(section) 的偏移有两条规则

修正完成后,按下F5重新运行模板ELF.bt,可以发现section的名称已经恢复,同时也有了dynamic_symbol_table

图片描述

然后,我们将libil2cpp.so_0x712a997000_0x13cc000.so拖入IDA中进行分析,待分析完成后,点击如图所示的选项重新定位基址为0x712a997000,这样可以分析出更多的符号

image-20230505144017295

之后,我们点击File->Script file...运行il2cppdumper中的ida_with_struct_py3.py,需要注意的这个脚本需要运行两次,第一次选择script.json,第二次选择il2cpp.h

处理之后的效果如下

image-20230506180743547

接下来需要知道这个OK按钮调用的函数

screenshot

我们可以使用这个工具frida-il2cppDumper,用法就直接用frida注入_agent.js就可以了

当我们进入该apk之后,下列函数被调用

我们去看一下最后调用的这个函数oO0oOo0,进入IDA去进行分析,很明显是生成TOKEN的地方

image-20230506185306047

当我们点击小键盘上的OK按钮后,下列函数被调用,由于调用的函数太多,我这里仅仅从首次调用的函数开始,截取了部分输出作为示例

SmallKeyboard类被调用了很多次,我们可以去dump.cs里面搜索一下,此处定义了KeyType不同的值对应的含义,那么这个EnterKey就是OK按钮了

image-20230507183715015

回到IDA,我们再去搜索一下SmallKeyboard,找到SmallKeyboard__iI1Ii(SmallKeyboard_o *this, SmallKeyboard_iII1i_o *info, const MethodInfo *method)这个函数,这是与KeyType有关的函数,显而易见,我们需要重点分析的是KeyType == 2的情况

image-20230808172326007

对于这行代码,我的猜测是v13存储了我输入的值,我们可以使用frida去hookSystem_Convert__ToUInt64_486054767044的返回值来验证我们的猜想

image-20230808172408181

当我输入123456,并点击OK按钮后,frida的回显如下,可以印证我们的猜测是正确的,v13是我们输入的数字

image-20230507190652325

v13作为参数传入了SmallKeyboard__iI1Ii_486050613936内,那么这应该就是我们要寻找的加密逻辑

经过两个B跳转后,我们来到了这里

image-20230809155725055

这段汇编很有意思,我们去分析一下,off_712BD51FF0存储的是导入函数g_sec2023_p_array的地址,而g_sec2023_p_array的函数定义在libsec2023.so中,BR指令是无条件寄存器跳转,那么这四行arm汇编的意义就是调用g_sec2023_p_array偏移0x48处的函数

来到libsec2023.so我们即可找到相对应的导出函数sub_31164

image-20230809160214205

那么显而易见,关键的逻辑就在libsec2023.so中的sub_31164

libsec2023.sosub_31164hook一下

但是当我注入将这段frida代码注入到libsec2023.so后,程序在短暂的延迟后显示hack detect后退出了

我们可以使用frida Stalker来查看这个so调用函数的过程

为了使用上的方便,我写了一个IDA插件来实现下面的过程,插件地址:https://github.com/oacia/stalker_trace_so,这应该算是我第一次造轮子吧:)

首先使用如下idaPython脚本打印出libsec2023.so的所有函数的地址和名称

将上面IDApython所打印出的内容填入下面frida代码的变量func_addrfunc_name

打开apk后frida输出如下

这里需要用到的工具是rwprocmem33,具体的编译和使用可以在我写的另一篇文章进行阅读,这里不在过多赘述

运行下面的frida代码获取libsec2023.so的基址

image-20230817132059046

利用下面的命令获取进程的PID

将得到的参数填入rwprocmem33

首先对我们最感兴趣的libil2cpp.so调用的libsec2023.so的导出函数sub_35404下硬件断点看看,毕竟之前我们用frida去hook这个函数失败了嘛,硬件断点下的位置可以通过基址(base)+偏移(func offset)得到

结果如下

image-20230817132705290

仅仅下了五秒的硬件断点,相同地址的命中次数进入达到了百万次

我们再对不同的地址打下硬件断点看看,发现均只有一个命中地址,并且命中次数都达到百万次

与基址相减得到偏移为0x37704

image-20230817133029502

进入ida查看sub_37704函数,代码很短,按下交叉引用也没有输出

image-20230817025119017

这该怎么办呢?

还记得上面我们曾用frida-stalker打印出了libsec2023.so函数的调用链嘛,我们从sub_37704向上回溯看看

sub_37704是被sub_376CC调用的,sub_376CC中的这个BR跳转应该是调用了sub_37704

image-20230817030756246

再看调用sub_376CC的函数sub_371AC,在这个函数中,我们发现了一条有趣的指令,CSEL

image-20230817133504656

熟悉arm指令集的朋友肯定知道,CSEL是arm中的分支结构指令,而BR跳转的位置由X8决定,所以这段汇编便可以改变便程序控制流

CSEL X8, X8, X9, EQ中,EQ表示Equal,即相等条件,其值由最近的CMP的比较后得出的值决定,例如此处判断的条件就是CMP W0, W8

用c语言来表示就是

X8X9相差0x10,X8的修改便导致了控制流的改变

为了不让控制流转向错误的分支导致frida注入后强制退出,我们可以对此处的汇编进行patch,将CSEL X8, X8, X9, EQ改为CSEL X8, X8, X8, EQ,即将汇编08 01 89 9A修改为08 01 88 9A

image-20230817154739431

但是要怎么让apk运行我们patch过后的libsec2023.so呢?

有以下的三种思路可以参考

前两种方法经过尝试均以失败告终,那么现在只剩下最后一种方法了,就是在libsec2023.so加载之后动态patch,而这利用frida可以说简直就是轻而易举,利用Memory.writeByteArray就可以做到

运行rpc.exports.anti_sec2023()的时机是在打开apk之后

之后再次尝试对sub_31164附加钩子

这一次,钩子成功附加上去了!

image-20230817170036802

sub_31164首先调用了sub_3B8CC,那我们就就去分析一下sub_3B8CC

image-20230818141550105

往下看最后一行汇编是是BR X8,我们看看BR表示的意思是什么

BR: 跳转到某寄存器(的值)指向的地址(无返回), 不会改变 lr (x30) 寄存器的值。

寄存器跳转的存在严重的阻碍了我们的逆向分析,那我们试试能不能稍稍修改一下

我们可以使用frida-stalker来追踪寄存器的值(绝对不是因为我用不来unicorn才用frida的(真的)

起初我是直接准备patch内存中的指令的,代码也写的差不多了(现在被注释了),没想到这寄存器跳转会有两种情况,没办法改成B跳转,不然进程会崩溃掉,所以就打印出跳转的地址手工分析咯

运行代码后,程序输出如下

我们不妨以地址0x3ba70作为分析的示例,这里我们发现0x3ba70会跳转的地址有两种情况,分别是0x3ba340x3ba74

等等,0x3ba74??这不就是0x3ba70之后要执行的指令吗?

那结果显而易见了,这BR寄存器跳转的前身肯定就是条件跳转,BGE,BLE这类的指令

接下来就是在IDA里面修复控制流咯,我们修复一下0x3ba00这个第一个BR跳转的地方,别的地方的思想都是一样的

image-20230819014827349

进入到off_72C40,加上W11得到正确的跳转,写了个简单的python脚本输出hex方便直接复制进去

这个地方修复完是这样的,可以看到*(off_72C40+0)*(off_72C40+0x28)的地方值已经被我加上去了

image-20230819020109133

接下来就是改是汇编了,ADD指令我们肯定是不需要了,因为已经被我们加上去了,所以接下来继续往下走看的是这条CSEL X10, XZR, X9, CC指令

image-20230819020355254

各个条件码的含义如下

那么这里BR分支跳转的意思就可以表示为

所以这里改成BGE,然后把不需要的指令NOP掉,一处地方就修复好啦

image-20230819022733118

还要注意的是,除了CSEL-BR结构之外,还有CSET-BR结构

image-20230825005445886

CSET: 比较指令,满足条件,则并置 1,否则置 0 ,如:

CSEL-BR结构的修复思路是相似的,对于上图(0x3B95C处)的CSET-BR结构,我们仅需关注这几行指令

其中的LDR X8, [X21,W23,UXTW#3]的含义可以用C语言这样表示X8 = *(X21 + (W23 << 3)),UXTW#3即将操作数左移三位的意思

这样一个一个修复过去,未免也太麻烦了,那索性就写个idapython脚本一键去除CSEL-BRCSET-BR结构来解放双手吧哈哈

第一个加密函数sub_3B9D4取出数据的每一位进行加密,其中出现的HIBYTE , BYTE2, BYTE1,LOBYTE 含义如下,假设有数据a1=0x12345678,则

我们可以使用frida去hooksub_3B9D4传入的值以及返回值,观察加密前后的变化,假设我此处在小键盘输入的数字是999999999999,hex(999999999999)=0xe8d4a50fff

image-20230829154207172

于是第一个算法如下

在对输入的值进行首轮加密之后,又再次对输入值经过bswap32函数加密

image-20230829160716908

这个函数对应的arm汇编为

那我们去arm手册看看REV指令的定义好了

REV

Byte-Reverse Word reverses the byte order in a 32-bit register.

Operation

Operation很清楚的知道这就是反转字节,比如

所以此处bswap32(v6),是对v6进行字节翻转,而v6 = HIDWORD(a1),故在进行第一个加密函数sub_3B9D4之后,将首先对输入的高32位进行加密处理,这在我们后续hook第二个加密函数sub_3A924之后,也可以体现出来这一点

我们首先hook一下sub_3A924让前后分析的逻辑连贯起来

在经过第一轮加密后,我们得到了密文cc ca 94 6d e3 d5 39 39,而在此处,第一次调用sub_3A924的输入为6d 94 ca cc,第二次调用sub_3A924的输入为39 39 d5 e3,正好对应了上文提到的翻转字节处理

image-20230830024642669

我们进入该函数后,发现如v11+1408LL,v11 + 1664LL等等的fastcall函数调用,一般这种形式的函数调用在安卓逆向中遇到的话,那大概率就是JNIEnv *

image-20230829154859854

在此题中,我们只需要对v11按下Y切换类型,然后输入JNIEnv *,就会转换成JNIEnv *的结构体函数指针如图

image-20230830000329982

在这里出现了jni函数GetStaticMethodID,我们hook一下这个函数观察调用了什么方法

在输出中,我们发现GetStaticMethodID调用了名为encrypt的方法

image-20230830000805212

但是我们在apk中却并未发现该方法

image-20230830000915933

那么由此就可以推断出这个方法是由dex动态加载的

我们可以使用frida-dexdump来把内存中的dex给dump下来,要注意frida的端口已经被我们修改为了1234,所以这里也要加上-H参数

image-20230830001101633

将所有dex dump下来之后,接下来的步骤就是把这些dex一个一个拖进jadx里面反编译,去看看哪一个dex包含encrypt方法

image-20230830001653193

这个控制流一眼看上去就是加了混淆的,据FallW1nd师傅说是BlackObfuscator混淆,本来准备去手工分析的,但是想起前几天刚下载了Jeb5.1,就想看看新工具的效果怎样

当我用Jeb5.1反编译这个dex之后,这BlackObfuscator混淆怎么就直接去除了????

好家伙这Jeb5.1竟然能自动去除控制流平坦化,crazy!

image-20230830022051922

那么这第二个加密的逻辑相当的清晰,算法如下

image-20230830033519965

我们可以hook一下第二次加密前后输入的变化

image-20230830064031273

我们在sub_31164中去hook最后的br x2跳转来观察之后跳转到了哪一个函数中

image-20230830065454042

可见在libsec2023.so中经过两次加密之后,apk回到了libil2cpp.so

image-20230830065541513

偏移0x138d64加上原来so的基址后,定位到了这个地方

image-20230830070108643

B跳转过去发现并不是一个函数,而是FUNCTION CHUNK

image-20230830070631442

那先修改一下.init_procEnd address

image-20230830070942449

然后回到之前chunk function的位置,按下P让IDA分析出函数,就可以看伪代码继续分析了

这个类的名称被o,O,0给混淆了,导致难以分辨类和变量,所以需要为这些类和变量进行重命名

image-20230830091801333

在看看其他函数,这最后的v6 + v8 + (v6 | ~v8) + (v8 ^ v6) - (v6 & ~v8) + 1看起来是MBA表达式

image-20230830091847819

在github找个工具GAMBA简化一下,有些表达式要分开简化效果才好,这里4294967296=0x100000000已经溢出32位了,所以4294967296+v8=v8

image-20230830101119023

重命名函数之后,很明显发现这个加密算法应该和VM指令相关

image-20230830102759333

我们回到类的初始化函数ctor完成之后,下一个要调用的函数OO0OoOOo_Oo0__oOOoO0o0

image-20230830105402607

进入该函数,又是经典的while(1)循环,那么在这个循环里面,必定会出现eipopcode,这两个分别对应着this->fields.oOOO0Oo0U16_arr,我们重命名之

image-20230830105501678

之后,我们以add函数为例分析其他全局变量的含义,这里对应的vm指令应该为add uS_arr[bbb], uS_arr[bbb], uS_arr[bbb+1]

image-20230830102726283

到这里可能会有人纠结uS_arr究竟代表寄存器还是代表栈呢?我们回到初始化函数中,发现变量bbb所赋的初值为-1,那么由此可以确定,uS_arr代表的是栈,而bbb则表示esp

image-20230830110257781

至此为止,vm所需的关键变量我们均已经分析清楚了

image-20230830110454534

接下来就可以分析vm虚拟机了,对于vm类题型,我们只需要找到vm指令中的加减乘除位运算的位置和输入输出是多少就够了,别的指令比如push,pop,mov,opcode是多少,opcode是如何被vm读取等等这些问题都不需要考虑,因为在vm中,所有的vm指令的最终目的都是为了对输入的值进行操作,我们知道了这些加密运算,那么逆运算自然是信手拈来

所以在这里,我们可以用frida去hook一下运算相关的指令

输出以及分析如下

由此可见,这个vm其实相当的简单

这个算法一看就知道是xtea,那么需要知道的就只有v24这个密钥了

image-20230831064228955

用frida把密钥hook下来

image-20230831065121629

再把xtea加密之后的值也顺便hook下来

image-20230831070953192

那么这部分的算法如下

至此为止,所有加密算法分析完毕

在所有的加密完成后,这里的result就是我们的token,加密的低32位和token比较,高32位和0比较

image-20230831072058487

ELF文件格式的详解

[原创]2023腾讯游戏安全竞赛初赛题解(安卓)

[原创]2023腾讯游戏安全大赛-安卓赛道初赛wp

[原创] 腾讯游戏安全技术竞赛2023 安卓客户端初赛WriteUp

ARMv8(aarch64)指令集特性

blueline:/data/local/tmp # ./fs
blueline:/data/local/tmp # ./fs
blueline:/data/local/tmp # ./fs -l 0.0.0.0:1234
blueline:/data/local/tmp # ./fs -l 0.0.0.0:1234
function dump_so(so_name) {
    Java.perform(function () {
        var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
        var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
        var libso = Process.getModuleByName(so_name);
        console.log("[name]:", libso.name);
        console.log("[base]:", libso.base);
        console.log("[size]:", ptr(libso.size));
        console.log("[path]:", libso.path);
        var file_path = dir + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so";
        var file_handle = new File(file_path, "wb");
         
        if (file_handle && file_handle != null) {
            Memory.protect(ptr(libso.base), libso.size, 'rwx');
            //如果报错为Error: access violation accessing,那么可以尝试添加下面的这一行代码,libso.base加上的值是通过address(access violation accessing)-address(base)计算出来的
            //Memory.protect(ptr(libso.base.add(0x13b7000)), libso.size-0x13b7000, 'rwx');
            var libso_buffer = ptr(libso.base).readByteArray(libso.size);
            file_handle.write(libso_buffer);
            file_handle.flush();
            file_handle.close();
            console.log("[dump]:", file_path);
        }
    });
}
 
rpc.exports = {
    dump_so: dump_so
};
function dump_so(so_name) {
    Java.perform(function () {
        var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
        var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
        var libso = Process.getModuleByName(so_name);
        console.log("[name]:", libso.name);
        console.log("[base]:", libso.base);
        console.log("[size]:", ptr(libso.size));
        console.log("[path]:", libso.path);
        var file_path = dir + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so";
        var file_handle = new File(file_path, "wb");
         
        if (file_handle && file_handle != null) {
            Memory.protect(ptr(libso.base), libso.size, 'rwx');
            //如果报错为Error: access violation accessing,那么可以尝试添加下面的这一行代码,libso.base加上的值是通过address(access violation accessing)-address(base)计算出来的
            //Memory.protect(ptr(libso.base.add(0x13b7000)), libso.size-0x13b7000, 'rwx');
            var libso_buffer = ptr(libso.base).readByteArray(libso.size);
            file_handle.write(libso_buffer);
            file_handle.flush();
            file_handle.close();
            console.log("[dump]:", file_path);
        }
    });
}
 
rpc.exports = {
    dump_so: dump_so
};
adb forward tcp:1234 tcp:1234
adb forward tcp:1234 tcp:1234
frida -H 127.0.0.1:1234 -l "D:\frida\sec2023\global-metadata_dump.js" -f "com.com.sec2023.rocketmouse.mouse"
frida -H 127.0.0.1:1234 -l "D:\frida\sec2023\global-metadata_dump.js" -f "com.com.sec2023.rocketmouse.mouse"
成员名称 含义
p_offset_FROM_FILE_BEGIN 在实际文件中的偏移
p_vaddr_VIRTUAL_ADDRESS 在虚拟空间中的偏移
p_filesz_SEGMENT_FILE_LENGTH 在实际文件中的大小
p_memsz_SEGMENT_RAM_LENGTH 在虚拟空间中的大小
成员名称 含义
s_addr 如果此 section 需要映射到进程空间,此成员指定映射的起始地址;如不需映射,此值为 0
s_offset 此 section 相对于文件开头的字节偏移量.如果 section 类型为 SHT_NOBITS,表明该 section 在文件中不占空间,这时 sh_offset 没什么用
frida -H 127.0.0.1:1234 -l "D:\frida\frida-il2cppDumper-main\_agent.js" -f "com.com.sec2023.rocketmouse.mouse"
frida -H 127.0.0.1:1234 -l "D:\frida\frida-il2cppDumper-main\_agent.js" -f "com.com.sec2023.rocketmouse.mouse"
method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:466300
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:46618C
 private Void Start(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:465E90
 private Void oO0oOo0(){ }
 
 method  end
method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:466300
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:iII1i
 methodPointer offset in IDA:4663A8
 public Void .ctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:46618C
 private Void Start(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:465E90
 private Void oO0oOo0(){ }
 
 method  end
method  call
 nameSpaze: class:<>c__DisplayClass14_0
 methodPointer offset in IDA:4663B0
 internal Void <Start>b__0(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:465FDC
 private Void iI1Ii(GameObject go) { }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:465880
 private Void iI1Ii(iII1i _info) { }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:465AB0
 private Void iI1Ii(UInt64 i1I) { }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:Oo0
 methodPointer offset in IDA:4660E8
 public Void .ctor(UInt16[] OoOOO00, Int32 oOOO0O0O, UInt32[] OOoOO0) { }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:Oo0
 methodPointer offset in IDA:46A55C
 private Void O000O000000o(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:oO0OoOOo
 methodPointer offset in IDA:46A4D8
 private Void .cctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:Oo0
 methodPointer offset in IDA:46AD44
 private Void oOOoO0o0(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:Oo0
 methodPointer offset in IDA:46B578
 private Void O00O00000o(){ }
 
 method  end
method  call
 nameSpaze: class:<>c__DisplayClass14_0
 methodPointer offset in IDA:4663B0
 internal Void <Start>b__0(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:465FDC
 private Void iI1Ii(GameObject go) { }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:465880
 private Void iI1Ii(iII1i _info) { }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze: class:SmallKeyboard
 methodPointer offset in IDA:465AB0
 private Void iI1Ii(UInt64 i1I) { }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:Oo0
 methodPointer offset in IDA:4660E8
 public Void .ctor(UInt16[] OoOOO00, Int32 oOOO0O0O, UInt32[] OOoOO0) { }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:Oo0
 methodPointer offset in IDA:46A55C
 private Void O000O000000o(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:oO0OoOOo
 methodPointer offset in IDA:46A4D8
 private Void .cctor(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:Oo0
 methodPointer offset in IDA:46AD44
 private Void oOOoO0o0(){ }
 
 method  end
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
 method  call
 nameSpaze:OO0OoOOo class:Oo0
 methodPointer offset in IDA:46B578
 private Void O00O00000o(){ }
 
 method  end
function hook_native(){
    // 程序入口
Java.perform(function()
{
     
    // 获取模块
    var module = Process.getModuleByName("libil2cpp.so")
    // 转为函数地址
    var addr=module.base.add("0x85b9c4");
    // 获取函数入口
    var func =  new NativePointer(addr.toString());
 
    console.log('[+] hook '+func.toString())
 
    // 函数hook钩子附加
    Interceptor.attach(func, {
     
        onEnter: function (args) {
      
            console.log('hook success');
            console.log(args[0]);
            console.log(args[1]);
        },
        onLeave: function (retval) {
            console.log("retvalue is :", retval.toInt32());
            console.log('method onleave');
        }
    });
});
}
setImmediate(function(){
    setTimeout(hook_native, 1000);
},0);
function hook_native(){
    // 程序入口
Java.perform(function()
{
     
    // 获取模块
    var module = Process.getModuleByName("libil2cpp.so")
    // 转为函数地址
    var addr=module.base.add("0x85b9c4");
    // 获取函数入口
    var func =  new NativePointer(addr.toString());
 
    console.log('[+] hook '+func.toString())
 
    // 函数hook钩子附加
    Interceptor.attach(func, {
     
        onEnter: function (args) {
      
            console.log('hook success');
            console.log(args[0]);
            console.log(args[1]);
        },
        onLeave: function (retval) {
            console.log("retvalue is :", retval.toInt32());
            console.log('method onleave');
        }
    });
});
}
setImmediate(function(){
    setTimeout(hook_native, 1000);
},0);
function hook_sub_31164(){
    // 程序入口
Java.perform(function()
{
     
    // 获取模块
    var module = Process.getModuleByName("libsec2023.so")
    // 转为函数地址
    var addr=module.base.add("0x31164");
    // 获取函数入口
    var func =  new NativePointer(addr.toString());
 
    console.log('[+] hook '+func.toString())
 
    // 函数hook钩子附加
    Interceptor.attach(func, {
     
        onEnter: function (args) {
      
            console.log('hook success');
            console.log(args[0]);
            console.log(args[1]);
            console.log(args[2]);
        },
        onLeave: function (retval) {
            console.log("retvalue is :", retval.toInt32());
            console.log('method onleave');
        }
    });
});
}
 
rpc.exports = {
    hook_sub_35404: hook_sub_35404
}
function hook_sub_31164(){
    // 程序入口
Java.perform(function()
{
     
    // 获取模块
    var module = Process.getModuleByName("libsec2023.so")
    // 转为函数地址
    var addr=module.base.add("0x31164");
    // 获取函数入口
    var func =  new NativePointer(addr.toString());
 
    console.log('[+] hook '+func.toString())
 
    // 函数hook钩子附加
    Interceptor.attach(func, {
     
        onEnter: function (args) {
      
            console.log('hook success');
            console.log(args[0]);
            console.log(args[1]);
            console.log(args[2]);
        },
        onLeave: function (retval) {
            console.log("retvalue is :", retval.toInt32());
            console.log('method onleave');
        }
    });
});
}
 
rpc.exports = {
    hook_sub_35404: hook_sub_35404
}
import idautils
import idc
 
func_addr = []
func_name = []
for i in idautils.Functions():
    func_addr.append(i)
    func_name.append(idc.get_func_name(i))
for i in func_addr:
    print(f"{hex(i)}, ",end='')
print('')
for i in func_name:
    print(f"\"{i}\", ",end='')
import idautils
import idc
 
func_addr = []
func_name = []
for i in idautils.Functions():
    func_addr.append(i)
    func_name.append(idc.get_func_name(i))
for i in func_addr:
    print(f"{hex(i)}, ",end='')
print('')
for i in func_name:
    print(f"\"{i}\", ",end='')
var func_addr = [...]
var func_name = [...]
 
function hook_dlopen(soName = '') {
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    if (path.indexOf(soName) >= 0) {
                        this.is_can_hook = true;
                    }
                }
            },
            onLeave: function (retval) {
                if (this.is_can_hook) {
                    //hook_sub_3530C();
                    var times = 1;
                    var module = Process.getModuleByName("libsec2023.so");
                    this.pid = Process.getCurrentThreadId();
                    console.log("start Stalker!");
                    Stalker.follow(this.pid,{
                        events:{
                            call:false,
                            ret:false,
                            exec:false,
                            block:false,
                            compile:false
                        },
                        onReceive:function(events){
                        },
                        transform: function (iterator) {
                            var instruction = iterator.next();
                            do{
                                if (func_addr.indexOf(instruction.address - module.base) != -1){
                                    console.log("call" + times+ ":" + func_name[func_addr.indexOf(instruction.address - module.base)])
                                    times=times+1
                                }
                                iterator.keep();
                            } while ((instruction = iterator.next()) !== null);
                        },
 
                        onCallSummary:function(summary){
 
                        }
                    });
                    console.log("Stalker end!");
                }
            }
        }
    );
}
setImmediate(hook_dlopen, "libsec2023.so")
var func_addr = [...]
var func_name = [...]
 
function hook_dlopen(soName = '') {
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    if (path.indexOf(soName) >= 0) {
                        this.is_can_hook = true;
                    }
                }
            },
            onLeave: function (retval) {
                if (this.is_can_hook) {
                    //hook_sub_3530C();
                    var times = 1;
                    var module = Process.getModuleByName("libsec2023.so");
                    this.pid = Process.getCurrentThreadId();
                    console.log("start Stalker!");
                    Stalker.follow(this.pid,{
                        events:{
                            call:false,
                            ret:false,
                            exec:false,
                            block:false,
                            compile:false
                        },
                        onReceive:function(events){
                        },
                        transform: function (iterator) {
                            var instruction = iterator.next();
                            do{
                                if (func_addr.indexOf(instruction.address - module.base) != -1){
                                    console.log("call" + times+ ":" + func_name[func_addr.indexOf(instruction.address - module.base)])
                                    times=times+1
                                }
                                iterator.keep();
                            } while ((instruction = iterator.next()) !== null);
                        },
 
                        onCallSummary:function(summary){
 
                        }
                    });
                    console.log("Stalker end!");
                }
            }
        }
    );
}
setImmediate(hook_dlopen, "libsec2023.so")
call1:JNI_OnLoad
call2:sub_FF14
call3:.memset
call4:.vsnprintf
call5:.time
call6:.localtime
call7:.__android_log_print
call8:sub_10070
call9:.fopen
call10:sub_21000
call11:.pthread_once
call12:sub_21054
call13:sub_412CC
call14:.malloc
call15:sub_21098
call16:sub_FABC
call17:sub_1010C
call18:sub_10194
call19:sub_11C4C
call20:.pthread_mutex_init
call21:sub_103D0
call22:sub_2BCA8
call23:sub_125E4
call24:sub_12660
call25:sub_1CE70
call26:sub_1CE34
call27:sub_1C664
call28:.pthread_mutex_lock
call29:.pthread_mutex_unlock
call30:.strlen
call31:sub_125F0
call32:sub_1D998
call33:sub_2C67C
call34:sub_2C40C
call35:.__strlcpy_chk
call36:.__strlen_chk
call37:sub_11BC4
call38:sub_2CCC0
call39:sub_355F0
call40:sub_35630
call41:sub_356C4
call42:sub_35700
call43:sub_11DF0
call44:sub_35870
call45:sub_36940
call46:sub_36B34
call47:sub_36B9C
call48:sub_36BC8
call49:sub_36BF0
call50:sub_36E00
call51:sub_36E70
call52:sub_36ED0
call53:sub_36F00
call54:sub_36F3C
call55:nullsub_17
call56:sub_36C8C
call57:sub_36CB8
call58:sub_2E318
call59:sub_2E288
call60:sub_2D590
call61:sub_1F450
call62:sub_20FD0
call63:.fstat
call64:sub_2DB5C
call65:sub_1FE3C
call66:sub_1FB70
call67:.sscanf
call68:sub_200C0
call69:.memcpy
call70:sub_1F6C0
call71:sub_1F8A4
call72:.free
call73:sub_36D38
call74:sub_36D70
call75:sub_36DA4
call76:sub_37060
call77:sub_41368
call78:sub_36A20
call79:sub_36D10
call80:sub_3C6A4
call81:sub_369B0
call82:sub_3DF74
call83:sub_3A054
call84:sub_3A090
call85:sub_3A0FC
call86:sub_3A138
call87:sub_24364
call88:sub_3852C
call89:sub_38D9C
call90:sub_36A90
call91:sub_3F2B0
call92:sub_36120
call93:sub_36144
call94:sub_370AC
call95:sub_36558
call96:sub_21BAC
call97:sub_21C20
call98:sub_21F50
call99:sub_21DB4
call100:j_.pthread_mutex_lock
call101:j_.pthread_mutex_unlock
call102:sub_11E30
call103:sub_11C60
call104:.pthread_attr_init
call105:.pthread_attr_setstacksize
call106:.pthread_attr_setdetachstate
call107:.pthread_create
call108:.pthread_attr_destroy
call109:sub_11C6C
call110:j_j_.free_2
call111:j_.free
call112:sub_37254
call113:sub_37740
call114:sub_377A8
call115:sub_377D8
call116:sub_37804
call117:sub_37A64
call118:sub_37AD4
call119:sub_37B34
call120:sub_37B64
call121:sub_37BA0
call122:nullsub_18
call123:sub_3789C
call124:sub_378C4
call125:sub_20DD0
call126:sub_20580
call127:sub_20CB0
call128:sub_20EBC
call129:j_.stat
call130:.stat
call131:sub_373B4
call132:sub_1240C
call133:sub_1F74C
call134:.lseek
call135:sub_1F9EC
call136:sub_1FA34
call137:sub_37940
call138:sub_37974
call139:sub_379A8
call140:sub_1235C
call141:sub_37134
call142:sub_37184
call143:sub_371AC
call144:sub_376CC
call145:sub_37704
call146:sub_37738
call147:sub_3715C
call148:sub_36580
call149:sub_36538
call150:sub_36178
...
call1:JNI_OnLoad
call2:sub_FF14
call3:.memset
call4:.vsnprintf
call5:.time
call6:.localtime
call7:.__android_log_print
call8:sub_10070
call9:.fopen
call10:sub_21000
call11:.pthread_once
call12:sub_21054
call13:sub_412CC
call14:.malloc
call15:sub_21098
call16:sub_FABC
call17:sub_1010C
call18:sub_10194
call19:sub_11C4C
call20:.pthread_mutex_init
call21:sub_103D0
call22:sub_2BCA8
call23:sub_125E4
call24:sub_12660
call25:sub_1CE70
call26:sub_1CE34
call27:sub_1C664
call28:.pthread_mutex_lock
call29:.pthread_mutex_unlock
call30:.strlen
call31:sub_125F0
call32:sub_1D998
call33:sub_2C67C
call34:sub_2C40C
call35:.__strlcpy_chk
call36:.__strlen_chk
call37:sub_11BC4
call38:sub_2CCC0
call39:sub_355F0
call40:sub_35630
call41:sub_356C4
call42:sub_35700
call43:sub_11DF0
call44:sub_35870
call45:sub_36940
call46:sub_36B34
call47:sub_36B9C
call48:sub_36BC8
call49:sub_36BF0
call50:sub_36E00
call51:sub_36E70
call52:sub_36ED0
call53:sub_36F00
call54:sub_36F3C
call55:nullsub_17
call56:sub_36C8C
call57:sub_36CB8
call58:sub_2E318
call59:sub_2E288
call60:sub_2D590
call61:sub_1F450
call62:sub_20FD0
call63:.fstat
call64:sub_2DB5C
call65:sub_1FE3C
call66:sub_1FB70
call67:.sscanf
call68:sub_200C0
call69:.memcpy
call70:sub_1F6C0
call71:sub_1F8A4
call72:.free
call73:sub_36D38
call74:sub_36D70
call75:sub_36DA4
call76:sub_37060
call77:sub_41368
call78:sub_36A20
call79:sub_36D10
call80:sub_3C6A4
call81:sub_369B0
call82:sub_3DF74
call83:sub_3A054
call84:sub_3A090
call85:sub_3A0FC
call86:sub_3A138
call87:sub_24364
call88:sub_3852C
call89:sub_38D9C
call90:sub_36A90
call91:sub_3F2B0
call92:sub_36120
call93:sub_36144
call94:sub_370AC
call95:sub_36558
call96:sub_21BAC
call97:sub_21C20
call98:sub_21F50
call99:sub_21DB4
call100:j_.pthread_mutex_lock
call101:j_.pthread_mutex_unlock
call102:sub_11E30
call103:sub_11C60
call104:.pthread_attr_init
call105:.pthread_attr_setstacksize
call106:.pthread_attr_setdetachstate
call107:.pthread_create
call108:.pthread_attr_destroy
call109:sub_11C6C
call110:j_j_.free_2
call111:j_.free
call112:sub_37254
call113:sub_37740
call114:sub_377A8
call115:sub_377D8
call116:sub_37804
call117:sub_37A64
call118:sub_37AD4
call119:sub_37B34
call120:sub_37B64
call121:sub_37BA0
call122:nullsub_18
call123:sub_3789C
call124:sub_378C4
call125:sub_20DD0
call126:sub_20580
call127:sub_20CB0
call128:sub_20EBC
call129:j_.stat
call130:.stat
call131:sub_373B4
call132:sub_1240C
call133:sub_1F74C
call134:.lseek
call135:sub_1F9EC
call136:sub_1FA34
call137:sub_37940
call138:sub_37974
call139:sub_379A8
call140:sub_1235C
call141:sub_37134
call142:sub_37184
call143:sub_371AC
call144:sub_376CC
call145:sub_37704
call146:sub_37738
call147:sub_3715C
call148:sub_36580
call149:sub_36538
call150:sub_36178
...
function dump_so(so_name) {
    Java.perform(function () {
        var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
        var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
        var libso = Process.getModuleByName(so_name);
        console.log("[name]:", libso.name);
        console.log("[base]:", libso.base);
        console.log("[size]:", ptr(libso.size));
        console.log("[path]:", libso.path);
    });
}
 
rpc.exports = {
    dump_so: dump_so
};
function dump_so(so_name) {
    Java.perform(function () {
        var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
        var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
        var libso = Process.getModuleByName(so_name);
        console.log("[name]:", libso.name);
        console.log("[base]:", libso.base);
        console.log("[size]:", ptr(libso.size));
        console.log("[path]:", libso.path);
    });
}
 
rpc.exports = {
    dump_so: dump_so
};
frida -H 127.0.0.1:1234 -l "D:\frida\sec2023\get_so_base.js" -f "com.com.sec2023.rocketmouse.mouse"
frida -H 127.0.0.1:1234 -l "D:\frida\sec2023\get_so_base.js" -f "com.com.sec2023.rocketmouse.mouse"
ps -A | grep mouse
ps -A | grep mouse
call135:sub_1F9EC
call136:sub_1FA34
call137:sub_37940
call138:sub_37974
call139:sub_379A8
call140:sub_1235C
call141:sub_37134
call142:sub_37184
call143:sub_371AC
call144:sub_376CC
call145:sub_37704
call135:sub_1F9EC
call136:sub_1FA34
call137:sub_37940
call138:sub_37974
call139:sub_379A8
call140:sub_1235C
call141:sub_37134
call142:sub_37184
call143:sub_371AC
call144:sub_376CC
call145:sub_37704
if(W0 == W8){
    X8 = X8
}
else{
    X8 = X9
}
if(W0 == W8){
    X8 = X8
}
else{
    X8 = X9
}
function anti_sec2023() {
    Java.perform(function () {
        var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
        var libso = Process.getModuleByName("libsec2023.so");
        console.log("[name]:", libso.name);
        console.log("[base]:", libso.base);
        console.log("[size]:", ptr(libso.size));
        console.log("[path]:", libso.path);
        Memory.protect(ptr(libso.base), libso.size, 'rwx');
        Memory.writeByteArray(ptr(libso.base).add(0x371DC),[0x08,0x01,0x88,0x9A]);
    });
}
rpc.exports = {
    anti_sec2023: anti_sec2023
};
function anti_sec2023() {
    Java.perform(function () {
        var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
        var libso = Process.getModuleByName("libsec2023.so");
        console.log("[name]:", libso.name);
        console.log("[base]:", libso.base);
        console.log("[size]:", ptr(libso.size));
        console.log("[path]:", libso.path);
        Memory.protect(ptr(libso.base), libso.size, 'rwx');
        Memory.writeByteArray(ptr(libso.base).add(0x371DC),[0x08,0x01,0x88,0x9A]);
    });
}
rpc.exports = {
    anti_sec2023: anti_sec2023
};
function hook_31164(){
    // 程序入口
Java.perform(function()
{
     
    // 获取模块
    var module = Process.getModuleByName("libsec2023.so")
    // 转为函数地址
    var addr=module.base.add("0x31164");
    // 获取函数入口
    var func =  new NativePointer(addr.toString());
 
    console.log('[+] hook '+func.toString())
 
    // 函数hook钩子附加
    Interceptor.attach(func, {
     
        onEnter: function (args) {
      
            console.log('hook success');
            console.log(args[0]);
            console.log(args[1]);
            console.log(args[2]);
        },
        onLeave: function (retval) {
            console.log("retvalue is :", retval.toInt32());
            console.log('method onleave');
        }
    });
});
}
function hook_31164(){
    // 程序入口
Java.perform(function()
{
     
    // 获取模块
    var module = Process.getModuleByName("libsec2023.so")
    // 转为函数地址
    var addr=module.base.add("0x31164");
    // 获取函数入口
    var func =  new NativePointer(addr.toString());
 
    console.log('[+] hook '+func.toString())
 
    // 函数hook钩子附加
    Interceptor.attach(func, {
     
        onEnter: function (args) {
      
            console.log('hook success');
            console.log(args[0]);
            console.log(args[1]);
            console.log(args[2]);
        },
        onLeave: function (retval) {
            console.log("retvalue is :", retval.toInt32());
            console.log('method onleave');
        }
    });
});
}
function addr_locate_so(addr){//定位某个内存地址在哪个so里面,虽然可以直接Process.getModuleByAddress,但是会抛出异常所以就用函数实现了
    var process_Obj_Module_Arr = Process.enumerateModules();
    for(var i = 0; i < process_Obj_Module_Arr.length; i++) {
        if(addr>process_Obj_Module_Arr[i].base && addr<process_Obj_Module_Arr[i].base.add(process_Obj_Module_Arr[i].size)){
            return process_Obj_Module_Arr[i].name+":0x"+(addr-process_Obj_Module_Arr[i].base).toString(16)
        }
    }
}
function anti_BR(){
    var libso = Process.getModuleByName("libsec2023.so")
    var hook_addr =  new NativePointer(libso.base.add(0x31164).toString());
    this.tid = Process.getCurrentThreadId();
    console.log('[+] hook '+hook_addr.toString())
    var reg_name;//br之后的寄存器的名称
    var inst_addr;
    Interceptor.attach(hook_addr, {
     
        onEnter: function (args) {
            console.log("start Stalker!");
            //不追踪libc.so,不然frida会报错退出..看堆栈回溯应该是动态编译执行了libc.so里面的ptrace才导致的异常
            Stalker.exclude({
                "base": Process.getModuleByName("libc.so").base,
                "size": Process.getModuleByName("libc.so").size
            })
            Stalker.follow(this.tid, {
                events: {
                    call: true, // CALL instructions: yes please           
                    ret: false, // RET instructions
                    exec: false, // all instructions: not recommended as it's
                    block: false, // block executed: coarse execution trace
                    compile: false // block compiled: useful for coverage
                },
                transform: (iterator) => {
                    let instruction = iterator.next();
                    const startAddress = instruction.address;
                    const isAppCode = startAddress.compare(libso.base) >= 0 &&startAddress.compare(libso.base.add(libso.size)) === -1;
                    do {
                        if (isAppCode) {
                            if (instruction.mnemonic === "br") {
                                reg_name = instruction.opStr;
                                inst_addr = new NativePointer(instruction.address);
 
                                iterator.putCallout((context) => {
                                    var addr_before = addr_locate_so(inst_addr);
                                    var addr_after = addr_locate_so(parseInt(context[reg_name],16));
                                    if(addr_after==undefined){
                                        addr_after = "unknown:"+context[reg_name];
                                    }
                                    console.log(addr_before,"jump to",addr_after," ",reg_name);
                                    //Memory.patchCode(inst_addr,4,code =>{
                                        //var cw = new Arm64Writer(code,{pc: inst_addr});
                                        //cw.putBImm(new NativePointer(context[reg_name]));
                                        //cw.flush();
                                    //})
                                });
                            }
                        }
                        iterator.keep();
                    } while ((instruction = iterator.next()) !== null);
                }
            })
            console.log("stalker end!");
        },
        onLeave: function (retval) {
            Stalker.unfollow(this.tid);
            Stalker.garbageCollect();
        }
    });
}
function addr_locate_so(addr){//定位某个内存地址在哪个so里面,虽然可以直接Process.getModuleByAddress,但是会抛出异常所以就用函数实现了
    var process_Obj_Module_Arr = Process.enumerateModules();
    for(var i = 0; i < process_Obj_Module_Arr.length; i++) {
        if(addr>process_Obj_Module_Arr[i].base && addr<process_Obj_Module_Arr[i].base.add(process_Obj_Module_Arr[i].size)){
            return process_Obj_Module_Arr[i].name+":0x"+(addr-process_Obj_Module_Arr[i].base).toString(16)
        }
    }
}
function anti_BR(){
    var libso = Process.getModuleByName("libsec2023.so")
    var hook_addr =  new NativePointer(libso.base.add(0x31164).toString());
    this.tid = Process.getCurrentThreadId();
    console.log('[+] hook '+hook_addr.toString())
    var reg_name;//br之后的寄存器的名称
    var inst_addr;
    Interceptor.attach(hook_addr, {
     
        onEnter: function (args) {
            console.log("start Stalker!");
            //不追踪libc.so,不然frida会报错退出..看堆栈回溯应该是动态编译执行了libc.so里面的ptrace才导致的异常
            Stalker.exclude({
                "base": Process.getModuleByName("libc.so").base,
                "size": Process.getModuleByName("libc.so").size
            })
            Stalker.follow(this.tid, {
                events: {
                    call: true, // CALL instructions: yes please           
                    ret: false, // RET instructions
                    exec: false, // all instructions: not recommended as it's
                    block: false, // block executed: coarse execution trace
                    compile: false // block compiled: useful for coverage
                },
                transform: (iterator) => {
                    let instruction = iterator.next();
                    const startAddress = instruction.address;
                    const isAppCode = startAddress.compare(libso.base) >= 0 &&startAddress.compare(libso.base.add(libso.size)) === -1;
                    do {
                        if (isAppCode) {
                            if (instruction.mnemonic === "br") {
                                reg_name = instruction.opStr;
                                inst_addr = new NativePointer(instruction.address);
 
                                iterator.putCallout((context) => {
                                    var addr_before = addr_locate_so(inst_addr);
                                    var addr_after = addr_locate_so(parseInt(context[reg_name],16));
                                    if(addr_after==undefined){
                                        addr_after = "unknown:"+context[reg_name];
                                    }
                                    console.log(addr_before,"jump to",addr_after," ",reg_name);
                                    //Memory.patchCode(inst_addr,4,code =>{
                                        //var cw = new Arm64Writer(code,{pc: inst_addr});
                                        //cw.putBImm(new NativePointer(context[reg_name]));
                                        //cw.flush();
                                    //})
                                });
                            }
                        }
                        iterator.keep();
                    } while ((instruction = iterator.next()) !== null);
                }
            })
            console.log("stalker end!");
        },
        onLeave: function (retval) {
            Stalker.unfollow(this.tid);
            Stalker.garbageCollect();
        }
    });
}
[Remote::com.com.sec2023.rocketmouse.mouse ]-> rpc.exports.anti_BR()
[+] hook 0x76cd136164
[Remote::com.com.sec2023.rocketmouse.mouse ]-> start Stalker!
stalker end!
libsec2023.so:0x3ba00 jump to libsec2023.so:0x3ba04   x10
libsec2023.so:0x3ba30 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba74   x12
libsec2023.so:0x3badc jump to libsec2023.so:0x3bae0   x13
libsec2023.so:0x3bb28 jump to libsec2023.so:0x3bae0   x13
libsec2023.so:0x3bb28 jump to libsec2023.so:0x3bae0   x13
libsec2023.so:0x3bb28 jump to libsec2023.so:0x3bae0   x13
libsec2023.so:0x3bb28 jump to libsec2023.so:0x3bb2c   x13
libsec2023.so:0x3bb4c jump to libsec2023.so:0x3ba04   x10
libsec2023.so:0x3bb4c jump to unknown:0x3   x10
libsec2023.so:0x3bb4c jump to unknown:0x2   x10
libsec2023.so:0x3bb4c jump to unknown:0x1   x10
libsec2023.so:0x3bb4c jump to unknown:0x0   x10
libsec2023.so:0x3bb4c jump to unknown:0xffffffffffffffff   x10
libsec2023.so:0x3bb4c jump to unknown:0x0   x10
libsec2023.so:0x3bb4c jump to unknown:0x6d000000   x10
libsec2023.so:0x3bb4c jump to unknown:0x6d940000   x10
libsec2023.so:0x3bb4c jump to unknown:0x6d94ca00   x10
libsec2023.so:0x3bb4c jump to unknown:0x6d94cae5   x10
libsec2023.so:0x3bb4c jump to libsec2023.so:0x3bb50   x10
libsec2023.so:0x3a08c jump to libsec2023.so:0x3a0f0   x8
libsec2023.so:0x3b508 jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b550   x11
libsec2023.so:0x3b5c0 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b608   x11
libsec2023.so:0x3aa70 jump to libsec2023.so:0x3aa74   x8
libsec2023.so:0x3aaa0 jump to libsec2023.so:0x3aaa4   x8
libsec2023.so:0x3aad4 jump to libsec2023.so:0x3aad8   x8
libsec2023.so:0x3ab04 jump to libsec2023.so:0x3ab70   x8
libsec2023.so:0xf28c jump to libc.so:0xb2688   x17
libsec2023.so:0xf4ac jump to libc.so:0xb2bd8   x17
libsec2023.so:0x3ac90 jump to libsec2023.so:0x3acc0   x11
libsec2023.so:0xf40c jump to libc.so:0x4bc20   x17
libsec2023.so:0xf40c jump to libc.so:0xb2688   x17
libsec2023.so:0xf40c jump to libc.so:0xb2bd8   x17
libsec2023.so:0x3b950 jump to libsec2023.so:0x3b95c   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3a0f0   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3aa74   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3aaa4   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3aad8   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3ab70   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3ab70   x8
libsec2023.so:0x3b950 jump to unknown:0x77ea7ac3a0   x8
libsec2023.so:0x3b950 jump to unknown:0x1c01f8026ad23c58   x8
libsec2023.so:0x3b950 jump to unknown:0x1c01f8026ad23c58   x8
libsec2023.so:0x3b950 jump to unknown:0x1c01f8026ad23c58   x8
libsec2023.so:0x3b950 jump to unknown:0xe   x8
libsec2023.so:0x3b990 jump to libsec2023.so:0x3b99c   x8
libsec2023.so:0x311a0 jump to libil2cpp.so:0x13b8d64   x2
[Remote::com.com.sec2023.rocketmouse.mouse ]-> rpc.exports.anti_BR()
[+] hook 0x76cd136164
[Remote::com.com.sec2023.rocketmouse.mouse ]-> start Stalker!
stalker end!
libsec2023.so:0x3ba00 jump to libsec2023.so:0x3ba04   x10
libsec2023.so:0x3ba30 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba74   x12
libsec2023.so:0x3badc jump to libsec2023.so:0x3bae0   x13
libsec2023.so:0x3bb28 jump to libsec2023.so:0x3bae0   x13
libsec2023.so:0x3bb28 jump to libsec2023.so:0x3bae0   x13
libsec2023.so:0x3bb28 jump to libsec2023.so:0x3bae0   x13
libsec2023.so:0x3bb28 jump to libsec2023.so:0x3bb2c   x13
libsec2023.so:0x3bb4c jump to libsec2023.so:0x3ba04   x10
libsec2023.so:0x3bb4c jump to unknown:0x3   x10
libsec2023.so:0x3bb4c jump to unknown:0x2   x10
libsec2023.so:0x3bb4c jump to unknown:0x1   x10
libsec2023.so:0x3bb4c jump to unknown:0x0   x10
libsec2023.so:0x3bb4c jump to unknown:0xffffffffffffffff   x10
libsec2023.so:0x3bb4c jump to unknown:0x0   x10
libsec2023.so:0x3bb4c jump to unknown:0x6d000000   x10
libsec2023.so:0x3bb4c jump to unknown:0x6d940000   x10
libsec2023.so:0x3bb4c jump to unknown:0x6d94ca00   x10
libsec2023.so:0x3bb4c jump to unknown:0x6d94cae5   x10
libsec2023.so:0x3bb4c jump to libsec2023.so:0x3bb50   x10
libsec2023.so:0x3a08c jump to libsec2023.so:0x3a0f0   x8
libsec2023.so:0x3b508 jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b50c   x11
libsec2023.so:0x3b54c jump to libsec2023.so:0x3b550   x11
libsec2023.so:0x3b5c0 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b5c4   x11
libsec2023.so:0x3b604 jump to libsec2023.so:0x3b608   x11
libsec2023.so:0x3aa70 jump to libsec2023.so:0x3aa74   x8
libsec2023.so:0x3aaa0 jump to libsec2023.so:0x3aaa4   x8
libsec2023.so:0x3aad4 jump to libsec2023.so:0x3aad8   x8
libsec2023.so:0x3ab04 jump to libsec2023.so:0x3ab70   x8
libsec2023.so:0xf28c jump to libc.so:0xb2688   x17
libsec2023.so:0xf4ac jump to libc.so:0xb2bd8   x17
libsec2023.so:0x3ac90 jump to libsec2023.so:0x3acc0   x11
libsec2023.so:0xf40c jump to libc.so:0x4bc20   x17
libsec2023.so:0xf40c jump to libc.so:0xb2688   x17
libsec2023.so:0xf40c jump to libc.so:0xb2bd8   x17
libsec2023.so:0x3b950 jump to libsec2023.so:0x3b95c   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3a0f0   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to unknown:0x76ccc36000   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3aa74   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3aaa4   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3aad8   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3ab70   x8
libsec2023.so:0x3b950 jump to libsec2023.so:0x3ab70   x8
libsec2023.so:0x3b950 jump to unknown:0x77ea7ac3a0   x8
libsec2023.so:0x3b950 jump to unknown:0x1c01f8026ad23c58   x8
libsec2023.so:0x3b950 jump to unknown:0x1c01f8026ad23c58   x8
libsec2023.so:0x3b950 jump to unknown:0x1c01f8026ad23c58   x8
libsec2023.so:0x3b950 jump to unknown:0xe   x8
libsec2023.so:0x3b990 jump to libsec2023.so:0x3b99c   x8
libsec2023.so:0x311a0 jump to libil2cpp.so:0x13b8d64   x2
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba74   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba34   x12
libsec2023.so:0x3ba70 jump to libsec2023.so:0x3ba74   x12
libsec2023.so:0x3ba00 jump to libsec2023.so:0x3ba04   x10
libsec2023.so:0x3ba00 jump to libsec2023.so:0x3ba04   x10
red_num = 0xFFFFFFFF8C034254
add_num = 0x740078FC
num = (red_num+add_num)&0xffffffff
my_byte = list(num.to_bytes(8,'little'))
my_byte = [hex(x)[2::].zfill(2) for x in my_byte]
print(' '.join(list(my_byte)))
red_num = 0xFFFFFFFF8C034254
add_num = 0x740078FC
num = (red_num+add_num)&0xffffffff
my_byte = list(num.to_bytes(8,'little'))
my_byte = [hex(x)[2::].zfill(2) for x in my_byte]
print(' '.join(list(my_byte)))
条件码 含义
EQ Z置位 ;结果相等才执行
NE Z清零,结果不相等才执行
CS C置位,结果无符号>= 才执行
CC C清零,结果无符号< 才执行
MI N置位,结果为负数才执行
PL N清零,结果为正数或0才执行
VS V置位,结果溢出才执行
VC V清零,结果无溢出才执行
HI C置位Z清零,结果为无符号数大于才执行
LS C清零Z置位,结果为无符号数小于或等于才执行
GE N等于V,结果为有符号数大于或等于才执行
LT N不等于V,结果为有符号数小于才执行
GT Z清零且N等于V ,结果为有符号大于才执行
LE Z置位或N不等于V ,结果为有符号数小于或等于
AL 无条件执行。省略。
if(X8 < 2){//由CC指令的含义知道是小于比较
    B 0x3BA04//即继续向下执行
}
else if(X8 >= 2){
    B 0x3BB50//跳转到其他地方
}
if(X8 < 2){//由CC指令的含义知道是小于比较
    B 0x3BA04//即继续向下执行
}
else if(X8 >= 2){
    B 0x3BB50//跳转到其他地方
}
cmp w8, #2        ; 将寄存器 w8 的值和常量 2 进行比较
cset w8, gt       ; 如果是大于(grater than),则将寄存器 w8 的值设置为 1,否则设置为 0
cmp w8, #2        ; 将寄存器 w8 的值和常量 2 进行比较
cset w8, gt       ; 如果是大于(grater than),则将寄存器 w8 的值设置为 1,否则设置为 0
CSET W23, NE
LDR  X8, [X21,W23,UXTW#3]
ADD  X8, X8, X22
BR   X8
CSET W23, NE
LDR  X8, [X21,W23,UXTW#3]
ADD  X8, X8, X22
BR   X8
import ida_segment
import idautils
import idc
import ida_bytes
from keystone import *
 
 
def patch_nop(begin, end):  # arm64中的NOP指令是b'\x1F\x20\x03\xD5'
    while end > begin:
        ida_bytes.patch_bytes(begin, b'\x1F\x20\x03\xD5')
        begin = begin + 4
 
 
# 获取text段的起始地址
text_seg = ida_segment.get_segm_by_name(".text")
start, end = text_seg.start_ea, text_seg.end_ea
# start, end = 0x3BA34, 0x3BA80
# start, end = 0x37390,0x373B4#测试ADRP指令
# start, end = 0x3FCE0, 0x3FD00  # 测试EQ情况
#start, end = 0x3AA90, 0x3AAA4
# start, end = 0x3A078, 0x3A090#测试CSET-BR去除情况
current_addr = start
# print(text_seg.start_ea,text_seg.end_ea)
nop_addr_array_after_finish = []  # 在CSEL/CSET-BR结构修复完成后需要NOP的指令
while current_addr < end:
    # 处理CSEL-BR结构
    if idc.print_insn_mnem(current_addr) == "CSEL":
        CSEL_addr = current_addr
        nop_addr_array_temp = []
        nop_addr_array_temp.append(CSEL_addr)
        BR_addr = 0
        BR_reg = ""
        temp_addr = idc.next_head(current_addr)
        for _ in range(9):  # 向下搜寻9条指令,寻找是否有BR指令
            if idc.print_insn_mnem(temp_addr) == "BR":
                BR_addr = temp_addr
                BR_reg = idc.print_operand(temp_addr, 0)
                break
            if idc.print_insn_mnem(temp_addr) == "CSEL":
                break
            temp_addr = idc.next_head(temp_addr)
        if BR_addr != 0# 匹配到了CSEL-BR结构的汇编,需要去除
            # 形如CSEL X11, X12, X11, GE,获取CSEL后的操作数op1~3,以及条件码cond
            CSEL_op1 = idc.print_operand(CSEL_addr, 0)
            CSEL_op2 = idc.print_operand(CSEL_addr, 1)
            CSEL_op2_val = -1
            CSEL_op3 = idc.print_operand(CSEL_addr, 2)
            CSEL_op3_val = -1
            CSEL_cond = idc.print_operand(CSEL_addr, 3)
 
            # 读取条件分支语句CSEL中要赋值给目标寄存器的两个源寄存器中存储的值
            temp_addr = idc.prev_head(CSEL_addr)
            while (CSEL_op2_val == -1 or CSEL_op3_val == -1) and temp_addr > text_seg.start_ea:
                if CSEL_op2 == "XZR"# 如果寄存器的值是XZR,说明该值为0
                    CSEL_op2_val = 0
                if CSEL_op3 == "XZR":
                    CSEL_op3_val = 0
                if idc.print_insn_mnem(temp_addr) == "MOV":
                    if idc.print_operand(temp_addr, 0)[1::] == CSEL_op2[
                                                               1::] and CSEL_op2_val == -1# 寄存器X11和W11是同一个寄存器
                        CSEL_op2_val = idc.get_operand_value(temp_addr, 1)
                        nop_addr_array_temp.append(temp_addr)
                    elif idc.print_operand(temp_addr, 0)[1::] == CSEL_op3[1::] and CSEL_op3_val == -1:
                        CSEL_op3_val = idc.get_operand_value(temp_addr, 1)
                        nop_addr_array_temp.append(temp_addr)
                temp_addr = idc.prev_head(temp_addr)
            # print(CSEL_op2_val, CSEL_op3_val, hex(current_addr))
            assert CSEL_op2_val != -1 and CSEL_op3_val != -1
 
            temp_addr = BR_addr
            jump_array_reg = ""  # 存贮跳转表的寄存器名称
            jump_array_addr = -1  # 跳转表所在的位置
            add_reg = []  # 加到跳转表的值所在的寄存器
            add_val = -1  # 加到跳转表的值
            while temp_addr > CSEL_addr:  # 从后往前找,以BR所在的地址开始,CSEL所在的地址结束,匹配必要的寄存器名称和值
                # print(hex(temp_addr),idc.print_insn_mnem(temp_addr))
                if idc.print_insn_mnem(temp_addr) == "ADD" and idc.print_operand(temp_addr, 0) == BR_reg:
                    add_reg.append(idc.print_operand(temp_addr, 1)[1::])
                    add_reg.append(idc.print_operand(temp_addr, 2)[1::])
                    nop_addr_array_temp.append(temp_addr)
                elif idc.print_insn_mnem(temp_addr) == "MOV":
                    if idc.print_operand(temp_addr, 0)[1::] in add_reg:
                        add_val = idc.get_operand_value(temp_addr, 1)
                        nop_addr_array_temp.append(temp_addr)
                elif idc.print_insn_mnem(temp_addr) == "LDR":
                    jump_array_reg = idc.print_operand(temp_addr, 1)[1:-1].split(',')[0# 获取存储跳转表的寄存器名称
                    nop_addr_array_temp.append(temp_addr)
                elif idc.print_insn_mnem(temp_addr) == "ADRL":
                    jump_array_reg = idc.print_operand(temp_addr, 0)
                    jump_array_addr = idc.get_operand_value(temp_addr, 1)
                    nop_addr_array_temp.append(temp_addr)
                temp_addr = idc.prev_head(temp_addr)
 
            # 如果在CSEL-BR间的指令中没找到跳转表所在的位置,则向上寻找
            if jump_array_addr == -1:
                temp_addr = CSEL_addr
                while temp_addr > text_seg.start_ea:
                    # print(hex(temp_addr), idc.print_insn_mnem(temp_addr))
                    if idc.print_insn_mnem(temp_addr) == "ADRL":
                        if idc.print_operand(temp_addr, 0) == jump_array_reg:
                            jump_array_addr = idc.get_operand_value(temp_addr, 1)
                            nop_addr_array_temp.append(temp_addr)
                            break
                    elif idc.print_insn_mnem(temp_addr) == "ADRP"# ADRP指令,还需要加上另一部分
                        if idc.print_operand(temp_addr, 0) == jump_array_reg:
                            jump_array_addr = idc.get_operand_value(temp_addr, 1)
                            nop_addr_array_temp.append(temp_addr)
                            while temp_addr < text_seg.end_ea:
                                if idc.print_insn_mnem(temp_addr) == "ADD":
                                    if idc.print_operand(temp_addr, 0) == jump_array_reg:
                                        jump_array_addr += idc.get_operand_value(temp_addr, 2)
                                        nop_addr_array_temp.append(temp_addr)
                                        break
                                temp_addr = idc.next_head(temp_addr)
                            break
                    temp_addr = idc.prev_head(temp_addr)
            # print(hex(jump_array_addr),hex(add_val))
 
            if add_val == -1:
                temp_addr = CSEL_addr
                while temp_addr > text_seg.start_ea:
                    # print(hex(temp_addr), idc.print_insn_mnem(temp_addr))
                    if idc.print_insn_mnem(temp_addr) == "MOV":
                        if idc.print_operand(temp_addr, 0)[1::] in add_reg and idc.print_operand(temp_addr, 0)[0] == 'X':
                            add_val = idc.get_operand_value(temp_addr, 1)
                            nop_addr_array_temp.append(temp_addr)
                            break
                    temp_addr = idc.prev_head(temp_addr)
 
            # 计算出分支跳转的两个位置
            branch_a = (ida_bytes.get_qword(jump_array_addr + CSEL_op2_val) + add_val) & 0xffffffffffffffff
            branch_b = (ida_bytes.get_qword(jump_array_addr + CSEL_op3_val) + add_val) & 0xffffffffffffffff
            # print(hex(branch_a), hex(branch_b))
 
            # print(CSEL_cond,hex(current_addr))
 
            # GE<->LT 有符号大于等于 vs 有符号小于
            # EQ<->NE 结果相等 vs 结果不相等
            # CC<->CS 无符号小于 vs 无符号大于等于
            # HI<->LS 无符号大于 vs 无符号小于等于
            # if CSEL_cond == "GE":#构造B.LT跳转
            logic_rev = {"GE": "LT", "LT": "GE", "EQ": "NE", "NE": "EQ", "CC": "CS", "CS": "CC", "HI": "LS", "LS": "HI"}
            ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
            code = ""
            if branch_b == idc.next_head(BR_addr):  # 判断逻辑不取反
                code = f"B.{CSEL_cond} #{hex(branch_a)}"
            elif branch_a == idc.next_head(BR_addr):  # 判断逻辑取反
                code = f"B.{logic_rev[CSEL_cond]} #{hex(branch_b)}"
 
            #print(hex(current_addr), hex(add_val), CSEL_op2_val, CSEL_op3_val, hex(jump_array_addr), code)
 
            # 修复BR跳转
            if code != "":
 
                patch_br_byte, count = ks.asm(code, addr=BR_addr)
                ida_bytes.patch_bytes(BR_addr, bytes(patch_br_byte))
                print(f"fix CSEL-BR at {hex(BR_addr)}")
                nop_addr_array_after_finish.extend(nop_addr_array_temp)
                current_addr = idc.next_head(BR_addr)
                continue
            else:
                print(f"error! unable to fix CSEL-BR at {hex(current_addr)},branch:{hex(branch_a)}, {hex(branch_b)}")
 
    # 处理CSET-BR结构
    elif idc.print_insn_mnem(current_addr) == "CSET":
        CSET_addr = current_addr
        nop_addr_array_temp = []
        nop_addr_array_temp.append(CSET_addr)
        BR_addr = 0
        BR_reg = ""
        temp_addr = idc.next_head(current_addr)
        for _ in range(15):  # 向下搜寻15条指令,寻找是否有BR指令
            if idc.print_insn_mnem(temp_addr) == "BR":
                BR_addr = temp_addr
                BR_reg = idc.print_operand(temp_addr, 0)
                break
            elif idc.print_insn_mnem(temp_addr) == "CSEL":
                break
            elif idc.print_insn_mnem(temp_addr) == "RET":
                break
            temp_addr = idc.next_head(temp_addr)
        if BR_addr != 0# 匹配到了CSET-BR结构的汇编,需要去除
            # 形如CSET W23, NE,获取CSET后的操作数op1,以及条件码cond
            CSET_op1 = idc.print_operand(CSET_addr, 0)
            CSET_op1_val = -1
            CSET_cond = idc.print_operand(CSET_addr, 1)
 
            temp_addr = BR_addr
            jump_array_reg = ""  # 存贮跳转表的寄存器名称
            jump_array_addr = 0  # 跳转表所在的位置
            add_reg = []  # 加到跳转表的值所在的寄存器
            add_val = 0  # 加到跳转表的值
            Lshift_val = -1
            while temp_addr > CSET_addr:  # 从后往前找,以BR所在的地址开始,CSET所在的地址结束,匹配必要的寄存器名称和值
                # print(hex(temp_addr),idc.print_insn_mnem(temp_addr))
                if idc.print_insn_mnem(temp_addr) == "ADD" and idc.print_operand(temp_addr, 0) == BR_reg:
                    add_reg.append(idc.print_operand(temp_addr, 1)[1::])
                    add_reg.append(idc.print_operand(temp_addr, 2)[1::])
                    nop_addr_array_temp.append(temp_addr)
                elif idc.print_insn_mnem(temp_addr) == "MOVK":
                    if idc.print_operand(temp_addr, 0)[1::] in add_reg:
                        add_val += (idc.get_operand_value(temp_addr, 1) << 16)
                elif idc.print_insn_mnem(temp_addr) == "MOV":
                    if idc.print_operand(temp_addr, 0)[1::] in add_reg:
                        add_val += idc.get_operand_value(temp_addr, 1)
                        nop_addr_array_temp.append(temp_addr)
                elif idc.print_insn_mnem(temp_addr) == "LDR":
                    LDR_temp = idc.print_operand(temp_addr, 1)[1:-1].split(',')
                    jump_array_reg = LDR_temp[0# 获取存储跳转表的寄存器名称
                    if len(LDR_temp) == 3:
                        Lshift_val = int(LDR_temp[2][-1:])
                    nop_addr_array_temp.append(temp_addr)
                elif idc.print_insn_mnem(temp_addr) == "ADRL":
                    jump_array_reg = idc.print_operand(temp_addr, 0)
                    jump_array_addr = idc.get_operand_value(temp_addr, 1)
                    nop_addr_array_temp.append(temp_addr)
                elif idc.print_insn_mnem(temp_addr) == "LSL":
                    if idc.print_operand(temp_addr, 0)[1::] == CSET_op1[1::]:
                        Lshift_val = idc.get_operand_value(temp_addr, 2)
 
                temp_addr = idc.prev_head(temp_addr)
 
            # 如果在CSET-BR间的指令中没找到跳转表所在的位置,则向上寻找
            if jump_array_addr == 0:
                temp_addr = CSET_addr
                while temp_addr > text_seg.start_ea:
                    # print(hex(temp_addr), idc.print_insn_mnem(temp_addr))
                    if idc.print_insn_mnem(temp_addr) == "ADRL":
                        if idc.print_operand(temp_addr, 0) == jump_array_reg:
                            jump_array_addr = idc.get_operand_value(temp_addr, 1)
                            nop_addr_array_temp.append(temp_addr)
                            break
                    elif idc.print_insn_mnem(temp_addr) == "ADRP"# ADRP指令,还需要加上另一部分
                        if idc.print_operand(temp_addr, 0) == jump_array_reg:
                            jump_array_addr = idc.get_operand_value(temp_addr, 1)
                            nop_addr_array_temp.append(temp_addr)
                            while temp_addr < text_seg.end_ea:
                                if idc.print_insn_mnem(temp_addr) == "ADD":
                                    if idc.print_operand(temp_addr, 0) == jump_array_reg:
                                        jump_array_addr += idc.get_operand_value(temp_addr, 2)
                                        nop_addr_array_temp.append(temp_addr)
                                        break
                                temp_addr = idc.next_head(temp_addr)
                            break
                    temp_addr = idc.prev_head(temp_addr)
            # print(hex(jump_array_addr),hex(add_val))
 
            # 向上寻找加到跳转表的值
            if add_val == 0:
                temp_addr = CSET_addr
                while temp_addr > text_seg.start_ea:
                    # print(hex(temp_addr), idc.print_insn_mnem(temp_addr))
                    if idc.print_insn_mnem(temp_addr) == "MOV":
                        if idc.print_operand(temp_addr, 0)[1::] in add_reg:
                            add_val = idc.get_operand_value(temp_addr, 1)
                            nop_addr_array_temp.append(temp_addr)
                            break
                    elif idc.print_insn_mnem(temp_addr) == "MOVK"# 形如MOV W9, #0x76BC;MOVK W9, #0x4C48,LSL#16;的形式
                        if idc.print_operand(temp_addr, 0)[1::] in add_reg:
                            # print(hex(add_val))
                            add_val = (idc.get_operand_value(temp_addr, 1) << 16)
                            # print(hex(add_val))
                            while temp_addr > text_seg.start_ea:
                                if idc.print_insn_mnem(temp_addr) == "MOV":
                                    if idc.print_operand(temp_addr, 0)[1::] in add_reg:
                                        add_val += idc.get_operand_value(temp_addr, 1)
                                        # print(hex(add_val))
                                        break
                                temp_addr = idc.prev_head(temp_addr)
 
                            break
 
                    temp_addr = idc.prev_head(temp_addr)
 
            # print(hex(current_addr))
            # 计算出分支跳转的两个位置
            branch_a = (ida_bytes.get_qword(jump_array_addr + (1 << Lshift_val)) + add_val) & 0xffffffffffffffff
            branch_b = (ida_bytes.get_qword(jump_array_addr + (0 << Lshift_val)) + add_val) & 0xffffffffffffffff
            # print(hex(branch_a), hex(branch_b))
 
            # print(CSEL_cond,hex(current_addr))
 
            # GE<->LT 有符号大于等于 vs 有符号小于
            # EQ<->NE 结果相等 vs 结果不相等
            # CC<->CS 无符号小于 vs 无符号大于等于
            # HI<->LS 无符号大于 vs 无符号小于等于
            # if CSEL_cond == "GE":#构造B.LT跳转
            logic_rev = {"GE": "LT", "LT": "GE", "EQ": "NE", "NE": "EQ", "CC": "CS", "CS": "CC", "HI": "LS", "LS": "HI"}
            ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
            code = ""
            if branch_b == idc.next_head(BR_addr):  # 判断逻辑不取反
                code = f"B.{CSET_cond} #{hex(branch_a)}"
            elif branch_a == idc.next_head(BR_addr):  # 判断逻辑取反
                code = f"B.{logic_rev[CSET_cond]} #{hex(branch_b)}"
 
            # print(hex(current_addr),add_reg,hex(add_val),CSET_op1,CSET_op1_val,jump_array_reg,hex(jump_array_addr),Lshift_val,code)
            # 修复BR跳转
            if code != "":
                patch_br_byte, count = ks.asm(code, addr=BR_addr)
                ida_bytes.patch_bytes(BR_addr, bytes(patch_br_byte))
                print(f"fix CSET-BR at {hex(BR_addr)}")
                nop_addr_array_after_finish.extend(nop_addr_array_temp)
                current_addr = idc.next_head(BR_addr)
                continue
            else:
                print(f"error! unable to fix CSET-BR at {hex(current_addr)},branch:{hex(branch_a)}, {hex(branch_b)}")
 
    current_addr = idc.next_head(current_addr)
 
for addr in nop_addr_array_after_finish:
    patch_nop(addr, addr + idc.get_item_size(addr))
import ida_segment
import idautils
import idc
import ida_bytes
from keystone import *
 
 
def patch_nop(begin, end):  # arm64中的NOP指令是b'\x1F\x20\x03\xD5'
    while end > begin:
        ida_bytes.patch_bytes(begin, b'\x1F\x20\x03\xD5')
        begin = begin + 4
 
 
# 获取text段的起始地址
text_seg = ida_segment.get_segm_by_name(".text")
start, end = text_seg.start_ea, text_seg.end_ea
# start, end = 0x3BA34, 0x3BA80
# start, end = 0x37390,0x373B4#测试ADRP指令
# start, end = 0x3FCE0, 0x3FD00  # 测试EQ情况
#start, end = 0x3AA90, 0x3AAA4
# start, end = 0x3A078, 0x3A090#测试CSET-BR去除情况
current_addr = start
# print(text_seg.start_ea,text_seg.end_ea)
nop_addr_array_after_finish = []  # 在CSEL/CSET-BR结构修复完成后需要NOP的指令
while current_addr < end:
    # 处理CSEL-BR结构
    if idc.print_insn_mnem(current_addr) == "CSEL":
        CSEL_addr = current_addr
        nop_addr_array_temp = []

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-11-17 18:48 被oacia编辑 ,原因: 写了一个IDA插件实现trace so
上传的附件:
收藏
免费 24
支持
分享
最新回复 (36)
雪    币: 948
活跃值: (1929)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
2
太强啦0.0
2023-8-31 18:33
0
雪    币: 7250
活跃值: (22025)
能力值: ( LV12,RANK:550 )
在线值:
发帖
回帖
粉丝
3
优秀
2023-8-31 18:52
0
雪    币: 928
活跃值: (1858)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
4
cool!
2023-8-31 18:55
0
雪    币: 948
活跃值: (1929)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
5
https://www.pnfsoftware.com/blog/control-flow-unflattening-in-the-wild/
2023-8-31 18:56
0
雪    币: 948
活跃值: (1929)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
fallw1nd https://www.pnfsoftware.com/blog/control-flow-unflattening-in-the-wild/
这个去除混淆是官方用jeb的ir做的,感兴趣可以看看hhh,间接跳转那些混淆其实也可以用反编译器的ir去除
2023-8-31 18:56
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
QQ附近人大佬有吗
2023-8-31 21:10
0
雪    币: 3505
活跃值: (4788)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
8
fallw1nd 这个去除混淆是官方用jeb的ir做的,感兴趣可以看看hhh,间接跳转那些混淆其实也可以用反编译器的ir去除
看来想要去除类似控制流平坦化这类的混淆还是需要词法分析,语法分析和语义分析,得到AST和IR之后才有机会去复原被混淆的代码本来的样子,去年学习Static Analysis的时候感觉这主要是为了程序安全,今天回头看了眼笔记突然发现编译优化也在Static Analysis的范畴,又是一个全新的领域呐
2023-8-31 23:10
0
雪    币: 3303
活跃值: (30941)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2023-9-1 09:10
1
雪    币: 573
活跃值: (1009)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
1024
2023-9-1 10:45
0
雪    币: 129
活跃值: (4580)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
6666666
2023-9-1 11:10
0
雪    币: 2149
活跃值: (2114)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
你才是我的佬啊!
2023-9-2 10:10
0
雪    币: 102
活跃值: (2095)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
mark,太溜了。。
2023-9-4 15:56
0
雪    币: 439
活跃值: (1208)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
14
MBA 表达式可以试试IDA官方的插件:https://github.com/janisslsm/goomba77 这个可以适用 7.7 (我没有使用过,只是推荐,不知道什么效果。)
2023-9-4 16:08
0
雪    币: 3505
活跃值: (4788)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
15
猫子 MBA 表达式可以试试IDA官方的插件:https://github.com/janisslsm/goomba77 这个可以适用 7.7 (我没有使用过,只是推荐,不知道什么效果。)
感谢推荐!刚刚尝试了一下这个工具,对题目中的MBA表达式去除的效果非常好,没想到真的有一天可以在IDA7.7用上IDA8才有的高级插件
看来以后对于不透明谓词的去除 除了D810又多了一个工具能用了
2023-9-4 16:26
0
雪    币: 2376
活跃值: (10510)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
frida-stalker导入ida的那个函数符号这一个小案例就够我学习了,只能说太硬核了,其他看不懂
2023-9-7 11:11
0
雪    币: 6182
活跃值: (4982)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
17
mark
2023-9-7 12:27
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
满分
2023-9-7 16:02
0
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
你是我滴神
2023-9-9 16:50
0
雪    币: 6456
活跃值: (4862)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
20
你为什么这么强啊
2023-9-20 23:11
0
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
这个软件的重打包检验挺有意思的 大佬有兴趣可以盘一下
2023-9-23 18:58
0
雪    币: 3505
活跃值: (4788)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
22
万里星河 这个软件的重打包检验挺有意思的 大佬有兴趣可以盘一下
重打包检测一般都是签名校验的吧,本地校验就去hook获取签名的函数,服务器校验就去抓包.更高级点的就是改完apk保留原始签名,然后在apk安装的时候去hook安卓系统的那个签名哈希校验的代码,让apk就算签名不匹配也能继续安装在手机上
2023-9-23 22:14
0
雪    币: 18
活跃值: (140)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
 。题目是我和组内的兄弟出的,有什么要问我的吗?
2023-9-24 22:04
0
雪    币: 3505
活跃值: (4788)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
24
wx_赛特 [em_84] 。题目是我和组内的兄弟出的,有什么要问我的吗?
大佬我想问一下您在libsec2023.so中的那些寄存器跳转的混淆是通过在llvm中编写pass生成的吗?因为我觉得这种程度的混淆不像是在源码中内联asm就可以做到的。还有就是假如我想给代码加上属于自己的混淆,应该学习哪些知识才能做到呢?
2023-9-25 01:53
0
雪    币: 1620
活跃值: (285)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
25
oacia 哇[em_84]大佬我想问一下您在libsec2023.so中的那些寄存器跳转的混淆是通过在llvm中编写pass生成的吗?因为我觉得这种程度的混淆不像是在源码中内联asm就可以做到的。还有就是假如我 ...
是pass,线上颁奖那天讲过
2023-9-25 12:22
0
游客
登录 | 注册 方可回帖
返回
//