그래오늘은이거야

[맥북/맥용] Android 난독화 복호화 적용 방법 Proguard 본문

세상 개발/Android

[맥북/맥용] Android 난독화 복호화 적용 방법 Proguard

jinhongstar 2019. 4. 3. 16:09
728x90
반응형

안녕하세요  LEO 입니다.


사실 난 IOS 개발자인데... Android 도 겸사 겸사 하는 개발자이다.

그래서 맥북환경이 익숙해서 모든 작업을 맥북으로 합니다.

Android 난독화 dex 파일을(class 또는 method) 함수를  암호화 하여 apk를 리버싱엔지니어링을 못하게 막는다고한다...

Proguard를 이용하여 많이들 한다고 하여 나도 해봤다...

왜 하는지 알 수가없다.

물어보니 이거 다른사람이 apk 파일을 열어보기 전에 복호화 하는 노력이라도??? 하라고 난독화를 하라고 한다.. "말" 인지.. "소" 인지..

Proguard 를 이용해서 난독화를 하려고 한다면...

http://www.apk-deguard.com/

사이트 가서 apk 를 올려서 확인해보는 순간.. 모든게 다 풀린다.. 

내 생각은 정말 쓸모 없는 짓 같다...

(물론 내 지식이 얕아서 이런 멍멍이 소리를 하는 거 일수도.....)


하지만 회사에서 하라면 해야하니 일단 난독화를 시작한다.

그래요 이틀을 버렸습니다.

난독화 그냥 설정에서 true  만 한다고 해서 되는게 아니다..

내가 찾아본 소스중에 이게 제일 잘 맞는듯 그리고 proguard-rules.pro 를 custom 해서 변경 할 수 있는데... 

그렇게까지 하는건 더 쓸모 없다고 생각하여 그냥 진행..


아래 와 같이 bulid.gradle 에 환경 설정!! 적용


buildTypes {

release {

// 프로가드 활성화

zipAlignEnabled true // apk 최적화
shrinkResources false
// signingConfig signingConfigs.release
minifyEnabled true
// runProguard true
// signingConfig signingConfigs.release
// 기본 프로가드 설정
// proguardFile getDefaultProguardFile('proguard-android.txt')
// 프로젝트에 필요한 프로가드 설정
// proguardFile 'proguard-rules.pro'

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// buildConfigField(BOOLEAN, KM_LL_V, FALSE)
}


}

난독화 구글링해서 검색해 본 결과.. 어렵다 뭐 이렇게 여러곳을 찾아 다니면서 적용해야 하는 지모르겠다..


처음에 진입할때 헷갈리는게 있다.


1. proguard-android.txt

/Users/ex)mac_pc/Library/Android/sdk/tools/proguard/proguard-android.txt

난 처음에 이걸 수정해야 하는지 알았다.

이건 뭐 수정 할 거 없다. 그냥 무시 냅둬라..


2. proguard-rules.pro

우리는 이것만 수정 하면된다.!!!


이제 설명을 시작 해본다.

안드로이드를 빌드 를 하면 기분 좋게 클리어!! 너무 행복하다.


자 이제 APK를 만들기 시작하는게 문제다.


우리 해야하는거는 난독화를 적용한 후 이걸 빌드를 해서 apk release 파일을 만들면된다.


Proguard 를 적용하는 방법은 true로 변경하면 된다 어렵지 않다.

minifyEnabled true



Build - Generate Signed Bundle / APK... 를 하게 된다



APK를 선택 한다


Key store 에서 키만드는건 회원가입 하듯 쉽다.

모르면 구글링 검색 키워드는 : android release apk 만들기

난 더 어려운것을 한다

쉬운건 패스!!

자 이제 여기는 apk만들기전에 

build,gradle 에서 설정할 수 있다.


productFlavors {
internal {
      생략 ...
}
mu {
생략 ...
}
official {
생략 ...
}

}


이제 Finish를 하면 멘붕이 시작된다.


내가 이걸 5시간 분석했다..

쓰벌...


아무 의미 없다 구글링해도 안나온다.

이게  뭐냐고 비슷한 힌트도 안준다. 쓰레기 다 그냥 이 로그는..

구글링을 5시간 끝에 하는 오류에 대하여 찾아냈다.

우리의 시간은 아까우니 아래에 글을 남긴다.

쓰레기지만 들어 오는 사람 도 있을 수 있느니 포스팅 

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:transformClassesAndResourcesWithProguardForInternalRelease'.

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:103)

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:73)

at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)

at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)

at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)

at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)

at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)

at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)

at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)

at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)

at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)

at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)

at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)

at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)

at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:256)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)

at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:249)

at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:238)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)

at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:663)

at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:597)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)

at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)

at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)

at java.lang.Thread.run(Thread.java:748)

Caused by: java.lang.RuntimeException: Job failed, see logs for details

at com.android.build.gradle.internal.transforms.ProGuardTransform.transform(ProGuardTransform.java:207)

at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:239)

at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:235)

at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:102)

at com.android.build.gradle.internal.pipeline.TransformTask.transform(TransformTask.java:230)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)

at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:50)

at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)

at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:124)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:113)

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:95)

... 33 more

Caused by: java.io.IOException: Please correct the above warnings first.

at proguard.Initializer.execute(Initializer.java:473)

at proguard.ProGuard.initialize(ProGuard.java:233)

at proguard.ProGuard.execute(ProGuard.java:98)

at com.android.build.gradle.internal.transforms.BaseProguardAction.runProguard(BaseProguardAction.java:64)

at com.android.build.gradle.internal.transforms.ProGuardTransform.doMinification(ProGuardTransform.java:262)

at com.android.build.gradle.internal.transforms.ProGuardTransform.access$000(ProGuardTransform.java:65)

at com.android.build.gradle.internal.transforms.ProGuardTransform$1.run(ProGuardTransform.java:176)

at com.android.builder.tasks.Job.runTask(Job.java:47)

at com.android.build.gradle.tasks.SimpleWorkQueue$EmptyThreadContext.runTask(SimpleWorkQueue.java:41)

at com.android.builder.tasks.WorkQueue.run(WorkQueue.java:282)

... 1 more




자 여기가 포인트다 진짜 하루를 버려서 찾아낸 결과 

이게 꿀팁이다.

Android Terminal 창에 다가 입력해 봐라 gradlew 이 너는 뭐가 문제가 있어서 어떤게 문제기 때문에 count  개수까지 친절하게 다 설명해준다. 그걸 이제 우리는

proguard-rules.pro 에 적용을 하면된다.


 ./gradlew clean build assemble



보이는 가? 

Note: there were 1 references to unknown classes.

      You should check your configuration for typos.

      (http://proguard.sourceforge.net/manual/troubleshooting.html#unknownclass)

Note: there were 24 unkept descriptor classes in kept class members.

      You should consider explicitly keeping the mentioned classes

      (using '-keep').

      (http://proguard.sourceforge.net/manual/troubleshooting.html#descriptorclass)

Warning: there were 10 unresolved references to classes or interfaces.

         You may need to add missing library jars or update their versions.

         If your code works fine without the missing classes, you can suppress

         the warnings with '-dontwarn' options.

         (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)

Warning: there were 5 instances of library classes depending on program classes.

         You must avoid such dependencies, since the program classes will

         be processed, while the library classes will remain unchanged.

         (http://proguard.sourceforge.net/manual/troubleshooting.html#dependency)

Warning: Exception while processing task java.io.IOException: Please correct the above warnings first.

Thread(Tasks limiter_1): destruction


이렇게 친절하게 정보가 나타난다.

여기서 포인트는 카운트와 
-keep / -dontwarn / classes.

이런 단어이다 이런 단어는 


여기 뒤에 #검색어 하면 더 자세하게 들어가진다.


여기 튜토리얼 가이드에 다 나와있다.

이걸 보면 감이 올 것이다.

하나하나 알려주는데로 저 단어를 어떻게 수정해야하는 검색해보고 

찾으면서 proguard-rules.pro 에 적용 시키면

BUILD SUCCESSFUL이 나올때까지

터미널에서  ./gradlew clean build assemble

명령어를 입력해라. 답이 나올 것이다.



이정보는 
여기 블로그를 찾아봐라 누군지 모르는데 정말 정리가 잘 되어 있다.

내가 따로 정리 하려 했지만 이걸 봐도 꿀팁


혹시 CMK  오류가 나면 아래 stackoverflow 참고

https://stackoverflow.com/questions/41084578/android-errorexecution-failed-for-task-appmergedebugresources


Proguard 예제 또는 example / sample 샘플 사이트 설정 추천

https://www.guardsquare.com/en/products/proguard/manual/examples


Proguard 난독화 가 모두 되었다면 

맥북 난독화 복호화

난독화 확인 방법은 아래 블로그를 참조 정말 잘나와 있음!

난 정리 잘된 사이트만 추가함.

 나중에 적용할때 보려고 링크 추가 한 것 임.

https://chelsea-kbj.tistory.com/9


난독화 확인하면 아래와 같이 가려져서 나옴





혹시 모르는거는 댓글 남겨주시면 바로 피드백  하겠습니다.

Comment on something you don't know.







반응형
Comments