这篇文章详细介绍了解决OWASP人员(Bernhard Mueller)发布的Android crackme
程序(owasp uncrackable)的几种方法。
链接:https://pan.baidu.com/s/1VJ7Y3psWoSi5NnlOpaohEw
提取码:1234
在owasp uncrackable
能够找到的安全机制:
Java层的反编译工具(Dalvik bytecode
):
So层
反编译程序:
动态二进制检测框架:
编译工具
使用Jadx
反编译工具打开apk
如下所示
来到MainActivity
入口
猜测会有root
权限的检测工具,顺着这个猜测,我们可以有两种思路解决这个root
检测
继续往下看
我们进入a
类
进入后,内容如下
经过观察,发现如果成功返回equals
(true
),就能suceeful
,由于没有涉及到so
层(没看到native
),所以我们直接在Java
层进行代码分析
手写一下伪代码
java
js实现上述java
函数
java
使用js
完成java
的功能
类如下
这个时候,我们综合之前的分析
可以写出java
脚本
js
脚本
跑出的结果是
就是我们想要的flag
注意,此时并没有绕过root
检测,就已经完成了分析过程,但为了尊重开发者,我们按照之前的两个思路进行解题
把smali文件丢到其他目录下,方便我们接下来使用AS导入
丢到H
盘,把smail
修改该名字为src
在AS
(Android Studio
下面统称AS)导入smalidea-0.06.zip
导入后会提示重启AS
重启AS
,然后开始进行下面修改
如果没有找到smail Files
说明在第三步(AS(Android Studio
下面统称AS)导入smalidea-0.06.zip
)出错,错误原因可能是当前AS的版本太低(低于4.0
)应该使用smalidea-0.05.zip
或者是当前AS
版本(高于4.0
)较高,但导入了低版本的smalidea-0.05.zip
新建项目,导入文件smail
文件
在Oncreate
函数下断点
运行如下
<img src="upload/attach/202310/940967_RFDNEHHANPPKYHD.png" alt="image-20231024110212864" style="zoom:50%;" />
这里是8980
使用adb
命令 转发本地端口
设置远程调试
点击右上方 AddConfiguration ...
点击Remote JVM Debug
设置端口8800
和名字app1
选择设备,并开始调试
由于root
检测,远程调试无法进入OnCreated
界面,所以选择直接看smaile
源码
思路是:直接在smail
层绕过Root
和debug
检测
来到smail
代码层需要修改绕过(Root
函数代码)代码如下
修改完后使用killer
重新编译一下
安装apk
到手机,显示已经没有root
检测窗口了
这个时候可以开启动态调试了,如图
按照这个思路,我们也可以直接跳转到登录成功的界面,修改的smail
代码如下
重新编译,无论输入什么都能成功登录
没什么好说的,直接hook
一把梭
速战速决
思路:绕过JAVA层的root
检测
右键复制frida
代码
把代码丢到vscode
一把梭
使用命令frida -U -l 11.js -f owasp.mstg.uncrackable2
于是我们过了root
检测
在使用JNI
在native
层调用了bar
函数,直接开始在so
分析
把so
丢ida
中,然后查看左边的字符栏,输入关键字bar
我们点进去,然后F5
反汇编
flag
直接出来
flag:Thanks for all the fish
题目难度变大
把apk
丢到JADX-GUI
查看MainActivity
界面
简化一下界面如下
得到的信息
由于CRC
校验和比较弱,我们也许能通过修改反编译得到的函数和native
层中的函数,直接绕过所有安全的检测
三个检测root
函数来检测设备是否可能存在root
权限
unzip xxx.apk -d fileso(文件夹名)
,进行解压
丢到ida
进行静态分析,结合jadx
,会发现so
层有个init
函数对字符数组(由private static final String xorkey = "pizzapizzapizzapizzapizz"
字符串得到字节数组)进行处理
ida里面搜索Init
反编译一下
看到这里的思路是,能不能用动态ida
调试查看一下,不过我们继续静态分析
这里介绍一下JNI
调用Java
方法的传参逻辑
用frida
脚本演示可能更加直观一些
根据上面的知识,我们在Java_sg_vantagepoint_uncrackable3_MainActivity_init
(init
),对传入参数的名字进行修改(选中参数,快捷键n)
因为传入的a3
是我们在jadx
看到的字节数组(pizzapizzapizzapizzapizz
)
所以result
肯定和前面的字节数组(pizzapizzapizzapizzapizz
)有关(具体情况目前不明朗)
思路中断不妨查看一下启动时的so
时候的ELF
文件,该部分执行程序启动时候的函数指针(JNI
)
其中的.init_array
里面sub_31B0
的引起了注意,点击进入
反编译
大概意思是sub_30D0
创建了一个线程,线程调用了sub_30D0
来里面是否有frida
和xpose
检测
绕过这个函数可以通过hook pthread_create
来阻止进程的创建来进行绕过也可以通过hooksub_30D0
进行绕过
在这里选择后者
这里先贴一下相关知识点
linker64 是 Android 64 位系统中的动态链接器,它负责加载和链接共享库,以及解析符号引用,使得程序能够正确执行。在 Android 系统中,linker64 是一个重要的组件,它在应用程序启动时被调用,负责加载应用程序所需的共享库,并建立共享库之间的依赖关系。
linker64 的主要功能包括:
在 Android 64 位系统中,init_array 一般会被 linker64 中的 call_array 函数调用。call_array 函数负责遍历共享库中的 init_array 段,并依次执行其中的函数指针所指向的初始化函数。它会在动态链接器加载共享库时被调用,确保在程序启动时执行这些初始化函数。
由于反调试函数(sub_30D0
)启动线程是在init_array
中,而so
层的init_array
都是被linker64
中的call_array
调用,所以我们直接去Hooklinker64 call_array
,在这之前需要动态调试so获得linker64 call_array
的地址
点击OK
弹出一个列表框,search
搜素app
的包名
我们在右边的Module
板块搜索我们在IDA
之前找到的重要call
或者so的关键字,会发现有时候根本搜索不到
因为没有F9
加载
原因如下
ida pro附加成功之后,会先调到其他so,比如libc.so这些,这个时候,需要先f9跳过,等没得跳之后,才需要执行jdb。
按F9
加载就行
搜索Module
: linker64
在Module
: linker64
下搜索call_array
记录一下call_array
地址0000007D68B58764
减去linker64
的基地址(7D68B38000
) =00020764
(偏移地址)
开始编写frida
的Hook
脚本
运行之后发现仍然存在检测,继续往下分析 native
层的init
函数
我们查看sub_323C
的调用次数以便把握Hook
时机(选中函数后按下x
查看引用次数)
只调用了一次,由于sub_323C
只在init
函数中,init
函数在apk
启动(oncreate
)才被调用,所以我们选择在libfool.so
加载的时候进行Hook
,libfoo.so
是apk
在java
层调用System.loadLibrary("foo")
进行加载,调用的底层逻辑是通过libandroid_runtime.so
的android_dlopen_ext
来加载的so
具体的调用逻辑如下:
需要注意的是,android_dlopen_ext
函数是Android Runtime
中的一个函数,用于加载动态链接库。它是通过JNI接口提供给应用程序使用的。在调用android_dlopen_ext
函数之前,应用程序需要先加载libandroid_runtime.so
,并通过JNI接口导入android_dlopen_ext
函数。这样才能在Java
层调用android_dlopen_ext
函数,并实现加载libfoo.so
的功能。
根据这些信息, 继续编写Frida
脚本
开始过java
层的root
检测
直接选择checkRoot1
右键获取Frida
脚本
添加到我们的之前的脚本上,返回false
简单概括一下,bar
函数通过生成key1和字符串pizzapizzapizzapizzapizz
进行异或来获取新的字符串,我们的思路就是hook
生成key1
函数(v6 = sub_10E0(v9);
)得到key1,再和"pizzapizzapizzapizzapizz"
进行异或
完整脚本如下
分析结束
public
void
verify(View view) {
String str;
String obj = ((EditText) findViewById(R.id.edit_text)).getText().toString();
AlertDialog create =
new
AlertDialog.Builder(
this
).create();
if
(a.a(obj)) {
create.setTitle(
"Success!"
);
str =
"This is the correct secret."
;
}
else
{
create.setTitle(
"Nope..."
);
str =
"That's not it. Try again."
;
}
create.setMessage(str);
create.setButton(-
3
,
"OK"
,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialogInterface,
int
i) {
dialogInterface.dismiss();
}
});
create.show();
}
public
void
verify(View view) {
String str;
String obj = ((EditText) findViewById(R.id.edit_text)).getText().toString();
AlertDialog create =
new
AlertDialog.Builder(
this
).create();
if
(a.a(obj)) {
create.setTitle(
"Success!"
);
str =
"This is the correct secret."
;
}
else
{
create.setTitle(
"Nope..."
);
str =
"That's not it. Try again."
;
}
create.setMessage(str);
create.setButton(-
3
,
"OK"
,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialogInterface,
int
i) {
dialogInterface.dismiss();
}
});
create.show();
}
public
class
a {
public
static
boolean
a(String str) {
byte
[] bArr;
byte
[] bArr2 =
new
byte
[
0
];
try
{
bArr = sg.vantagepoint.a.a.a(b(
"8d127684cbc37c17616d806cf50473cc"
), Base64.decode(
"5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc="
,
0
));
}
catch
(Exception e) {
Log.d(
"CodeCheck"
,
"AES error:"
+ e.getMessage());
bArr = bArr2;
}
return
str.equals(
new
String(bArr));
}
public
static
byte
[] b(String str) {
int
length = str.length();
byte
[] bArr =
new
byte
[length /
2
];
for
(
int
i =
0
; i < length; i +=
2
) {
bArr[i /
2
] = (
byte
) ((Character.digit(str.charAt(i),
16
) <<
4
) + Character.digit(str.charAt(i +
1
),
16
));
}
return
bArr;
}
}
public
class
a {
public
static
boolean
a(String str) {
byte
[] bArr;
byte
[] bArr2 =
new
byte
[
0
];
try
{
bArr = sg.vantagepoint.a.a.a(b(
"8d127684cbc37c17616d806cf50473cc"
), Base64.decode(
"5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc="
,
0
));
}
catch
(Exception e) {
Log.d(
"CodeCheck"
,
"AES error:"
+ e.getMessage());
bArr = bArr2;
}
return
str.equals(
new
String(bArr));
}
public
static
byte
[] b(String str) {
int
length = str.length();
byte
[] bArr =
new
byte
[length /
2
];
for
(
int
i =
0
; i < length; i +=
2
) {
bArr[i /
2
] = (
byte
) ((Character.digit(str.charAt(i),
16
) <<
4
) + Character.digit(str.charAt(i +
1
),
16
));
}
return
bArr;
}
}
public
static
byte
[] getdecode(String word){
byte
[] base64decodedBytes = Base64.getDecoder().decode(word);
byte
[] newbase64decodedBytes =Base64.getDecoder().decode(word);
String strcode =
new
String(newbase64decodedBytes);
System.out.println(strcode);
System.out.println(newbase64decodedBytes);
return
base64decodedBytes;
}
public
static
byte
[] getdecode(String word){
byte
[] base64decodedBytes = Base64.getDecoder().decode(word);
byte
[] newbase64decodedBytes =Base64.getDecoder().decode(word);
String strcode =
new
String(newbase64decodedBytes);
System.out.println(strcode);
System.out.println(newbase64decodedBytes);
return
base64decodedBytes;
}
getBase64decode =
function
(){
var
encode =
"5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc="
;
let decrypted = atob(encode);
let base64decodedBytes =
new
Uint8Array(atob(encode).split(
''
).map((char) => char.charCodeAt(0)));
return
base64decodedBytes;
}
getBase64decode =
function
(){
var
encode =
"5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc="
;
let decrypted = atob(encode);
let base64decodedBytes =
new
Uint8Array(atob(encode).split(
''
).map((char) => char.charCodeAt(0)));
return
base64decodedBytes;
}
public
static
byte
[] b(String str) {
int
length = str.length();
byte
[] bArr =
new
byte
[length /
2
];
for
(
int
i =
0
; i < length; i +=
2
) {
bArr[i /
2
] = (
byte
) ((Character.digit(str.charAt(i),
16
) <<
4
) + Character.digit(str.charAt(i +
1
),
16
));
}
return
bArr;
}
public
static
byte
[] b(String str) {
int
length = str.length();
byte
[] bArr =
new
byte
[length /
2
];
for
(
int
i =
0
; i < length; i +=
2
) {
bArr[i /
2
] = (
byte
) ((Character.digit(str.charAt(i),
16
) <<
4
) + Character.digit(str.charAt(i +
1
),
16
));
}
return
bArr;
}
const byte = (x) => ((((x | 0) & 0xff) + 128) % 256) - 128;
Judgment_capitalization =
function
(input){
if
(
'A'
<=input &&input <=
'Z'
){
return
true
;
}
else
return
false
;
}
Determine_whether_to_lower =
function
(input){
if
(
'a'
<=input &&input <=
'z'
){
return
true
;
}
else
return
false
;
}
digit =
function
(input,radis) {
try
{
if
(!isNaN(parseInt(input))) {
if
(parseInt(input) < 10 && parseInt(input) > -1) {
return
parseInt(input) < parseInt(radis) ? parseInt(input) : -1;
}
}
}
catch
(err) {
}
try
{
if
(Judgment_capitalization(input)) {
return
input.charCodeAt(0) < radis +
'A'
.charCodeAt(0) - 10 ? input.charCodeAt(0) -
'A'
.charCodeAt(0) + 10 : -1;
}
}
catch
(err) {
}
try
{
if
(Determine_whether_to_lower(input)) {
return
input.charCodeAt(0) < radis +
'a'
.charCodeAt(0) - 10 ? input.charCodeAt(0) -
'a'
.charCodeAt(0) + 10 : -1;
}
}
catch
(err) {
}
}
b =
function
(paramString){
var
nlength = paramString.length;
var
arrofByte =
new
Int8Array(nlength/2);
for
(
var
i=0;i<nlength;i+=2){
arrofByte[i/2] = (byte)(((digit(paramString.charAt(i),16)<<4)+digit(paramString.charAt(i+1),16)));
}
return
(arrofByte);
}
const byte = (x) => ((((x | 0) & 0xff) + 128) % 256) - 128;
Judgment_capitalization =
function
(input){
if
(
'A'
<=input &&input <=
'Z'
){
return
true
;
}
else
return
false
;
}
Determine_whether_to_lower =
function
(input){
if
(
'a'
<=input &&input <=
'z'
){
return
true
;
}
else
return
false
;
}
digit =
function
(input,radis) {
try
{
if
(!isNaN(parseInt(input))) {
if
(parseInt(input) < 10 && parseInt(input) > -1) {
return
parseInt(input) < parseInt(radis) ? parseInt(input) : -1;
}
}
}
catch
(err) {
}
try
{
if
(Judgment_capitalization(input)) {
return
input.charCodeAt(0) < radis +
'A'
.charCodeAt(0) - 10 ? input.charCodeAt(0) -
'A'
.charCodeAt(0) + 10 : -1;
}
}
catch
(err) {
}
try
{
if
(Determine_whether_to_lower(input)) {
return
input.charCodeAt(0) < radis +
'a'
.charCodeAt(0) - 10 ? input.charCodeAt(0) -
'a'
.charCodeAt(0) + 10 : -1;
}
}
catch
(err) {
}
}
b =
function
(paramString){
var
nlength = paramString.length;
var
arrofByte =
new
Int8Array(nlength/2);
for
(
var
i=0;i<nlength;i+=2){
arrofByte[i/2] = (byte)(((digit(paramString.charAt(i),16)<<4)+digit(paramString.charAt(i+1),16)));
}
return
(arrofByte);
}
public class a {
public static byte[] a(byte[] bArr, byte[] bArr2) {
SecretKeySpec secretKeySpec =
new
SecretKeySpec(bArr,
"AES/ECB/PKCS7Padding"
);
Cipher cipher = Cipher.getInstance(
"AES"
);
cipher.init(2, secretKeySpec);
return
cipher.doFinal(bArr2);
}
}
public class a {
public static byte[] a(byte[] bArr, byte[] bArr2) {
SecretKeySpec secretKeySpec =
new
SecretKeySpec(bArr,
"AES/ECB/PKCS7Padding"
);
Cipher cipher = Cipher.getInstance(
"AES"
);
cipher.init(2, secretKeySpec);
return
cipher.doFinal(bArr2);
}
}
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Base64;
public class AES128ECBwithPKCS7 {
private static final String SECRET =
"AES"
;
private static final String CIPHER_ALGORITHM =
"AES/ECB/PKCS7Padding"
;
public static String newaes256ECBPkcs7PaddingDecrypt(byte[] bArr, byte[] bArr2) throws Exception {
String strbrr =
new
String(bArr);
String strbrr2 =
new
String(bArr2);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,
new
SecretKeySpec(bArr, SECRET));
byte[] doFinal = cipher.doFinal(bArr2);
return
new
String(doFinal);
}
public static byte[] b(String str) {
int length = str.length();
byte[] bArr =
new
byte[length / 2];
for
(int i = 0; i < length; i += 2) {
bArr[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16));
}
System.out.println(bArr);
return
bArr;
}
public static byte[] getdecode(String word) {
byte[] base64decodedBytes = Base64.getDecoder().decode(word);
byte[] newbase64decodedBytes = Base64.getDecoder().decode(word);
String strcode =
new
String(newbase64decodedBytes);
System.out.println(strcode);
System.out.println(newbase64decodedBytes);
return
base64decodedBytes;
}
public static void main(String[] args) throws Exception {
String text = newaes256ECBPkcs7PaddingDecrypt(b(
"8d127684cbc37c17616d806cf50473cc"
), getdecode(
"5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc="
));
System.out.println(text);
}
}
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Base64;
public class AES128ECBwithPKCS7 {
private static final String SECRET =
"AES"
;
private static final String CIPHER_ALGORITHM =
"AES/ECB/PKCS7Padding"
;
public static String newaes256ECBPkcs7PaddingDecrypt(byte[] bArr, byte[] bArr2) throws Exception {
String strbrr =
new
String(bArr);
String strbrr2 =
new
String(bArr2);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,
new
SecretKeySpec(bArr, SECRET));
byte[] doFinal = cipher.doFinal(bArr2);
return
new
String(doFinal);
}
public static byte[] b(String str) {
int length = str.length();
byte[] bArr =
new
byte[length / 2];
for
(int i = 0; i < length; i += 2) {
bArr[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16));
}
System.out.println(bArr);
return
bArr;
}
public static byte[] getdecode(String word) {
byte[] base64decodedBytes = Base64.getDecoder().decode(word);
byte[] newbase64decodedBytes = Base64.getDecoder().decode(word);
String strcode =
new
String(newbase64decodedBytes);
System.out.println(strcode);
System.out.println(newbase64decodedBytes);
return
base64decodedBytes;
}
public static void main(String[] args) throws Exception {
String text = newaes256ECBPkcs7PaddingDecrypt(b(
"8d127684cbc37c17616d806cf50473cc"
), getdecode(
"5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc="
));
System.out.println(text);
}
}
const CryptoJS = require(
'crypto-js'
)
const base = require(
"./Crypted/Base64"
);
const byte = (x) => ((((x | 0) & 0xff) + 128) % 256) - 128;
Judgment_capitalization =
function
(input){
if
(
'A'
<=input &&input <=
'Z'
){
return
true
;
}
else
return
false
;
}
Determine_whether_to_lower =
function
(input){
if
(
'a'
<=input &&input <=
'z'
){
return
true
;
}
else
return
false
;
}
digit =
function
(input,radis) {
try
{
if
(!isNaN(parseInt(input))) {
if
(parseInt(input) < 10 && parseInt(input) > -1) {
return
parseInt(input) < parseInt(radis) ? parseInt(input) : -1;
}
}
}
catch
(err) {
}
try
{
if
(Judgment_capitalization(input)) {
return
input.charCodeAt(0) < radis +
'A'
.charCodeAt(0) - 10 ? input.charCodeAt(0) -
'A'
.charCodeAt(0) + 10 : -1;
}
}
catch
(err) {
}
try
{
if
(Determine_whether_to_lower(input)) {
return
input.charCodeAt(0) < radis +
'a'
.charCodeAt(0) - 10 ? input.charCodeAt(0) -
'a'
.charCodeAt(0) + 10 : -1;
}
}
catch
(err) {
}
}
b =
function
(paramString){
var
nlength = paramString.length;
var
arrofByte =
new
Int8Array(nlength/2);
for
(
var
i=0;i<nlength;i+=2){
arrofByte[i/2] = (byte)(((digit(paramString.charAt(i),16)<<4)+digit(paramString.charAt(i+1),16)));
}
return
(arrofByte);
}
function
byteToString(arr) {
if
(
typeof
arr ===
'string'
) {
return
arr;
}
var
str =
''
,
_arr = arr;
for
(
var
i = 0; i < _arr.length; i++) {
var
one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if
(v && one.length == 8) {
var
bytesLength = v[0].length;
var
store = _arr[i].toString(2).slice(7 - bytesLength);
for
(
var
st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
}
else
{
str += String.fromCharCode(_arr[i]);
}
}
return
str;
}
function
stringToByte(str) {
var
len, c;
len = str.length;
var
bytes = [];
for
(
var
i = 0; i < len; i++) {
c = str.charCodeAt(i);
if
(c >= 0x010000 && c <= 0x10FFFF) {
bytes.push(((c >> 18) & 0x07) | 0xF0);
bytes.push(((c >> 12) & 0x3F) | 0x80);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
}
else
if
(c >= 0x000800 && c <= 0x00FFFF) {
bytes.push(((c >> 12) & 0x0F) | 0xE0);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
}
else
if
(c >= 0x000080 && c <= 0x0007FF) {
bytes.push(((c >> 6) & 0x1F) | 0xC0);
bytes.push((c & 0x3F) | 0x80);
}
else
{
bytes.push(c & 0xFF);
}
}
return
new
Int8Array(bytes);
}
getBase64decode =
function
(){
var
encode =
"5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc="
;
let decrypted = atob(encode);
let base64decodedBytes =
new
Int8Array(atob(encode).split(
''
).map((char) => char.charCodeAt(0)));
const strbrr = String.fromCharCode.apply(
null
,base64decodedBytes);
console.log(strbrr);
return
base64decodedBytes;
}
deCryptedByAes_ECB =
function
(data,AESkey){
var
strdata = byteToString(data);
var
strAESKey = byteToString(AESkey)
var
key = CryptoJS.enc.Utf8.parse(AESkey);
var
decrypt = CryptoJS.AES.decrypt(data, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
});
return
CryptoJS.enc.Utf8.stringify(decrypt).toString();
把加密的内容和秘钥转化为wordarry对象
}
const str = byteToString(b(
"8d127684cbc37c17616d806cf50473cc"
))
gettext =
function
() {
var
text = deCryptedByAes_ECB(b(
"8d127684cbc37c17616d806cf50473cc"
),getBase64decode(
"5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc="
))
console.log(text);
}
console.log(gettext())
const CryptoJS = require(
'crypto-js'
)
const base = require(
"./Crypted/Base64"
);
const byte = (x) => ((((x | 0) & 0xff) + 128) % 256) - 128;
Judgment_capitalization =
function
(input){
if
(
'A'
<=input &&input <=
'Z'
){
return
true
;
}
else
return
false
;
}
Determine_whether_to_lower =
function
(input){
if
(
'a'
<=input &&input <=
'z'
){
return
true
;
}
else
return
false
;
}
digit =
function
(input,radis) {
try
{
if
(!isNaN(parseInt(input))) {
if
(parseInt(input) < 10 && parseInt(input) > -1) {
return
parseInt(input) < parseInt(radis) ? parseInt(input) : -1;
}
}
}
catch
(err) {
}
try
{
if
(Judgment_capitalization(input)) {
return
input.charCodeAt(0) < radis +
'A'
.charCodeAt(0) - 10 ? input.charCodeAt(0) -
'A'
.charCodeAt(0) + 10 : -1;
}
}
catch
(err) {
}
try
{
if
(Determine_whether_to_lower(input)) {
return
input.charCodeAt(0) < radis +
'a'
.charCodeAt(0) - 10 ? input.charCodeAt(0) -
'a'
.charCodeAt(0) + 10 : -1;
}
}
catch
(err) {
}
}
b =
function
(paramString){
var
nlength = paramString.length;
var
arrofByte =
new
Int8Array(nlength/2);
for
(
var
i=0;i<nlength;i+=2){
arrofByte[i/2] = (byte)(((digit(paramString.charAt(i),16)<<4)+digit(paramString.charAt(i+1),16)));
}
return
(arrofByte);
}
function
byteToString(arr) {
if
(
typeof
arr ===
'string'
) {
return
arr;
}
var
str =
''
,
_arr = arr;
for
(
var
i = 0; i < _arr.length; i++) {
var
one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if
(v && one.length == 8) {
var
bytesLength = v[0].length;
var
store = _arr[i].toString(2).slice(7 - bytesLength);
for
(
var
st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
}
else
{
str += String.fromCharCode(_arr[i]);
}
}
return
str;
}
function
stringToByte(str) {
var
len, c;
len = str.length;
var
bytes = [];
for
(
var
i = 0; i < len; i++) {
c = str.charCodeAt(i);
if
(c >= 0x010000 && c <= 0x10FFFF) {
bytes.push(((c >> 18) & 0x07) | 0xF0);
bytes.push(((c >> 12) & 0x3F) | 0x80);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
}
else
if
(c >= 0x000800 && c <= 0x00FFFF) {
bytes.push(((c >> 12) & 0x0F) | 0xE0);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2023-10-24 11:56
被4Chan编辑
,原因: