1.介绍
为了防止app被次打包,通常会进行签名校验,当app被修改并重新签名后,签名信息与原来的签名信息不一致,导致app不能正常运行
1.获取签名信息
keytool -printcert -jarfile app-debug.apk
2.遇到这种有签名校验的,就不能通过修改代码,重新编译对它进行篡改了,这个时候就需要使用frida对它动态修改了。
1.反编译找到签名校验的关键点
反编译apk文件,来找到签名校验的关键点,也就是它使用了哪个函数来实现的这个签名校验.
2.编写hook代码
找到这个类和函数之后就可以编写hook代码对它的函数进行一个动态的修改.
3.注入js
最后就可以通过frida来加载我们的js脚本对app进行注入达到绕过签名校验的目的.
1.安装vs code,点扩展,搜索frida Workbench安装,然后新建一个js文件,就可以开始编写hook代码了。
2.frida官网js hook安卓的例子.
3.使用Androidkiller反编译一下,打开Androidmanifest.xml文件,找到主界面,搜索一下MainActivity主界面.
4.在smali代码中看到了两个关键的函数调用.
5.接下来仿照示例编写js脚本:
6.按照上节课的方法进行注入:
1)打开shell窗口
2)打开cmd窗口
7.成功绕过签名校验和root检测。
1.参考教程:https://frida.re/
C:\Users\LENOVO\Desktop>keytool
-
printcert
-
jarfile app
-
debug.apk
签名者
签名:
所有者: C
=
US, O
=
Android, CN
=
Android Debug
发布者: C
=
US, O
=
Android, CN
=
Android Debug
序列号:
1
生效时间: Thu Dec
30
19
:
07
:
22
CST
2021
, 失效时间: Sat Dec
23
19
:
07
:
22
CST
2051
证书指纹:
SHA1:
4C
:D7:B7:FB:D5:
03
:
36
:
24
:
02
:
91
:A4:
55
:
3A
:
44
:
16
:A9:DF:F1:
56
:
09
SHA256:
18
:B9:
03
:E7:
4C
:
51
:A6:
26
:
98
:
2B
:C2:
54
:
7A
:
9C
:
0E
:
69
:BB:
49
:A3:D1:
6F
:
00
:B1:
73
:
9C
:
89
:
8A
:B5:
21
:F2:
53
:CA
签名算法名称: SHA1withRSA (弱)
主体公共密钥算法:
2048
位 RSA 密钥
版本:
1
Warning:
证书 使用的 SHA1withRSA 签名算法被视为存在安全风险。此算法将在未来的更新中被禁用。
C:\Users\LENOVO\Desktop>keytool
-
printcert
-
jarfile app
-
debug.apk
签名者
签名:
所有者: C
=
US, O
=
Android, CN
=
Android Debug
发布者: C
=
US, O
=
Android, CN
=
Android Debug
序列号:
1
生效时间: Thu Dec
30
19
:
07
:
22
CST
2021
, 失效时间: Sat Dec
23
19
:
07
:
22
CST
2051
证书指纹:
SHA1:
4C
:D7:B7:FB:D5:
03
:
36
:
24
:
02
:
91
:A4:
55
:
3A
:
44
:
16
:A9:DF:F1:
56
:
09
SHA256:
18
:B9:
03
:E7:
4C
:
51
:A6:
26
:
98
:
2B
:C2:
54
:
7A
:
9C
:
0E
:
69
:BB:
49
:A3:D1:
6F
:
00
:B1:
73
:
9C
:
89
:
8A
:B5:
21
:F2:
53
:CA
签名算法名称: SHA1withRSA (弱)
主体公共密钥算法:
2048
位 RSA 密钥
版本:
1
Warning:
证书 使用的 SHA1withRSA 签名算法被视为存在安全风险。此算法将在未来的更新中被禁用。
Java.perform(function () {
/
/
Create an instance of java.lang.String
and
initialize it with a string
var JavaString
=
Java.use(
'java.lang.String'
);
var exampleString1
=
JavaString.$new(
'Hello World, this is an example string in Java.'
);
console.log(
'[+] exampleString1: '
+
exampleString1);
console.log(
'[+] exampleString1.length(): '
+
exampleString1.length());
/
/
Create an instance of java.nio.charset.Charset,
and
initialize the default character
set
var Charset
=
Java.use(
'java.nio.charset.Charset'
);
var charset
=
Charset.defaultCharset();
/
/
Create a byte array of a Javascript string
var charArray
=
'This is a Javascript string converted to a byte array.'
.split('').
map
(function(c) {
return
c.charCodeAt(
0
);
});
/
/
Create an instance of java.lang.String
and
initialize it through an overloaded $new,
/
/
with a byte array
and
a instance of java.nio.charset.Charset
var exampleString2
=
JavaString.$new.overload(
'[B'
,
'java.nio.charset.Charset'
).call(JavaString, charArray, charset)
console.log(
'[+] exampleString2: '
+
exampleString2);
console.log(
'[+] exampleString2.length(): '
+
exampleString2.length());
/
/
Intercept the initialization of java.lang.Stringbuilder's overloaded constructor,
/
/
and
write the partial argument to the console
var StringBuilder
=
Java.use(
'java.lang.StringBuilder'
);
/
/
We need to replace .$init() instead of .$new(), since .$new()
=
.alloc()
+
.init()
var ctor
=
StringBuilder.$init.overload(
'java.lang.String'
);
ctor.implementation
=
function (arg) {
var partial
=
'';
var result
=
ctor.call(this, arg);
if
(arg !
=
=
null) {
partial
=
arg.toString().replace(
'\n'
, '').
slice
(
0
,
10
);
}
/
/
console.log(
'new StringBuilder(java.lang.String); => '
+
result);
console.log(
'new StringBuilder("'
+
partial
+
'");'
);
return
result;
};
console.log(
'[+] new StringBuilder(java.lang.String) hooked'
);
/
/
Intercept the toString() method of java.lang.StringBuilder
and
write its partial contents to the console.
var toString
=
StringBuilder.toString;
toString.implementation
=
function () {
var result
=
toString.call(this);
var partial
=
'';
if
(result !
=
=
null) {
partial
=
result.toString().replace(
'\n'
, '').
slice
(
0
,
10
);
}
console.log(
'StringBuilder.toString(); => '
+
partial);
return
result;
};
console.log(
'[+] StringBuilder.toString() hooked'
);
});
Java.perform(function () {
/
/
Create an instance of java.lang.String
and
initialize it with a string
var JavaString
=
Java.use(
'java.lang.String'
);
var exampleString1
=
JavaString.$new(
'Hello World, this is an example string in Java.'
);
console.log(
'[+] exampleString1: '
+
exampleString1);
console.log(
'[+] exampleString1.length(): '
+
exampleString1.length());
/
/
Create an instance of java.nio.charset.Charset,
and
initialize the default character
set
var Charset
=
Java.use(
'java.nio.charset.Charset'
);
var charset
=
Charset.defaultCharset();
/
/
Create a byte array of a Javascript string
var charArray
=
'This is a Javascript string converted to a byte array.'
.split('').
map
(function(c) {
return
c.charCodeAt(
0
);
});
/
/
Create an instance of java.lang.String
and
initialize it through an overloaded $new,
/
/
with a byte array
and
a instance of java.nio.charset.Charset
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)