난독화(obfuscation) 질문 드립니다.

4,626 views
Skip to first unread message

pranludi

unread,
Dec 1, 2012, 9:19:17 AM12/1/12
to ks...@googlegroups.com
안녕하세요.

개발/운영 환경 : spring 3.x + ibatis 2.x + oracle 입니다.
프로젝트를 일부분을 다른 업체에서 서비스하게 되었습니다.
역컴파일 같은걸 방지하기 위해 코드 또는 클래스를 난독화를 할려고 합니다.

난독화는 ProGuard 으로 해서 테스트하고 있습니다만, 쉽지 않네요.
환경 설정을 아래와 같이 해서 테스트하였습니다. 난독화는 되기는 하였지만, 구동을 시키면 p.cmm.web.TimeoutFilter 클래스를 찾을 수 없다고 나옵니다.

- ProGuard를 이용해서 난독화를 할려면 어떻게 하는게 좋을지요?
- 저희의 목적과 같이 역컴파일 같은걸 방지하기 위해서는 어떤 방법이 좋을까요?




-injars in.jar
-outjars out.jar

-libraryjars 'C:\Program Files\Java\jre6\lib\rt.jar'
-libraryjars lib\aopalliance-1.0.jar
-libraryjars lib\aspectjrt-1.6.8.jar
-libraryjars lib\com.springsource.javax.validation-1.0.0.GA.jar
-libraryjars lib\com.springsource.net.sf.cglib-2.2.0.jar
-libraryjars lib\com.springsource.org.hibernate-3.3.1.GA.jar
-libraryjars lib\com.springsource.org.hibernate.annotations-3.4.0.GA.jar
-libraryjars lib\com.springsource.org.hibernate.validator-4.0.2.GA.jar
-libraryjars lib\commons-codec-1.5.jar
-libraryjars lib\commons-io.jar
-libraryjars lib\commons-logging-1.1.1.jar
-libraryjars lib\commons-pool-1.6.jar
-libraryjars lib\ecj-3.7.2.jar
-libraryjars lib\el-api.jar
-libraryjars lib\html2image-0.9.jar
-libraryjars lib\httpclient-4.1.1.jar
-libraryjars lib\httpclient-cache-4.1.1.jar
-libraryjars lib\httpcore-4.1.jar
-libraryjars lib\httpmime-4.1.1.jar
-libraryjars lib\ibatis-2.3.4.726.jar
-libraryjars lib\jackson-core-asl-1.5.1.jar
-libraryjars lib\jackson-mapper-asl-1.5.1.jar
-libraryjars lib\jasper-el.jar
-libraryjars lib\jasper.jar
-libraryjars lib\javax.inject-1.jar
-libraryjars lib\jdom-2.0.3.jar
-libraryjars lib\jericho-html-3.2.jar
-libraryjars lib\jsp-api.jar
-libraryjars lib\jstl.jar
-libraryjars lib\log4j-1.2.16.jar
-libraryjars lib\ojdbc6.jar
-libraryjars lib\org.springframework.aop-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.asm-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.aspects-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.beans-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.context-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.context.support-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.core-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.expression-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.instrument-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.jdbc-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.jms-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.orm-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.oxm-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.test-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.transaction-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.web-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.web.portlet-3.1.1.RELEASE.jar
-libraryjars lib\org.springframework.web.servlet-3.1.1.RELEASE.jar
-libraryjars lib\servlet-api.jar
-libraryjars lib\sitemesh-3.0-alpha-2.jar
-libraryjars lib\slf4j-api-1.6.4.jar
-libraryjars lib\slf4j-jcl-1.6.4.jar
-libraryjars lib\spring-security-acl-3.1.0.RELEASE.jar
-libraryjars lib\spring-security-aspects-3.1.0.RELEASE.jar
-libraryjars lib\spring-security-config-3.1.0.RELEASE.jar
-libraryjars lib\spring-security-core-3.1.0.RELEASE.jar
-libraryjars lib\spring-security-taglibs-3.1.0.RELEASE.jar
-libraryjars lib\spring-security-web-3.1.0.RELEASE.jar
-libraryjars lib\standard.jar
-libraryjars lib\tomcat-dbcp.jar
-libraryjars lib\xalan.jar

-dontskipnonpubliclibraryclassmembers
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontpreverify
-verbose

-keep public class p.cmm.binding.BindingInitializer
-keep public class p.cmm.web.TimeoutFilter
-keep public class p.cmm.web.ModelAndJsonViewResolver
-keep public class p.service.security.AuthenticationSuccessSuppotHandler
-keep public class p.service.security.UserDetailsService
#-keep public class * extends portal.common.web.AjaxSessionTimeoutFilter
-keep class * extends @Crontroller *


#-keep class Calc {
#  public static void main(java.lang.String[]);
#}


#-keepclasseswithmembers,allowshrinking class * {
#    public <init>(android.content.Context,android.util.AttributeSet);
#}
#-keepclasseswithmembers,allowshrinking class * {
#    public <init>(android.content.Context,android.util.AttributeSet,int);
#}
# Also keep - Enumerations. Keep the special static methods that are required in
# enumeration classes.
-keepclassmembers enum  * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
# Keep names - Native method names. Keep all native class/method names.
-keepclasseswithmembers,allowshrinking class * {
    native <methods>;
}

안병현

unread,
Dec 1, 2012, 11:29:54 PM12/1/12
to ks...@googlegroups.com
개인적으로 프로가드를 써보면서 느낀 몇가지 내용 공유 드립니다.

1. Keep 클래스 관리
    - 개인적으로 외부로 노출되어야 하는 인터페이스와 클래스만 별도로 패키지에 모아서 keep 클래스에 추가해주고 있습니다.
    - p.cmm.web.TimeoutFilter를 찾지 못하면 keep public class p.cmm.web.* 로 한번 설정해 보세요
    - jar 내에 리소스를 포함시켰다면 리소스도 한군데에 모아서 keep에 추가해주는 것이 안전합니다.
      (resource까지 난독화 되서 정상동작 하지 않는 케이스가 있습니다.)

2. Enumeration 사용
    - Enumeration의 toString() 메소드를 사용하시는 경우가 있다면 keep 목록에 포함시키거나 toString()를 overriding하셔서 난동화 되도 본래의 스트링 값이 유지도도록 해주셔야 합니다.
    - enum MyTest{ foo, bar.... };
      MyTest.foo.toString().equal("test") ;
      이런 로직은 100% 에러납니다.
 
3. 테스트는 난독화 후에 꼭 다시 해보시길 권합니다.
    - 클래스, 변수 명들이 전부 난독화 되면서 종종 예측하기 힘든 예외사항들이 발생합니다. (난독화 전엔 잘 돌아가던 부분이!)
      대부분 keep 설정을 잘못해주거나 Enumeration처럼 중요한 String 값들이 난독화 되서 생기는 부분입니다.
    - 난독화 map을 출력해주는 옵션을 추가하여 map을 테스트때 활용하면 그나마 좀 편합니다.

4. 근본적으로 역컴파일 방지는 불가능하다고 합니다. 프로가드도 결국은 클래스나 멤버 변수들의 이름을 A,B,C 등으로 치환해서 단순히 읽기 힘들게 만들어줄 뿐이라 결국은 다 분석 가능하다고 합니다. 좀 웃긴 이야기인데 회사 선배님이 난독화된 jar를 막 분석해서 보니 마지막에 이런 문구가 있었다고 합니다. "너도 소프트웨어로 밥벌어 먹고 살면서 꼭 이래야 겠니?"

대단한 내용은 아니지만 조금 도움이라도 되셨기를...

2012/12/1 pranludi <pran...@gmail.com>

kingori

unread,
Dec 2, 2012, 6:59:03 AM12/2/12
to ks...@googlegroups.com
에러 메시지가 의미하듯, 난독화를 거치면서 해당 클래스의 이름이 바뀌어버린 듯 합니다.
proguard를 하고 나면 mapping 정보를 담은 파일이 나올 겁니다. 거기서 한번 p.cmm.web.TimeoutFilter 를 찾아보시면 다른 이름으로 바뀌어버린 걸 확인할 수 있을겁니다.

병현님 의견에 제 경험을 좀 더 공유하면. 다음 대상들은 keep 옵션을 줘서 난독화 대상에서 제외하시는 게 안전할 것 같습니다.

1. annotation 붙은 class, method, member
2. reflection 대상이 되는 class, method, member
3. config 파일 등에서 언급하는 class

한가지, 난독화 한 jar를 공유하시면 사용하는 측에서 debugging하기 굉장히 어려워집니다. 굳이 역컴파일이라는 나쁜 짓(?)을 하는 상황이 아니더라도, 해당 모듈을 사용하는 중 발생한 오류를 가지고 의사소통하기 굉장히 어렵습니다. 예를 들면.

고객사: com.a.b.c.d() 메서드를 호출하다 com.e.f.g.1.g 라는 예외가 났는데 왜 그렇죠?

뭐 이런 상황이 발생합니다. 다행히 mapping 파일을 잘 관리하고 있다면 그럭저럭 해결할 순 있겠지만, 고객사가 충분히 대응할 수 있는 상황도 난독화를 거쳐버리면 일일이 대응해줘야 하기 때문에 상호간에 굉장히 피곤해집니다. exception 클래스도 제외하는 류의 생각도 해 볼 순 있겠지만요. 그래서 굳이 난독화를 해야 하는지 여부에 대해서 고민을 많이 해얄 듯 싶어요.


2012년 12월 2일 일요일 오후 1시 29분 54초 UTC+9, 병현 안 님의 말:
Reply all
Reply to author
Forward
0 new messages