---
# System prepended metadata

title: AndroidMobilePentest101
tags: [pentest android]

---

# AndroidMobilePentest101

## bài 1 - thiết lập môi trường

- tải virtualbox và genymotion

![image](https://hackmd.io/_uploads/BJae2Dbs0.png)

## bài 2 - ADB

- bật USB	Debugging	 lên,	chức	này	cho	phép	ta	tương	tác	điện	thoại	ảo	với	máy	thật


![image](https://hackmd.io/_uploads/H1H42w-sC.png)

- Bây giờ bạn	đã	đủ	điều	kiện	để	cài	1 file apk	bằng adb
 
![image](https://hackmd.io/_uploads/HknK2vbsR.png)

- Cài	file	apk vào	điện	thoại	ảo	bằng	câu	lệnh:

```bash
adb install /path/to/apkfile
```

- vào shel

```bash
adb shell
```

![image](https://hackmd.io/_uploads/HycHpvbs0.png)


- xem log 

```bash
adb logcat
```

![image](https://hackmd.io/_uploads/ByN8aw-oC.png)

- để tải lên 1 file từ máy thật đến điện thoại ảo:

```bash
adb push /path/to/file/PC /path/to/file/device
```

- để tải 1 file từ điện thoại ảo đến máy thật :

```bash
addb pull /path/to/file/device /path/to/file/PC 
```

## bài 3 - Phân tích tĩnh 

### kiểm tra bằng tool
- MobSF là một bộ	công cụ kiểm tra ứng dụng di	động (Android	 /	iOS	/	Windows)	tự động,	tất cả-trongmột,	 có khả năng thực hiện phân tích tĩnh,	phân tích động,	phân tích phần mềm độc hại và kiểm tra API	
web.


![image](https://hackmd.io/_uploads/B1Awo_-iC.png)

- MobSF	 cung	cấp	nhiều	 thông	 tin	cần	thiết	để	chúng	 ta	đánh	giá	độ	bảo	mật	của	chương	 trình

![image](https://hackmd.io/_uploads/SJ5VlY-sA.png)

### kiểm tra bằng tay 

- Để	làm	việc	này,	chúng	 ta	sử	dụng	ByteCode	Viewer,	1	tool	dùng	 xem	code	nhanh	 trong	file	apk

    - * Easily	edit	APKs via	Smali/Baksmali integration
    - *	Scan	for	malicious	code	with	the	Malicious	Code	Scanner	plugin.
    - * Export	as	DEX,	Jar,	Class,	Zip	or	Java	Source	File.

Ném file apk vào, Bytecode Viewer sẽ phân tích file apk và hiển thị code bên trong cho chúng ta

![image](https://hackmd.io/_uploads/SymXWYWi0.png)

- Sử	dụng	Malicious	Code	Scanner	plugin	để	scan	những	đoạn	code	có	vẻ	nguy	hiểm

![image](https://hackmd.io/_uploads/rJnr-tWsC.png)

- https://the.bytecode.club/pages.php?page=bytecode-viewer

- demo Malicious	Code	Scanner	

https://www.youtube.com/watch?v=I5GT6PoTGOw&t=1s

![image](https://hackmd.io/_uploads/HyjVYK-s0.png)

![image](https://hackmd.io/_uploads/ryaEYtZjC.png)

![image](https://hackmd.io/_uploads/H1Bdtt-oR.png)



![image](https://hackmd.io/_uploads/SyuCutWiC.png)


- Ví	dụ:	Tìm	ra	được	đoạn	code	lạ	trong	com/android/insecurebankv2/DoLogin$RequestTask.class
- Nếu	đăng	nhập	với	nick "devadmin"	thì	tự	động	login	được,	không	 cần	quan	 tâm	password,	chương	 trình	gì
kì	ha


![image](https://hackmd.io/_uploads/BkRWHtWoR.png)

![image](https://hackmd.io/_uploads/H1CNrYWiA.png)

![image](https://hackmd.io/_uploads/rkbKYONjC.png)


- Trong	quá	trình	phân	 tích	tĩnh,	 chúng	 ta	phải	kiểm	tra	các	cơ	chế	anti-root,	anti-vm,	cert-pinning	 có	được	
cài	đặt	hay	không,	 và	có	lỏng	lẻo	hay	không	(sẽ	nói	ở	bài	khác)
- Kiểm	tra	xem	key, mật	khẩu,	vv… có	nằm	trong	 code	hay	thư	mục	nào	không.
- Kiểm	tra	xem	các	thông	 tin	nhạy	cảm	(credit	card,	pass...)	có	được	lưu	trong	 database	không


![image](https://hackmd.io/_uploads/S1icoYbjC.png)

- Xem	thử	trong	 database	có	chứa	thông	 tin	đăng	nhập	nhạy	cảm	không

![image](https://hackmd.io/_uploads/SkIN6YboR.png)

==> thấy không có thông tin nhạy cảm được lưu


### các bước kiểm tra 
- Thông	tin	đăng	nhập	không	được	mã	hoá	trong	cơ	sở	dữ	liệu ![image](https://hackmd.io/_uploads/HJiwk5bjR.png)

- Thông tin nhạy cảm lưu dưới dạng plain-text ![image](https://hackmd.io/_uploads/rkAK15-oR.png)

- Lưu	trữ	Cookie	không	an	toàn ![image](https://hackmd.io/_uploads/rJ3sk9WoC.png)

- File	Backup	không	được	mã	hoá ![image](https://hackmd.io/_uploads/r1uJlc-s0.png)
![image](https://hackmd.io/_uploads/HJPp-9boC.png)
![image](https://hackmd.io/_uploads/SJO0bqWjC.png) ![image](https://hackmd.io/_uploads/H1wTGcWsA.png)

- Thông tin nhạy cảm lộ trong log ![image](https://hackmd.io/_uploads/HkYyX5bsA.png)

- Phương thức mã hoá yếu ![image](https://hackmd.io/_uploads/Hkib7qbjR.png)
![image](https://hackmd.io/_uploads/rygI7cboR.png)

- Activity	Hijacking ![image](https://hackmd.io/_uploads/BJs5Lc-sR.png)
![image](https://hackmd.io/_uploads/ryrVEc-s0.png)
![image](https://hackmd.io/_uploads/Hy33S5ZiR.png)

```bash
am start -n com.android.insecurebankv2/.PostLm start -n com.android.insecurebankv2/.PostLogin 
```

- xem thêm checklist tại đây : https://www.mediafire.com/file/fsx9gdpddgcpz2g/Android+Applicatio

## bài 4 - dịch ngược


### Inside	the	apk

- META-INF/:	Thư mục này có ở trong file	APK	đã sign,	nó bao gồm các danh sách file	trong APK	và chữ kí
của chúng
- lib/:	Các file	của thư viện native	(file	có đuôi *.so)	được lưu vào thư mục con	của lib/	như x86,	x86_64
- res/:	Folder	này gồm tất cả các resource	XML,	drawables(PNG,JPEG)	với các loại khác nhau từ mdpi,	hdpi,	
sw600dp...	cho tới resource	ngôn ngữ
- AndroidManifest.xml:	Mô	tả	tên,	phiên	bản,	và	nội	 dung	 của	file	APK
- classes.dex:	Bao gồm mã nguồn đã biên dịch,	được chuyển đưới dạng Dex bytecode
- resources.arsc:	Một số tài nguyên và định nghĩa được biên dịch và lưu trữ ở đây.	Các resource	này lưu vào
APK	mà không cần nén để truy cập nhanh hơn lúc runtime.


![image](https://hackmd.io/_uploads/Bk2Ph2Zi0.png)

- có thể đọc được smali code

![image](https://hackmd.io/_uploads/HkuZWpZs0.png)

![image](https://hackmd.io/_uploads/Bktb-TZj0.png)

### Patching android	app

- Patch	đơn	giản	là	tác	động	và	làm	thay	đổi	code	của	chương	trình,	khiến	 nó	hoạt	động	 theo	ý	mình.


![image](https://hackmd.io/_uploads/rJFhb6boA.png)

```bash
apktool d InsecureBankv2.apk
```

![image](https://hackmd.io/_uploads/SkvVLTWoA.png)

![image](https://hackmd.io/_uploads/SkbIUaZs0.png)

![image](https://hackmd.io/_uploads/BJQRLaWsC.png)

![image](https://hackmd.io/_uploads/BJTLvaWoA.png)


![image](https://hackmd.io/_uploads/rkBzUaZoC.png)

![image](https://hackmd.io/_uploads/B1zT_aboA.png)

```bash
apktool b InsecureBankv2
```

![image](https://hackmd.io/_uploads/rylCtTZoC.png)

- File	apk	vừa	recompile	sẽ	nằm	ở	thư	mục	“dist”

![image](https://hackmd.io/_uploads/Byobq6ZiC.png)


![image](https://hackmd.io/_uploads/HJrQtTWi0.png)

- Cài	nó	thôi	nhỉ?


![image](https://hackmd.io/_uploads/Sy2TqaWjC.png)

- Oops,	Failed!	Bởi	vì	Every	new	compiled	Android .apk needs	to	be	signed	if	it	is	going	 to	be	installed	on	a	
phone (nôm	 na	là	file	compiled	Android	.apk	mới	phải	được	sign	trước	khi	cài	đặt)

tiến hành tạo chứng chỉ

- Đầu	tiên	tạo	1	cái	key:
```bash
keytool -genkey -v	-keystore my-release-key.keystore -alias	alias_name -keyalg RSA	-keysize 2048	-validity	10000
```

keystore password: 123456

![image](https://hackmd.io/_uploads/Bk__hp-sC.png)

- Sau	đó	xài	jarsigner	với	key	vừa	tạo	để	sign:

```bash
jarsigner -verbose	-sigalg SHA1withRSA	-digestalg SHA1	-keystore my-release-key.keystore InsecureBankv2.apk	alias_name
```

- https://www.youtube.com/watch?v=FaGCRQLxuoA


![image](https://hackmd.io/_uploads/S1F7C6ZoA.png)

- khi tải xong jarsigner có thể chạy được sign in 


![image](https://hackmd.io/_uploads/Skf_ApZoA.png)

![image](https://hackmd.io/_uploads/Hyys0abjC.png)

- Chúng	 ta	đổi	tên	file	để	tránh	nhầm	lẫn:

![image](https://hackmd.io/_uploads/rk5lyRbo0.png)

![image](https://hackmd.io/_uploads/ByO41RWoA.png)

- Oh,	vẫn	có	vấn	đề! Lỗi	này	là	do	chương	trình	 cũ	đã	được	cài	đặt	rồi,	do	đó	ta	gỡ	nó	 ra	và	cài	cái	mới	vào


![image](https://hackmd.io/_uploads/S1mMgC-sA.png)

- tải app-release_patched.apk thành công 


![image](https://hackmd.io/_uploads/ry7Bl0bi0.png)

![image](https://hackmd.io/_uploads/HkzYbCZsC.png)

```bash
$ apktool d <source.apk> -o <destination_directory>/
```

1. Recompile and recompress the application using Apktool.

```bash
$ apktool b <source_directory>/ -o <patched.apk>
```

2. Create a signing key using Keytool.

```bash
$ keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
```


3. Sign the resulting APK with Java’s JarSigner.

```bash
$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore <patched.apk> alias_name
```

4. Install the application on our device once more using Android’s ADB.

```bash
$ adb install <patched.apk>
```


### Detection

![image](https://hackmd.io/_uploads/S1orEAbs0.png)

#### Detection	->	Anti-emu

![image](https://hackmd.io/_uploads/BkxNrR-jR.png)

![image](https://hackmd.io/_uploads/ByQ0SRWiR.png)

![image](https://hackmd.io/_uploads/rJSwuAWiC.png)

![image](https://hackmd.io/_uploads/SkGPtR-j0.png)

![image](https://hackmd.io/_uploads/HkndKC-sC.png)

![image](https://hackmd.io/_uploads/BJ5FKRWjR.png)

![image](https://hackmd.io/_uploads/ryOcK0ZiR.png)

#### Detection	->	Anti-root


![image](https://hackmd.io/_uploads/ryrDIAbiA.png)

- Chúng	 ta	sẽ	nói	về	vấn	đề	tại	sao	anti-root	code	không	 phát	hiện	được. Đoạn	code	check	root	như	sau:
- Nó	kiểm	tra	/system/app/Superuser.apk có	tồn	tại	không?
- Nếu	có	=>	phát	hiện,	không	 thì	thôi.


![image](https://hackmd.io/_uploads/ryYwwAZi0.png)

![image](https://hackmd.io/_uploads/BksCv0-oC.png)

## bài 5 - phân tích động

- dùng burp suit và cấu hình bắt request qua burp

![image](https://hackmd.io/_uploads/ryDyyyMj0.png)

- Sử	dụng	 tab	Scanner	(BurpSuite	 pro	mới	có	nha)	để	tiến	hành	scan	tìm	lỗi	trong	 request	được	
chỉ	định

![image](https://hackmd.io/_uploads/S14eJyzj0.png)

- thấy trong server có gửi các request liên tục 


![image](https://hackmd.io/_uploads/r11By1fjR.png)

- kết quả thấy phát hiện lỗi XSS


![image](https://hackmd.io/_uploads/H1sjkJzjC.png)

![image](https://hackmd.io/_uploads/HkN2kyfjC.png)

![image](https://hackmd.io/_uploads/r1CnJkMiR.png)

![image](https://hackmd.io/_uploads/BJS1g1Mo0.png)

![image](https://hackmd.io/_uploads/B1wylyMsR.png)

![image](https://hackmd.io/_uploads/SkzVe1MsA.png)

## bài 6 - SSL Pinning

- SSL	Pinning	 là	quá	trình	liên	kết	host	với	chứng	chỉ X.509	certificate	hoặc	public	key.	Khi	chứng	 chỉ	hoặc	key	
đã	được	chỉ	định	cho	host,	nó	được	gọi	là ‘pinned’	 với	host.
- Phần	mềm	giao	tiếp	với	server	thông	 qua	giao	thức	https	và	có	pinning	 sẽ	khiến	kiểu	tấn	công	Man-In-TheMiddle	attack thất	bại,	và	cũng	không	lấy	được	dữ	liệu	dưới	dạng	 clear	text	khi	sử	dụng	 các	công	cụ	proxy	
(như	 burpsuite)

Có	3	lựa	chọn	 dùng	để	pin:
- Certificate	Pinning	 (Chủ	yếu	nói	về	cái	này) ![image](https://hackmd.io/_uploads/BJsldJGsR.png)

- Public Key ![image](https://hackmd.io/_uploads/HJcZ_1fsC.png)

- Hashing ![image](https://hackmd.io/_uploads/rJNGuJzjA.png)

### Detect	Pinning
Để	kiểm	tra	xem	app	có	ssl	pinning	 hay	không	 thường	 sử	dụng	 các	cách	sau:
1. Chỉ	intercept	được	request	đầu	tiên	(hoặc	không	 được	request	nào)
2. Tìm	string	“Trusted”
Hoặc sử	dụng MobSF:
(menu trái)	Security	Analysis	tab	->		File	Analysis.
Nếu	thấy	"Certificate/Key	Files	Hard-coded	inside	the	App”	hoặc	chỗ	nào	có	chuỗi	“Pinning”	=>	Pinning

![image](https://hackmd.io/_uploads/ByqvaGfiA.png)

### Bypass	The	Pinning
#### Method	1:			Adding	a	Custom	CA	to	the	User	Certificate	Store
- Mặc	định	thì các kết	nối	bảo	mật	(sử	dụng	protocols	như	TLS	and	HTTPS)	từ	các	app	
sẽ	tin	tưởng	vào	các pre-installed	system	CAs,	và	các	app	trên Android	 6.0	(API	level 23)	trở	xuống	 cũng	tin	tưởng	vào user-added	 CA

![image](https://hackmd.io/_uploads/HJxXAzfo0.png)

- Nếu	chúng	 ta	có	1	cái	certificated trusted	hợp	lệ	trong	 user	CA	ở	máy	android	 6.0	api	
level	23- thì	sẽ	bypass	được

![image](https://hackmd.io/_uploads/H1K9CGGjC.png)

- Đôi	khi	người	dev	bắt	ta	sử	dụng	android	 7	để	tránh	trường	hợp	 trên,	thường	định	nghĩa	trong	 file	
AndroidManifest.xml

![image](https://hackmd.io/_uploads/H1MwJmMsR.png)

- Ta decompile	nó	sử	dụng	apktool,	đổi	thành:	

![image](https://hackmd.io/_uploads/Sk8qyQzj0.png)

- Rồi	recompile	nó	lại,	nếu	app	chỉ	check	dựa	trên valid	certificate,	kĩ	thuật	này	sẽ	giúp	chúng	 ta	bypass	ssl	pinning

==> thay đổi viết lại chương trình

#### Method	2:			Overwrite	Packaged	CA	Certificate	with	Custom	CA	Certificate

- Đôi	khi	decompile	 file	apk	ra	sẽ	thấy	1	cái	custom	cert	trong	đó,	có	thể	app	sẽ	dùng	
nó	để	check

![image](https://hackmd.io/_uploads/rJdNxXMj0.png)

- Ghi	đè	‘CustomCA.cer’ certificate	với	cert	của	ta,	từ	đó	làm	cho	app	nghĩ	 rằng	cert	
của	ta	hợp	lệ

==> thay đổi viết lại cert của chương trình

#### Method	3: Patch the app

- Decompile	file	apk,	đọc	code,	tìm	đoạn	check	ssl	pinning,	 patch	nó	


![image](https://hackmd.io/_uploads/rJ0fQmMj0.png)


Một	số	case-study	thực	tế:
1. Bypassing	OkHTTP3	Certificate	Pinning
https://blog.securityevaluators.com/bypassing-okhttp3-certificate-pinning-c68a872ca9c8
2. Bypassing	certificate	pinning/hardcoded	 ssl certificate/certificate	pinning
https://www.youtube.com/watch?v=uEndLXB4tfA
3. Facebook	Bypassing	Certificate	Pinning
https://blog.dewhurstsecurity.com/2015

==> thay đổi viết lại chương trình

#### Method	4:	Hook

- dùng Frida ==> không tthayy đổi chương trình mà thay đổi hành vi tiến trình lúc  chạy chương trình

## bài 7 - Hooking	Với	Frida

Installation	->	Client	(máy	thật)

Cài	đặt	Frida	CLI	Tools:
pip3	install	frida-tools
- Cài	đặt	Frida	Python	 bindings	 (Sử	dụng	 chính	trong	 bài	viết)
pip3	install	frida
- Kiểm	tra	lại	xem	frida	đã	cài	thành	công	chưa:

![image](https://hackmd.io/_uploads/BkdTr7GoA.png)

Installation	->	Server	(điện	thoại	ảo)

- frida-server version	phải	đúng	với Frida	version.

![image](https://hackmd.io/_uploads/HkN8LQMoR.png)

### Hook mã nguồn Java

Việc hook vào phần mã nguồn Java đơn giản hơn nhiều so với hook vào mã nguồn Native. Với mã nguồn Native chúng ta sẽ gặp những vấn đề cần giải quyết bằng kỹ thuật dịch ngược, kiểu dữ liệu hạn chế,... thì với phần mã nguồn Java, những thứ này đều dễ hơn nhiều. Nếu phần mã nguồn Native có nhiều API khác nhau để hỗ trợ chúng ta làm 1 việc là tìm địa chỉ hàm cần hook, chúng ta có thể tùy từng trường hợp để lựa chọn các API cần thiết, thì khi hook vào phần mã nguồn Java chúng ta chỉ cần quan tâm đến 2 API chính, đó là:
- Java.choose()
- Java.use()

Hai API này sẽ hỗ trợ chúng ta hook thẳng vào bất cứ hàm nào chúng ta muốn, và chúng ta chỉ cần biết tên hàm đó là được.

##### API Java.choose()
API Java.choose() hoạt động theo nguyên lý tìm kiếm các Object được tạo sẵn trên vùng nhớ Heap.

![image](https://hackmd.io/_uploads/S1GM1ZVjC.png)


Khi các Object được tạo ra từ Class, chúng sẽ được đặt trong vùng nhớ heap cho tới khi được huỷ để giải phóng bộ nhớ. API Java.choose() sẽ tìm kiếm trên heap xem có Object nào được tạo ra từ Class chúng ta cần hook vào chưa. Nếu tìm thấy thì nó sẽ hook vào cho chúng ta.

Với nguyên lý hoạt động như này thì Java.choose() thường được sử dụng để sử dụng lại các hàm. Lúc này chúng ta có thể gọi lại hàm nhiều lần, thử truyền vào các đối số khác nhau,... qua đó hiểu hơn về cách hàm này hoạt động. Chúng ta cũng có thể gọi lại hàm để lấy được ra những giá trị chúng ta muốn. VD như gọi lại hàm giải mã và truyền vào đúng dữ liệu mã hoá, từ đó lấy được bản gốc.

API này có 2 event là:

- onMatch: được thực hiện mỗi khi tìm thấy một instance (mình hiểu đơn giản là một đối tượng sinh ra từ Class, mỗi Object đều độc lập nên chúng là các instance).
- onComplete: được thực hiện khi hoàn thành tìm ra toàn bộ các instance.
Vì thế nếu muốn hook vào các hàm thì chúng ta nên viết trong onMatch.

##### API Java.use()
Khác với Java.choose() chỉ lấy bánh, API Java.use() xử lý triệt để bằng cách kiểm soát cái khuôn. Lúc này muốn tạo ra bánh mới, huỷ bánh vừa tạo đi, thay đổi một chút trong khuôn bánh thì đều được. Hiểu đơn giản thì Java.use() cho phép chúng ta thay đổi logic của hàm ngay từ lúc nó được tạo ra bằng cú pháp new. Vì thế thường thì chúng ta sẽ sử dụng API này nhiều hơn.

![image](https://hackmd.io/_uploads/rJYXWb4iA.png)

API này không có event nào cả, đơn giản là chúng ta muốn viết lại nội dung hàm như nào thôi. Chúng ta sẽ sử dụng như sau:

```javascript
// frida -U -l hook.js -f <tên-package>
Java.perform(function () {
    // Hook 1 hàm của class
    Java.use("tên-class").<tên-hàm>.implementation = function() {
        // Nội dung thực hiện khi hook thành công
    };
    
    // Hook nhiều hàm cùng class
    var hookClass = Java.use("tên-class");
    hookClass.<tên-hàm-1>.implementation = function() {
        // Nội dung thực hiện khi hook thành công
    };
    hookClass.<tên-hàm-2>.implementation = function() {
        // Nội dung thực hiện khi hook thành công
    };
    
    // Hook hàm có tham số
    Java.use("tên-class").<tên-hàm>.implementation = function(var_1, var_2,...) {
        // Nội dung thực hiện khi hook thành công
    };
});

```

Trong trường hợp hàm chúng ta muốn hook có những hàm overloading thì chúng ta cần chỉ rõ hàm muốn hook bằng cách khai báo rõ số lượng và kiểu tham số.

```javascript
Java.perform(function () {
    // Hook 1 hàm của class
    Java.use("tên-class").<tên-hàm>.override("kiểu-biến-1", "kiểu-biến-2",...).implementation = function(var_1, var_2,...) {
        // Nội dung thực hiện khi hook thành công
    };
});
```


### Python	bindings

- Spawn app: Khi bạn sử dụng lệnh "spawn" trong Frida, bạn yêu cầu Frida khởi động ứng dụng mục tiêu trong trạng thái tạm dừng (not yet started) để bạn có thể bắt đầu chèn mã vào ngay từ thời điểm đầu tiên ứng dụng được khởi chạy. Điều này hữu ích trong việc phân tích các hành vi xảy ra ngay khi ứng dụng bắt đầu hoạt động, ví dụ như khi ứng dụng tải mã hoặc thiết lập các biến môi trường quan trọng.

```bash
frida -U -f [app_id] -l [script.js] --no-pause
```


![image](https://hackmd.io/_uploads/BktOi7GjA.png)

1. Kết nối đến thiết bị USB:
```bash!
device = frida.get_usb_device()
```

Dòng lệnh này kết nối với thiết bị Android đang kết nối qua USB. get_usb_device() là hàm của Frida để lấy thông tin về thiết bị USB hiện tại.

2. Spawn ứng dụng:

```bash!
pid = device.spawn("com.android.insecurebankv2")
```

Bạn sử dụng spawn() để khởi động ứng dụng mục tiêu trong trạng thái tạm dừng. Ở đây, "com.android.insecurebankv2" là tên của gói ứng dụng (package name) mà bạn muốn phân tích.

3. Resume ứng dụng:

```bash
device.resume(pid)
```

Sau khi spawn ứng dụng, nó sẽ bị tạm dừng. Lệnh resume() sẽ tiếp tục cho phép ứng dụng chạy bình thường.

4. Attach vào ứng dụng:

```bash
session = device.attach(pid)
```

Lệnh attach() này gắn Frida vào quá trình (process) của ứng dụng vừa spawn, để có thể thực hiện các thao tác tiếp theo, như chèn mã JavaScript vào.

5. Inject script vào ứng dụng:

```bash
script = session.create_script(hook_script)
script.load()
```

- create_script(hook_script) tạo một script dựa trên đoạn mã JavaScript mà bạn đã viết, dùng để hook vào các chức năng của ứng dụng.
- script.load() sẽ tải đoạn script đó vào ứng dụng, cho phép bạn bắt đầu phân tích hoặc thao tác các phần của ứng dụng theo cách bạn muốn.


```python
import frida, sys

def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)

jscode = """
Java.perform(() => {
  // Function to hook is defined here
  const MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');

  // Whenever button is clicked
  const onClick = MainActivity.onClick;
  onClick.implementation = function (v) {
    // Show a message to know that the function got called
    send('onClick');

    // Call the original onClick handler
    onClick.call(this, v);

    // Set our values after running the original onClick handler
    this.m.value = 0;
    this.n.value = 1;
    this.cnt.value = 999;

    // Log to the console that it's done, and we should have the flag!
    console.log('Done:' + JSON.stringify(this.cnt));
  };
});
"""

process = frida.get_usb_device().attach('com.example.seccon2015.rock_paper_scissors')
script = process.create_script(jscode)
script.on('message', on_message)
print('[*] Running CTF')
script.load()
sys.stdin.read()
```

- frida.get_usb_device().attach('com.example.seccon2015.rock_paper_scissors'): Kết nối đến thiết bị Android qua USB và attach vào ứng dụng mục tiêu.
- process.create_script(jscode): Tạo một script Frida từ đoạn mã JavaScript đã định nghĩa.
- script.on('message', on_message): Gắn hàm xử lý thông điệp với script.
- script.load(): Tải script vào tiến trình của ứng dụng.
- sys.stdin.read(): Giữ chương trình Python hoạt động để tiếp tục nhận các thông điệp từ script.

![image](https://hackmd.io/_uploads/ByzRXVMjC.png)

![image](https://hackmd.io/_uploads/HkYJ4hzo0.png)

#### hook vào Java code 
##### Java.choose()

![image](https://hackmd.io/_uploads/Hyi543zjR.png)

```java
package com.android.insecurebankv2;

import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class CryptoClass {
   String base64Text;
   byte[] cipherData;
   String cipherText;
   byte[] ivBytes = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
   String key = "This is the super secret key 123";
   String plainText;

   public static byte[] aes256decrypt(byte[] var0, byte[] var1, byte[] var2) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
      IvParameterSpec var4 = new IvParameterSpec(var0);
      SecretKeySpec var3 = new SecretKeySpec(var1, "AES");
      Cipher var5 = Cipher.getInstance("AES/CBC/PKCS5Padding");
      var5.init(2, var3, var4);
      return var5.doFinal(var2);
   }

   public static byte[] aes256encrypt(byte[] var0, byte[] var1, byte[] var2) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
      IvParameterSpec var4 = new IvParameterSpec(var0);
      SecretKeySpec var3 = new SecretKeySpec(var1, "AES");
      Cipher var5 = Cipher.getInstance("AES/CBC/PKCS5Padding");
      var5.init(1, var3, var4);
      return var5.doFinal(var2);
   }

   public String aesDeccryptedString(String var1) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
      byte[] var2 = this.key.getBytes("UTF-8");
      this.cipherData = aes256decrypt(this.ivBytes, var2, Base64.decode(var1.getBytes("UTF-8"), 0));
      this.plainText = new String(this.cipherData, "UTF-8");
      return this.plainText;
   }

   public String aesEncryptedString(String var1) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
      byte[] var2 = this.key.getBytes("UTF-8");
      this.plainText = var1;
      this.cipherData = aes256encrypt(this.ivBytes, var2, this.plainText.getBytes("UTF-8"));
      this.cipherText = Base64.encodeToString(this.cipherData, 0);
      return this.cipherText;
   }
}
```

- Vậy	gọi	function	lên	bằng	Frida	như	nào?	Chúng	 ta	sẽ	sử	dụng	```Java.choose()```


![image](https://hackmd.io/_uploads/B1iur2MoA.png)

Java.choose: liệt kê
Object (Đối tượng):
- Định nghĩa: Một object là một thực thể cụ thể trong bộ nhớ, được tạo ra từ một lớp (class). Nó bao gồm cả dữ liệu (thuộc tính) và hành vi (phương thức) mà lớp định nghĩa.
- Ngữ cảnh sử dụng: Từ "object" được sử dụng phổ biến nhất để chỉ một thực thể đang tồn tại trong bộ nhớ, có thể được tương tác bằng cách gọi các phương thức hoặc truy cập các thuộc tính của nó.
- Ví dụ: Khi nói "car1 là một object của lớp Car", chúng ta đang nói về một thực thể cụ thể của lớp Car.
Instance (Thực thể):
- Định nghĩa: Instance cũng là một đối tượng, nhưng từ "instance" thường được dùng để nhấn mạnh rằng đối tượng này là một "thực thể" của một lớp cụ thể.
- Ngữ cảnh sử dụng: "Instance" được sử dụng để nhấn mạnh mối quan hệ giữa đối tượng và lớp của nó. Khi bạn nói một đối tượng là một "instance" của một lớp nào đó, bạn đang nhấn mạnh rằng đối tượng này đã được tạo ra từ lớp đó.
- Ví dụ: Khi nói "car1 là một instance của lớp Car", chúng ta nhấn mạnh rằng car1 được tạo ra từ lớp Car.
Sự khác biệt chính:
- Ngữ cảnh: "Object" là thuật ngữ chung, có thể dùng cho mọi thực thể trong lập trình hướng đối tượng. "Instance" nhấn mạnh vào việc đối tượng là một thực thể của một lớp cụ thể.
- Sử dụng: Mọi instance đều là một object, nhưng không phải mọi object đều được gọi là instance. "Instance" thường được sử dụng khi nói về việc khởi tạo một đối tượng từ một lớp.

![image](https://hackmd.io/_uploads/rJEQdhMsA.png)

- trong ```mySharedPreferences``` chứa ```superSecurePassword``` và ```EncryptedUsername```

![image](https://hackmd.io/_uploads/BysicnGj0.png)


![image](https://hackmd.io/_uploads/ryLLx6Ms0.png)


![image](https://hackmd.io/_uploads/SkrWbdmi0.png)

![image](https://hackmd.io/_uploads/r1olG_7o0.png)


Found instance: com.android.insecurebankv2.CryptoClass@45c9ffd

![image](https://hackmd.io/_uploads/Byg57OXoC.png)

- Như	đã	biết,	Dinesh@123$	là	password	của	user	dinesh 


![image](https://hackmd.io/_uploads/SJo97uQj0.png)

```python
import frida
import sys
import time

device = frida.get_usb_device()

pid = device.spawn("com.android.insecurebankv2")
device.resume(pid)

time.sleep(0.5)  # Without it Java.perform silently fails 
session = device.attach(pid)

# with open("frida_script.js") as f:

#     script = session.create_script(f.read())
#     script.load()
hook_script = """ 
Java.perform(
    function () 
    {
        console.log('Inside the hook_script');
        class_CryptoClass = Java.choose('com.android.insecurebankv2.CryptoClass',
            {
                onMatch: function(instance) {
                    console.log('Found instance: ' + instance);
                    console.log('Result of decrypt: ' + instance.aesDeccryptedString('DTrW2VXjSoFdg0e61fHxJg=='));  
                },
                onComplete: function() {console.log('end');}
            }
        );
    }
);
"""

script=session.create_script(hook_script)
script.load()

input('[!] Press <Enter> at any time to detach from instrumented program.\n\n')

```

- nhưng khi chạy file riêng trong frida do có độ trễ khi khởi động không nhanh được như code nên instance đã bị giải phóng khỏi heap -> không bắt được 

![image](https://hackmd.io/_uploads/S1xiuQ4o0.png)

##### Java.use()

![image](https://hackmd.io/_uploads/HJB8LdXsA.png)

![image](https://hackmd.io/_uploads/HyqcRWNsR.png)

![image](https://hackmd.io/_uploads/SyqAyQ4sR.png)

![image](https://hackmd.io/_uploads/BJn01QVjC.png)

```python
import frida
import sys
import time

device = frida.get_usb_device()

pid = device.spawn("com.android.insecurebankv2")
device.resume(pid)

time.sleep(3)  # Without it Java.perform silently fails 
session = device.attach(pid)

# with open("frida_script.js") as f:

#     script = session.create_script(f.read())
#     script.load()
hook_script = """ 
Java.perform(
    function () 
    {
        console.log('Inside the hook_script');
        class_PostLogin = Java.use('com.android.insecurebankv2.PostLogin');
        class_PostLogin.doesSuperuserApkExist.implementation = function(var1) {
            return true;
        };
    }
);
"""

script=session.create_script(hook_script)
script.load()

input('[!] Press <Enter> at any time to detach from instrumented program.\n\n')

```

![image](https://hackmd.io/_uploads/BJdSefEjA.png)

![image](https://hackmd.io/_uploads/HkiDezEoA.png)

#### hook vào code Native

- đa	số	các	app	đều	có	client-side	filter,	giờ	 sử	dụng	 frida	để	bypass	thử	xem
- Nhìn	đoạn	code	này	trong	 com/android/insecurebankv2/ChangePassword$RequestChangePasswordTask.class:


![image](https://hackmd.io/_uploads/rkhw6Q4j0.png)


- Để	ý	đoạn	regex:
((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})
Đoạn	này	kiểm	tra	độ	phức	tạp	của password,	nghĩa	là	nếu	chúng	 ta	đổi	password	dễ	quá	thì	sẽ	không	 được
- Mình	là	người	đơn	giản nên	mình	đổi	thử	password	thành	“1234”:


![image](https://hackmd.io/_uploads/H1yATmNsC.png)

- Fail,	vì	pw	phải	từ	6->20	kí	tự
“1234”	chỉ	có	4	thôi


- Chúng	 ta	sẽ	sử	dụng	 frida	để	bypass.	Lần	này	không	inject	vào	app	class	nữa,	vì	regex	method	là	từ	java	package,	
không	 phải	từ	code của	dev.


![image](https://hackmd.io/_uploads/HyNL0XNjR.png)


- Hook:
regex_Pattern_hook =	Java.use('java.util.regex.Pattern')
- Khác	với	lần	trước,	ta	không	 thể	xài	regex_Pattern_hook.compile.implementation bởi	vì	trong	Pattern	package	có	
nhiều	loại	compile	methods	 (	compile(String	 x);	compile(String	 x,int y);	etc…),	do	đó	frida	sẽ	bị	rối!
- Chúng	 ta	phải	nói	với frida chính	xác	method	nào	để	hook,	ở	đây	là:	compile(String	 x)
- Sử	dụng	overload:
regex_Pattern_hook.compile.overload("java.lang.String").implementation


```python
import frida
import sys
import time

device = frida.get_usb_device()

pid = device.spawn("com.android.insecurebankv2")
device.resume(pid)

# time.sleep(1)  # Without it Java.perform silently fails 
session = device.attach(pid)


hook_script = """ 
Java.perform(
    function () 
    {
        console.log('Inside the hook_script');
        regex_Pattern_hook = Java.use('java.util.regex.Pattern');
        regex_Pattern_hook.compile.overload('java.lang.String').implementation = function(x) {
            console.log('Inside the compile function');
            console.log('Pattern: ' + x);
            return this.compile(".*");
        };
    }
);
"""

script=session.create_script(hook_script)
script.load()

input('[!] Press <Enter> at any time to detach from instrumented program.\n\n')
```

![image](https://hackmd.io/_uploads/SkE4K4VjA.png)

## bài 7.5 - frida lab
yeswehack
- Dịch	ngược	phần	mềm,	sử	dụng	 frida	để	crack	pin,	lấy	flag

### bước 1: dùng thử

![image](https://hackmd.io/_uploads/S1Ur6NVi0.png)


### bước 2: dịch ngược đọc code và đọc log
- Không	 thấy	thêm	gì,	nên	chuyển	qua	dịch	ngược	file	apk	để	phân	tích

![image](https://hackmd.io/_uploads/HJL_pNNsA.png)

- bật	logcat lên và	sử	dụng	app	để	có	cái	nhìn	 tổng	quan

![image](https://hackmd.io/_uploads/Sk93A4NiR.png)

![image](https://hackmd.io/_uploads/BJnukSNsA.png)

![image](https://hackmd.io/_uploads/B1CYJrVsA.png)

- Như	đã	thấy	trong	log,	ta	có	thể	đoán	rằng	nếu	pin	length	<	6,	chương	trình	in	ra	số	pin	hiện	tại
- Nếu pin	length	=	6,	nó	sẽ	tạo	ra	1	chuỗi kí	tự	(nhìn	giống	 cái	key)	và	búng	 ra	lỗi
- Sau	đó	in	ra stack	trace:
- Có	thể	“123456”	không	 phải	là	mã	pin	đúng	=>	“Ciphertext failed	verification”	=>	Error!

- Bây	giờ	chúng	 ta	sẽ	xem	qua	code	để	biết	chính	xác	chuyện	gì	xảy	ra
- Class	MainActivity.class:

![image](https://hackmd.io/_uploads/SJlIWrEoC.png)

![image](https://hackmd.io/_uploads/H17oa84iR.png)

- Chúng	 ta	có	thể	thấy	1	thứ	thú	vị	nè,	cipherText được	gán	bằng	giá	trị	của	Hex().decode của một	đoạn	hex	
string
- Sau	đó	chương	 trình	sử	dụng	PinLockListener để	thực	hiện	 các	thao	tác	check	pin	UI
- Trong	MainActivity$1.class,	ta	có	thể	thấy:

![image](https://hackmd.io/_uploads/HJvHkDEsA.png)

- onPinChange,	 onComplete biểu	hiện	giống	 những	gì	chúng	ta	đoán	dựa	vào logcat,	bây	giờ	 chúng	ta	tập	
trung	vào	onComplete để	biết	chương	trình	làm	gì	khi	input	6-length	pin

![image](https://hackmd.io/_uploads/SkEyzwViR.png)

![image](https://hackmd.io/_uploads/BJ_HXPVoC.png)

- chạy fail


## bài 8 - các công cụ hỗ trợ

- Root	Detection	Bypass

![image](https://hackmd.io/_uploads/H1O9jvEjC.png)

- Emulator	Detection	Bypass


![image](https://hackmd.io/_uploads/HJqIhPNs0.png)

- SSL	Pinning	Bypass	->	JustTrustMe

![image](https://hackmd.io/_uploads/SyMhnDEiC.png)

![image](https://hackmd.io/_uploads/HyiIpPEjC.png)

```bash
objection patchapk --source InsecureBankv2.apk
```


![image](https://hackmd.io/_uploads/HyiZAwEjR.png)

![image](https://hackmd.io/_uploads/Bk02ADVsR.png)

![image](https://hackmd.io/_uploads/SJMSgu4jC.png)

```bash
objection --gadget "com.android.insecurebankv2" explore
```

![image](https://hackmd.io/_uploads/S1PpJOViA.png)

- Với	Objection	 chúng	ta	có	thể	thu	thập	thông	 tin	về	app,	ví	dụ	lệnh env sẽ	trả	về	vị	trí	của	các	thư	mục Files,	
Caches	và	nhiều	 thư	mục	khác:

![image](https://hackmd.io/_uploads/SJn9eu4i0.png)

-Hoặc	liệt	kê	các Activities	mà	app	có:

![image](https://hackmd.io/_uploads/rkel-_4iC.png)

![image](https://hackmd.io/_uploads/S1oZbdEoC.png)

- Sử	dụng activities	liệt	kê	được,	invoking	arbitrary	activities:

- android intent launch_activity com.android.insecurebankv2.PostLogin ==> cho ta vào luôn trang chủ


![image](https://hackmd.io/_uploads/BJlpWuNiC.png)

```bash
android sslpinning disable
```

- để bypass	SSL	Pinning	sử	dụng	Objection,	gõ	lệnh	(mặc	dù	app	của	chúng	ta	
không	 có	ssl	pinning,	 ví	dụ	thôi J):


![image](https://hackmd.io/_uploads/BknSz_Ei0.png)

- đọc thêm tại https://book.hacktricks.xyz/mobile-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial

## bài 9 - ví dụ thực tế

## bài 10 - code app android