R e d A l i e n Click

엄청난 기술을 접하면, 마치 외계인의 기술을 훔친 것과 같다고 말합니다

붉은외계인은 그러한 놀라운 기술을 탐구하고, 기술적인 도전에 맞서는 것을 의미하는 저의 또 다른 이름입니다

서로가 성장할 수 있는 건설적인 토론을 좋아합니다.

article_thumbnail

[붉은외계인] Mobile - smali 코드 분석 1 with KGB Messenger

2024. 2. 14.
클릭 시, 이동!

KGB Messenger CTF를 하던 중에, 처음으로 smali 코드 분석을 하게 되었다

smali코드를 이해할 수 있다면 추후, 취약점 분석에 많은 도움이 될 거 같아서,
오늘 공부한 내용을 정리하려한다
시작해보자

 


 

Java 소스 코드

아래는 원본 Java 소스 코드이다 ( 디컴파일은 jadx-gui를 통해 하였다 )

package com.tlamb96.kgbmessenger;

import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.p022v7.app.ActivityC0494c;
import android.support.p022v7.app.DialogInterfaceC0492b;
import android.widget.LinearLayout;
import com.tlamb96.spetsnazmessenger.R;
import p000a.p001a.p002a.p003a.C0000a;

/* loaded from: classes.dex */
public class MainActivity extends ActivityC0494c {
    /* renamed from: a */
    private void m531a(String str, String str2) {
        DialogInterfaceC0492b m2324b = new DialogInterfaceC0492b.C0493a(this).m2324b();
        m2324b.setTitle(str);
        m2324b.m2331a(str2);
        m2324b.setCancelable(false);
        m2324b.m2333a(-3, "EXIT", new DialogInterface.OnClickListener() { // from class: com.tlamb96.kgbmessenger.MainActivity.1
            @Override // android.content.DialogInterface.OnClickListener
            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.dismiss();
                MainActivity.this.finish();
            }
        });
        m2324b.show();
        LinearLayout linearLayout = (LinearLayout) m2324b.m2334a(-3).getParent();
        linearLayout.setGravity(1);
        linearLayout.getChildAt(1).setVisibility(8);
    }

    @Override // android.support.p008v4.p010b.ActivityC0099l, android.app.Activity
    public void onBackPressed() {
        Intent intent = new Intent("android.intent.action.MAIN");
        intent.addCategory("android.intent.category.HOME");
        intent.setFlags(268435456);
        startActivity(intent);
    }

    @Override // android.support.p022v7.app.ActivityC0494c, android.support.p008v4.p010b.ActivityC0099l, android.support.p008v4.p010b.AbstractActivityC0090h, android.app.Activity
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_main);
        String property = System.getProperty("user.home");
        String str = System.getenv("USER");
        if (property == null || property.isEmpty() || !property.equals("Russia")) {
            m531a("Integrity Error", "This app can only run on Russian devices.");
        } else if (str == null || str.isEmpty() || !str.equals(getResources().getString(R.string.User))) {
            m531a("Integrity Error", "Must be on the user whitelist.");
        } else {
            C0000a.m3944a(this);
            startActivity(new Intent(this, LoginActivity.class));
        }
    }
}

 


 

smali 코드 1

smali코드를 부분부분 보면서, 해석을 하겠다

그 전에, 미리 알아둬야 할 것을 적어두겠다

◆ p0, p1, p2 ~ : p0은 보통 java에서와 같이 this를 의미한다 p1, p2 ~ 는 레지스터를 의미하되,
     매개변수로 들어가는 것을 의미한다
◆ v0, v1, v2 ~ : 이것 또한 레지스터를 의미하되, 전역 변수를 담는 레지스터이다

1번째 줄 : 현재 클래스의 경로를 나타낸다
2번째 줄 : 부모 클래스의 경로를 나타낸다

6번째 줄 : 생성자를 정의하는 부분이다 <init>()은 어떠한 매개변수도 받지 않는다는 의미

Java에서는 객체를 생성할 때, 반드시 생성자를 호출하게 된다 
하지만 클래스를 정의할 때, 생성자를 정의하지 않았더라도, 컴파일러가 자동으로 생성자를 생성한다
원본 소스 코드를 보면, 생성자를 정의하는 부분이 없다 그래서 이러한 smali 코드가 생성된 것 같다

7번쨰 줄 : 해당 메소드에서 사용되는 레지스터는 1개이다

9번째 줄 : invoke-direct는 메소드를 직접 호출하는 명령어이다
invoke-direct의 특징은 public,protected의 상관없이 메소드를 호출할 수 있다

11번째 줄: return-void는 아무것도 반환하지 않고 return(종료) 한다는 의미이다
12번째 줄: 메소드 정의 종료


 

smali 코드 2

1번째 줄: 2개의 String 자료형을 매개 변수로 받는 메소드 a 정의
2번째 줄: 해당 메소드는 8개의 레지스터를 사용한다
4번째 줄: 레지스터 v4에 4비트 상수 1을 저장 ( const/4는 4bit를 의미 )
6번째 줄: 레지스터 v3에 4비트 상수 -3을 저장
8번째 줄: 레지스터 v0에 객체 할당
10번째 줄: v0과 p0을 매개변수로 받는 생성자 호출 ( 여기서 p0은 this와 같은 의미 )
12번째 줄: v0을 매개변수로 받는 가상 메소드 b를 호출한다 해당 메소드의 반환 타입은 Landroid/support/v7/app/b 
16번째 줄: v0과 p1을 매개변수로 받는, setTitle 매소드를 호출한다 여기서 p1은 Ljava/lang/CharSequence를 의미한다
또한 반환 타입은 아무것도 반환하지 않는 V(void)이다
18번째 줄: v0과 p2를 매개변수로 받는 a 메소드를 호출한다 여기서 p2는 Ljava/lang/Charsequence를 의미한다 
이것 또한 반환 타입은 V이다
20번째 줄: 생략
22번째 줄: 생략 ( 여기서 Z는 Boolean 자료형을 의미한다 )

 


 

smali 코드 3

1번째 줄: v1 레지스터에 문자열 "EXIT" 할당
3번째 줄: MainActivity의 내부 클래스 객체 생성
5번째 줄: v2와 p0(MainActivity)를 매개변수로 받는 생성자 호출
8번째 줄: android/support/v7/app/b에 속한 a 메소드 호출, CharSequence와 OnClickListener를 매개변수로 받으며, 반환하는게 없는 V 
11번째 줄: v0을 매개변수로 받는 가상메소드 show()  호출 반환 타입 V
13번째 줄: v0과 v3를 매개변수로 받는 android/support/v7/app/b에 속한 a 메소드 호출, I(Integer)를 매개변수로 으며, Landroid/widget/button을 반환한다
15번째 줄: 이전에 호출된 반환값을 v0 레지스터에 저장한다
--------- 생략 -----------
33번째 줄: return-void는 아무것도 반환하지 않는다는 뜻

 


 

smali 코드 4 ( 이번건 길기 때문에, 중복된 내용은 과감히 건너뛴다 )

4번째 줄: invoke-super는 부모 클래스의 메소드를 호출하는 명령어로서, 여기서는 onCreate을 호출한다
6번째 줄: 레지스터 v0에 상수 0x7f09001c를 할당하고 있다 이것은 리소스 ID를 의미한다
12번째 줄: invoke-static은 정적 메소드를 호출하는 명령어로서, getProperty를 호출하고 있다
22번째 줄: if-eqz는 equal to zero의 약자로, 0일 때 실행하는 조건문이다 여기서는 v0이 0일 때, cond_25 레이블로 이동하라는 의미이다

28번째 줄: if-nez는 not equal to zero의 약자로, 0이 아닐때 실행하는 조건문이다 여기서는 v2가 0이 아닐 때, con_25 레이블로 이동하라는 의미이다
38 ~ 46번째 줄: cond_25 레이블을 의미한다

 


  

마무리

오늘 알아본 소스코드의 smali 코드는 하나씩, 천천히 알아보면서 읽어나가다 보면 어렵지 않다
여담으로, 나는 다른 툴도 써보았지만 리버싱할 때, jadx-gui와 apktool-GUI를 자주 사용한다

 jadx-GUI의 경우,  업데이트도 꾸준히 하고 있고 무엇보다 smali 코드와 
소스 코드를 같이 볼 수 있다는 점, 그리고 검색 기능이 가장 강력하다고 생각한다

apktool-GUI의 경우, CLI 기반인 apktool을 사용하다 불편하여, 찾아보다가 apktool-GUI를 택하였다
이것 또한 업데이트가 꾸준한데, 무려 3주전에 업데이트가 됐을 정도로 따끈따끈하다
또한, 디컴파일한 apk파일의 코드를 수정하여 다시 컴파일 할 때, 서명 과정도 알아서 해준다
기존에는, uber-apk-signer를 통해 서명을 해줘야 했지만, apktool-GUI는 그러한 번거로움을 없애준다

끝 !@