안녕하세요.
제가 만든 코드를 프로가드를 적용해 본 다음, 다시 디컴파일을 해 봤습니다.
프로가드를 써 보기 전에 코드가 얼마나 어떻게 난독화된다는 것인지 궁금했었는데,
혹시나 저처럼 궁금하신 분들 계실 것 같아 올려봅니다.
- 클릭 가능한 이미지 뷰만 두 개 있는 코드입니다.
- 프로가드는 아무 옵션변경없이 적용했습니다.
원래 코드
public class Help extends Activity { private ImageView iv_help_facebook; private ImageView iv_help_youtube; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.help); iv_help_facebook = (ImageView)findViewById(R.id.iv_help_facebook); iv_help_youtube = (ImageView)findViewById(R.id.iv_help_youtube); iv_help_facebook.setOnClickListener(mClickListener); iv_help_youtube.setOnClickListener(mClickListener); } Button.OnClickListener mClickListener = new Button.OnClickListener() { public void onClick(View v) { switch(v.getId()){ case R.id.iv_help_facebook: Intent intent_facebook = new Intent(Intent.ACTION_VIEW,Uri.parse("http://m.facebook.com/pages/xxxxxxx")); startActivity(intent_facebook); intent_facebook = null; break; case R.id.iv_help_youtube: Intent intent_youtube = new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.youtube.com/watch?v=xxxxxxx")); startActivity(intent_youtube); intent_youtube = null; break; } } }; }
APK를 디컴파일한 코드 (프로가드 적용안함)
public class Help extends Activity { private ImageView iv_help_facebook; private ImageView iv_help_youtube; View.OnClickListener mClickListener; public Help() { Help.1 local1 = new Help.1(this); this.mClickListener = local1; } public void onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentView(2130903041); ImageView localImageView1 = (ImageView)findViewById(2131296259); this.iv_help_facebook = localImageView1; ImageView localImageView2 = (ImageView)findViewById(2131296260); this.iv_help_youtube = localImageView2; ImageView localImageView3 = this.iv_help_facebook; View.OnClickListener localOnClickListener1 = this.mClickListener; localImageView3.setOnClickListener(localOnClickListener1); ImageView localImageView4 = this.iv_help_youtube; View.OnClickListener localOnClickListener2 = this.mClickListener; localImageView4.setOnClickListener(localOnClickListener2); } } class Help$1 implements View.OnClickListener { public void onClick(View paramView) { switch (paramView.getId()) { default: return; case 2131296259: Uri localUri1 = Uri.parse("http://m.facebook.com/pages/xxxxxx"); Intent localIntent1 = new Intent("android.intent.action.VIEW", localUri1); this.this$0.startActivity(localIntent1); return; case 2131296260: } Uri localUri2 = Uri.parse("http://www.youtube.com/watch?v=xxxxxx"); Intent localIntent2 = new Intent("android.intent.action.VIEW", localUri2); this.this$0.startActivity(localIntent2); } }
프로가드를 적용한 APK를 디컴파일한 코드
public class Help extends Activity { private ImageView a; private ImageView b; private View.OnClickListener c; public Help() { o localo = new o(this); this.c = localo; } public void onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentView(2130903041); ImageView localImageView1 = (ImageView)findViewById(2131296259); this.a = localImageView1; ImageView localImageView2 = (ImageView)findViewById(2131296260); this.b = localImageView2; ImageView localImageView3 = this.a; View.OnClickListener localOnClickListener1 = this.c; localImageView3.setOnClickListener(localOnClickListener1); ImageView localImageView4 = this.b; View.OnClickListener localOnClickListener2 = this.c; localImageView4.setOnClickListener(localOnClickListener2); } } final class o implements View.OnClickListener { o(Help paramHelp) { } public final void onClick(View paramView) { switch (paramView.getId()) { default: return; case 2131296259: Uri localUri1 = Uri.parse("http://m.facebook.com/pages/xxxxxx"); Intent localIntent1 = new Intent("android.intent.action.VIEW", localUri1); this.a.startActivity(localIntent1); return; case 2131296260: } Uri localUri2 = Uri.parse("http://www.youtube.com/watch?v=xxxxxx"); Intent localIntent2 = new Intent("android.intent.action.VIEW", localUri2); this.a.startActivity(localIntent2); } }
프로가드를 적용한 APK를 디컴파일하니까 기존에는 없는 자잘한 클래스들 (a~z)이 생겼습니다.
디컴파일 결과가 프로가드 적용한 것과 적용안 한 것과 큰 차이가 없는 것 같은데요. 효과가 있을지도 좀 궁금하네요. ㅎ
아. 물론 전 프로가드 적용안된 코드도 마치 난독화가 되어있는 듯 합니다 (해석불가 -.-)
클래스 갯수, 메소드 갯수, 변수 갯수가 많을수록 좀 더 귀찮게 할 수 있겠네요. ㅎㅎ
디컴파일로 이정도 퀄리티가 나오는지는 처음 알았습니다. 머엉.
구글에서 애초에 무슨 생각으로 APK 파일을 설계했는지 모르겠지만 수익을 만들려는 개발자들에게 소스와 리소스가 전부 공개가 된다는건 정말 알몸으로 전쟁터에 나간 기분을 제대로 느끼게 해주죠. 이런 점은 아이폰이 부럽습니다.
실제 디컴파일 해봐서 소스 분석 해보면 프로가드를 꼭 해야 좋습니다.
마음만 먹으면 프로가드 해도 어느정도 알 수 있다고는 하지만..
난독화 되어 있어서 그런지 시간이 많이 걸립니다. 복잡하면 더더욱 소스를 분석하는데
문제가 되더라고요..
View 나 Activity처럼 이름이 바뀌면 실행에 영향을 주는 클래스는 많이 안변합니다.
Android Base class를 상속받지 않고 그냥 만든 클래스는 많이 지저분하게(?) 변합니다.^^
그래서. 중요 로직은 View/Activity 클래스에 넣지 말고 따로 클래스를 만든 후 거기다 넣으시면 좀 나아집니다.
jni+ssl 안 쓰면 다 나오지 안나요?? 분석 시간이야 사람마다 다르니까요 머..;
어차피 흐름은 매니페스트에 다 있고 디컴파일된 클래스파일이야 몇분이면 소스파일되는데;;
어려운거 없으면 복제는 얼마 안 걸릴듯해요..귀차니즘과 양심의 문제
음....맘먹고 분석하면 소스 정리는 가능할거 같은데요....프로가드 한다해도 말이죠