首页
社区
课程
招聘
[原创]零基础算法还原01以及使用python和JS还原C++部分细节
发表于: 2023-11-5 13:42 10824

[原创]零基础算法还原01以及使用python和JS还原C++部分细节

2023-11-5 13:42
10824

你能从本文中学到apk中的so层简单算法还原以及使用js和python还原C代码的部分细节

题目链接

链接:https://pan.baidu.com/s/1HbkzNZqIQYj6rwDpSYt_aQ
提取码:1234

使用jadx 打开algorithmbase_10.apk

image-20231101144427292

使用Frida获取先生成的随机字符串

传入的随机字符串和字符串在Native层加密后的结果如下

image-20231101145832850

我们进入Native层查看加密后的结果

使用unzip命令解压apk获取so文件

unzip algorithmbase_10.apk -d fileso10

image-20231101144703961

使用Ida打开so文件,在Export表输入JNI查看加密函数的位置

image-20231101150231637

使用快捷键YN修改传入的参数名称,以便我们方便我们后续分析

image-20231101150546220

返回值是v13

我们从下往上回溯来到 sub_EE38(v9, v10, v11) 函数

使用Fridasub_EE38 函数进行hook,目的是为了查看传入的参数和传出的参数

脚本如下

点击app按钮,Hook的代码如下所示

image-20231101151718613

我们获取到如下参数

也就是说 sub_EE38 就是我们找的加密call

我们不妨进入sub_EE38 查看加密细节

根据call,还原加密算法

用C代码还原加密算法如下

image-20231101171459516

还原得到加密结果

使用JS还原加密算法如下

image-20231101171616527

使用Python还原算法如下

image-20231101171651251

algorithmbase_12.apk

image-20231104100416930

使用apkInfo打开发现是32位程序

image-20231104100119863

分析如图,先生成随机字符串(我们可以通过Hook encodeFromJni_12 函数来查看生成的随机字符串的值),然后把生成的随机字符串丢到encodeFromJni_12里面处理

我们先Hook一下encodeFromJni_12函数,查看加密前的字符串和加密后的字符串

结果如下

image-20231104101314842

加密的结果看起来很像是Base64 ,我们用64编码后的结果对比一下
image-20231104101716116

不是64编码,但是结果很像。猜测可能是换了码表或并非完全的base64加密

打开IDA,来到加密函数Java_com_kanxue_algorithmbase_MainActivity_encodeFromJni_112(int a1, int a2, int a3, char *a4) 里面 进行分析

从下往上回溯,定位到sub_8B04 函数

image-20231104103843906

进行hook

这里有个坑,就是在使用拦截器对sub_8B04 位置进行定位,如果使用var sub_8B04 = base_address.add(0x8B04); 拦截出错就加一

这样才能进入函数里面

hook代码如下

hook显示的结果如下

使用IDAlibnative-lib.so进行动态调试的时候会发现 aAyzpq23ijrtffg 字符串和我们之前记录的字符串(aAyzpq23ijrtffg DCB "AYZpq23IJrTFfghijklCDE1KLMmBdestU5678GHz0cuvwabN9+/VWXnoOPQRSxy4",0)并不相同,结合前面的思考,换了码表可能性更大

image-20231104105122522

我们开始hook aAyzpq23ijrtffg 码表(0x1B000),这个有个hook技巧: 复制使用readCString打印字符串 可能会造成数据丢失,所以我们使用hexdump(16进制)显示码表的内容会更精确

hook代码如下

码表果然发生改变

image-20231104105804418

看看是不是只是简单换了码表,其他地方有没有进行加密

image-20231104110924545

是的,和猜测的结果完全一致!

再来看看码表是在哪个位置发生改变的,在sub_8ABC 找到码表发生变化的位置,并且发现传参(a1)就是加密前的字符串被int强转

image-20231104111158979

完整的hook代码如下

使用C++还原加密流程

image-20231104111904900

使用JS对加密算法进行还原

image-20231104111644647

使用python还原加密流程

image-20231104112034664

algorithmbase_13.apk

使用JADX打开apk文件

image-20231104215709725

通过调用MainActivity类中的encodeFromJni_12方法,将randomAscii字符串进行加密,并将加密后的结果存储在encodeFromJni_12字符串中。然后,使用Log.e方法将randomAscii字符串和加密后的结果一起打印出来,以便进行调试和分析。

使用IDA打开,按照以前的思路继续从下往上分析

按照第二题的思路,来到sub_8B04

image-20231104220620285

发现和上一题加密没啥区别就只是多了和参数a3的异或

使用Frida Hook 一下传入参数和传出参数

image-20231104220256358

hook的结果更加验证了我们的思路

直接开始还原算法验证

C++代码如下

image-20231104220755239

JS代码如下

image-20231104224728140

python代码如下

image-20231104231103817

C++的函数传参是如果char数组,当使用JS对其进行还原时候,为了方便后面字符串型参数在JS中计算字符串偏移,最好把字符串转为8位无符号整型数组Uint8Array(对应是C++中的(unsigned char*))

如下

这么看不太直观。拿刚才的第三题举例
C++中

这里面str1是char数组被强转为整型当成传参进入的sub_8B04 函数

但在JS中,我们进入sub_8B04 就是传参str是字符串,不需要变整型

image-20231105115216312

为了方便后面的字节偏移计算,我们再把字符串str 转为8位无符号整型数组

在JS中还原C++函数sub_8B04里面的参数V9思路:

因为a2 原先是被int强转char数组。v9是(char*)a2数组偏移v7个字节后的参数
在前面的步骤中,a2在JS中已经被我们设置为8位无符号整型数组,所以v9=a2[v7]

根据这个思路

使用JS还原一下C++代码中* (unsigned __int8*)(v9 + 2) 和 * (unsigned __int8*)(v9 + 2) 代码如下

由于JS语言的特性,不能直接把字符和数字进行直接的运算,所以要把字符转为Unicode 编码与数字进行运算后,再把得到的结果重新转为字符

需要用js的charat charCodeAt fromCharCode 三个函数进行转化这里面贴一下介绍

charAt 方法用于返回指定索引位置的字符。索引位置从0开始计数。

语法: string.charAt(index)

示例:

Copy

charCodeAt 方法返回指定索引位置的字符的Unicode编码。索引位置从0开始计数。

语法: string.charCodeAt(index)

示例:

fromCharCode 方法从Unicode编码创建一个字符串。

语法: String.fromCharCode(number1, number2, ... , numberX)

示例:

现在分析一下前面第三题贴的C代码

这段C代码的含义是将变量a2和v7的和作为地址,取出该地址处的一个字节数据,将其右移两位后转换为无符号8位整数,然后使用这个值作为索引,从数组aAyzpq23ijrtffg中取出对应位置的值,与变量a3进行异或操作,并将结果赋给变量v8。

在JS中aAyzpq23ijrtffg[*(unsigned __int8*)(a2 + v7) >> 2] 这个字符要和a3进行异或,a3是整型不能和字符异或,所以我们要把先把字符转为Unicode码再和a3进行异或运算,然后转为字符串如下

C++的函数传参是如果char数组,当使用python对其进行还原时候,为了方便后面字符串型参数在python中计算字符串偏移,最好把字符串转为bytes数组(对应是C++中的(unsigned char*))

如下

在python中还原C++函数sub_8B04里面的参数V9思路:

因为a2 原先是被int强转char数组。v9是(char*)a2数组偏移v7个字节后的参数
在前面的步骤中,a2在python中已经被我们设置为bytes数组,所以v9=a2[v7]

根据这个思路

使用python还原一下C++代码中* (unsigned __int8*)(v9 + 2) 和 * (unsigned __int8*)(v9 + 2) 代码如下

由于python语言的特性,不能直接把字符和数字进行直接的运算,所以要把字符转为Unicode 编码与数字进行运算后,再把得到的结果重新转为字符

chr和ord是Python中的内置函数,用于字符和对应的Unicode编码之间的转换。

chr函数接受一个整数参数,返回对应的字符。例如:

ord函数接受一个字符参数,返回对应的Unicode编码。例如:

通过chr和ord函数,我们可以方便地在字符和对应的Unicode编码之间进行转换。

现在分析一下前面第三题贴的C代码

这段C代码的含义是将变量a2和v7的和作为地址,取出该地址处的一个字节数据,将其右移两位后转换为无符号8位整数,然后使用这个值作为索引,从数组aAyzpq23ijrtffg中取出对应位置的值,与变量a3进行异或操作,并将结果赋给变量v8。

在python中aAyzpq23ijrtffg[*(unsigned __int8*)(a2 + v7) >> 2] 这个字符要和a3进行异或,a3是整型不能和字符异或,所以我们要把先把字符转为Unicode码再和a3进行异或运算,然后转为字符串如下

// 定义一个名为hook_js的JavaScript函数
function hook_js(){
    // 使用Java.perform()函数来执行JavaScript代码
    Java.perform(function(){
        // 使用Java.use()函数来获取Java类com.kanxue.algorithmbase.MainActivity
        var m_randomAscii = Java.use("com.kanxue.algorithmbase.MainActivity")
 
        // 检查获取的类对象是否存在
        if(m_randomAscii!=undefined){
            console.log("开始Hook"); // 打印开始Hook的消息
 
            // 重写函数encodeFromJni_11的实现
            m_randomAscii.encodeFromJni_11.implementation = function(input){
                // 获取输入参数input
                var res = this.encodeFromJni_11(input);
 
                // 打印输入参数和返回值
                console.log("input:==>"+input);
                console.log("res:==>"+res);
 
                // 返回结果
                return res;
            }
        }
    })
}
function main(){
    hook_js();
}
 
setImmediate(main);
// 定义一个名为hook_js的JavaScript函数
function hook_js(){
    // 使用Java.perform()函数来执行JavaScript代码
    Java.perform(function(){
        // 使用Java.use()函数来获取Java类com.kanxue.algorithmbase.MainActivity
        var m_randomAscii = Java.use("com.kanxue.algorithmbase.MainActivity")
 
        // 检查获取的类对象是否存在
        if(m_randomAscii!=undefined){
            console.log("开始Hook"); // 打印开始Hook的消息
 
            // 重写函数encodeFromJni_11的实现
            m_randomAscii.encodeFromJni_11.implementation = function(input){
                // 获取输入参数input
                var res = this.encodeFromJni_11(input);
 
                // 打印输入参数和返回值
                console.log("input:==>"+input);
                console.log("res:==>"+res);
 
                // 返回结果
                return res;
            }
        }
    })
}
function main(){
    hook_js();
}
 
setImmediate(main);
input:==> meUx3DppB%Gj]-2J
res:==> LCllTadbMHYZ0kNnDitri5== 
input:==> meUx3DppB%Gj]-2J
res:==> LCllTadbMHYZ0kNnDitri5== 
function hook_js(){
    Java.perform(function(){
        var m_randomAscii = Java.use("com.kanxue.algorithmbase.MainActivity") //获取MainActivity类
        if(m_randomAscii!=undefined){
            console.log("开始Hook");
            m_randomAscii.encodeFromJni_11.implementation = function(input){ //找到encodeFromJni_11方法,并拦截调用
                var res = this.encodeFromJni_11(input); //调用原始方法
                console.log("input:==>"+input); //打印输入参数
                console.log("res:==>"+res); //打印返回结果
                return res; //返回结果
 
            }
        }
    })
}
 
function hook_native(){
    Java.perform(function(){
        //找到基地址
        var base_address = Module.getBaseAddress("libnative-lib.so") //获取libnative-lib.so的基地址
        var sub_EE38 = base_address.add(0xEE38); //计算函数偏移地址
        //开启拦截器
        Interceptor.attach(sub_EE38,{
            //进入函数
            onEnter:function(args){
            this.arg0 = args[0]; //保存第一个参数
            console.log("======>onENter<==========");
            console.log("第一个参数未处理前===>"+args[0].readCString()); //打印第一个参数内容
            console.log("第二个参数未处理前===>"+args[1].readCString()); //打印第二个参数内容
            console.log("第三个参数未处理前===>"+args[2]); //打印第三个参数内容
            },
            onLeave:function(nresult){  
                console.log("======>onLeave<==========");
                console.log("第一个参数处理后======>"+this.arg0.readCString()); //打印处理后的第一个参数
 
 
            }
        })
    })
}
 
 
function main(){
    hook_js();
    hook_native();
}
 
setImmediate(main);
function hook_js(){
    Java.perform(function(){
        var m_randomAscii = Java.use("com.kanxue.algorithmbase.MainActivity") //获取MainActivity类
        if(m_randomAscii!=undefined){
            console.log("开始Hook");
            m_randomAscii.encodeFromJni_11.implementation = function(input){ //找到encodeFromJni_11方法,并拦截调用
                var res = this.encodeFromJni_11(input); //调用原始方法
                console.log("input:==>"+input); //打印输入参数
                console.log("res:==>"+res); //打印返回结果
                return res; //返回结果
 
            }
        }
    })
}
 
function hook_native(){
    Java.perform(function(){
        //找到基地址
        var base_address = Module.getBaseAddress("libnative-lib.so") //获取libnative-lib.so的基地址
        var sub_EE38 = base_address.add(0xEE38); //计算函数偏移地址
        //开启拦截器
        Interceptor.attach(sub_EE38,{
            //进入函数
            onEnter:function(args){
            this.arg0 = args[0]; //保存第一个参数
            console.log("======>onENter<==========");
            console.log("第一个参数未处理前===>"+args[0].readCString()); //打印第一个参数内容
            console.log("第二个参数未处理前===>"+args[1].readCString()); //打印第二个参数内容
            console.log("第三个参数未处理前===>"+args[2]); //打印第三个参数内容
            },
            onLeave:function(nresult){  
                console.log("======>onLeave<==========");
                console.log("第一个参数处理后======>"+this.arg0.readCString()); //打印处理后的第一个参数
 
 
            }
        })
    })
}
 
 
function main(){
    hook_js();
    hook_native();
}
 
setImmediate(main);
sub_EE38(_BYTE *a1, __int64 a2, int a3) 第一个参数 第二个参数 第三个参数
未处理前 "" meUx3DppB%Gj]-2J 0x10
处理后后 LCllTadbMHYZ0kNnDitri5==
第一个参数未处理前===>
第二个参数未处理前===>meUx3DppB%Gj]-2J
第三个参数未处理前===>0x10
======>onLeave<==========
第一个参数处理后======>LCllTadbMHYZ0kNnDitri5==
input:==>meUx3DppB%Gj]-2J
res:==>LCllTadbMHYZ0kNnDitri5== 
第一个参数未处理前===>
第二个参数未处理前===>meUx3DppB%Gj]-2J
第三个参数未处理前===>0x10
======>onLeave<==========
第一个参数处理后======>LCllTadbMHYZ0kNnDitri5==
input:==>meUx3DppB%Gj]-2J
res:==>LCllTadbMHYZ0kNnDitri5== 
__int64 __fastcall sub_EE38(_BYTE *a1, __int64 a2, int a3)
{
  __int64 v3; // x9,循环计数器
  _BYTE *v4; // x12,用于存储结果的指针
  unsigned __int8 *v5; // x10,用于指向输入数据的指针
  unsigned __int64 v6; // x13,临时变量
  _BYTE *v7; // x10,下一个结果的存储位置
  __int64 v8; // x11,临时变量
  char v9; // w8,临时变量
  __int64 v10; // x9,临时变量
  __int64 result; // x0,函数返回值
 
  if (a3 - 2 < 1) // 当数据长度小于等于2时
  {
    LODWORD(v3) = 0;
    v7 = a1;
    if (a3 <= 0)
      goto LABEL_11;
  }
  else
  {
    v3 = 0LL;
    v4 = a1;
    do
    {
      v5 = (unsigned __int8 *)(a2 + v3); // 从输入数据中取出三个字节进行处理
      v6 = *(unsigned __int8 *)(a2 + v3);
      v3 += 3LL;
      *v4 = aAyzabfghz0cmbd[v6 >> 2]; // 取出第一个字节的前6位对应的字符
      v4[1] = aAyzabfghz0cmbd[(16 * (unsigned int)*v5) & 0x30LL | ((unsigned __int64)v5[1] >> 4)]; // 取出第二个字节的前4位和第一个字节的后2位所对应的字符
      v4[2] = aAyzabfghz0cmbd[(4 * (unsigned int)v5[1]) & 0x3CLL | ((unsigned __int64)v5[2] >> 6)]; // 取出第三个字节的前2位和第二个字节的后4位所对应的字符
      LOBYTE(v6) = aAyzabfghz0cmbd[v5[2] & 0x3F]; // 取出第三个字节的后6位对应的字符
      v7 = v4 + 4; // 指向下一个结果的存储位置
      v4[3] = v6; // 存储刚才取出的字符
      v4 += 4; // 指向下一个处理位置
    }
    while (v3 < a3 - 2); // 处理到倒数第三个字节为止
    if ((int)v3 >= a3) // 如果处理到倒数第二个字节或最后一个字节
      goto LABEL_11;
  }
  *v7 = aAyzabfghz0cmbd[(unsigned __int64)*(unsigned __int8 *)(a2 + (unsigned int)v3) >> 2]; // 取出最后一个字节的前6位对应的字符
  v8 = (16 * (unsigned int)*(unsigned __int8 *)(a2 + (unsigned int)v3)) & 0x30LL; // 取出最后一个字节的前4位
  if ((_DWORD)v3 == a3 - 1) // 如果只有最后一个字节
  {
    v7[1] = aAyzabfghz0cmbd[v8]; // 存储最后一个字节的前4位对应的字符
    v9 = 61; // 存储'='字符
  }
  else
  {
    v10 = a2 + (unsigned int)v3; // 最后两个字节的指针
    v7[1] = aAyzabfghz0cmbd[v8 | ((unsigned __int64)*(unsigned __int8 *)(v10 + 1) >> 4)]; // 存储最后一个字节的前4位和倒数第二个字节的后2位对应的字符
    v9 = aAyzabfghz0cmbd[(4 * (unsigned int)*(unsigned __int8 *)(v10 + 1)) & 0x3CLL]; // 存储倒数第二个字节的后4位对应的字符
  }
  v7[2] = v9; // 存储倒数第二个字节的后4位或'='字符
  v7[3] = 61; // 存储'='字符
  v7 += 4; // 指向下一个结果的存储位置
LABEL_11:
  result = (unsigned int)((_DWORD)v7 - (_DWORD)a1 + 1); // 计算结果的长度
  *v7 = 0; // 结果字符串结尾添加NULL字符
  return result; // 返回结果长度
}
__int64 __fastcall sub_EE38(_BYTE *a1, __int64 a2, int a3)
{
  __int64 v3; // x9,循环计数器
  _BYTE *v4; // x12,用于存储结果的指针
  unsigned __int8 *v5; // x10,用于指向输入数据的指针
  unsigned __int64 v6; // x13,临时变量
  _BYTE *v7; // x10,下一个结果的存储位置
  __int64 v8; // x11,临时变量
  char v9; // w8,临时变量
  __int64 v10; // x9,临时变量
  __int64 result; // x0,函数返回值
 
  if (a3 - 2 < 1) // 当数据长度小于等于2时
  {
    LODWORD(v3) = 0;
    v7 = a1;
    if (a3 <= 0)
      goto LABEL_11;
  }
  else
  {
    v3 = 0LL;
    v4 = a1;
    do
    {
      v5 = (unsigned __int8 *)(a2 + v3); // 从输入数据中取出三个字节进行处理
      v6 = *(unsigned __int8 *)(a2 + v3);
      v3 += 3LL;
      *v4 = aAyzabfghz0cmbd[v6 >> 2]; // 取出第一个字节的前6位对应的字符
      v4[1] = aAyzabfghz0cmbd[(16 * (unsigned int)*v5) & 0x30LL | ((unsigned __int64)v5[1] >> 4)]; // 取出第二个字节的前4位和第一个字节的后2位所对应的字符
      v4[2] = aAyzabfghz0cmbd[(4 * (unsigned int)v5[1]) & 0x3CLL | ((unsigned __int64)v5[2] >> 6)]; // 取出第三个字节的前2位和第二个字节的后4位所对应的字符
      LOBYTE(v6) = aAyzabfghz0cmbd[v5[2] & 0x3F]; // 取出第三个字节的后6位对应的字符
      v7 = v4 + 4; // 指向下一个结果的存储位置
      v4[3] = v6; // 存储刚才取出的字符
      v4 += 4; // 指向下一个处理位置
    }
    while (v3 < a3 - 2); // 处理到倒数第三个字节为止
    if ((int)v3 >= a3) // 如果处理到倒数第二个字节或最后一个字节
      goto LABEL_11;
  }
  *v7 = aAyzabfghz0cmbd[(unsigned __int64)*(unsigned __int8 *)(a2 + (unsigned int)v3) >> 2]; // 取出最后一个字节的前6位对应的字符
  v8 = (16 * (unsigned int)*(unsigned __int8 *)(a2 + (unsigned int)v3)) & 0x30LL; // 取出最后一个字节的前4位
  if ((_DWORD)v3 == a3 - 1) // 如果只有最后一个字节
  {
    v7[1] = aAyzabfghz0cmbd[v8]; // 存储最后一个字节的前4位对应的字符
    v9 = 61; // 存储'='字符
  }
  else
  {
    v10 = a2 + (unsigned int)v3; // 最后两个字节的指针
    v7[1] = aAyzabfghz0cmbd[v8 | ((unsigned __int64)*(unsigned __int8 *)(v10 + 1) >> 4)]; // 存储最后一个字节的前4位和倒数第二个字节的后2位对应的字符
    v9 = aAyzabfghz0cmbd[(4 * (unsigned int)*(unsigned __int8 *)(v10 + 1)) & 0x3CLL]; // 存储倒数第二个字节的后4位对应的字符
  }
  v7[2] = v9; // 存储倒数第二个字节的后4位或'='字符
  v7[3] = 61; // 存储'='字符
  v7 += 4; // 指向下一个结果的存储位置
LABEL_11:
  result = (unsigned int)((_DWORD)v7 - (_DWORD)a1 + 1); // 计算结果的长度
  *v7 = 0; // 结果字符串结尾添加NULL字符
  return result; // 返回结果长度
}
// 01.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
 
#include <iostream>
#include <memory>
#include <Windows.h> 
#include <minwindef.h>
#include <rpcndr.h>
 
using namespace std;
 
unsigned char* sub_EE38(char* strResult, long long inPut, signed int nCnt)
{
    long long v3 = 0;
    unsigned char* v4 = new unsigned char[100];
    unsigned char* v5 = nullptr;
    unsigned long long v6 = 0;
    char aAyzabfghz0cmbd[] = "AYZabFGHz0cmBdefghijklCDE1KLMNTU56789+/VWXnopq23IJrstuvwOPQRSxy4";
    long long result = 0;
    unsigned long long v8 = 0;
    char v9;
    unsigned char* v7;
    long long v10;
    //记录v4初始
    unsigned char* vCount = v4;
    do
    {
        *v4 = 0;
        v5 = (unsigned char*)(inPut + v3);
        v6 = *(unsigned char*)(inPut + v3);
        v3 += 3;
        *v4 = aAyzabfghz0cmbd[v6 >> 2];
        v4[1] = aAyzabfghz0cmbd[(16 * (unsigned int)*v5) & 0x30 | ((unsigned long long)v5[1] >> 4)];
        v4[2] = aAyzabfghz0cmbd[(4 * (unsigned int)v5[1]) & 0x3C | ((unsigned long long)v5[2] >> 6)];
        unsigned char lowByte = aAyzabfghz0cmbd[v5[2] & 0x3F];
        v6 = (v6 & ~(0xFFull)) | lowByte;
        v7 = v4 + 4;
        v4[3] = v6;
        v4 += 4;
    } while (v3 < nCnt - 2);
    if ((int)v3 >= nCnt)
        goto LABEL_11;
    *v7 = aAyzabfghz0cmbd[(unsigned long long) * (unsigned char*)(inPut + (unsigned int)v3) >> 2];
    v8 = (16 * (unsigned int)*(unsigned __int8*)(inPut + (unsigned int)v3)) & 0x30LL;
    if (v3 == nCnt - 1)
    {
        v7[1] = aAyzabfghz0cmbd[v8];
        v9 = 61;
    }
    else
    {
        v10 = inPut + (unsigned int)v3;
        v7[1] = aAyzabfghz0cmbd[v8 | ((unsigned long long) * (unsigned char*)(v10 + 1) >> 4)];
        v9 = aAyzabfghz0cmbd[(4 * (unsigned int)*(unsigned char*)(v10 + 1)) & 0x3CLL];
    }
    v7[2] = v9;
    v7[3] = 61;
    v7 += 4;
    std::cout << (unsigned char*)vCount;
     return (unsigned char*)vCount;
 
LABEL_11:
    result = (unsigned int)((DWORD)v7 - (DWORD)strResult + 1);
    *v7 = 0;
    delete[] v4;
    std::cout << result;
    return (unsigned char*)result;
}
 
int main()
{
    char str[] = "";
    unsigned char* str2=  sub_EE38(str, (__int64)"meUx3DppB%Gj]-2J", 0x10);
     std::cout << str2;
}
// 01.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
 
#include <iostream>
#include <memory>
#include <Windows.h> 
#include <minwindef.h>
#include <rpcndr.h>
 
using namespace std;
 
unsigned char* sub_EE38(char* strResult, long long inPut, signed int nCnt)
{
    long long v3 = 0;
    unsigned char* v4 = new unsigned char[100];
    unsigned char* v5 = nullptr;
    unsigned long long v6 = 0;
    char aAyzabfghz0cmbd[] = "AYZabFGHz0cmBdefghijklCDE1KLMNTU56789+/VWXnopq23IJrstuvwOPQRSxy4";
    long long result = 0;
    unsigned long long v8 = 0;
    char v9;
    unsigned char* v7;
    long long v10;
    //记录v4初始
    unsigned char* vCount = v4;
    do
    {
        *v4 = 0;
        v5 = (unsigned char*)(inPut + v3);
        v6 = *(unsigned char*)(inPut + v3);
        v3 += 3;
        *v4 = aAyzabfghz0cmbd[v6 >> 2];
        v4[1] = aAyzabfghz0cmbd[(16 * (unsigned int)*v5) & 0x30 | ((unsigned long long)v5[1] >> 4)];
        v4[2] = aAyzabfghz0cmbd[(4 * (unsigned int)v5[1]) & 0x3C | ((unsigned long long)v5[2] >> 6)];
        unsigned char lowByte = aAyzabfghz0cmbd[v5[2] & 0x3F];
        v6 = (v6 & ~(0xFFull)) | lowByte;
        v7 = v4 + 4;
        v4[3] = v6;
        v4 += 4;
    } while (v3 < nCnt - 2);
    if ((int)v3 >= nCnt)
        goto LABEL_11;
    *v7 = aAyzabfghz0cmbd[(unsigned long long) * (unsigned char*)(inPut + (unsigned int)v3) >> 2];
    v8 = (16 * (unsigned int)*(unsigned __int8*)(inPut + (unsigned int)v3)) & 0x30LL;
    if (v3 == nCnt - 1)
    {
        v7[1] = aAyzabfghz0cmbd[v8];
        v9 = 61;
    }
    else
    {
        v10 = inPut + (unsigned int)v3;
        v7[1] = aAyzabfghz0cmbd[v8 | ((unsigned long long) * (unsigned char*)(v10 + 1) >> 4)];
        v9 = aAyzabfghz0cmbd[(4 * (unsigned int)*(unsigned char*)(v10 + 1)) & 0x3CLL];
    }
    v7[2] = v9;
    v7[3] = 61;
    v7 += 4;
    std::cout << (unsigned char*)vCount;
     return (unsigned char*)vCount;
 
LABEL_11:
    result = (unsigned int)((DWORD)v7 - (DWORD)strResult + 1);
    *v7 = 0;
    delete[] v4;
    std::cout << result;
    return (unsigned char*)result;
}
 
int main()
{
    char str[] = "";
    unsigned char* str2=  sub_EE38(str, (__int64)"meUx3DppB%Gj]-2J", 0x10);
     std::cout << str2;
}
LCllTadbMHYZ0kNnDitri5==
LCllTadbMHYZ0kNnDitri5==
function stringToUint8Array(str){
    var arr = [];
    for (var i=0;i<str.length;i++)
    {
     arr.push(str.charCodeAt(i));
    }
 
    var outputbytes = new Uint8Array(arr);
    return outputbytes;
}
 
 
function sub_EE38(str,input,nCnt){
    var input_bytes = stringToUint8Array(input);
    var aAyzabfghz0cmbd = "AYZabFGHz0cmBdefghijklCDE1KLMNTU56789+/VWXnopq23IJrstuvwOPQRSxy4";
    var result =0;
    var v4 ="";
    var  v7=0;
    var v3 =0;
    var v6 =0
    var v8 =0
    var v9 = ""
 
    while (v3 <nCnt-2){
    var v5 = input_bytes[v3];
    var v5_1 = input_bytes[v3+1]
    var v5_2 = input_bytes[v3+2]
    v6 = input_bytes[v3];
    v3 +=3;
    v4 +=  aAyzabfghz0cmbd.charAt(v6 >>2)
    v4 +=  aAyzabfghz0cmbd.charAt(((16*v5)& 0x30) | v5_1 >>4);
    v4 += aAyzabfghz0cmbd.charAt((4*v5_1)&0x3C |v5_2 >>6 );
    v6 = aAyzabfghz0cmbd[v5_2 & 0x3F]
    v4 += v6;
    }
    v4 +=aAyzabfghz0cmbd[(input_bytes[v3]) >> 2];
    v8 = 16 * input_bytes[v3] & 0x30
    if (v3 >= nCnt -1){
        v4 += aAyzabfghz0cmbd[v8]
        v9 = "="
    }else{
        v4 += aAyzabfghz0cmbd[v8 |(v4[v3+1] >>4)]
        v9 = aAyzabfghz0cmbd[(4*v4[v3+1] & 0x3C)]
    }
    v4 += v9
    v4 += "="
    return v4
}
 
console.log(sub_EE38("","meUx3DppB%Gj]-2J",0x10))
function stringToUint8Array(str){
    var arr = [];
    for (var i=0;i<str.length;i++)
    {
     arr.push(str.charCodeAt(i));
    }
 
    var outputbytes = new Uint8Array(arr);
    return outputbytes;
}
 
 
function sub_EE38(str,input,nCnt){
    var input_bytes = stringToUint8Array(input);
    var aAyzabfghz0cmbd = "AYZabFGHz0cmBdefghijklCDE1KLMNTU56789+/VWXnopq23IJrstuvwOPQRSxy4";
    var result =0;
    var v4 ="";
    var  v7=0;
    var v3 =0;
    var v6 =0
    var v8 =0
    var v9 = ""
 
    while (v3 <nCnt-2){
    var v5 = input_bytes[v3];
    var v5_1 = input_bytes[v3+1]
    var v5_2 = input_bytes[v3+2]
    v6 = input_bytes[v3];
    v3 +=3;
    v4 +=  aAyzabfghz0cmbd.charAt(v6 >>2)
    v4 +=  aAyzabfghz0cmbd.charAt(((16*v5)& 0x30) | v5_1 >>4);
    v4 += aAyzabfghz0cmbd.charAt((4*v5_1)&0x3C |v5_2 >>6 );
    v6 = aAyzabfghz0cmbd[v5_2 & 0x3F]
    v4 += v6;
    }
    v4 +=aAyzabfghz0cmbd[(input_bytes[v3]) >> 2];
    v8 = 16 * input_bytes[v3] & 0x30
    if (v3 >= nCnt -1){
        v4 += aAyzabfghz0cmbd[v8]
        v9 = "="
    }else{
        v4 += aAyzabfghz0cmbd[v8 |(v4[v3+1] >>4)]
        v9 = aAyzabfghz0cmbd[(4*v4[v3+1] & 0x3C)]
    }
    v4 += v9
    v4 += "="
    return v4
}
 
console.log(sub_EE38("","meUx3DppB%Gj]-2J",0x10))
def sub_EE38(strResult,inPut,nCnt):
    v3 =0
    v4 = bytes(inPut, "utf-8")
    aAyzabfghz0cmbd ="AYZabFGHz0cmBdefghijklCDE1KLMNTU56789+/VWXnopq23IJrstuvwOPQRSxy4"
    v6=0
    result =0
    v8=0
    output = ""
    v7 =0
    while True:
        v5= v4[v3]
        v5_1 = v4[v3+1]
        v5_2 = v4[v3+2]
        v6 =v4[v3]
        v3 +=3
        output += aAyzabfghz0cmbd[v6>>2]
        output+= aAyzabfghz0cmbd[(16*v5) & 0x30 | (v5_1 >>4)]
        output+= aAyzabfghz0cmbd[(4*v5_1)&0x3C | (v5_2>>6)]
        v6 = aAyzabfghz0cmbd[v5_2&0x3F]
        output +=v6
        v7 +=4
        if v3>=nCnt-2:
            break
    output += aAyzabfghz0cmbd[v4[v3] >>2]
    v8 = 16 * v4[v3] & 0x30
    if(v3 >=nCnt -1):
        output +=  aAyzabfghz0cmbd[v8]
        v9 = '='
    else:
        output += aAyzabfghz0cmbd[v8 | (v4[v3+1]>>4)]
        v9 = aAyzabfghz0cmbd[(4*v4[v3+1]&0x3C)]
 
    output += v9
    output += '='
    return output
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
     print(sub_EE38("","meUx3DppB%Gj]-2J",0x10))
def sub_EE38(strResult,inPut,nCnt):
    v3 =0
    v4 = bytes(inPut, "utf-8")
    aAyzabfghz0cmbd ="AYZabFGHz0cmBdefghijklCDE1KLMNTU56789+/VWXnopq23IJrstuvwOPQRSxy4"
    v6=0
    result =0
    v8=0
    output = ""
    v7 =0
    while True:
        v5= v4[v3]
        v5_1 = v4[v3+1]
        v5_2 = v4[v3+2]
        v6 =v4[v3]
        v3 +=3
        output += aAyzabfghz0cmbd[v6>>2]
        output+= aAyzabfghz0cmbd[(16*v5) & 0x30 | (v5_1 >>4)]
        output+= aAyzabfghz0cmbd[(4*v5_1)&0x3C | (v5_2>>6)]
        v6 = aAyzabfghz0cmbd[v5_2&0x3F]
        output +=v6
        v7 +=4
        if v3>=nCnt-2:
            break
    output += aAyzabfghz0cmbd[v4[v3] >>2]
    v8 = 16 * v4[v3] & 0x30
    if(v3 >=nCnt -1):
        output +=  aAyzabfghz0cmbd[v8]
        v9 = '='
    else:
        output += aAyzabfghz0cmbd[v8 | (v4[v3+1]>>4)]
        v9 = aAyzabfghz0cmbd[(4*v4[v3+1]&0x3C)]
 
    output += v9
    output += '='
    return output
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
     print(sub_EE38("","meUx3DppB%Gj]-2J",0x10))
// 定义一个名为hook_js的函数
function hook_js() {
    // 使用Java.perform方法执行函数体
    Java.perform(function() {
        // 定义变量enrandomcode并使用Java.use方法获取com.kanxue.algorithmbase.MainActivity类
        var enrandomcode = Java.use("com.kanxue.algorithmbase.MainActivity")
        // 如果enrandomcode已定义
        if(enrandomcode != undefined) {
            // 打印开始JAVA层Hook
            console.log("开始JAVA层Hook");
            // 重写encodeFromJni_12方法的实现
            enrandomcode.encodeFromJni_12.implementation = function(intput) {
                // 调用原始的encodeFromJni_12方法,并将结果赋值给变量res
                var res = this.encodeFromJni_12(intput);
                // 打印传入参数的值
                console.log("传入参数是====>" + intput);
                // 打印加密后的参数的值
                console.log("加密后的参数是====>" + res);
                // 返回加密后的结果
                return res;
            }
        }
    })
}
// 定义一个名为hook_js的函数
function hook_js() {
    // 使用Java.perform方法执行函数体
    Java.perform(function() {
        // 定义变量enrandomcode并使用Java.use方法获取com.kanxue.algorithmbase.MainActivity类
        var enrandomcode = Java.use("com.kanxue.algorithmbase.MainActivity")
        // 如果enrandomcode已定义
        if(enrandomcode != undefined) {
            // 打印开始JAVA层Hook
            console.log("开始JAVA层Hook");
            // 重写encodeFromJni_12方法的实现
            enrandomcode.encodeFromJni_12.implementation = function(intput) {
                // 调用原始的encodeFromJni_12方法,并将结果赋值给变量res
                var res = this.encodeFromJni_12(intput);
                // 打印传入参数的值
                console.log("传入参数是====>" + intput);
                // 打印加密后的参数的值
                console.log("加密后的参数是====>" + res);
                // 返回加密后的结果
                return res;
            }
        }
    })
}
传入参数是====>xVjHx-D&nji8i*rBZ)j
加密后的参数是====>`!^fZFrxI^q~[+\~p<yT#p~F==
传入参数是====>xVjHx-D&nji8i*rBZ)j
加密后的参数是====>`!^fZFrxI^q~[+\~p<yT#p~F==
// 定义一个名为sub_8B04的函数,参数为a1、a2和a3,返回值为_BYTE类型的指针
_BYTE *__fastcall sub_8B04(int a1, int a2, int a3)
{
  int v3; // r12
  int v6; // r6
  int v7; // r5
  _BYTE *v8; // r3
  int v9; // r2
  unsigned int v10; // r0
  char v11; // r4
  int v12; // r6
  char v13; // r1
 
  // 计算v3的值
  v3 = a3 - 2;
  v6 = 0;
  v7 = 0;
  // 进入while循环,直到v7 >= v3
  while ( 1 )
  {
    // 获取a1+v6处的_BYTE类型指针
    v8 = (_BYTE *)(a1 + v6);
    if ( v7 >= v3 )
      break;
    // 计算v9的值
    v9 = a2 + v7;
    // v6加上4
    v6 += 4;
    // 将aAyzpq23ijrtffg[*(unsigned __int8 *)(a2 + v7) >> 2]的值赋给v8指向的地址
    *v8 = aAyzpq23ijrtffg[*(unsigned __int8 *)(a2 + v7) >> 2];
    // 计算v10的值
    v10 = *(unsigned __int8 *)(a2 + v7 + 1);
    // 获取a2+v7处的值
    v11 = *(_BYTE *)(a2 + v7);
    // v7加上3
    v7 += 3;
    // 将aAyzpq23ijrtffg[(v10 >> 4) & 0xFFFFFFCF | (16 * (v11 & 3))]的值赋给v8指向的地址+1处
    v8[1] = aAyzpq23ijrtffg[(v10 >> 4) & 0xFFFFFFCF | (16 * (v11 & 3))];
    // 将aAyzpq23ijrtffg[(*(unsigned __int8 *)(v9 + 2) >> 6) & 0xFFFFFFC3 | (4 * (*(_BYTE *)(v9 + 1) & 0xF))]的值赋给v8指向的地址+2处
    v8[2] = aAyzpq23ijrtffg[(*(unsigned __int8 *)(v9 + 2) >> 6) & 0xFFFFFFC3 | (4 * (*(_BYTE *)(v9 + 1) & 0xF))];
    // 将*(_BYTE *)(v9 + 2) & 0x3F的值赋给v8指向的地址+3处
    v8[3] = aAyzpq23ijrtffg[*(_BYTE *)(v9 + 2) & 0x3F];
  }
  // 如果v7 < a3,执行以下代码
  if ( v7 < a3 )
  {
    // 将aAyzpq23ijrtffg[*(unsigned __int8 *)(a2 + v7) >> 2]的值赋给v8指向的地址
    *v8 = aAyzpq23ijrtffg[*(unsigned __int8 *)(a2 + v7) >> 2];
    // 计算v12的值
    v12 = (16 * *(unsigned __int8 *)(a2 + v7)) & 0x30;
    // 如果a3 - 1 == v7,执行以下代码
    if ( a3 - 1 == v7 )
    {
      v13 = 61;
      // 将aAyzpq23ijrtffg[v12]的值赋给v8指向的地址+1处
      v8[1] = aAyzpq23ijrtffg[v12];
    }
    else
    {
      // 将aAyzpq23ijrtffg[v12 | (*(unsigned __int8 *)(a2 + v7 + 1) >> 4)]的值赋给v8指向的地址+1处
      v8[1] = aAyzpq23ijrtffg[v12 | (*(unsigned __int8 *)(a2 + v7 + 1) >> 4)];
      // 将aAyzpq23ijrtffg[4 * (*(_BYTE *)(a2 + v7 + 1) & 0xF)]的值赋给v13
      v13 = aAyzpq23ijrtffg[4 * (*(_BYTE *)(a2 + v7 + 1) & 0xF)];
    }
    // 将61的值赋给v8指向的地址+3处
    v8[3] = 61;
    // 将v13的值赋给v8指向的地址+2处
    v8[2] = v13;
    // v8加上4
    v8 += 4;
  }
  // 将0赋给v8指向的地址
  *v8 = 0;
  // 返回&v8[-a1 + 1]的值
  return &v8[-a1 + 1];
}
// 定义一个名为sub_8B04的函数,参数为a1、a2和a3,返回值为_BYTE类型的指针
_BYTE *__fastcall sub_8B04(int a1, int a2, int a3)
{
  int v3; // r12
  int v6; // r6
  int v7; // r5
  _BYTE *v8; // r3
  int v9; // r2
  unsigned int v10; // r0
  char v11; // r4
  int v12; // r6
  char v13; // r1
 
  // 计算v3的值
  v3 = a3 - 2;
  v6 = 0;
  v7 = 0;
  // 进入while循环,直到v7 >= v3
  while ( 1 )
  {
    // 获取a1+v6处的_BYTE类型指针
    v8 = (_BYTE *)(a1 + v6);
    if ( v7 >= v3 )
      break;
    // 计算v9的值
    v9 = a2 + v7;
    // v6加上4
    v6 += 4;
    // 将aAyzpq23ijrtffg[*(unsigned __int8 *)(a2 + v7) >> 2]的值赋给v8指向的地址
    *v8 = aAyzpq23ijrtffg[*(unsigned __int8 *)(a2 + v7) >> 2];
    // 计算v10的值
    v10 = *(unsigned __int8 *)(a2 + v7 + 1);
    // 获取a2+v7处的值
    v11 = *(_BYTE *)(a2 + v7);
    // v7加上3
    v7 += 3;
    // 将aAyzpq23ijrtffg[(v10 >> 4) & 0xFFFFFFCF | (16 * (v11 & 3))]的值赋给v8指向的地址+1处
    v8[1] = aAyzpq23ijrtffg[(v10 >> 4) & 0xFFFFFFCF | (16 * (v11 & 3))];
    // 将aAyzpq23ijrtffg[(*(unsigned __int8 *)(v9 + 2) >> 6) & 0xFFFFFFC3 | (4 * (*(_BYTE *)(v9 + 1) & 0xF))]的值赋给v8指向的地址+2处
    v8[2] = aAyzpq23ijrtffg[(*(unsigned __int8 *)(v9 + 2) >> 6) & 0xFFFFFFC3 | (4 * (*(_BYTE *)(v9 + 1) & 0xF))];
    // 将*(_BYTE *)(v9 + 2) & 0x3F的值赋给v8指向的地址+3处
    v8[3] = aAyzpq23ijrtffg[*(_BYTE *)(v9 + 2) & 0x3F];
  }
  // 如果v7 < a3,执行以下代码
  if ( v7 < a3 )
  {
    // 将aAyzpq23ijrtffg[*(unsigned __int8 *)(a2 + v7) >> 2]的值赋给v8指向的地址
    *v8 = aAyzpq23ijrtffg[*(unsigned __int8 *)(a2 + v7) >> 2];
    // 计算v12的值
    v12 = (16 * *(unsigned __int8 *)(a2 + v7)) & 0x30;
    // 如果a3 - 1 == v7,执行以下代码
    if ( a3 - 1 == v7 )
    {
      v13 = 61;
      // 将aAyzpq23ijrtffg[v12]的值赋给v8指向的地址+1处
      v8[1] = aAyzpq23ijrtffg[v12];
    }
    else
    {
      // 将aAyzpq23ijrtffg[v12 | (*(unsigned __int8 *)(a2 + v7 + 1) >> 4)]的值赋给v8指向的地址+1处
      v8[1] = aAyzpq23ijrtffg[v12 | (*(unsigned __int8 *)(a2 + v7 + 1) >> 4)];
      // 将aAyzpq23ijrtffg[4 * (*(_BYTE *)(a2 + v7 + 1) & 0xF)]的值赋给v13
      v13 = aAyzpq23ijrtffg[4 * (*(_BYTE *)(a2 + v7 + 1) & 0xF)];
    }
    // 将61的值赋给v8指向的地址+3处
    v8[3] = 61;
    // 将v13的值赋给v8指向的地址+2处
    v8[2] = v13;
    // v8加上4
    v8 += 4;
  }
  // 将0赋给v8指向的地址
  *v8 = 0;
  // 返回&v8[-a1 + 1]的值
  return &v8[-a1 + 1];
}
var sub_8B04 = base_address.add(0x8B04+1);
var sub_8B04 = base_address.add(0x8B04+1);
function hook_native(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        if(base_address !=undefined){
        console.log("开始native层hook");
        //定位拦截位置
        var sub_8B04 = base_address.add(0x8B04+1);
        console.log("sub_8b04:",sub_8B04)
        if(sub_8B04!=undefined){
        console.log("进入native层0x8B04");
        }else{
        console.log("拦截器加载失败");
        }
        //使用拦截器
        Interceptor.attach(sub_8B04,{
        //开始进入函数,传入了三个参数依次打印
        onEnter:function(args){
            //保存参数
            this.arg0 = args[0];
            this.arg1 = args[1];
            this.arg2 = args[2];
 
            console.log("========>ENTER<========");
            console.log("sub_8B04未初始化时第一个参数是===>"+this.arg0.readCString());
            console.log("sub_8B04未初始化时第二个参数是===>"+this.arg1.readCString());
            console.log("sub_8B04未初始化时第三个参数是===>"+this.arg2.readCString());           
        },
        onLeave:function(result){
            console.log("========>LEAVE<========");
            console.log("sub_8B04已经初始化时第一个参数是===>"+this.arg0.readCString());
        }
        }
        )
        }
    })
}
function hook_native(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        if(base_address !=undefined){
        console.log("开始native层hook");
        //定位拦截位置
        var sub_8B04 = base_address.add(0x8B04+1);
        console.log("sub_8b04:",sub_8B04)
        if(sub_8B04!=undefined){
        console.log("进入native层0x8B04");
        }else{
        console.log("拦截器加载失败");
        }
        //使用拦截器
        Interceptor.attach(sub_8B04,{
        //开始进入函数,传入了三个参数依次打印
        onEnter:function(args){
            //保存参数
            this.arg0 = args[0];
            this.arg1 = args[1];
            this.arg2 = args[2];
 
            console.log("========>ENTER<========");
            console.log("sub_8B04未初始化时第一个参数是===>"+this.arg0.readCString());
            console.log("sub_8B04未初始化时第二个参数是===>"+this.arg1.readCString());
            console.log("sub_8B04未初始化时第三个参数是===>"+this.arg2.readCString());           
        },
        onLeave:function(result){
            console.log("========>LEAVE<========");
            console.log("sub_8B04已经初始化时第一个参数是===>"+this.arg0.readCString());
        }
        }
        )
        }
    })
}
sub_8B04未初始化时第一个参数是===>
sub_8B04未初始化时第二个参数是===>xVjHx-D&nji8i*rBZ)j
sub_8B04未初始化时第三个参数是===>0x13(传入参数的字符串大小)
sub_8B04已经初始化时第一个参数是===>`!^fZFrxI^q~[+\~p<yT#p~F==
sub_8B04未初始化时第一个参数是===>
sub_8B04未初始化时第二个参数是===>xVjHx-D&nji8i*rBZ)j
sub_8B04未初始化时第三个参数是===>0x13(传入参数的字符串大小)
sub_8B04已经初始化时第一个参数是===>`!^fZFrxI^q~[+\~p<yT#p~F==
function hook_native_sub_8B04(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        if(base_address !=undefined){
        console.log("开始native层hook");
        //定位拦截位置
        var sub_8B04 = base_address.add(0x8B04+1);
        if(sub_8B04){
        console.log("进入native层0x8B04");
    }else{
        console.log("拦截器加载失败");
    }
        //使用拦截器
        Interceptor.attach(sub_8B04,{
        //开始进入函数,传入了三个参数依次打印
        onEnter:function(args){
 
            //保存第一个参数
            this.arg0 = args[0];
            this.arg1 = args[1];
            this.arg2 = args[2];
            console.log("========>ENTER<========");
            // console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg0,{length:32,header:false}));
            // console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg1,{length:32,header:false}));
            //console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg2,{length:32,header:false}));
            var hook_aAyzpq23ijrtffg = base_address.add(0x1B000);
            if(hook_aAyzpq23ijrtffg!=undefined){console.log("aAyzpq23ijrtffg进入8B04的形状=====>"+hexdump(hook_aAyzpq23ijrtffg))};
     
 
 
        },
        onLeave:function(result){
            console.log("========>LEAVE<========");
            console.log("sub_8B04第一个参数处理后======>"+hexdump(this.arg0)); //打印处理后的第一个参数
            //console.log("sub_8B04得到的结果是====>"+result.readCString());
            // console.log("sub_8B04处理后第一个参数是===>"+hexdump(this.arg0,{length:32,header:false}));
            console.log("sub_8B04处理后时第一个参数是===>"+result);
            // console.log("sub_8B04处理后时第一个参数是===>"+hexdump(this.arg2,{length:32,header:false}));
 
        }
        })
        }
    })
}
function hook_native_sub_8B04(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        if(base_address !=undefined){
        console.log("开始native层hook");
        //定位拦截位置
        var sub_8B04 = base_address.add(0x8B04+1);
        if(sub_8B04){
        console.log("进入native层0x8B04");
    }else{
        console.log("拦截器加载失败");
    }
        //使用拦截器
        Interceptor.attach(sub_8B04,{
        //开始进入函数,传入了三个参数依次打印
        onEnter:function(args){
 
            //保存第一个参数
            this.arg0 = args[0];
            this.arg1 = args[1];
            this.arg2 = args[2];
            console.log("========>ENTER<========");
            // console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg0,{length:32,header:false}));
            // console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg1,{length:32,header:false}));
            //console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg2,{length:32,header:false}));
            var hook_aAyzpq23ijrtffg = base_address.add(0x1B000);
            if(hook_aAyzpq23ijrtffg!=undefined){console.log("aAyzpq23ijrtffg进入8B04的形状=====>"+hexdump(hook_aAyzpq23ijrtffg))};
     
 
 
        },
        onLeave:function(result){
            console.log("========>LEAVE<========");
            console.log("sub_8B04第一个参数处理后======>"+hexdump(this.arg0)); //打印处理后的第一个参数
            //console.log("sub_8B04得到的结果是====>"+result.readCString());
            // console.log("sub_8B04处理后第一个参数是===>"+hexdump(this.arg0,{length:32,header:false}));
            console.log("sub_8B04处理后时第一个参数是===>"+result);
            // console.log("sub_8B04处理后时第一个参数是===>"+hexdump(this.arg2,{length:32,header:false}));
 
        }
        })
        }
    })
}
function hook_js(){
    Java.perform(function(){
    var enrandomcode = Java.use("com.kanxue.algorithmbase.MainActivity")
    //如果定义好了
    if(enrandomcode !=undefined)
        {
          console.log("开始JAVA层Hook");
          enrandomcode.encodeFromJni_12.implementation = function(intput){
            var res = this.encodeFromJni_12(intput);
            console.log("传入参数是====>"+intput);
            console.log("加密后的参数是====>"+res);
            return res;
          }
           
        }
 
    })
 
}
 
function hook_native(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        if(base_address !=undefined){
        console.log("开始native层hook");
        //定位拦截位置
        var sub_8B04 = base_address.add(0x8B04+1);
        console.log("sub_8b04:",sub_8B04)
        if(sub_8B04){
        console.log("进入native层0x8B04");
        }else{
        console.log("拦截器加载失败");
        }
        //使用拦截器
        Interceptor.attach(sub_8B04,{
        //开始进入函数,传入了三个参数依次打印
        onEnter:function(args){
 
            //保存第一个参数
            this.arg0 = args[0];
            this.arg1 = args[1];
            this.arg2 = args[2];
 
            console.log("========>ENTER<========");
            // console.log("sub_8B04未初始化时第一个参数是===>"+this.arg0.readCString());
            // console.log("sub_8B04未初始化时第二个参数是===>"+this.arg1.readCString());
            //console.log("sub_8B04未初始化时第三个参数是===>"+hexdump(this.arg2,{length:64,header:false}));
            var hook_aAyzpq23ijrtffg = base_address.add(0x1B000);
             
            if(hook_aAyzpq23ijrtffg!=undefined){console.log("aAyzpq23ijrtffg进入8B04的形状=====>"+hook_aAyzpq23ijrtffg.readCString().length())};
 
             
        },
        onLeave:function(result){
            console.log("========>LEAVE<========");
            // console.log("sub_8B04已经初始化时第一个参数是===>"+hexdump(this.arg0,{length:64,header:false}));
            // console.log("sub_8B04已经初始化时第二个参数是===>"+hexdump(this.arg1,{length:64,header:false}));
            //console.log("sub_8B04已经初始化时第三个参数是===>"+hexdump(this.arg2,{length:64,header:false}));
        }
        }
        )
        }
    })
}
 
function hookencodeFromJni(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        var base_address_method = Module.findExportByName("libnative-lib.so","Java_com_kanxue_algorithmbase_MainActivity_encodeFromJni_112")
        if(base_address_method!=undefined)
        {
            console.log("=======>进入初始界面进行Hook<=======");
            //使用拦截器
            Interceptor.attach(base_address_method,{
                onEnter:function(args){
                    //打印我们想要的param1和param2
                    // console.log("args[0]===>"+args[0]);
                    // console.log("args[1]===>"+args[1]);
                     
                    // console.log("args[2]===>"+args[2]);
                    // console.log("args[3]===>"+args[3]);
                    var hook_aAyzpq23ijrtffghijklmn = base_address.add(0x1B000+1);
                    console.log("aAyzpq23ijrtffghijklmn在导出函数里面=====>"+hook_aAyzpq23ijrtffghijklmn.readCString());
                     
                },
                onLeave:function(nreval){
                    nreval.replace(0);
                    console.log(nreval);
                }
 
            })
 
        }
 
    })
 
 
}
 
 
function hook_native_sub_8B04(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        if(base_address !=undefined){
        console.log("开始native层hook");
        //定位拦截位置
        var sub_8B04 = base_address.add(0x8B04+1);
        if(sub_8B04){
        console.log("进入native层0x8B04");
    }else{
        console.log("拦截器加载失败");
    }
        //使用拦截器
        Interceptor.attach(sub_8B04,{
        //开始进入函数,传入了三个参数依次打印
        onEnter:function(args){
 
            //保存第一个参数
            this.arg0 = args[0];
            this.arg1 = args[1];
            this.arg2 = args[2];
            console.log("========>ENTER<========");
            // console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg0,{length:32,header:false}));
            // console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg1,{length:32,header:false}));
            //console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg2,{length:32,header:false}));
            var hook_aAyzpq23ijrtffg = base_address.add(0x1B000);
            if(hook_aAyzpq23ijrtffg!=undefined){console.log("aAyzpq23ijrtffg进入8B04的形状=====>"+hexdump(hook_aAyzpq23ijrtffg))};
     
 
 
        },
        onLeave:function(result){
            console.log("========>LEAVE<========");
            console.log("sub_8B04第一个参数处理后======>"+hexdump(this.arg0)); //打印处理后的第一个参数
            //console.log("sub_8B04得到的结果是====>"+result.readCString());
            // console.log("sub_8B04处理后第一个参数是===>"+hexdump(this.arg0,{length:32,header:false}));
            console.log("sub_8B04处理后时第一个参数是===>"+result);
            // console.log("sub_8B04处理后时第一个参数是===>"+hexdump(this.arg2,{length:32,header:false}));
 
        }
        })
        }
    })
}
 
 
 
 
 
function main(){
 
    hook_js();
    hook_native_sub_8B04()
    hook_native();
    hookencodeFromJni()
}
 
setImmediate(main);
function hook_js(){
    Java.perform(function(){
    var enrandomcode = Java.use("com.kanxue.algorithmbase.MainActivity")
    //如果定义好了
    if(enrandomcode !=undefined)
        {
          console.log("开始JAVA层Hook");
          enrandomcode.encodeFromJni_12.implementation = function(intput){
            var res = this.encodeFromJni_12(intput);
            console.log("传入参数是====>"+intput);
            console.log("加密后的参数是====>"+res);
            return res;
          }
           
        }
 
    })
 
}
 
function hook_native(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        if(base_address !=undefined){
        console.log("开始native层hook");
        //定位拦截位置
        var sub_8B04 = base_address.add(0x8B04+1);
        console.log("sub_8b04:",sub_8B04)
        if(sub_8B04){
        console.log("进入native层0x8B04");
        }else{
        console.log("拦截器加载失败");
        }
        //使用拦截器
        Interceptor.attach(sub_8B04,{
        //开始进入函数,传入了三个参数依次打印
        onEnter:function(args){
 
            //保存第一个参数
            this.arg0 = args[0];
            this.arg1 = args[1];
            this.arg2 = args[2];
 
            console.log("========>ENTER<========");
            // console.log("sub_8B04未初始化时第一个参数是===>"+this.arg0.readCString());
            // console.log("sub_8B04未初始化时第二个参数是===>"+this.arg1.readCString());
            //console.log("sub_8B04未初始化时第三个参数是===>"+hexdump(this.arg2,{length:64,header:false}));
            var hook_aAyzpq23ijrtffg = base_address.add(0x1B000);
             
            if(hook_aAyzpq23ijrtffg!=undefined){console.log("aAyzpq23ijrtffg进入8B04的形状=====>"+hook_aAyzpq23ijrtffg.readCString().length())};
 
             
        },
        onLeave:function(result){
            console.log("========>LEAVE<========");
            // console.log("sub_8B04已经初始化时第一个参数是===>"+hexdump(this.arg0,{length:64,header:false}));
            // console.log("sub_8B04已经初始化时第二个参数是===>"+hexdump(this.arg1,{length:64,header:false}));
            //console.log("sub_8B04已经初始化时第三个参数是===>"+hexdump(this.arg2,{length:64,header:false}));
        }
        }
        )
        }
    })
}
 
function hookencodeFromJni(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        var base_address_method = Module.findExportByName("libnative-lib.so","Java_com_kanxue_algorithmbase_MainActivity_encodeFromJni_112")
        if(base_address_method!=undefined)
        {
            console.log("=======>进入初始界面进行Hook<=======");
            //使用拦截器
            Interceptor.attach(base_address_method,{
                onEnter:function(args){
                    //打印我们想要的param1和param2
                    // console.log("args[0]===>"+args[0]);
                    // console.log("args[1]===>"+args[1]);
                     
                    // console.log("args[2]===>"+args[2]);
                    // console.log("args[3]===>"+args[3]);
                    var hook_aAyzpq23ijrtffghijklmn = base_address.add(0x1B000+1);
                    console.log("aAyzpq23ijrtffghijklmn在导出函数里面=====>"+hook_aAyzpq23ijrtffghijklmn.readCString());
                     
                },
                onLeave:function(nreval){
                    nreval.replace(0);
                    console.log(nreval);
                }
 
            })
 
        }
 
    })
 
 
}
 
 
function hook_native_sub_8B04(){
    Java.perform(function(){
        var base_address = Module.getBaseAddress("libnative-lib.so");
        if(base_address !=undefined){
        console.log("开始native层hook");
        //定位拦截位置
        var sub_8B04 = base_address.add(0x8B04+1);
        if(sub_8B04){
        console.log("进入native层0x8B04");
    }else{
        console.log("拦截器加载失败");
    }
        //使用拦截器
        Interceptor.attach(sub_8B04,{
        //开始进入函数,传入了三个参数依次打印
        onEnter:function(args){
 
            //保存第一个参数
            this.arg0 = args[0];
            this.arg1 = args[1];
            this.arg2 = args[2];
            console.log("========>ENTER<========");
            // console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg0,{length:32,header:false}));
            // console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg1,{length:32,header:false}));
            //console.log("sub_8B04未初始化时第一个参数是===>"+hexdump(this.arg2,{length:32,header:false}));

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

最后于 2023-11-5 13:47 被4Chan编辑 ,原因:
收藏
免费 10
支持
分享
最新回复 (4)
雪    币: 3525
活跃值: (31011)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2023-11-5 15:23
1
雪    币: 2899
活跃值: (1646)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
冯哥厉害!
2023-11-5 17:23
0
雪    币: 3
活跃值: (326)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
支持楼主。
2023-11-6 09:44
0
雪    币: 1229
活跃值: (1765)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享
2023-11-6 18:53
0
游客
登录 | 注册 方可回帖
返回
//