你能从本文中学到apk中的so层简单算法还原以及使用js和python还原C代码的部分细节
题目链接
链接:https://pan.baidu.com/s/1HbkzNZqIQYj6rwDpSYt_aQ
提取码:1234
使用jadx
打开algorithmbase_10.apk
使用Frida
获取先生成的随机字符串
传入的随机字符串和字符串在Native层加密后的结果如下
我们进入Native
层查看加密后的结果
使用unzip
命令解压apk
获取so
文件
unzip algorithmbase_10.apk -d fileso10
使用Ida
打开so
文件,在Export
表输入JNI
查看加密函数的位置
使用快捷键Y
和N
修改传入的参数名称,以便我们方便我们后续分析
返回值是v13
我们从下往上回溯来到 sub_EE38(v9, v10, v11)
函数
使用Frida
对sub_EE38
函数进行hook
,目的是为了查看传入的参数和传出的参数
脚本如下
点击app按钮,Hook的代码如下所示
我们获取到如下参数
也就是说 sub_EE38
就是我们找的加密call
我们不妨进入sub_EE38
查看加密细节
根据call,还原加密算法
用C代码还原加密算法如下
还原得到加密结果
使用JS还原加密算法如下
使用Python还原算法如下
algorithmbase_12.apk
使用apkInfo打开发现是32位程序
分析如图,先生成随机字符串(我们可以通过Hook
encodeFromJni_12
函数来查看生成的随机字符串的值),然后把生成的随机字符串丢到encodeFromJni_12
里面处理
我们先Hook一下encodeFromJni_12
函数,查看加密前的字符串和加密后的字符串
结果如下
加密的结果看起来很像是Base64
,我们用64编码后的结果对比一下
不是64编码,但是结果很像。猜测可能是换了码表或并非完全的base64
加密
打开IDA
,来到加密函数Java_com_kanxue_algorithmbase_MainActivity_encodeFromJni_112(int a1, int a2, int a3, char *a4)
里面 进行分析
从下往上回溯,定位到sub_8B04
函数
进行hook
这里有个坑,就是在使用拦截器对sub_8B04
位置进行定位,如果使用var sub_8B04 = base_address.add(0x8B04);
拦截出错就加一
这样才能进入函数里面
hook代码如下
hook显示的结果如下
使用IDA
对libnative-lib.so
进行动态调试的时候会发现 aAyzpq23ijrtffg
字符串和我们之前记录的字符串(aAyzpq23ijrtffg DCB "AYZpq23IJrTFfghijklCDE1KLMmBdestU5678GHz0cuvwabN9+/VWXnoOPQRSxy4",0
)并不相同,结合前面的思考,换了码表可能性更大
我们开始hook
aAyzpq23ijrtffg
码表(0x1B000
),这个有个hook
技巧: 复制使用readCString
打印字符串 可能会造成数据丢失,所以我们使用hexdump
(16进制)显示码表的内容会更精确
hook代码如下
码表果然发生改变
看看是不是只是简单换了码表,其他地方有没有进行加密
是的,和猜测的结果完全一致!
再来看看码表是在哪个位置发生改变的,在sub_8ABC
找到码表发生变化的位置,并且发现传参(a1)就是加密前的字符串被int强转
完整的hook代码如下
使用C++还原加密流程
使用JS对加密算法进行还原
使用python还原加密流程
algorithmbase_13.apk
使用JADX
打开apk
文件
通过调用MainActivity类中的encodeFromJni_12方法,将randomAscii字符串进行加密,并将加密后的结果存储在encodeFromJni_12字符串中。然后,使用Log.e方法将randomAscii字符串和加密后的结果一起打印出来,以便进行调试和分析。
使用IDA
打开,按照以前的思路继续从下往上分析
按照第二题的思路,来到sub_8B04
发现和上一题加密没啥区别就只是多了和参数a3
的异或
使用Frida Hook
一下传入参数和传出参数
hook的结果更加验证了我们的思路
直接开始还原算法验证
C++代码如下
JS代码如下
python代码如下
C++的函数传参是如果char数组,当使用JS
对其进行还原时候,为了方便后面字符串型参数在JS
中计算字符串偏移,最好把字符串转为8位无符号整型数组Uint8Array(对应是C++
中的(unsigned char*
))
如下
这么看不太直观。拿刚才的第三题举例
C++中
这里面str1是char数组被强转为整型当成传参进入的sub_8B04
函数
但在JS
中,我们进入sub_8B04
就是传参str是字符串,不需要变整型
为了方便后面的字节偏移计算,我们再把字符串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进行异或运算,然后转为字符串如下
function
hook_js(){
Java.perform(
function
(){
var
m_randomAscii = Java.use(
"com.kanxue.algorithmbase.MainActivity"
)
if
(m_randomAscii!=undefined){
console.log(
"开始Hook"
);
m_randomAscii.encodeFromJni_11.implementation =
function
(input){
var
res =
this
.encodeFromJni_11(input);
console.log(
"input:==>"
+input);
console.log(
"res:==>"
+res);
return
res;
}
}
})
}
function
main(){
hook_js();
}
setImmediate(main);
function
hook_js(){
Java.perform(
function
(){
var
m_randomAscii = Java.use(
"com.kanxue.algorithmbase.MainActivity"
)
if
(m_randomAscii!=undefined){
console.log(
"开始Hook"
);
m_randomAscii.encodeFromJni_11.implementation =
function
(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"
)
if
(m_randomAscii!=undefined){
console.log(
"开始Hook"
);
m_randomAscii.encodeFromJni_11.implementation =
function
(input){
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"
)
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"
)
if
(m_randomAscii!=undefined){
console.log(
"开始Hook"
);
m_randomAscii.encodeFromJni_11.implementation =
function
(input){
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"
)
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;
_BYTE *v4;
unsigned
__int8
*v5;
unsigned
__int64
v6;
_BYTE *v7;
__int64
v8;
char
v9;
__int64
v10;
__int64
result;
if
(a3 - 2 < 1)
{
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];
v4[1] = aAyzabfghz0cmbd[(16 * (unsigned
int
)*v5) & 0x30LL | ((unsigned
__int64
)v5[1] >> 4)];
v4[2] = aAyzabfghz0cmbd[(4 * (unsigned
int
)v5[1]) & 0x3CLL | ((unsigned
__int64
)v5[2] >> 6)];
LOBYTE(v6) = aAyzabfghz0cmbd[v5[2] & 0x3F];
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];
v8 = (16 * (unsigned
int
)*(unsigned
__int8
*)(a2 + (unsigned
int
)v3)) & 0x30LL;
if
((_DWORD)v3 == a3 - 1)
{
v7[1] = aAyzabfghz0cmbd[v8];
v9 = 61;
}
else
{
v10 = a2 + (unsigned
int
)v3;
v7[1] = aAyzabfghz0cmbd[v8 | ((unsigned
__int64
)*(unsigned
__int8
*)(v10 + 1) >> 4)];
v9 = aAyzabfghz0cmbd[(4 * (unsigned
int
)*(unsigned
__int8
*)(v10 + 1)) & 0x3CLL];
}
v7[2] = v9;
v7[3] = 61;
v7 += 4;
LABEL_11:
result = (unsigned
int
)((_DWORD)v7 - (_DWORD)a1 + 1);
*v7 = 0;
return
result;
}
__int64
__fastcall sub_EE38(_BYTE *a1,
__int64
a2,
int
a3)
{
__int64
v3;
_BYTE *v4;
unsigned
__int8
*v5;
unsigned
__int64
v6;
_BYTE *v7;
__int64
v8;
char
v9;
__int64
v10;
__int64
result;
if
(a3 - 2 < 1)
{
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];
v4[1] = aAyzabfghz0cmbd[(16 * (unsigned
int
)*v5) & 0x30LL | ((unsigned
__int64
)v5[1] >> 4)];
v4[2] = aAyzabfghz0cmbd[(4 * (unsigned
int
)v5[1]) & 0x3CLL | ((unsigned
__int64
)v5[2] >> 6)];
LOBYTE(v6) = aAyzabfghz0cmbd[v5[2] & 0x3F];
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];
v8 = (16 * (unsigned
int
)*(unsigned
__int8
*)(a2 + (unsigned
int
)v3)) & 0x30LL;
if
((_DWORD)v3 == a3 - 1)
{
v7[1] = aAyzabfghz0cmbd[v8];
v9 = 61;
}
else
{
v10 = a2 + (unsigned
int
)v3;
v7[1] = aAyzabfghz0cmbd[v8 | ((unsigned
__int64
)*(unsigned
__int8
*)(v10 + 1) >> 4)];
v9 = aAyzabfghz0cmbd[(4 * (unsigned
int
)*(unsigned
__int8
*)(v10 + 1)) & 0x3CLL];
}
v7[2] = v9;
v7[3] = 61;
v7 += 4;
LABEL_11:
result = (unsigned
int
)((_DWORD)v7 - (_DWORD)a1 + 1);
*v7 = 0;
return
result;
}
#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;
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;
}
#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;
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
=
=
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
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
if
__name__
=
=
'__main__'
:
print
(sub_EE38("
","
meUx3DppB
%
Gj]
-
2J
",
0x10
))
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_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;
}
}
})
}
传入参数是
=
=
=
=
>xVjHx
-
D&nji8i
*
rBZ)j
加密后的参数是
=
=
=
=
>`!^fZFrxI^q~[
+
\~p<yT
传入参数是
=
=
=
=
>xVjHx
-
D&nji8i
*
rBZ)j
加密后的参数是
=
=
=
=
>`!^fZFrxI^q~[
+
\~p<yT
_BYTE *__fastcall sub_8B04(
int
a1,
int
a2,
int
a3)
{
int
v3;
int
v6;
int
v7;
_BYTE *v8;
int
v9;
unsigned
int
v10;
char
v11;
int
v12;
char
v13;
v3 = a3 - 2;
v6 = 0;
v7 = 0;
while
( 1 )
{
v8 = (_BYTE *)(a1 + v6);
if
( v7 >= v3 )
break
;
v9 = a2 + v7;
v6 += 4;
*v8 = aAyzpq23ijrtffg[*(unsigned
__int8
*)(a2 + v7) >> 2];
v10 = *(unsigned
__int8
*)(a2 + v7 + 1);
v11 = *(_BYTE *)(a2 + v7);
v7 += 3;
v8[1] = aAyzpq23ijrtffg[(v10 >> 4) & 0xFFFFFFCF | (16 * (v11 & 3))];
v8[2] = aAyzpq23ijrtffg[(*(unsigned
__int8
*)(v9 + 2) >> 6) & 0xFFFFFFC3 | (4 * (*(_BYTE *)(v9 + 1) & 0xF))];
v8[3] = aAyzpq23ijrtffg[*(_BYTE *)(v9 + 2) & 0x3F];
}
if
( v7 < a3 )
{
*v8 = aAyzpq23ijrtffg[*(unsigned
__int8
*)(a2 + v7) >> 2];
v12 = (16 * *(unsigned
__int8
*)(a2 + v7)) & 0x30;
if
( a3 - 1 == v7 )
{
v13 = 61;
v8[1] = aAyzpq23ijrtffg[v12];
}
else
{
v8[1] = aAyzpq23ijrtffg[v12 | (*(unsigned
__int8
*)(a2 + v7 + 1) >> 4)];
v13 = aAyzpq23ijrtffg[4 * (*(_BYTE *)(a2 + v7 + 1) & 0xF)];
}
v8[3] = 61;
v8[2] = v13;
v8 += 4;
}
*v8 = 0;
return
&v8[-a1 + 1];
}
_BYTE *__fastcall sub_8B04(
int
a1,
int
a2,
int
a3)
{
int
v3;
int
v6;
int
v7;
_BYTE *v8;
int
v9;
unsigned
int
v10;
char
v11;
int
v12;
char
v13;
v3 = a3 - 2;
v6 = 0;
v7 = 0;
while
( 1 )
{
v8 = (_BYTE *)(a1 + v6);
if
( v7 >= v3 )
break
;
v9 = a2 + v7;
v6 += 4;
*v8 = aAyzpq23ijrtffg[*(unsigned
__int8
*)(a2 + v7) >> 2];
v10 = *(unsigned
__int8
*)(a2 + v7 + 1);
v11 = *(_BYTE *)(a2 + v7);
v7 += 3;
v8[1] = aAyzpq23ijrtffg[(v10 >> 4) & 0xFFFFFFCF | (16 * (v11 & 3))];
v8[2] = aAyzpq23ijrtffg[(*(unsigned
__int8
*)(v9 + 2) >> 6) & 0xFFFFFFC3 | (4 * (*(_BYTE *)(v9 + 1) & 0xF))];
v8[3] = aAyzpq23ijrtffg[*(_BYTE *)(v9 + 2) & 0x3F];
}
if
( v7 < a3 )
{
*v8 = aAyzpq23ijrtffg[*(unsigned
__int8
*)(a2 + v7) >> 2];
v12 = (16 * *(unsigned
__int8
*)(a2 + v7)) & 0x30;
if
( a3 - 1 == v7 )
{
v13 = 61;
v8[1] = aAyzpq23ijrtffg[v12];
}
else
{
v8[1] = aAyzpq23ijrtffg[v12 | (*(unsigned
__int8
*)(a2 + v7 + 1) >> 4)];
v13 = aAyzpq23ijrtffg[4 * (*(_BYTE *)(a2 + v7 + 1) & 0xF)];
}
v8[3] = 61;
v8[2] = v13;
v8 += 4;
}
*v8 = 0;
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
sub_8B04未初始化时第一个参数是
=
=
=
>
sub_8B04未初始化时第二个参数是
=
=
=
>xVjHx
-
D&nji8i
*
rBZ)j
sub_8B04未初始化时第三个参数是
=
=
=
>
0x13
(传入参数的字符串大小)
sub_8B04已经初始化时第一个参数是
=
=
=
>`!^fZFrxI^q~[
+
\~p<yT
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<========"
);
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);
}
})
}
})
}
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<========"
);
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);
}
})
}
})
}
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<========"
);
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<========"
);
}
}
)
}
})
}
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){
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<========"
);
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);
}
})
}
})
}
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<========"
);
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<========"
);
}
}
)
}
})
}
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){
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<========"
);
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2023-11-5 13:47
被4Chan编辑
,原因: