Java.choose를 활용해 힙에서 인스턴스된 객체를 찾아보기
이번 시간에는 프리다(Frida)의 Java.choose 기능을 사용해 힙 메모리에서 인스턴스화된 객체를 탐색하는 방법을 다뤄보겠습니다. 특히 android.view.View 객체를 찾아보고, 그 결과를 분석하는 과정을 단계별로 살펴보겠습니다.
힙에서 android.view.View 객체 찾기
android.view.View는 안드로이드 애플리케이션에서 화면에 보이는 모든 UI 요소(버튼,이미지,텍스트 등)를 나타내는 기본 클래스입니다. 이 클래스는 애플리케이션이 시각적 요소를 구성하는 핵심 역할을 합니다.
아래는 Java.choose를 사용해 힙에서 android.view.View 객체를 찾는 자바스크립트 코드입니다.
setImmediate(function () {
Java.perform(function () {
Java.choose("android.view.View", {
onMatch: function (instance) {
console.log("[*] Instance found: " + instance);
},
onComplete: function () {
console.log("[*] Finished heap search");
}
});
});
});
setlmmediate : 비동기적으로 코드를 실행하도록 예약합니다. 프리다에서 메인 스레드가 블록되지 않도록 하기 위해 사용됩니다.
Java.perform : 안드로이드의 Java 런타임에 접근해 작업을 수행할 수 있게 합니다. 이 함수 안에서 Java 관련 작업을 정의합니다.
Java.choose : 힙 메모리에서 지정된 클래스(andrioid.view.View)의 인스턴스를 검색합니다. 두 개의 콜백 함수를 받습니다🔻
onMatch :조건에 맞는 인스턴스를 찾을 때마다 호출됩니다. 여기서 각 인스턴스를 콘솔에 출력합니다.
onComplete : 검색이 완료되면 호출되며, 작업 종료를 알립니다.
console.log : 프리다 콘솔에 메시지를 출력합니다. onMatch에서는 찾은 인스턴스를, onComplete에서는 검색 종료 메시지를 표시합니다.
코드 실행 준비
위 코드를 log_3.js라는 파일로 저장합니다. 저장 경로는 이전 글에서 사용했던 C:\Users\사용자_이름으로 동일하게 설정하겠습니다.
CMD 창을 열어 frida -U org.mozilla.firefox -l log_3.js 를 입력합니다. 해당 코드를 실행 후 콘솔에 아래와 같은 출력이 나타납니다. 이는 android.view.View 인스턴스가 총 5개 발견되었으며, 더 이상 검색할 객체가 없음을 확인한 뒤"Finished heap search"가 출력된 결과입니다.
결과값 분석
실행 결과로 나온 출력은 다음과 같습니다.
[*] Instance found: android.view.View{993140d V.ED..... ........ 0,1168-900,1344} [*] Instance found: android.view.View{2c9afc2 V.ED..... ........ 0,1552-900,1600 #1020030 android:id/navigationBarBackground} [*] Instance found: android.view.View{57921d3 V.ED..... ........ 0,0-900,112 #7f090181 app:id/bottom_bar} [*] Instance found: android.view.View{913e110 V.ED..... ........ 0,112-900,114 #7f090180 app:id/bottomBarShadow} [*] Instance found: android.view.View{e69e409 VFED..... ........ 0,32-900,32} [*] Finished heap search
각 줄은 힙에서 발견된 android.view.View 인스턴스를 나타냅니다. 출력 형식을 하나씩 분석해보겠습니다.
android.view.View{993140d ...} :
android.view.View: 클래스 이름
993140d: 객체의 해시코드(메모리 주소의 고유 식별자)
V.ED..... 또는 VFED..... :
뷰의 상태 플래그(View Flags)를 나타냅니다.
V: Visible(보임)
E: Enabled(활성화됨)
F: Focused(포커스 받음)
D: Drawable(그릴 수 있음)
점(.): 해당 플래그가 비활성 상태임을 의미
0,1168-900,1344 :
뷰의 화면 좌표를 나타냅니다. 형식은 (left, top - right, bottom)
예: 0,1168-900,1344는 왼쪽 0px, 위쪽 1168px에서 오른쪽 900px, 아래쪽 1344px까지의 영역을 의미합니다.
#1020030 android:id/navigationBarBackground :
뷰의 ID(리소스 식별자). XML에서 정의된 경우 해당 이름이 표시됩니다.
예: navigationBarBackground는 네비게이션 바 배경을 나타냄.
#7f090181 app:id/bottom_bar :
애플리케이션 고유 ID. app:id는 앱에서 커스텀으로 정의한 리소스를 의미합니다.
예: bottom_bar는 하단 바 UI 요소일 가능성이 높습니다.
추가학습: 객체, 클래스, 인스턴스 이해하기
프로그래밍에서 자주 사용되는 개념인 객체, 클래스, 인스턴스를 좀 더 쉽게 이해하기 위해, "스마트폰" 예시를 들어 설명하겠습니다.
객체
뜻: 현실 세계에서 우리가 다룰 수 있는 구체적인 "것". 프로그래밍에서는 데이터를 속성과 기능으로 표현한 것입니다.
예: 스마트폰
클래스
뜻: 객체를 만들기 위한 설계도 또는 틀. 객체의 속성과 동작을 정의입니다.
예: 스마트폰 설계도
인스턴스
뜻: 클래스를 기반으로 실제로 생성된 구체적인 객체.
예: 갤럭시 S23, 아이폰 14, 샤오미 13
Java.choose를 사용하면 힙 메모리에서 원하는 클래스의 인스턴스를 쉽게 탐색할 수 있습니다. 이번 예제에서는 android.view.View 객체를 찾아 UI 요소를 확인했으며, 출력 결과를 분석해 각 인스턴스의 역할도 유추해봤습니다.