Basilica android

sharku.egloos.com



자바 난독화 기법(Java Obfuscation Techniques) by sharku


영문 사이트에 있는 것을 간단히 보기편하게 정리했슴니다 보기편하라는 사람은 나 자신이기 때문에 설명이이상하거나 추가설명이 필요하면 물어보셔요 ㅋ

예제는 원문 하단 링크에 들어가보면 있으니 이해가 안가면 참고

자바 난독화 기법
1. 지역변수를 비트필드로 묶기
2. Try-Catch 블록 과 if(non)null 구문으로 배치
3. 부분적 차단되는 스위치 구문 사용
4. 쓰레기코드인 스위치 구문을 추가
5. 복제 문장의 재사용
6. 브랜치를 jsr 구문으로 변환
7. 간접 if구문
8. load 구문을 if구문 위에 다시 불러오기
9. 식별자 이름 변경(클래스, 메소드, 필드)
10. 생성자 규약 파괴
11. Try 블록과 Catch 블록을 혼합
12. Goto를 사용


1. Packing Local Variables into Bitfields (PLVB)
지역변수를 비트필드로 묶기
지역변수를 long과 같은 변수(비트값)의 결합으로 만들어서 원래의 값을 찾기 힘들도록 만드는 것
예시) int 변수 -> long 변수 && long 값
이것을 pack variables 라고 칭함


2. Replacing if(non)null Instructions with Try-Catch Blocks (RIITCB)
Try-Catch 블록 과 if(non)null 구문으로 배치
if에 null구문이 포함되어 있을때 구문 전체를 Try-Catch 구문으로 변경한다. 이때 Catch구문은 nullPointerException구문이 항상 포함되어 실행된다.
예제) if(null)구문 -> TryCatch 로 변경됨


3. Partially Trapping Switch Statements (PTSS)
부분적 차단되는 스위치 구문 사용

스위치 구문일 경우 구조적으로는 문제가 없도록 중요 부위는 포장하고 그 구문 주위에서 이동경로를 추가한다
특히 스위치 구문같이 불연속적인 구문에 적용하기 좋다


4. Adding Dead-code Switch Statements (ADSS)
쓰레기코드인 스위치 구문을 추가
스위치 구문을 추가하여 전혀 의미없는 구문들을 생성하고 코드를 더 어렵게 하기 위해 두개이상의 스위치 구문을 추가한다 이건 바이트코드 단계에서 추가되기 때문에 디컴파일한 것을 다시 컴파일 할 수 없다


5. Finding and Reusing Duplicate Sequences (RDS)
복제 문장의 재사용
바이트코드 단계에서는 수많은 같은 코드가 중복되어 쓰여지고 있다 수백번 되는것도 있다 이런 것들을 재배치해서 중복사용을 없애주면 바이트코드의 크기를 줄일수 있다 이런 과정을 거치게 되면 난독화가 자연스레 발생하게 된다는 것


6. Converting Branches to jsr Instructions (CB2JI)
브랜치를 jsr 구문으로 변환
jsr 바이트코드는 일반적인 goto, jump(브랜치) 명령어이다 jsr구문은 ret 주소를 이용하여 이동한다
if 구문을 goto 구문인 jsr로 변경하게되며 ret 주소로 이동하게 된다 먼저 ret을 이용해버려서 pop이 ret함수를 제거할수 없다 그래서 디컴파일된 코드를 보면 return구문이 있고 뒤에 값들이 밀려 있는 것을 볼 수있다 그래서 이 코드는 다시 컴파일 할 수 없다


7. Indirecting if Instructions (III)
간접 if구문
javac 에서는 try구문을 남용한다 if 구문도 마찬가지인데 goto구문에 try구문을 추가한다 이런 중복적인 것들은 불필요한것이 많다 그래서 현대 컴파일러들은 불필요한 구문들은 제거해버리고 if 구문의 최종 목표점으로 바로 이동하게 한다 그래서 디컴파일후 return의 값이 이상하게 바껴있을 수 있으며 이런것은 재컴파일 할 수 없다


8. Reordering load Instructions Above if Instructions (RLAII)
load 구문을 if구문 위에 다시 불러오기
if구문에 지역변수를 사용할 경우 발생된다 if then i ... else i ..와 같이 i의 변수가 한 범위내에서 같은 변수를 사용 했을 때 이 변수를 if 구문 위로 빼버린다 방법은 load 명령어를 if 구문 전에 사용해서 변수 데이터를 스택에 적재하고 클론들은 삭제해버린다 최신 디컴파일러로 복구 가능하지만 약간의 문제가 있고 재컴파일이 불가능 하다


9. Renaming Identifiers: Classes, Methods, and Fields (RI[C,M,F])
식별자 이름 변경(클래스, 메소드, 필드)
흔히 쓰이는 것이기에 특별한 언급 안함
{S, 5, $}, {l, I, 1}, {_} 같은 걸로 복잡하게 만듦


10. Disobeying Constructor Conventions (DCC)
생성자 규약 파괴
함수를 불러올때 부모 클래스와 다른 클래스를 참조해서 불러올 수 있는데 호출할 경우 제일 상위 클래스로 바로 호출을 하도록 변경한다

Wrapping the super call within a try block
try
슈퍼콜을 블럭으로 싼다는 얘기 함수는 대신 throw 명령어로 대체되고 원래의 함수는 찾을수 없으며 재컴파일도 불가능하다 throw 가 메소드의 끝에 오는게 특징이다
Taking advantage of classes which are children of java.lang.Throwable
throw 구문이 try 구문 보다 앞에 생성되어 먼저 실행된다는 특징이 있다 마찬가지로 재컴파일 불가하며 원래 이름도 찾을수 없다

Inserting a jsr jump and a pop instruction directly before the super constructor call
위에서 했던것처럼 jsr 구문과 pop구문을 추가해서 바로 return 주소로 건너 뛰도록 한다
위에와 비슷해서 예제가 없는듯

Adding new instructions before the super call
ifnull 을 이용해서 push null 과 if 구문을 추가한다 이후 pop, load, goto 구문으로 채워지고 goto 구문에서 super call 로 이동한다
이것도 마찬가지로 재컴파일 되지 않으며 원래 함수는 if null 구문으로 찾을수 있다


11. Combing Try Blocks With Their Catch Blocks (CTBCB)
Try 블록과 Catch 블록을 혼합
try 와 catch 구문을 하나로 합칠수 있다 특히 bytecode에서 catch구문또는 throws가 상위에 하나 더 있을때 try 구문을 보호할 수 있다
이 방식은 각각 try와 catch의 시작이 같을때 가능하다 또한 if가 catch 또는 try에 있을경우 성립된다


12. Goto Instruction Augmentation (GIA)
Goto를 사용
자바는 기본적으로 goto구문을 사용할 수 없다 하지만 고차원 작업에는 필요하기에 bytecode 에서는 사용이 가능하다
The final method now looks like { goto P1, P2, P1, goto P2 }.
이런식으로 x자 형태로 진행된다


출처
http://www.sable.mcgill.ca/JBCO/examples.html

덧글

※ 로그인 사용자만 덧글을 남길 수 있습니다.