티스토리 뷰
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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | .class public Lcom/example/tribal/filereader/MainActivity; .super Landroid/support/v7/app/AppCompatActivity; .source "MainActivity.java" # static fields .field public static final ReadFilePath:Ljava/lang/String; = "C:\\TagFile" # direct methods .method public constructor <init>()V .locals 0 .prologue .line 13 invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V return-void .end method # virtual methods .method protected onCreate(Landroid/os/Bundle;)V .locals 9 .param p1, "savedInstanceState" # Landroid/os/Bundle; .prologue .line 18 invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V .line 19 const v6, 0x7f04001b invoke-virtual {p0, v6}, Lcom/example/tribal/filereader/MainActivity;->setContentView(I)V .line 21 new-instance v2, Ljava/io/File; const-string v6, "C:\\TagFile" invoke-direct {v2, v6}, Ljava/io/File;-><init>(Ljava/lang/String;)V .line 22 .local v2, "fhandle":Ljava/io/File; invoke-virtual {v2}, Ljava/io/File;->length()J move-result-wide v4 .line 24 .local v4, "fsize":J :try_start_0 new-instance v3, Ljava/io/FileReader; invoke-direct {v3, v2}, Ljava/io/FileReader;-><init>(Ljava/io/File;)V .line 25 .local v3, "fread":Ljava/io/FileReader; long-to-int v6, v4 new-array v0, v6, [C .line 27 .local v0, "Tag":[C const/4 v6, 0x0 long-to-int v7, v4 invoke-virtual {v3, v0, v6, v7}, Ljava/io/FileReader;->read([CII)I move-result v6 int-to-long v6, v6 cmp-long v6, v4, v6 if-eqz v6, :cond_0 .line 28 const/4 v6, -0x1 invoke-static {v6}, Ljava/lang/System;->exit(I)V .line 31 :cond_0 sget-object v6, Ljava/lang/System;->out:Ljava/io/PrintStream; new-instance v7, Ljava/lang/StringBuilder; invoke-direct {v7}, Ljava/lang/StringBuilder;-><init>()V const-string v8, "Logger Tag : " invoke-virtual {v7, v8}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v7 invoke-virtual {v7, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder; move-result-object v7 invoke-virtual {v7}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v7 invoke-virtual {v6, v7}, Ljava/io/PrintStream;->print(Ljava/lang/String;)V .line 33 invoke-virtual {v3}, Ljava/io/FileReader;->close()V :try_end_0 .catch Ljava/io/FileNotFoundException; {:try_start_0 .. :try_end_0} :catch_0 .catch Ljava/io/IOException; {:try_start_0 .. :try_end_0} :catch_1 .line 39 .end local v0 # "Tag":[C .end local v3 # "fread":Ljava/io/FileReader; :goto_0 return-void .line 34 :catch_0 move-exception v1 .line 35 .local v1, "e":Ljava/io/FileNotFoundException; invoke-virtual {v1}, Ljava/io/FileNotFoundException;->printStackTrace()V goto :goto_0 .line 36 .end local v1 # "e":Ljava/io/FileNotFoundException; :catch_1 move-exception v1 .line 37 .local v1, "e":Ljava/io/IOException; invoke-virtual {v1}, Ljava/io/IOException;->printStackTrace()V goto :goto_0 .end method | cs |
원본 Java 소스 코드
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 | package com.example.tribal.filereader; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class MainActivity extends AppCompatActivity { public static final String ReadFilePath = "C:\\TagFile"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); File fhandle = new File(ReadFilePath) ; long fsize = fhandle.length(); try { FileReader fread = new FileReader(fhandle); char[] Tag = new char[((int) fsize)]; if(fsize != fread.read(Tag, 0, ((int) fsize))) { System.exit(-1); } System.out.print("Logger Tag : " + Tag); fread.close() ; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } | cs |
Smali 코드 분석(Smali 코드 라인별 분석)
- 1번째 줄 : 클래스 명과 상속, 패키지 경로를 나타낸다.
- 2번째 줄 : MainActivity Class가 받는 상속 클래스를 나타낸다.
- 3번째 줄 : 원본 파일의 이름을 나타낸다.
- 7번째 줄 : 클래스 내부 static 변수와 자료형, 값을 나타낸다.
- 10번째 줄 : 메소드 호출이 direct인지 virtual인지를 나타낸다.
- 11번째 줄 : 메소드는 constructor로 표시되어 있고, <init>라는 이름으로 클래스의 생성자를 나타낸다.
- 12번째 줄 : .locals는 메소드 내부에서 사용되는 레지스터의 갯수인데 0개이다.
- 14번째 줄 : 메소드 내부의 코드 시작을 나타낸다.
- 15번째 줄 : 실제 자바 소스 코드와 매칭되는 line 넘버이다.
- 16번째 줄 : 오브젝트 android/support/v7/app/AppCompatActivity의 생성자인 <init>() 함수를 direct 호출하는 것을 나타낸다.
- 18번째 줄 : 함수의 반환 값 타입을 나타낸다.
- 19번째 줄 : 해당 함수의 종료를 나타낸다.
- 따라서 기본적인 생성자를 호출하고, 특별한 과정이 없었음을 알 수 있다.
- 22번째 줄 : 해당 함수가 virtual method라는 것을 나타낸다.
- 23번째 줄 : onCreate 함수가 android/os/Bundle을 인자로 하고, Void형을 반환한다.
- 24번째 줄 : 사용되는 레지스터의 갯수가 9개인 것을 나타낸다.
- 25번째 줄 : 인자 p1이 android/os/Bundle 타입이고, 변수 명이 "savedInstanceState" 임을 나타낸다.
- 29번째 줄 : 상속된 AppCompatActivity의 onCreate 함수를 p1을 인자로 호출한다.
- 32번째 줄 : 상수 v6의 값은 0x7f04001b이다.
- 34번째 줄 : MainActivity의 setContentView 함수를 v6을 인자로 호출한다.
- 37번째 줄 : java/io/File에 대해 새로운 instance v2를 생성한다.
- 39번째 줄 : 상수 문자열 v6은 "C:\\TagFile"이다.
- 41번째 줄 : 생성한 java/io/File 인스턴스의 생성자를 호출하는데 v6을 인자로 한다.
- 44번째 줄 : java/io/File 인스턴스 v2에 "fhandle"이라는 이름을 명명한다.
- 45번째 줄 : v2를 매개체로 length() 함수를 호출하고, 반환 값은 long 형이다.
- 47번째 줄 : long 형(8 byte) 반환 값을 v4에 저장한다.
- 50번째 줄 : long v4를 "fsize"라는 이름으로 명명한다.
- 51번째 줄 : try_start_0이라는 라벨로 try 구문의 시작을 나타낸다.
- 52번째 줄 : java/io/FileReader 인스턴스 v3를 생성한다.
- 54번째 줄 : 생성한 java/io/FilreReader 인스턴스의 생성자를 호출하는데 v2를 인자로 한다.
- 57번째 줄 : 인스턴스 v3에 "fread"라고 명명한다.
- 58번째 줄 : v4에 저장된 파일 크기를 long에서 int로 캐스팅하여 v6에 저장
- 60번째 줄 : v6에 저장된 값만큼 char형 배열 v0 생성
- 61번째 줄 : 0x0을 v6 레지스터에 저장
- 63번째 줄 : 배열 v0을 "Tag"라고 명명
- 66번째 줄 : v4에 저장된 파일 크기를 long에서 int로 캐스팅하여 v7에 저장
- 68번째 줄 : java/io/FileReader의 read 함수 호출, 인자는 버퍼(v0), 오프셋(v6), 크기(v7)이 전달된다.
- 70번째 줄 : 결과 값을 v6 레지스터에 저장
- 72번째 줄 : v6의 값을 int에서 long으로 캐스팅하여 v6에 저장
※ FileReader.read의 fsize는 long이 아닌 int로 캐스팅되어 전달됨
- 74번째 줄 : v4와 v6를 비교하여, 결과 값을 v6에 저장(1번 operand가 destination, 2번과 3번 operand는 source)
- 76번째 줄 : v6의 값을 0과 비교, 같으면 jmp
- 79번째 줄 : v6에 -0x1을 32bits 만큼 확장하여 저장
- 81번째 줄 : v6의 값을 인자로 static 함수인 java/lang/System의 exit 함수 호출
- 84번째 줄 : 76번째 줄의 jmp와 관련된 분기문
- 85번째 줄 : java/lang/System->out의 java/io/PrintStream에 해당하는 필드 id를 가져와 v6에 저장
- 87번째 줄 : java/lang/StringBuilder 인스턴스 v7 생성한다.
- 89번째 줄 : java/lang/StringBuider의 생성자 호출
- 91번째 줄 : 상수 문자열 v8에 "Logger Tag : " 저장
- 93번째 줄 : java/lang/string인 v8을 인자로 java/lang/StringBuilder->append 함수 호출
- 95번째 줄 : 결과 값을 v7에 저장
- 97번째 줄 : java/lang/Object인 v0을 인자로 java/lang/StringBuilder->append 함수 호출
- 96번째 줄 : 결과 값을 v7에 저장
- 101번째 줄 : java/lang/stringBuilder->toString() 함수 호출
- 103번째 줄 : 결과 값을 v7에 저장
- 105번째 줄 : java/io/PrintStream 오브젝트인 v6을 통해 v7을 인자로 print 함수 실행
- 108번째 줄 : v3을 매개체로 close 함수 호출
- 109번째 줄 : 51번째 줄의 try 실행 중 예외가 발생했을 때 예외처리 실시
- 110번째 줄 : 파일이 존재하지 않을 경우, FileNotFoundException을 가지고 catch_0로 이동
- 111번째 줄 : 입출력 예외 발생, IOException을 가지고 catch_1로 이동
- 114번째 줄 : char 배열 v0를 해제
- 115번째 줄 : FileReader 인스턴스 v3을 해제
- 116번째 줄 : goto_0 라벨
- 117번째 줄 : void 반환, 함수 종료
- 120번째 줄 : catch_0 라벨, FileNotFoundException 예외 발생 시 여기로 이동
- 121번째 줄 : v1에 FileNotFoundException 예외 전달
- 124번째 줄 : v1을 "e"라고 명명
- 125번째 줄 : v1을 매개체로 printStackTrace 함수 호출
- 127번째 줄 : goto 구문, goto_0 라벨인 116번째 줄로 이동
- 130번째 줄 : FileNotFoundException인 v1을 "e"라고 명명
- 131번째 줄 : catch_1 라벨, IOException 예외 발생 시 여기로 이동
- 132번째 줄 : v1에 FileNotFoundException 예외 전달
- 135번째 줄 : IOException인 v1을 "e"라고 명명
- 136번째 줄 : v1을 매개체로 printStackTrace 함수 호출
- 138번째 줄 : goto 구문, goto_0 라벨인 116번째 줄로 이동
- 139번째 줄 : method 종료
분석 완료 코드
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 | package com.example.tribal.filereader; import android/support/v7/app/AppCompatActivity; import android/os/Bundle import java/lang/System import java/lang/StringBuilder import java/io/PrintStream import java/io/File import java/io/FileReader import java/io/IOException import java/io/FileNotFoundException public class MainActivity extends AppCompatActivity { public static final String ReadFilePath = "C:\\TagFile"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(0x7f04001b); File fhandle = new File("C:\\TagFile"); long fsize = fhandle.length(); try { FileReader fread = new FileReader(fhandle); char[] Tag = new char[((int)fsize)]; if(fsize != ((long)fread.read(Tag, 0, fsize))) { System.exit(-0x1); } v6 = out:java/io/PrintStream; StringBuilder v7 = new StringBuilder(); v8 = "Logger Tag : "; v7 = v7.append(v8); v7 = v7.append(Tag); v7 = v7.toString(); v6.print(v7); fread.close() } catch(FileNotFoundException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } } | cs |
※ 28번째 줄 : FileReader.read의 fsize는 long이 아닌 int로 캐스팅되어 전달됨
참고 :
- Bytecode Reference : http://netmite.com/android/mydroid/dalvik/docs/dalvik-bytecode.html
- Types, Methods, Fields : https://github.com/JesusFreke/smali/wiki/TypesMethodsAndFields
'Reversing' 카테고리의 다른 글
Ida Plugin 리스트 및 사용법 (0) | 2017.10.03 |
---|---|
[Android] Main Activity 검색 스크립트 (2) | 2017.08.23 |
Windbg 사용법 정리 (0) | 2017.07.16 |
C++ 클래스 멤버 함수 (0) | 2016.07.01 |
구조체 핸드레이 (0) | 2016.04.26 |