Quay lại blog

Cách tìm API ẩn của ứng dụng di động: mitmproxy, Frida và proxy trong năm 2026

Trang web sử dụng Cloudflare, trong khi ứng dụng di động của cùng một dịch vụ nhận được JSON sẵn mà không có bất kỳ thử thách nào. Chúng ta sẽ phân tích cách tìm API ẩn này: cấu hình mitmproxy, kho chứng chỉ hệ thống trên Android, gỡ bỏ certificate pinning qua Frida, xuất yêu cầu sang curl — và tại sao việc mở rộng lại phụ thuộc vào việc xoay vòng IP.

📅1 tháng 8, 2026
Cách tìm API ẩn của ứng dụng di động: mitmproxy, Frida và proxy trong năm 2026
```html

Trang web bị đóng bởi Cloudflare, Turnstile xuất hiện ở mỗi yêu cầu thứ hai, và bố cục thay đổi mỗi hai tuần. Trong khi đó, dịch vụ cùng có một ứng dụng di động, kết nối trực tiếp với backend và nhận được JSON đã hoàn thành - không có thách thức, không có định dạng, với sơ đồ trường ổn định. Đây chính là "API ẩn": giao diện không được tài liệu hóa, nhưng hoàn toàn hoạt động, mà khách hàng chính thức sử dụng.

Chúng ta sẽ phân tích từng bước, cách tìm nó bằng mitmproxy, cách xử lý với certificate pinning và lý do tại sao trong giai đoạn mở rộng thu thập mà không có proxy mọi thứ lại sụp đổ.

Tại sao lại phải can thiệp vào lưu lượng của ứng dụng

Scraping phiên bản web và gọi API riêng tư là những nhiệm vụ có chi phí khác nhau. So sánh:

  • Web. Cần một trình duyệt headless, vượt qua anti-bot, phân tích HTML, sửa chữa các bộ chọn định kỳ. Một yêu cầu = megabyte lưu lượng và giây thời gian xử lý.
  • API riêng tư. Một yêu cầu HTTP thông thường với một vài tiêu đề, phản hồi - JSON gọn nhẹ với các trường kiểu. Thường cung cấp nhiều dữ liệu hơn so với giao diện hiển thị: các định danh nội bộ, cờ, các trường dịch vụ.

Các backend di động lịch sử được bảo vệ yếu hơn so với web. Nguyên nhân rất đơn giản: các nền tảng chống bot được thiết kế cho lưu lượng trình duyệt (thách thức JS, canvas, tín hiệu hành vi), và khách hàng di động sẽ không thể vượt qua chúng. Thay vào đó, các nhà phát triển dựa vào khóa tĩnh của ứng dụng và TLS-pinning - cả hai đều được gỡ bỏ trên thiết bị cục bộ.

Những gì cần thiết

  1. mitmproxy - một trình chặn proxy HTTPS mã nguồn mở (hơn 44.000 sao trên GitHub, nhánh hiện tại 12.2.2 ra mắt vào tháng 4 năm 2026, yêu cầu Python 3.12+). Cài đặt bằng một lệnh: pip install mitmproxy. Hiểu HTTP/1, HTTP/2, HTTP/3, WebSocket và TCP thô, hoạt động với TLS 1.2 và 1.3.
  2. Thiết bị Android hoặc trình giả lập có root. Thực tiễn cho thấy, tiện lợi nhất là Android 7–11: các phiên bản mới đã thắt chặt việc làm việc với chứng chỉ rất nhiều.
  3. ADB để kết nối với thiết bị và Frida (pip install frida-tools) - sẽ cần nếu ứng dụng pin chứng chỉ.

Mitmproxy có ba giao diện trên cùng một động cơ: mitmproxy (TUI trong terminal), mitmweb (giao diện web, tiện hơn cho người mới) và mitmdump (headless, cho các kịch bản và tự động hóa).

Bước 1. Khởi động trình chặn

Khởi động giao diện web sao cho nó lắng nghe các kết nối bên ngoài, không chỉ localhost:

mitmweb --web-host 0.0.0.0

Mặc định, proxy khởi động trên cổng 8080. Khi khởi động lần đầu, mitmproxy tạo một trung tâm chứng nhận riêng và đặt các khóa vào thư mục ~/.mitmproxy. Ở đó sẽ xuất hiện bốn tệp: mitmproxy-ca.pem (chứng chỉ cùng với khóa riêng), mitmproxy-ca-cert.pem (chỉ chứng chỉ), mitmproxy-ca-cert.p12 cho Windows và mitmproxy-ca-cert.cer - định dạng cho Android.

Bước 2. Định hướng thiết bị qua proxy

Trong cài đặt Wi-Fi trên điện thoại, chọn proxy thủ công: IP của máy tính của bạn trong mạng cục bộ và cổng 8080. Tiếp theo, mở trình duyệt của thiết bị đến miền đặc biệt mitm.it - đây là trang tích hợp trong mitmproxy, tự động xác định nền tảng và cung cấp định dạng chứng chỉ cần thiết với hướng dẫn.

Trên iOS, quy trình bao gồm ba phần, và nửa sau thường bị mọi người quên: tải xuống hồ sơ qua Safari, cài đặt nó trong "Cài đặt → Chung → VPN và quản lý thiết bị", và sau đó tách biệt bật độ tin cậy hoàn toàn trong "Cài đặt → Chung → Về thiết bị này → Tin cậy chứng chỉ". Nếu không có bước cuối cùng, chứng chỉ đã được cài đặt nhưng không hoạt động.

Nếu không muốn lăn tăn với cài đặt Wi-Fi, mitmproxy có chế độ máy chủ VPN: mitmweb --mode wireguard. Thiết bị kết nối bằng khách hàng WireGuard tiêu chuẩn, và lưu lượng được chặn một cách minh bạch, không cần cài đặt proxy thủ công trong hệ thống.

Bước 3. Bức tường chính - độ tin cậy của chứng chỉ

Ở đây hầu hết các nỗ lực bị thất bại. Có hai vấn đề, và đó là hai vấn đề khác nhau.

CA tùy chỉnh không được ưa chuộng từ năm 2016

Bắt đầu từ Android 7 Nougat (API 24), các ứng dụng theo mặc định chỉ tin tưởng vào kho chứng chỉ hệ thống. CA tùy chỉnh bị bỏ qua nếu nhà phát triển không rõ ràng cho phép nó trong Network Security Config - thông qua khối <certificates src="user" /> trong trust anchors. Đây là một quyết định có chủ đích của Google nhằm giảm bề mặt tấn công, và không thể vượt qua nó bằng cài đặt điện thoại. Chrome, thực tế, cũng không tin tưởng vào chứng chỉ tùy chỉnh. Trong Android 11, các hạn chế đã được thắt chặt hơn nữa.

Kết luận thực tiễn: trên thiết bị có root, chứng chỉ mitmproxy cần được đặt trong kho chứng chỉ hệ thống, không phải trong kho người dùng. Đó là lý do tại sao root có trong danh sách yêu cầu, chứ không phải "mong muốn".

Certificate pinning

Bức tường thứ hai - pinning: ứng dụng mang theo dấu vân tay của chứng chỉ máy chủ mong đợi và từ chối giao tiếp với bất kỳ ai khác. Ngay cả CA hệ thống cũng không cứu được. Nghiên cứu của ACM năm 2022 cho thấy pinning phổ biến trong các lĩnh vực "rủi ro cao" (ngân hàng, taxi, tiền điện tử), nhưng thường được thực hiện không đầy đủ và do đó có thể bị vượt qua.

Có một vài công cụ cho nhiệm vụ này, và chúng giải quyết nó theo nhiều cách khác nhau:

  • Frida - chỉnh sửa hành vi trong thời gian chạy: chúng ta hook các hàm kiểm tra chứng chỉ và buộc chúng trả về thành công. Ứng dụng trong trường hợp này không bị sửa đổi - đây là lựa chọn linh hoạt nhất. Khởi động điển hình: frida -U -f com.target.app -l ssl_bypass.js --no-pause.
  • apk-mitm - tự động cắt pinning từ tệp APK một cách tĩnh.
  • android-unpinner - tái cấu trúc APK, nhúng Frida và các kịch bản gỡ bỏ pinning.
  • objection - bộ công cụ trên Frida, có thể làm việc với cả iOS và Android.
  • ssl-kill-switch2 - tắt pinning trong các ứng dụng iOS và macOS.

Nếu miền cụ thể bị pinning chặt chẽ và gây cản trở cho việc làm việc, có thể đơn giản loại trừ nó khỏi việc chặn bằng tùy chọn ignore_hosts (nhận biểu thức chính quy) - lưu lượng sẽ đi qua mitmproxy mà không được giải mã.

Bước 4. Tìm yêu cầu cần thiết

Tiếp theo - là công việc thường nhật. Mở ứng dụng, thực hiện đúng một hành động có ý nghĩa (mở thẻ sản phẩm, cuộn qua dòng thời gian, áp dụng bộ lọc) và xem những yêu cầu nào đã xuất hiện. Trong giao diện terminal, điều này được thực hiện nhanh chóng: Z xóa danh sách luồng, Enter mở yêu cầu đã chọn, E xuất nó - bao gồm cả lệnh curl đã hoàn thành.

Những gì cần tìm trong yêu cầu bị chặn:

  • Endpoint và tham số. Thường có nhiều hơn đáng kể so với những gì giao diện ứng dụng sử dụng.
  • Khóa khách hàng. Cổ điển - định danh tĩnh, được nhúng trong ứng dụng. Trong phân tích nổi tiếng về API công khai MyAnimeList, khóa này là tiêu đề x-mal-client-id với giá trị 6591a087c62b3e94d769cd8e35ffe909, mở quyền truy cập vào các endpoint api.myanimelist.net/v3/anime/season/v3/anime với hai chục tham số.
  • User-Agent. Đối với các khách hàng di động, nó rất đặc thù và là một phần của "giấy phép" - trong ví dụ đó là MAL (ios, 139).
  • Token và thời gian sống của chúng. Ngay lập tức xem, khóa có tĩnh hay không: điều này ảnh hưởng đến toàn bộ kiến trúc của bộ thu thập.

Curl đã xuất có thể dễ dàng chuyển đổi thành mã qua curlconverter - bạn sẽ nhận được yêu cầu sẵn sàng trên requests, và sau đó làm việc với HTTP client thông thường, không cần trình duyệt.

Bước 5. Mở rộng - và nơi mọi thứ bị hỏng

Tại đây, sự thất vọng đến, điều mà mọi người đã thử đều quen thuộc: từ một IP gia đình, API riêng tư phản hồi rất tốt trong nửa giờ đầu, và sau đó bắt đầu trả về 429 và 403. Các backend di động được bảo vệ yếu hơn khỏi việc giả mạo khách hàng, nhưng giới hạn theo IP thì nghiêm ngặt hơn - máy chủ giả định rằng một địa chỉ là một điện thoại, không phải một bộ phân tích với hai mươi luồng.

Từ đây, có những kết luận thực tiễn.

  1. Giữ cho hồ sơ yêu cầu có vẻ hợp lý. Ứng dụng thực tế không thực hiện 50 yêu cầu mỗi giây và không hoạt động theo lịch trình nghiêm ngặt. Thứ tự gọi cũng có ý nghĩa: khách hàng thực sự sẽ yêu cầu cấu hình phiên trước, sau đó là nội dung.
  2. Phân tán tải trọng qua các địa chỉ. Một IP = một "điện thoại". Về các chiến lược luân chuyển, độ trễ với jitter và exponential backoff đã được phân tích chi tiết trong tài liệu cách vượt qua giới hạn tỷ lệ API khi phân tích qua proxy.
  3. Xem xét địa lý. Nhiều API di động cung cấp nội dung và giá khác nhau tùy thuộc vào quốc gia của địa chỉ - đây vừa là hạn chế, vừa là cơ hội.

Việc gỡ lỗi thuận tiện hơn khi không rời khỏi mitmproxy: nó có thể kết nối với proxy cấp trên. Lệnh mitmdump --mode upstream:http://example.com:8081 chuyển toàn bộ lưu lượng đến upstream, và xác thực với nó được chỉ định bằng tùy chọn --upstream-auth theo định dạng username:password. Như vậy, bạn sẽ thấy những yêu cầu giống như trước, nhưng chúng đã đi từ địa chỉ bên ngoài - có thể ngay lập tức kiểm tra cách API phản ứng với một quốc gia hoặc loại IP cụ thể.

Loại proxy nào nên chọn cho API di động

Việc lựa chọn ở đây không phải là trừu tượng, nó xuất phát từ việc bạn đang giả vờ là ai.

  • Proxy di động - lựa chọn ưu tiên. Bạn đang giả lập lưu lượng của ứng dụng, và địa chỉ của nhà mạng trông hoàn toàn tự nhiên với backend: nhờ CGNAT, thực tế có hàng trăm thuê bao ngồi sau một địa chỉ, vì vậy giới hạn đối với những IP này nhẹ nhàng hơn. Các proxy di động 4G/LTE là phù hợp.
  • Proxy cư trú - lựa chọn giữa, nếu khối lượng lớn và không cần gắn bó với nhà mạng: IP gia đình của các nhà cung cấp mang lại độ phủ rộng về địa lý với giá cả hợp lý. Đây là proxy cư trú.
  • Proxy trung tâm dữ liệu - chỉ dành cho các endpoint không có kiểm tra nghiêm ngặt về độ tin cậy của địa chỉ. ASN của chúng được nhận diện ngay lập tức, và trên backend di động, điều này trông rất kỳ lạ: không có điện thoại trong các trung tâm dữ liệu.

Các cạm bẫy mà bạn sẽ biết muộn

  • HTTP/3. Hỗ trợ QUIC trong mitmproxy có và được bật theo mặc định, nhưng trên lưu lượng di động thực tế, nó bị hạn chế: thường phải ép buộc kết nối quay lại HTTP/2 thông qua các thao tác với ALPN. QUIC hoạt động tốt nhất trong các chế độ reverse và WireGuard.
  • API riêng tư thay đổi mà không báo trước. Nó không có nghĩa vụ về tính tương thích ngược - đây là giao diện nội bộ. Phiên bản ứng dụng trong User-Agent một ngày nào đó sẽ ngừng được phục vụ, và bộ thu thập sẽ lặng lẽ bắt đầu nhận được phản hồi trống rỗng. Theo dõi không chỉ mã phản hồi mà còn cả cấu trúc JSON.
  • Đừng nhầm lẫn giữa "tìm thấy khóa" và "nhận quyền." Khóa khách hàng tĩnh - không phải là sự cho phép cho việc thu thập không giới hạn.

Về khía cạnh pháp lý

Chặn lưu lượng trên thiết bị của riêng bạn là một thực tiễn hợp pháp và hàng ngày trong việc gỡ lỗi, được sử dụng bởi các nhà phát triển di động và chuyên gia bảo mật. Ranh giới bắt đầu từ đó: hãy tuân thủ các điều khoản sử dụng dịch vụ, không thu thập dữ liệu cá nhân mà không có cơ sở pháp lý (tại EU điều này được quy định trực tiếp bởi GDPR), không chạm vào các endpoint yêu cầu xác thực của người khác, và giữ tải trọng ở mức không cản trở hoạt động của dịch vụ. Hướng dẫn thực tiễn: nếu dữ liệu có thể nhìn thấy trong ứng dụng cho bất kỳ người dùng nào mà không cần đăng nhập vào tài khoản - bạn đang ở trong khu vực tương đối an toàn; nếu cần tài khoản của người khác để truy cập - bạn đã ra ngoài giới hạn đó.

Tóm tắt

Sơ đồ hoạt động và tiết kiệm hàng tuần lộn xộn với anti-bot: khởi động mitmproxy, đặt chứng chỉ vào kho chứng chỉ hệ thống của thiết bị có root, nếu cần gỡ bỏ pinning qua Frida, bắt một yêu cầu có ý nghĩa, xuất nó sang curl và viết lại trên Python. Tiếp theo, nhiệm vụ từ loại "vượt qua bảo vệ" chuyển thành nhiệm vụ "phân phối tải một cách cẩn thận" - và được giải quyết bằng cách luân chuyển địa chỉ, các khoảng dừng hợp lý và loại proxy phù hợp. Bắt đầu dễ nhất với proxy di động: chúng gần nhất với lưu lượng mà backend mong đợi thấy.

```