최근 수정 시각 : 2025-08-07 07:14:03

난독화


1. 개요2. 종류
2.1. 소스 코드 난독화2.2. 바이너리 난독화
3. 자동화4. 기타

1. 개요

Obfuscation /

프로그램의 수행과 결과를 변경하지 않으면서, 사람이 의미를 파악하기 어렵고 역설계에 오랜 시간이 소모되도록 하는 행위, 또는 그러한 기술을 말한다.

주로 디컴파일, 리버스 엔지니어링, 코드 유출 및 취약점 분석 방지 등을 목적으로 행해진다.

obfuscation의 반댓말로는 deofuscation라고 불린다.[1]

uglification으로도 불린다.

2. 종류

2.1. 소스 코드 난독화

프로그래밍 언어로 된 원본 소스 코드 자체를 사람이 읽기 어렵게 만드는 행위. 프로그래밍 언어는 기본적으로 사람이 코드를 쉽게 이해하도록 돕는 다양한 장치를 마련하고 있으나, 소스 코드 난독화를 통해 이러한 장치를 대부분 제거할 수 있다. 런타임에 로딩되는 실제 프로그램이 소스 코드 그 자체여야 하기에 주로 인터프리터 언어의 배포에 사용된다.

리네임을 사용하지 않는 경우 주석, 화이트스페이스 등 불필요한 lexical elements를 제거하고 선형으로 압축하는 format obfuscation이 가장 기본적이다. 단, 이 경우 코드 포매터 등을 통해 원본에 가깝게 되돌릴 수 있어 단독으로는 잘 쓰이지 않는다.

대부분의 경우 식별자를 lexical scope에 따라 겹치지 않게 a, b, DJd3PO9d 등 무작위한 이름으로 rename한다. rename refactoring과 동일한 메커니즘이지만, 단회 시행되는 것이 아니라 노출되지 않은 내부 식별자까지 AST 순회를 하며 전부 수정하게 된다. minification을 겸하는 경우 식별자명을 최대한 짧은 길이로 수정하는 편.

이외에도 바이너리 난독화와 마찬가지로 임베딩된 상수, 정적 문자열 등의 data obfuscation을 추가로 진행하기도 한다. 예를 들면 문자열"토큰 생성일"

#!syntax javascript
(function(){var z=Array.prototype.slice.call(arguments),F=z.shift();return z.reverse().map(function(u,I){return String.fromCharCode(u-F-4-I)}).join('')})(11,53679)+(function(){var g=Array.prototype.slice.call(arguments),A=g.shift();return g.reverse().map(function(G,N){return String.fromCharCode(G-A-48-N)}).join('')})(41,49464,122,53449)+(function(){var z=Array.prototype.slice.call(arguments),e=z.shift();return z.reverse().map(function(t,m){return String.fromCharCode(t-e-60-m)}).join('')})(28,51157,49545)

처럼 나타내는 식이다.

필요에 따라 난독화를 더욱 어렵게 만들기 위해 dead code 삽입, function inlining, code duplication 등을 수행하기도 한다. 이 경우 트리가 아니라 flow 단위의 조작이 필요한데, 정적 분석만으로는 모든 flow를 예측하기 힘들어 간단한 깊이만 구현되기도 한다.

2.2. 바이너리 난독화

고수준의 프로그래밍 언어를 바이트코드, 또는 기계어로 컴파일하며 디버깅 심볼 정보 등을 삭제하는 방식이 자주 쓰인다. 이 경우 컴파일러가 같이 생성하는 맵핑 파일만으로 원본에 가까운 복원이 가능하다.

다만 이 경우 맵핑 정보가 없어도 디컴파일 자체는 일정 수준까지 가능하기 때문에, 본격적인 난독화를 수행할 경우 어셈블리 수준의 instruction fuzzing을 수행하는 것이 일반적이다. 특히 전체 소스를 CFG로 만든 다음 불규칙적인 점프 명령어를 삽입하여 실행 흐름을 수정하는 방법이 있다. 어셈블리 수준 난독화의 경우 소스보다 본격적인 인라이닝이나 unwinding이 들어가는 편.

3. 자동화

사람이 일일히 코드를 난독화하는 것은 시간 소모가 크고 개발에 좋지 않기 때문에 대부분 CI 파이프라인 또는 배포시에 자동으로 수행된다.

4. 기타

암호화와는 다르다. 암호화는 원본과 동일하게 복호화가 가능한 대칭 연산이지만 난독화는 일반적으로 심볼 맵 등이 없다면 난독화된 소스 자체만으로는 원본으로의 복호화가 불가능하다. 즉, 비대칭 연산이다.

DRM과도 차이가 있다. DRM은 동적 컨텐츠 자체의 복제를 방지하기 위한 기술이지 정적 데이터인 코드를 조작하는 개념이 아니다. 대부분 난독화는 CI 등 단계에서 배포 이전에 이루어진다.

minification과 매우 비슷하지만 목적이 다르다. minification은 주로 웹에서, 스크립트의 배포 용량을 줄이기 위한 과정으로 소스 코드를 최대한 압축하는 것이 유일한 목적으로, 소스를 읽을 수 없게만 하면 되는 난독화와는 다르다. 예를 들어 경우에 따라 난독화 과정에서 혼란을 주기 위한 dead code, stub code 등이 삽입되기도 하는데, minification은 반대로 사용하지 않는 모든 코드를 반드시 걸러낸다(dead code elimination). 다만 현실적으로 두 결과가 거의 비슷하기 때문에 혼용되어 쓰이기도 하는 편.
[1] 난독화를 해제한다는 의미다.