这个app的本地证书做了处理,对证书名加密以及去掉证书后缀,导致用常规全局搜索.p12等文件失败。
该app可以抓到包,但是存在以下问题
一般是由于做了双向认证校验,服务器校验客户端证书导致的。
对app进行脱壳,全局搜索".cer"、".crt"、".pfx"、"PKCS12"、"keyStore"、".p12"等关键字。在
跳转到目标代码上
找到调用上面Client的方法
从代码中可以看到
sslSocketFactory中参数open(E.i(value))打开本地的证书文件,参数EncryptNDK.getInstance().gainValue(value)为获取证书的key。
跟踪获取证书的key函数
调用了so文件,而gainValue中的str即是证书的key。利用frida去hook EncryptNDK.gainValue以及E.i(value)。
利用hook到的值去全局搜索即可得到被调用的证书以及证书的key。在burpsuit中的User options 》 TLS中导入相对于的证书与域名即可。
在证书存在于本地的资源文件中,对证书名进行加密和去掉证书后缀。导致常规的全局搜索找不到证书的所在,若是证书通过远程进行下载,以及存在这样的情况下如何去解决。
1、可以通过本地文件的更新时间去判断,然而可能需要去甄别那些是证书。若是存在上述的加密以及去掉证书后缀,则可能要花费很大功夫甚至是无法达成目的。
2、如果证书是以java.security.KeyStore来进行双向认证校验,那么通过hook该函数的load方法可获取证书文件和证书密码,即
针对于该脚本的实践中,发现应用于本次的app是需要改动的。本次的app存在spwan的检测,无法使用device.spawn去启动app,因此需要修改。去掉
同时将pid改为app_name
经过实践该脚本是可以成立的,但是好像只生成有带密码的证书文件,而且证书后缀为.jks。
3、如果app本身不存在检测的话,可以利用objection,去hook java.io.File
或使用spawn方式
HTTP
/
1.1
400
Bad Request
Server: openresty
/
1.17
.
8.1
Date: Wed,
14
Oct
2020
10
:
00
:
30
GMT
Content
-
Type
: text
/
html; charset
=
utf8
Content
-
Length:
645
Connection: close
<html>
<head><title>
400
No required SSL certificate was sent<
/
title><
/
head>
<body>
<center><h1>
400
Bad Request<
/
h1><
/
center>
<center>No required SSL certificate was sent<
/
center>
<hr><center>openresty
/
1.17
.
8.1
<
/
center>
<
/
body>
<
/
html>
HTTP
/
1.1
400
Bad Request
Server: openresty
/
1.17
.
8.1
Date: Wed,
14
Oct
2020
10
:
00
:
30
GMT
Content
-
Type
: text
/
html; charset
=
utf8
Content
-
Length:
645
Connection: close
<html>
<head><title>
400
No required SSL certificate was sent<
/
title><
/
head>
<body>
<center><h1>
400
Bad Request<
/
h1><
/
center>
<center>No required SSL certificate was sent<
/
center>
<hr><center>openresty
/
1.17
.
8.1
<
/
center>
<
/
body>
<
/
html>
if
(!hashMap.containsKey(host2)) {
hashMap.put(host2, host2
+
".p12"
);
}
}
Client(hashMap);
}
if
(!hashMap.containsKey(host2)) {
hashMap.put(host2, host2
+
".p12"
);
}
}
Client(hashMap);
}
private void Client(
Map
<String, String>
map
) {
...
OkHttpClient.Builder createClientBuilder
=
createClientBuilder();
createClientBuilder.sslSocketFactory(surea.a(App.b().getAssets().
open
(E.i(value)),EncryptNDK.getInstance().gainValue(value)), a.a());
private void Client(
Map
<String, String>
map
) {
...
OkHttpClient.Builder createClientBuilder
=
createClientBuilder();
createClientBuilder.sslSocketFactory(surea.a(App.b().getAssets().
open
(E.i(value)),EncryptNDK.getInstance().gainValue(value)), a.a());
createClientBuilder.sslSocketFactory(surea.a(App.b().getAssets().
open
(E.i(value)),EncryptNDK.getInstance().gainValue(value)), a.a());
createClientBuilder.sslSocketFactory(surea.a(App.b().getAssets().
open
(E.i(value)),EncryptNDK.getInstance().gainValue(value)), a.a());
public
class
EncryptNDK {
static {
System.loadLibrary(
"EncryptLib"
);
}
...
public native String gainValue(String
str
);
....
}
public
class
EncryptNDK {
static {
System.loadLibrary(
"EncryptLib"
);
}
...
public native String gainValue(String
str
);
....
}
import
frida, sys, time
app_name
=
'包名'
i
=
0
ext
=
''
def
on_message(message, data):
global
i, ext
if
(message[
'type'
]
=
=
'send'
and
'event'
in
message[
'payload'
]):
if
(message[
'payload'
][
'event'
]
=
=
'+found'
):
i
+
=
1
print
(
"\n[+] Hooked keystore"
+
str
(i)
+
"..."
)
elif
(message[
'payload'
][
'event'
]
=
=
'+type'
):
print
(
" [+] Cert Type: "
+
'
'.join(message['
payload
']['
certType']))
if
(message[
'payload'
][
'certType'
]
=
=
'PKCS12'
):
ext
=
'.jks'
elif
(message[
'payload'
][
'event'
]
=
=
'+pass'
):
print
(
" [+] Password: "
+
'
'.join(message['
payload
']['
password']))
elif
(message[
'payload'
][
'event'
]
=
=
'+write'
):
print
(
" [+] Writing to file: keystore"
+
str
(i)
+
ext)
f
=
open
(
'keystore'
+
str
(i)
+
ext,
'wb'
)
f.write(bytes.fromhex(message[
'payload'
][
'cert'
]))
f.close()
else
:
print
(message)
jscode
=
print
(
"[.] Attaching to device..."
)
try
:
device
=
frida.get_remote_device()
except
:
print
(
"[-] Can't attach. Is the device connected?"
)
sys.exit()
print
(
"[.] Spawning the app..."
)
try
:
pid
=
device.spawn(app_name)
device.resume(pid)
time.sleep(
1
)
except
:
print
(
"[-] Can't spawn the App. Is filename correct?"
)
sys.exit()
print
(
"[.] Attaching to process..."
)
try
:
process
=
device.attach(pid)
except
:
print
(
"[-] Can't connect to App."
)
sys.exit()
print
(
"[.] Launching js code..."
)
print
(
" (run the app until needed, close it and then kill this script)"
)
script
=
process.create_script(jscode)
script.on(
'message'
, on_message)
script.load()
try
:
sys.stdin.read()
except
KeyboardInterrupt:
print
(
"\nExiting now"
)
exit(
0
)
import
frida, sys, time
app_name
=
'包名'
i
=
0
ext
=
''
def
on_message(message, data):
global
i, ext
if
(message[
'type'
]
=
=
'send'
and
'event'
in
message[
'payload'
]):
if
(message[
'payload'
][
'event'
]
=
=
'+found'
):
i
+
=
1
print
(
"\n[+] Hooked keystore"
+
str
(i)
+
"..."
)
elif
(message[
'payload'
][
'event'
]
=
=
'+type'
):
print
(
" [+] Cert Type: "
+
'
'.join(message['
payload
']['
certType']))
if
(message[
'payload'
][
'certType'
]
=
=
'PKCS12'
):
ext
=
'.jks'
elif
(message[
'payload'
][
'event'
]
=
=
'+pass'
):
print
(
" [+] Password: "
+
'
'.join(message['
payload
']['
password']))
elif
(message[
'payload'
][
'event'
]
=
=
'+write'
):
print
(
" [+] Writing to file: keystore"
+
str
(i)
+
ext)
f
=
open
(
'keystore'
+
str
(i)
+
ext,
'wb'
)
f.write(bytes.fromhex(message[
'payload'
][
'cert'
]))
f.close()
else
:
print
(message)
jscode
=
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)