안드로이드 악성코드 분석 시, 원본 dex를 숨기기 위해 dex파일 동적로딩을 하는 경우가 많이 있습니다.

 

동적으로 Dex파일을 로드하기 위해선 파일 혹은 메모리에서 로드하는데 다음과 같은 함수를 사용하게 됩니다.

 

From file:
dalvik.system.DexFile.loadDex depreciated after API 26
dalvik.system.DexClassLoader
dalvik.system.PathClassLoader


From memory:
dalvik.system.InMemoryDexClassLoader (not common in malwares)

 

파일을 통한 동적로딩 중 DexClassLoader함수를 이용하여 동적로딩하는 코드 작성 및 분석 방법을 확인하겠습니다.

android developer를 통해 확인한 dexclassloader 함수 형식입니다.

아래는 dexclassloader를 이용하여 외부 apk의 dex를 로드하는 코드 예제입니다.

 

dexclassloader.java


public class MainActivity extends AppCompatActivity {
   static final int BUF_SIZE = 8 * 1024;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      findViewById(R.id.button).setOnClickListener(
      new Button.OnClickListener(){
         public void onClick(View v){
         String text = loadClass2();
         Toast.makeText(getApplicationContext(),text,Toast.LENGTH_LONG).show();
         }
      });

   }

 

   private String loadClass2(){
      String APPJS = "test.apk";   // 불러올 apk 이름 명시
      File dexInternalStoragePath = new File(getDir("cache",Context.MODE_PRIVATE), APPJS);
      BufferedInputStream bis = null;
      OutputStream dexWriter = null;

      try {                             // asset 폴더 내 저장된 apk파일을 앱 내 read가 가능한 영역으로 복사                    

                                        // (/data/data/<app>/app_cache/)
         bis = new BufferedInputStream(getAssets().open(APPJS));
         dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath));
         byte[] buf = new byte[BUF_SIZE];
         int len;
         while ((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
            dexWriter.write(buf, 0, len);
         }
         dexWriter.close();
         bis.close();
      } catch (Exception e) {
// TODO Auto-generated catch block
         e.printStackTrace();
      }

      final File optimizedDexOutputPath = getDir("cache",Context.MODE_PRIVATE);    // 복사한 apk파일 경로 획득
      DexClassLoader dexClassLoader = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
optimizedDexOutputPath.getAbsolutePath(), null,getClassLoader());     //dex 파일 로드
     try {
        Class clazz = dexClassLoader.loadClass("com.example.user.test.test");  // dex 파일 내 class 로드
        Object object = clazz.newInstance();
        Method method = clazz.getMethod("get_Message");    //class 내 method 로드
        String text = (String) method.invoke(object);   //method 호출
        return text;
      }catch (Exception e){
        e.printStackTrace();
      }
      return "Error..!!";
   }

}


test.java(test.apk)

 

package com.example.user.flag;

 

 

public class test{
  public String get_Message(){
      return "Catch Me!";
   }

}

 

test.java의 경우 앱 실행은 되지 않지만 빌드를 통해 apk파일 생성 및 dexclassloader.java가 있는 프로젝트 assets 파일 내 apk파일 복사


이렇게 작성된 앱의 경우, assets파일 내 apk파일이 존재하는 것을 모른다면 test.java의 내용을 알기 어렵습니다.

 

원본 Dex 추출을 위해 앱 실행 및 단말기 내 /proc/<pid>/maps를 확인하여 불러오는 dex파일의 위치를 확인합니다.

그 후 해당 위치(위 예제 앱의 경우 /data/data/<package_name>/app_cache/)에 복사한 dex파일이 존재합니다.

 

다만, 복사한 dex파일은 odex파일로 dex형식으로 변환하여 원본소스코드 확인이 가능합니다.

'Mobile' 카테고리의 다른 글

Frida cheat sheet  (0) 2020.10.11
MultiDex Dynamic Debug(feat. JEB)  (0) 2020.05.18
odex to dex  (0) 2020.05.08
ro.debuggable 변경을 통한 동적 디버깅  (2) 2019.09.23
IDA DEX,SO 동적디버깅  (0) 2019.09.23

+ Recent posts