관리 메뉴

JHLBLUE

안드로이드 smali 패치 설명 본문

Android

안드로이드 smali 패치 설명

JHLBLUE 2019. 1. 15. 17:04

안드로이드 smali 패치하기에서 smali로 디코딩한 뒤 볼 수 있는 MainActivitry.smali의 전체 코드 및 설명은 아래와 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# 클래스의 이름 및 경로 정보
.class public Ljhlblue/ddns/net/sampleapk/MainActivity;
 
#해당 클래스가 상속받는 클래스 정보
.super Landroid/support/v7/app/AppCompatActivity;
 
#원래 프로젝트의 파일 이름
.source "MainActivity.java"
 
 
#다이렉트 메소드 정보
#다이렉트 메소드는 private 이거나 생성자(constructor)
# direct methods
.method public constructor <init>()V
 
    #해당 메소드에서 사용할 로컬 레지스터의 개수
    #locals가 1 이상일 경우에는 v0부터 v1, v2, ... 등의 레지스터를 사용할 수 있다.
    #locals의 값을 15 이상으로 설정한 뒤 빌드를 할 경우 Invalid register: v16. Must be between v0 and v15, inclusive라는 에러가 생성된다.
    # 아래 블로그 내용 참고
    # http://blog.rebforpwn.com/index.php/2018/01/23/599/
    # http://modapk.tistory.com/13
    .locals 0
 
    #실제 자바 코드와 매칭되는 줄번호
    .line 7
    #direct 메소드 AppCompatActivity 호출
    #{p0}은 해당 함수에 전달할 수 있는 파라미터이다.
    #이 부분에서 p0은 this를 의미한다.
    invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V
 
    return-void
.end method
 
 
# virtual methods
#.method 접근지정자 메소드이름(인자정보) 리턴타입
#onCreate라는 메소드의 접근지정자는 protected, 인자로는 android.os.Bundle 하나를 받으며 리턴 타입은 Void이다.
.method protected onCreate(Landroid/os/Bundle;)V
    .locals 1
 
    .line 11
    #상위 클래스의 메소드 onCreate를 호출
    invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
 
    #p1 레지스터에 데이터 0x7f09001b를 저장
    #const 레지스터이름 데이터
    const p1, 0x7f09001b
 
    .line 12
    invoke-virtual {p0, p1}, Ljhlblue/ddns/net/sampleapk/MainActivity;->setContentView(I)V
 

    const p1, 0x7f070083
 
    .line 14
    #java의 findViewById 함수를 호출하는 부분
    #해당 함수의 리턴값이 textview object이다.
    #java 코드의 TextView textView = findViewById(R.id.textview);
    invoke-virtual {p0, p1}, Ljhlblue/ddns/net/sampleapk/MainActivity;->findViewById(I)Landroid/view/View;
 
    #findViewById 함수의 리턴 타입은 android.view.View이기 때문에 반환된 값을 저장할 레지스터를 지정해야 함
    #레지스터 p1에 findViewById 함수의 반환된 값을 저장
    #move-result-object 레지스터이름
    move-result-object p1
 
    #타입 캐스팅 체크
    #check-cast 레지스터, 타입이름
    check-cast p1, Landroid/widget/TextView;
 
    const v0, 0x7f070084
 
    .line 15
    invoke-virtual {p0, v0}, Ljhlblue/ddns/net/sampleapk/MainActivity;->findViewById(I)Landroid/view/View;
 
    move-result-object p0
 
    check-cast p0, Landroid/widget/TextView;
 
    #레지스터 p0에 string값인 "Input any text to textview2"을 저장
    #const와 거의 동일한 방법으로 사용 가능
    const-string p0, "Input any text to textview2"
 
    .line 17
    #java의 setText 함수를 호출하는 부분
    #해당함수를 호출한 뒤 textview의 텍스트가 변경된다.
    #java 코드의 textView.setText("Input any text to textview2");
    invoke-virtual {p1, p0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
 
    #메소드 값 반환 부분
    #return-void는 void를 반환한다는 뜻
    return-void
#메소드의 끝부분
.end method
 
cs


위의 코드의 58번째 줄과 72번 줄에서 findViewById() 함수를 두 번 호출했고, 각각 호출될 때 사용된 파라미터 데이터가 다르며 (0x7f070083과  0x7f070084) findViewById() 함수 호출 이후에 check-cast Landroid/widget/TextView로 타입 캐스팅 체크 코드가 실행되는 것으로 보아 이 MainActivity에서는 두 개의 TextView가 존재하고, 이 중 하나의 TextView에만 setText 함수를 이용하여 텍스트를 입력했다는 것을 알 수 있다.


또한, 73~77번째 줄의 코드를 살펴보면 두 번째 findViewById() 함수의 결과값이 저장된 레지스터는 p0이지만 81번째 줄에서 레지스터 p0에 const-string 명령으로 텍스트 값을 저장했기 때문에 textview의 객체로 사용할 수 없게 되었다.


따라서 위의 코드에서 텍스트 값을 레지스터 p0이 아닌 다른 레지스터를 사용해야 한다. onCreate에서 사용하는 레지스터는 p0, p1, v0의 총 3개이고, 이 중 p0과 p1은 TextView의 객체정보가 저장되어있기 때문에 v0에 텍스트 값을 저장하도록 한다.


#const-string p0, "Input any text to textview2"

const-string v0"Input any text to textview2"


텍스트가 저장되는 레지스터를 p0에서 v0으로 변경했기 때문에 이전에 p0를 사용했던 함수의 인자 역시 변경을 해줘야 한다. 87번째 줄의 코드를 아래와 같이 변경한다.


#invoke-virtual {p1, p0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

invoke-virtual {p1, v0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V


다음은 setText() 함수를 한번 더 호출하여 원래 텍스트 출력을 하지 않았던 textview에도 텍스트를 출력할 수 있도록 한다.


invoke-virtual {p1, v0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V


만약 출력할 텍스트를 변경하고 싶다면 아래의 코드를 추가한 뒤 setText() 함수를 호출하도록 한다.


const-string v0, "text value"


변경된 코드는 아래와 같다.


그 밖에 해당 내용에는 없는 smali 코드에 대한 설명은 안드로이드 dalvik-bytecodeMod Apk 블로그 게시물을 확인하면 된다.

Comments