---
# System prepended metadata

title: ssl pinning
tags: [CyberJutsu]

---

# ssl pinning

## 1. Cài đặt Frida, rms
### 1. Cài đặt Frida
với tùy chọn ```--force-reinstall```, bắt buộc pip gỡ bản hiện tại (nếu có) và cài lại từ đầu, kể cả khi phiên bản đã đúng.
```
pip install --force-reinstall frida-tools==12.2.1 frida==16.1.4
```


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

- Cài đặt frida-server tại github https://github.com/frida/frida/releases (Releases · frida/frida) hoặc tải file frida-server https://github.com/trongngk/tmp/releases/download/checklist/frida-server-16.1.4-android-x86_64

- Sao chép frida server vào máy ảo emulator
```
$ adb root # Sử dụng quyền root
$ adb push <file frida server> /data/local/tmp
Cấp quyền cho Frida server.
$ adb shell 
$ chmod 755 /data/local/tmp/<file frida server>
Chạy frida server:
./<file frida sever>
```
![image](https://hackmd.io/_uploads/SyuSOP_7ge.png)


- Trên máy windows chạy frida để check kết nối đến frida-server

```
frida-ps -U
```

-  Chạy script để bypass SSL Pinning

```javascript!
frida -U -f <Package name> -l <script> 
```

### 2. Cài đặt RMS
- RMS là một UI + framework wrapper cho Frida nhằm đơn giản hóa quá trình hook, monitor, và phân tích ứng dụng Android Java/Kotlin.
-  RMS (Runtime Mobile Security) hoạt động hoàn toàn dựa trên môi trường của Frida.
-  RMS (Runtime Mobile Security) hiện tại chỉ hỗ trợ ứng dụng Android viết bằng Java hoặc Kotlin


1. Cài đặt nodejs và npm
2. Cài đặt RMS theo các bước sau

```!
git clone https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security.git
cd RMS-Runtime-Mobile-Security
npm install (local installation)
Launch RMS via node rms.js



You can also install RMS as global package by running the following commands:
npm install -g to install dependencies
npm run compile to compile the frida-agent
rms to run RMS (anywhere)
```


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

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

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

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


Khởi chạy RMS: Tương tự như frida, lựa chọn package name và script để chạy

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

#### Load APIs Monitors
![image](https://hackmd.io/_uploads/ryIxJduXeg.png)

- là tập hợp các điểm hook có sẵn được chuẩn bị trước bằng các script Frida
- Khi Cường tick chọn một chức năng (ví dụ: Crypto, Clipboard, SharedPreferences...), RMS sẽ nạp sẵn script Frida tương ứng để hook các API/hàm thuộc nhóm đó.

Khi app thực thi những hàm đó, Frida sẽ log thông tin, dữ liệu, argument, kết quả,

Vì vậy:
🔸 Nếu app không dùng API đó, thì hook vẫn chạy, nhưng không log gì cả.
🔸 Không có quét tĩnh trước để phát hiện app có dùng hay không.




| STT | Nhóm API                      | Mô tả                                                                 |
|-----|-------------------------------|----------------------------------------------------------------------|
| 1   | Device Info                   | Lấy thông tin thiết bị (IMEI, model, Android ID, v.v.)               |
| 2   | Device Data                   | Truy cập dữ liệu thiết bị như địa chỉ MAC, IP, v.v.                  |
| 3   | Permissions                   | Theo dõi việc truy cập/cấp quyền runtime                             |
| 4   | Process                       | Quản lý tiến trình, PID, phân tích fork/exec                         |
| 5   | Commands Execution            | Theo dõi việc app chạy shell command (như `exec`, `su`, `ls`)       |
| 6   | Dex Class Loader              | Hook khi app load thêm `.dex` hoặc thư viện Java động               |
| 7   | Java Native Interface (JNI)   | Hook các hàm gọi qua JNI sang thư viện native (C/C++)                |
| 8   | IPC                           | Inter-Process Communication, hook giao tiếp giữa app và service khác|
| 9   | Binder                        | Hook các giao tiếp qua Android Binder (service system)              |
| 10  | System Manager                | Hook các API truy cập service hệ thống Android                      |
| 11  | WebView                       | Theo dõi hoạt động WebView (tải URL, inject code, v.v.)             |
| 12  | SharedPreferences             | Theo dõi truy cập, ghi/đọc dữ liệu trong SharedPreferences           |
| 13  | Database                      | Hook truy cập SQLite, Room, Realm, v.v.                              |
| 14  | Bluetooth                     | Hook API liên quan đến Bluetooth                                     |
| 15  | SMS                           | Gửi, nhận, đọc tin nhắn SMS                                          |
| 16  | Audio/Media/Screen Recording  | Ghi âm, chụp ảnh, quay video hoặc ghi màn hình                       |
| 17  | Clipboard                     | Hook clipboard: sao chép/dán                                         |
| 18  | Accessibility - a11y         | Hook các API liên quan đến accessibility (hay dùng trong spyware)    |
| 19  | Clicks - MotionEvent          | Hook touch event, nhấn, click, gesture                               |
| 20  | Crypto                        | Hook API mã hóa (AES, RSA, Cipher, v.v.)                             |
| 21  | Hash                          | Theo dõi hàm băm (MD5, SHA1, SHA256...)                              |
| 22  | Base64 encode/decode         | Theo dõi việc encode/decode dữ liệu bằng Base64                     |
| 23  | Compression - Gzip           | Theo dõi nén/giải nén dữ liệu                                        |
| 24  | JSON                          | Hook thao tác JSON (parse, stringify)                                |
| 25  | String                        | Theo dõi xử lý chuỗi                                                 |
| 26  | String Comparison             | Theo dõi việc so sánh chuỗi (hay dùng để kiểm tra root/Jailbreak)   |
| 27  | Network                       | Hook các kết nối mạng (HTTP, HTTPS)                                  |
| 28  | Socket                        | Hook tạo và dùng socket (TCP/UDP)                                   |
| 29  | FileSystem - Java             | Theo dõi thao tác file qua API Java (FileInputStream, FileWriter...) |
| 30  | FileSystem - Native           | Hook thao tác file native (`open`, `read`, `write`, v.v.) *(Hook riêng lẻ)* |

#### Load Default Frida Scripts

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

-🔧 Danh sách các Frida Custom Scripts trong RMS

Đây là các script Frida được viết sẵn để:

- 🛡️ Bypass các cơ chế bảo vệ (debugger, root, SSL pinning, emulator...).
- 🔍 Hook các hàm quan trọng để lấy dữ liệu nhạy cảm.
- 🧩 Phân tích class Java/native, unpack Dex, dump info...

- 📋 Danh sách & Mô tả

| STT | Tên Script | Mô tả |
|-----|------------|-------|
| 1 | `debugger_conneted_bypass.js` | Bypass `Debug.isDebuggerConnected()` / `ptrace` để tránh bị phát hiện debug. |
| 2 | `dex_classes_enumeration.js` | Liệt kê toàn bộ các class trong app (Java). |
| 3 | `dex_dump_unpacker.js` | Dump dex đang chạy trong memory (khi app pack). |
| 4 | `emulator_detection_bypass.js` | Bypass các check xem app có đang chạy trên giả lập (emulator) không. |
| 5 | `enum_all_native_lib_exports.js` | Liệt kê toàn bộ hàm được export từ thư viện native (lib*.so). |
| 6 | `enum_native_lib_exports.js` | Giống cái trên, có thể giới hạn theo thư viện cụ thể. |
| 7 | `file_system_monitor.js` | Hook các truy cập file (mở, đọc, ghi...) để xem app làm gì với file. |
| 8 | `fingerprint_bypass_1.js` | Bypass xác thực vân tay – kỹ thuật 1. |
| 9 | `fingerprint_bypass_2.js` | Bypass xác thực vân tay – kỹ thuật 2. |
| 10 | `flag_secure_bypass.js` | Bỏ cờ `FLAG_SECURE` (chặn chụp màn hình) để có thể capture. |
| 11 | `get_android_id.js` | Hook API lấy `ANDROID_ID`. |
| 12 | `get_app_env_info.js` | Lấy thông tin về môi trường của app (path, package, version...). |
| 13 | `hook_JNI_by_address.js` | Hook JNI native function bằng địa chỉ cụ thể. |
| 14 | `intercept_crypto.js` | Hook các hàm mã hóa/giải mã để lấy plaintext/key. |
| 15 | `load_stetho.js` | Tải module `Stetho` nếu app có dùng (debugging tool của Facebook). |
| 16 | `native_hook_template.js` | Template mẫu để tự viết script hook native. |
| 17 | `root_detection_bypass.js` | Bypass phát hiện máy đã root. |
| 18 | `ssl_pinning_multi_bypass.js` | Bypass nhiều kiểu SSL pinning trong một script. |
| 19 | `ssl_pinning_okhttp3_bypass.js` | Bypass SSL pinning dành riêng cho thư viện OkHttp3. |
| 20 | `ssl_pinning_uni_bypass_1.js` | Universal SSL pinning bypass kỹ thuật 1. |
| 21 | `ssl_pinning_uni_bypass_2.js` | Universal SSL pinning bypass kỹ thuật 2. |
| 22 | `ssl_pinning_uni_bypass_CA.js` | Bypass bằng cách can thiệp vào CA hoặc TrustManager. |

---

💡 Khi nào nên dùng?

- Khi cần **bypass bảo vệ** để phân tích hoặc hook.
- Khi muốn **lấy thông tin bị mã hóa** hoặc bị che giấu.
- Dễ dàng test: tick script → khởi chạy app → quan sát log.

> ✅ Có thể dùng nhiều script cùng lúc nếu không xung đột.

🔍 So sánh: API Monitors vs Frida Custom Scripts (RMS)

| Tiêu chí             | **API Monitors**                                      | **Frida Custom Scripts**                                         |
|----------------------|--------------------------------------------------------|------------------------------------------------------------------|
| 🎯 Dành cho ai       | Người mới / trung cấp                                 | Trung cấp / nâng cao                                             |
| 🧠 Hook gì           | API Java Android                                       | Java + Native (lib.so, JNI)                                     |
| 🎯 Mục tiêu          | Theo dõi hành vi API                                   | Bypass bảo vệ, trích xuất sâu                                   |
| 🧩 Giao diện         | Dạng checkbox chọn sẵn                                 | Dạng file `.js` chạy theo ý người dùng                         |
| 🛠️ Cách hoạt động   | Hook sẵn các API Android để log                       | Chạy script tùy chỉnh từ thư mục `custom_scripts/`              |
| 🚀 Ưu điểm           | Dễ dùng, bao quát nhiều hành vi ứng dụng               | Hook sâu, hỗ trợ bypass, trích xuất nâng cao                    |
| ⚠️ Giới hạn          | Không hook được native, có thể không tương thích hoàn toàn | Cần hiểu rõ Frida/Android để viết và chỉnh sửa script           |

---

#### 📱 RMS (Runtime Mobile Security) hỗ trợ app gì?

##### ✅ Hỗ trợ tốt

| Thành phần ứng dụng Android           | Hỗ trợ | Ghi chú |
|--------------------------------------|--------|---------|
| Java API (`android.*`)               | ✅ Có   | RMS hook tốt các API Java Android |
| Kotlin                               | ✅ Có   | Kotlin biên dịch ra bytecode Java nên hoạt động tương tự |
| Java Native Interface (JNI)          | ✅ Có   | Có thể hook các hàm native thông qua Frida |
| Native Libraries (`.so`, C/C++)      | ⚠️ Có giới hạn | Hook được nếu biết địa chỉ hoặc export cụ thể |

---

##### ❌ Không hỗ trợ hoặc hỗ trợ kém

| Loại ứng dụng                        | Hỗ trợ | Ghi chú |
|--------------------------------------|--------|---------|
| Flutter                              | ❌ Không | RMS không hook được code Dart runtime |
| React Native                         | ❌ Không | Hook JavaScript runtime là không khả thi qua RMS |
| Unity (C# / IL2CPP)                  | ❌ Không | Không hook được logic C# hoặc engine Unity runtime |
| WebView nội dung (HTML/JS)          | ❌ Không | RMS không hook được nội dung trang web trong WebView |
| Ứng dụng iOS                         | ❌ Không | RMS chỉ dành cho Android |

---

##### 🤔 Tại sao lại như vậy?

- RMS dựa trên **Frida** để hook vào:
  - Các API Java (Android runtime)
  - JNI & native library (`.so`)
- App Flutter, Unity, React Native sử dụng runtime riêng biệt (Dart VM, IL2CPP, JavaScriptCore...), nên **không bị hook bằng kỹ thuật Java truyền thống**.

---

##### 🧰 Vậy dùng gì nếu không phải app Java?

| Loại app         | Gợi ý công cụ thay thế RMS             |
|------------------|-----------------------------------------|
| Flutter          | Ghidra, JADX, hoặc Frida + reverse memory |
| React Native     | Objection, Frida + manual script         |
| Unity (C#)       | Ghidra, Il2CppDumper, dnSpy              |
| iOS              | Frida, Objection, Cycript, LLDB          |

> ⚠️ Với app không phải Java/Kotlin, sẽ cần kết hợp nhiều công cụ và kiến thức reverse nâng cao hơn.

## 2. Bypass SSL Pinning bằng frida/RMS

### APP Viettel money
- app viettel monney sẽ có key mã hóa giải mã cho từng thiết bị trả về trong response khi lần đầu tải và đăng nhập app

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

- lấy được private key của client và public key của serrver
- cần dùng key này để mã hóa giải mã request


```
client_private_key=MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgK4Wy6HuPEcXPtPylnSyMRmLj6qBwnSSQ5oiPOmT8YTqyCXc3A/pKzeGLS5rL4UExS+cWbnuEJk1TDl4KB/gx6FyNENfIVufasYH1yRs2WA9tK1d2JXp67/dRie4qb3O0es9lf7NHZ7IqXotXL60p9AlfXsaNHGOEibe+Jbq+9Cqk0qOUi/4p0ubFx0cHDMQcP3AnEjq/+SbPF8aI0/cV5VlbLQLwBlfruzlscmpfrUUARtpuQusDrSMtoOf7M3a+ZRzYNvmH9X/04UPNCnmgd8ovsKLJhzCpZj3SpTm5reCUhR1tJ8XADP9xRJgZQZfOk1wB/gzHvK3+m8Yiz0PLAgMBAAECggEARbWLc+kg1YyrphGkH8Q/PjHoGj/kYf7Sikn7RzLn/rumWxQpkYUmquXd8s0N6wv3XqglRCsDkOlGoA5RuVXsnHP/y9l3wJaqRBEbech0EnvTAvVpFF+NZfIIlrFMOaXWGseUeh1Q/pPQBAav6Fs0p1yxs5NBIOspGOcDVDuBgld6y/15uogcRQ9Gjmhc5h03As3fj8lprs8AVFJcPvP4PHvRxDmcqAwEbxMNatmsxXywl68p2aEVwQe4jOgoLbWOtUubxq77UrKFsu3S9sJJstS653xn1VUaUd2/2u0WEBPqJP7ooX1h70FOj/ah4voPs1zTnWcsAnLq5WTOF+vc0QKBgQDi7GzkUJyQSF9BDTPokOiMkVxOmMGfvH88U+2c1bgB4RAY20EA4kgHspf5JwKmZCwqdD4jU2AYkWJaDm9+qd6r//JcuiG96E6cYuipG3WV+HP9IiHL9IcxoI5lXwRqszkYioDMEwC1C3o4hkJbXYeFT/bA7zUDCjp5/wxtnzenuQKBgQC0sXBwawYVne0jp7Gqo4l9/SI90mj4EQyyAZSMysr5COPOuHQQeI9zEGv5CS0Z36+cz1UW6tMH/dWggN0pCdZIWCnzrW/taFSAfSA/rgZwh7onG7ofr6nmbwsUGpXpsrVrPHmb9aOZ/AglxAAu6jyjN1Ef2cI7K5A12ClUQNXBowKBgGf4IRAeqw0kS5hXf0AAHLxC4YMVVClmyPkQDx87gHpD7wckdcz84Dm+pwi9yeYIoX+2EL5Itg+rlN9kG8tx8xblRtsbYNhM9q+KVcUdUquq0SHaoJd86vBe+r8RYMmuYeuPkeFul3Vb09zQDtkjqjL3ZzwQnT5OUmqQ49XaDDrpAoGAYJZY3D7ZScTZdi21stkoLciZ/SH0KmYyuxRNK9VbGjO+UkoXAJbxVzh3/u8AxMvlO5U4jr+HfsYY42r+zWkMui8mfbNAGU+jm+tGycNkfdKPl0gi/b0QvLSu31g2um1kvKXe+5calL08PbO/xVRAhZ6UJspoIOjwdVfO/9KIcLECgYEAhoxD5rReAmlrD0YNarAIKMDbEg7RddyFvrEnfztkW5hWjZne0tcfuhS1fq+raZ21ypfUnPm/yvX6WFFdrFDCDMKbD2g5WWzAwawI5pXJchAL2V6ydLS+1U/Cn8CVOh3TJSPNLeseG/YuLWt4XtRfms2LUsx4jFeVNk0HN/WH1Qg=
```



```
viettel_public_key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6oQ1Jh6+uMi7cYgc+t92NhgSaWymCGhRUdArFFS4oVjhMwjf0WAQ2wFMUiS88zQJmd7xYRU5+Nmo099UnX15sknEef2FPdHEd7OPMGodXedw6HL1uwKUunfW6uJ4NKzKNFIWaIU8Y3PpupfFee0dw+GgqUrNHRwwxLADJkvIMXQIDAQAB
```

- dùng RMS để hook loại bỏ mã hóa request chuyển vào burp suite 


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

- Nhấn chạy RMS


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

1. Load class => sẽ load tất cả các class được nạp tính đến thời điểm hiện tại trong bộ nhớ RAM (Check which Classes and Methods have been loaded in memory)

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

2. Insert a filter => chọn class để hook vào 

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

- tìm hàm class cryto xử lý mã hóa
![image](https://hackmd.io/_uploads/B1G-jMKQgx.png)

- chọn Hook selected

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

3. Load methods => để hiển thị các methods trong class vừa chọn

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

- ở dump tab không thể chọn các method để hook 
![image](https://hackmd.io/_uploads/r1GhaGt7gx.png)


- Chọn tab Hook lab để chọn method để hook

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

- chọn Select a class

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



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

- chọn Hook hàm encrypt => thấy có thể thấy được request dạng rõ

- tiếp theo cần mã hóa request gửi đi và đọc được response trả về bằng cách thêm 1 header để đọc
- tải mitmproxy
```
pip install mitmproxy
```

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

- copy source code mã hóa, giải mã và convert sang code python 
![image](https://hackmd.io/_uploads/SJZuovYXlx.png)

- đoạn code mã hóa giải mã sẽ được áp dụng trong mitm

```python!
from termcolor import colored
import base64
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
from Crypto.Util.Padding import pad, unpad
from Crypto.Hash import SHA1
from mitmproxy import http
import re
import html

public_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6oQ1Jh6+uMi7cYgc+t92NhgSaWymCGhRUdArFFS4oVjhMwjf0WAQ2wFMUiS88zQJmd7xYRU5+Nmo099UnX15sknEef2FPdHEd7OPMGodXedw6HL1uwKUunfW6uJ4NKzKNFIWaIU8Y3PpupfFee0dw+GgqUrNHRwwxLADJkvIMXQIDAQAB"

private_key = open('private_key.pem', 'r').read()

def a(string):
    return base64.b64decode(string)


def b(string, key, bool):
    private_key = f(key, bool)
    cipher = PKCS1_v1_5.new(private_key)
    replace = string.replace("\r", "").replace("\n", "")
    bit_length = private_key.size_in_bits() // 8
    i = bit_length % 3
    i2 = (bit_length // 3) * 4
    if i != 0:
        i2 += 4
    length = len(replace) / i2
    i3 = 0
    encrypted_blocks = []
    # for block in replace.split("=="):
    #     block += "=="
    for i4 in range(0, len(replace)):
        i5 = i2 * i4
        part = replace[i5:i5+i2]
        block_bytes = part.encode('utf-8')
        if len(block_bytes) == 0:
            break
        encrypted_block = cipher.decrypt(h(a(block_bytes)), None)
        encrypted_blocks.append(encrypted_block)
    decrypted_data = b''.join(encrypted_blocks)
    return decrypted_data.decode('utf-8').strip()


def c(data):
    return base64.b64encode(data).decode('utf-8')


def d(string, key, bool):
    public_key = g(key, bool)
    cipher = PKCS1_v1_5.new(public_key)
    bit_length = (public_key.size_in_bits() // 8) - 42
    bytes = string.encode('utf-8')
    length = len(bytes)
    i = length // bit_length
    encrypted_blocks = []
    # padded_data = pad(string.encode('utf-8'), block_size)
    for i2 in range(0, i + 1):
        i3 = bit_length * i2
        i4 = length - i3
        to = i4
        if to > bit_length:
            to = bit_length
        # print("start at ", i3, " to ", i3 + to)
        byte_block = bytes[i3: i3 + to]
        encrypted_block = cipher.encrypt(byte_block)
        encrypted_block = h(encrypted_block)
        encrypted_blocks.append(c(encrypted_block))
        # print(c(encrypted_block))
    encrypted_data = ''.join(encrypted_blocks)
    return encrypted_data.replace("\r", "").replace("\n", "")


def e(file_path):
    with open(file_path, 'rb') as file:
        return file.read().decode('utf-8').strip()


def f(key, bool):
    key_data = e(key) if bool else key.strip()
    key_data = key_data.replace("-----BEGIN PRIVATE KEY-----", "").replace(
        "-----END PRIVATE KEY-----", "").replace("\n", "").replace("\r", "").replace(" ", "")
    return RSA.import_key(a(key_data))


def g(key, bool):
    try:
        key_data = e(key) if bool else key.strip()
        return RSA.import_key(a(key_data))
    except:
        return None


def h(data):
    return data[::-1]


def i(string, key, bool):
    private_key = f(key, bool)
    signer = pkcs1_15.new(private_key)
    signature = signer.sign(string.encode('utf-8'))
    return c(signature).replace("\r", "").replace("\n", "")


def j(string, signature, key, bool):
    public_key = g(key, bool)
    verifier = pkcs1_15.new(public_key)
    return verifier.verify(string.encode('utf-8'), a(signature))


def signature(data, private_key, bool):
    m2 = g(private_key, bool)
    signer = pkcs1_15.new(m2)
    h = SHA1.new(data.encode())
    signature = signer.sign(h)
    return base64.b64encode(signature).decode().replace("\r", "").replace("\n", "")




def request(flow: http.HTTPFlow):        
    content_type = flow.request.headers.get("Content-Type", "")
    if "text/xml" not in content_type:
        return

    # Đọc request body
    body = flow.request.get_text()
    if "SETUP_SOFTWARE" in body:
        return
    # Regex extract
    encrypted_match = re.search(r"<encrypted>(.*?)</encrypted>", body, re.DOTALL)
    
    encrypted = encrypted_match.group(1) if encrypted_match else None
    
    encryp_data = d(encrypted, public_key, False)
    sign_data = signature(encrypted, private_key, False)
    body = re.sub(r"<encrypted>.*?</encrypted>", f"<encrypted>{encryp_data}</encrypted>", body, flags=re.DOTALL)
    body = re.sub(r"<signature>.*?</signature>", f"<signature>{sign_data}</signature>", body, flags=re.DOTALL)
    flow.request.set_text(body)
    
def response(flow: http.HTTPFlow):
    global private_key
    content_type = flow.request.headers.get("Content-Type", "")
    if "text/xml" not in content_type:
        return

    body = flow.response.get_text()
    private_key_match = re.search(r"client_private_key=([A-Za-z0-9+/=]+)", body)
    if private_key_match:
        private_key = private_key_match.group(1)
        with open("private_key.pem", "w") as f:
            f.write(private_key)

        print("[+] Found client private key and saved to private_key.pem")
        pass
    else:
        encrypted_match = re.search(r"<return>encrypted=(.*?)&amp;signature=", body, re.DOTALL)
        return_content = encrypted_match.group(1) if encrypted_match else None
        if return_content:
            return_content = html.unescape(return_content)
            decrypted_data = b(return_content, private_key, False)
            decrypt_header =  decrypted_data[:1000]
            flow.response.headers["X-Decrypted-Data"] = decrypt_header

```

- chạy mitm với 
```
mitmdump -s mitmproxy.py --listen-port 8088
```

- để burp qua proxy 127.0.0.1

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

- thấy bắt được request dạng rõ và ứng dụng hoạt động bình thường


![image](https://hackmd.io/_uploads/BJX2-UFQlx.png)

- ngoài ra có thể chạy luôn frida để hook mà ko cần vào RMS với lệnh sau 
```
frida -U -f com.bplus.vtpay -l .\hook.js
```


```
Java.perform(function () {
    var classname = "com.bplus.vtpay.ws.Crypto";
    var classmethod = "decrypt";
    var methodsignature = "public static java.lang.String decrypt(java.lang.String,java.lang.String,java.lang.Boolean) throws java.lang.Exception";
    var hookclass = Java.use(classname);


    hookclass.decrypt.overload("java.lang.String", "java.lang.String", "java.lang.Boolean").implementation = function (v0, v1, v2) {
        send("[Call_Stack]\nClass: " + classname + "\nMethod: " + methodsignature + "\n");
        var ret = this.decrypt(v0, v1, v2);


        send("Decrypted Data: " + ret);

        return ret;
    };

    var classname = "com.bplus.vtpay.ws.Crypto";
    var classmethod = "encrypt";
    var methodsignature = "public static java.lang.String encrypt(java.lang.String,java.lang.String,java.lang.Boolean) throws java.lang.Exception";
    var hookclass = Java.use(classname);

    hookclass.encrypt.overload("java.lang.String", "java.lang.String", "java.lang.Boolean").implementation = function (v0, v1, v2) {

        send("Encrypted Data: " + v0);

        return v0;
    };


});
```

### Mobifone money app

1. Decrypt request
- Sau khi truy cập được app thành công thì lại xuất hiện thêm 1 vấn đề. đó là app mã hóa request và response, dẫn đến không thể đọc được những gì ứng dụng gửi đi, từ đó khó khăn trong việc inject payload, vậy nên ta sẽ cần tiếp tục tìm ra key mã hóa data, sau đó giải dữ liệu.

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

Truy cập chức năng `Load Frida Script`

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

- Chọn `tracer_cipher.js`


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

Sử dụng script có sẵn ta đã có thể lấy được request trước khi mã hóa. Tuy nhiên cần tìm Key để tiện cho việc pentest luôn

Chỉnh sửa script `tracer_cipher.js` một chút để in ra key dưới dạng base64

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

Paste lại script vào trang `load_frida_script` và chạy

https://github.com/trongngk/tmp/blob/main/hookfrida_getkey.js

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

Lấy được key, sử dụng python để check lại key đã đúng chưa

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


https://github.com/trongngk/tmp/blob/main/encryptwithkey_3DES.py

(Ứng dụng sử dụng thuật toán 3DES là mật mã khóa đối xứng nên key giải mã và mã hóa là giống nhau). 


## 3. Bypass SSL Pinning bằng reverse apk
