결론 및 결정 조건
- 함수를 비즈니스 손실과 공격자 ROI 를 기준으로 먼저 분류한 후, VMP, Java2C, 제어 흐름 난독화, 또는 이름 난독화 중 적용 방식을 결정합니다.
- 스타트업 시퀀스, 렌더링 루프, 고빈도 암호화/복호화, 크로스 언어 경계는 고감도 경로이므로 성능 및 호환성 베이스라인 대신 표준 기능적 회귀 테스트에만 의존해서는 안 됩니다.
- 보호 목록은 버전 관리되어야 하며 고유한 릴리스 후보, 서명 식별자, 빌드 구성, 회귀 테스트 기록과 바인딩되어야 합니다. 그렇지 않을 경우 이상 현상의 원인을 규명할 수 없습니다.
- VMP 는 클라이언트 측 코드 분석 및 재사용 비용을 증가시키지만, 서명 거버넌스, 플랫폼 무결성 신호, 서버 측 권한 부여, 또는 위험 제어를 대체하지는 않습니다.
함수 목록을 비즈니스 자산 인벤토리로 전환
무차별 커버리지의 주된 문제는 성능이 아니라 선택 기준의 부재입니다. 코드 저장소에는 핵심 알고리즘, 권한 확인, 프로토콜 인코딩/디코딩, UI 바인딩, 일반 유틸리티, 서드파티 적응 계층이 동시에 존재합니다. 이러한 구성 요소를 역공학했을 때의 영향은 극명하게 다릅니다. 패키지 이름, 클래스 이름, 또는 함수 개수만으로 대상을 선정하면 저 가치 코드에 보호 예산을 빠르게 소진하여 정작 중요한 경로에는 안정적인 회귀 테스트 자원을 할당하지 못하게 됩니다.
실행 가능한 접근 방식을 위해서는 비즈니스, 보안, 엔지니어링 팀이 공동으로 자산 인벤토리를 작성해야 합니다. 각 후보 함수는 다음 네 가지 질문에 답해야 합니다. 공격자가 이를 이해함으로써 얻는 이득은 무엇인가? 이를 수정할 때 발생하는 피해는 무엇인가? 로직을 서버로 이전할 수 있는가? 실패 시 안전한 대체 경로가 존재하는가? 명확한 손실 가능성, 클라이언트 측 필수 실행 조건, 그리고 검증 가능한 경계를 갖춘 경로만 기술 선정 단계로 진행해야 합니다.
OWASP MASVS 는 역공학 방지 및 변조 방지를 심층 방어 조치로 분류하며, 이들이 견고한 보안 아키텍처를 대체할 수 없다고 명시합니다. 이러한 경계는 VMP 선정 기준이 기술 이름과 보안 결과를 직접 동일시하는 것이 아니라 위협 모델링에서 도출되어야 함을 의미합니다.
| 평가 차원 | 답변해야 할 질문 | 고강도 보호가 필요한 신호 | 등급 하향 또는 연기가 필요한 신호 |
|---|---|---|---|
| 비즈니스 손실 | 로직이 복제, 우회 또는 수정될 경우 어떤 손실이 발생하는가? | 인증, 권한, 핵심 알고리즘 또는 중요 프로토콜이 직접 우회될 수 있습니다. | UI 표현 또는 저 가치 보조 기능에만 영향을 미칩니다. |
| 클라이언트 측 필수성 | 최종 결정이 반드시 온디바이스에서 이루어져야 하는가? | 오프라인 요구사항, 지연 시간 제약 또는 플랫폼 기능이 클라이언트 측 실행을 필수적으로 요구합니다. | 고위험 결정은 서버에서 완료할 수 있습니다. |
| 실행 특성 | 함수 호출 빈도, 스레드 컨텍스트 및 시작 단계는 어떠한가? | 낮은 빈도, 명확한 경계, 그리고 격리 상태에서 측정 가능합니다. | 메인 스레드 시작 단계, 고빈도 루프 또는 제한 없는 실행 시간을 포함합니다. |
| 실패 시 대체 경로 | 보호 실패 시 시스템을 안전하게 중지하거나 전환할 수 있는가? | 명확한 실패 상태와 구성 롤백 메커니즘이 존재합니다. | 실패 시 시작 과정이 차단되며 신속하게 격리할 수 없습니다. |
| 검증 가능성 | 보호 적용 후 비즈니스 정확성을 어떻게 입증할 것인가? | 입출력, 시나리오 및 인수 책임자가 명확히 정의되어 있습니다. | 안정적인 테스트 경로 없이 암시적 상태에 의존합니다. |
- 자산 소유자가 손실 모델을 확인합니다.
- 엔지니어링 팀이 호출 경계와 종속성을 확인합니다.
- QA 팀이 반복 가능한 인수 경로를 확인합니다.
- 릴리스 관리자가 롤백 조건을 확인합니다.
VMP 는 실행 표현 방식을 변경할 뿐, 전체 보안 책임을 대체하지는 않습니다.
이름 난독화는 심볼과 구조의 가독성을 낮추며, 제어 흐름 난독화는 경로 복원에 필요한 노력을 증가시킵니다. Java2C 는 관리되는 코드의 일부를 네이티브 표현으로 이전하고, VMP 는 선택된 로직을 새로운 명령어 세트와 실행 메커니즘을 통해 수행합니다. 이러한 기법들은 계층화될 수 있지만, 각각 다른 문제를 해결하며 고유한 런타임 비용과 실패 모드를 가집니다. 모든 함수에 균일한 보호 수준을 적용하는 것보다 구성 가능한 계층화 전략을 정의하는 것이 검증하기 더 용이합니다.
공격자는 여전히 입력/출력, 함수 호출 타이밍, 네트워크 동작 및 런타임 상태를 관찰할 수 있습니다. 결제, 권한 부여, 계정 인증 또는 고위험 리소스 접근과 같은 시나리오에서는 서버가 계정 권한, 버전 세트, 요청 컨텍스트 및 플랫폼 무결성 신호를 반드시 검증해야 합니다. 클라이언트 측 보호의 역할은 분석, 수정 및 대규모 재사용에 드는 비용을 높이는 것이며, 클라이언트를 절대적으로 신뢰할 수 있는 환경으로 변환하는 것이 아닙니다.
보호 범위는 유지보수성도 고려해야 합니다. 매 릴리스마다 고강도 처리를 거치는 자주 변경되는 비즈니스 글루 코드는 빌드 델타와 회귀 표면을 확대합니다. 상대적으로 안정적이고 고가치의 명확한 인터페이스를 가진 핵심 모듈은 장기 보호 단위로 더 적합합니다.
| 보호 계층 | 주요 기능 | 일반적인 비용 | 추가로 필요한 통제 수단 |
|---|---|---|---|
| 이름 및 구조 난독화 | 정적 분석 읽기 효율성과 대량 위치 추적을 저하시킵니다. | 디버깅, 크래시 원인 규명 및 매핑 파일 관리가 필요합니다. | 무결성 검사, 서버 측 권한 부여, 핵심 로직 보호가 필요합니다. |
| 제어 흐름 및 문자열 처리 | 로컬 복원 비용을 증가시키고 직접적인 민감 단서를 줄입니다. | 패키지 크기 증가, 런타임 오버헤드 및 호환성 위험이 발생합니다. | 키 거버넌스, 로그 정제, 런타임 검증이 필요합니다. |
| Java2C 또는 네이티브 변환 | 관리되는 코드의 일부에 대한 분석 표면을 변경합니다. | JNI 경계, ABI 호환성 및 네이티브 크래시 위험이 발생합니다. | SO 의존성, 심볼, 예외 처리 및 스레드 검사가 필요합니다. |
| VMP (가상 머신 보호) | 선택된 코드의 실행 표현 및 분석 경로를 변경합니다. | 성능 저하, 폭발 범위 (blast radius) 및 릴리스 후보 (release candidate) 의 회귀 테스트 위험이 발생합니다. | 서명, 버전 관리, 서버 측 정책 및 릴리스 게이트가 필요합니다. |
앱 시작 경로과 고빈도 경로는 먼저 동등한 기준선이 확보되어야 합니다
애플리케이션 시작은 단일 지점이 아닙니다. Android 는 공식적으로 콜드 스타트 를 프로세스 생성, Application 생성, 메인 스레드 시작, Activity 생성, 레이아웃 인플레이션, 첫 번째 드로우로 분해하며, 각각 TTID(Time to Initial Display) 와 TTFD(Time to Fully Drawn) 을 사용하여 첫 프레임 시간과 완전 상호작용 가능 시간을 관측합니다. 보호된 코드가 Application, ContentProvider, 클래스 초기화 또는 주요 첫 화면 경로에 위치할 경우 모니터링 SDK 가 초기화되기 전에 장애가 발생할 수 있으므로 표준 온라인 로그로는 이를 완전히 포착하지 못할 수 있습니다.
고빈도 함수의 위험은 누적 비용에서 비롯됩니다. 호출당 실행 시간의 미세한 증가라도 렌더 루프, 오디오/비디오 처리, 프로토콜 루프 또는 배치 데이터 처리에서는 증폭됩니다. 수용 여부는 단일 평균값으로 판단할 수 없으며, 동일한 디바이스 상태와 릴리스 후보 (release candidate) 식별자 하에서 분포, 롱테일, 메인 스레드 점유율, 메모리 변화 및 예외 발생률을 비교해야 합니다. 본 문서에서는 구체적인 오버헤드 수치를 제시하지 않습니다. 특정 결과는 함수 구조, 보호 구성, 디바이스, 컴파일러 및 실행 빈도에 따라 달라지기 때문입니다.
콜드 스타트, 웜 스타트 및 예열된 테스트 환경을 혼동해서는 안 됩니다. 최소한 설치 상태, 프로세스 상태, 계정 데이터 및 네트워크 조건을 고정하고, 동일한 방법론으로 비보호 기준선과 보호된 릴리스 후보 (release candidate) 를 모두 측정해야 합니다.
| 경로 | 민감한 이유 | 관측 필수 항목 | 릴리스 조건 |
|---|---|---|---|
| Application 및 ContentProvider | 첫 화면 렌더링 및 대부분의 모니터링 초기화 이전에 발생합니다. | 프로세스 생성, 초기화 순서, 최초 예외, TTID. | 새로운 시작 장애가 없어야 하며, 시간 변동 폭이 프로젝트 예산 범위 내에 있어야 합니다. |
| 고빈도 메인 스레드 함수 | 누적 지연 시간이 상호작용성에 직접적인 영향을 미칩니다. | 호출 횟수, 단일/총 소요 시간, 쟁크 및 ANR. | 주요 사용자 경로의 분포가 허용 가능하며 새로운 롱테일이 발생하지 않아야 합니다. |
| 네이티브 및 JNI 경계 | ABI, 등록, 예외 및 스레드 제약 사항과 관련이 있습니다. | 라이브러리 로딩, JNI 예외, 대상 ABI, 크래시 스택. | 대상 매트릭스가 항목별로 통과해야 하며, 커버되지 않은 항목은 플래그로 표시되어야 합니다. |
| 백그라운드 배치 처리 | CPU, 배터리 및 메모리 비용을 증폭시킬 수 있습니다. | 작업 지속 시간, 피크 리소스 사용량, 취소 및 재시도. | 시스템 제한이나 비즈니스 마감 시간을 위반해서는 안 됩니다. |
- 콜드 스타트업 시간과 비즈니스 인터랙션 시간을 별도로 기록합니다.
- 동일한 설치 환경과 계정 데이터 조건을 사용합니다.
- 평균값과 롱테일 분포를 모두 관찰합니다.
- 성능 예산을 사후 설명이 아닌 승인 기준에 명시적으로 인코딩합니다.
보호 범위를 감사 가능하고 롤백 준비가 된 구성으로 정의합니다.
유지 가능한 보호 목록은 단순한 도구 인터페이스의 체크박스 집합이어서는 안 됩니다. 릴리스 구성처럼 버전 관리 시스템에 등록되어 자산 식별자, 선택 근거, 보호 수준, 의존성, 성능 예산, 담당자, 롤백 조건을 기록해야 합니다. 이를 통해 문제 발생 시 특정 함수가 왜 보호되었는지, 어느 버전부터 적용되었는지, 누가 승인했는지 명확히 추적할 수 있습니다.
구성 변경은 소규모 배치로 진행해야 합니다. 경계가 가장 명확하고 가치가 높은 경로 몇 가지를 선정해 개념 증명 (PoC) 을 먼저 수행한 후 그룹별로 확장합니다. 각 확장 단계마다 새로운 릴리스 후보 식별자와 회귀 테스트 기록을 생성해야 하며, 기존 아티팩트를 동일한 파일명으로 덮어써서는 안 됩니다.
다음 YAML 은 데이터 구조의 공개적이고 안전한 예시이며, Yudun 내부 구성 형식이나 실제 클래스명, 함수명, 제품 구현체와 무관합니다.
- 모든 선택 항목에는 비즈니스적 타당성이 있어야 합니다.
- 구성 변경 사항은 특정 릴리스 후보와 매핑되어야 합니다.
- 고위험 경로에는 독립적인 회귀 테스트 스위트가 있어야 합니다.
- 롤백 작업은 과거 구성을 추측하는 방식에 의존해서는 안 됩니다.
asset: premium-entitlement-decision
owner: commerce-team
client_required: true
threats:
- unauthorized-logic-reuse
- local-branch-tampering
execution:
phase: post-login
frequency: low
main_thread: false
protection:
tier: high
rollback_group: entitlement-v1
acceptance:
- output-parity
- latency-budget
- target-os-matrix
- signed-candidate-identity승인 절차는 반드시 동일한 릴리스 후보 및 릴리스 체인에 바인딩되어야 합니다.
빌드 성공은 툴체인이 아티팩트를 생성했다는 사실만 증명하며, 설치 성공은 현재 패키지가 현재 디바이스의 설치 조건을 만족한다는 것만 증명합니다. 최종 승인에는 서명 신원 확인, 실사용 버전에서의 업그레이드, 콜드 스타트업, 핵심 비즈니스 경로, 예외 복구, 대상 시스템, 대상 ABI 검증이 모두 포함되어야 합니다. 정적 분석, 성능 측정, 호환성 회귀 테스트는 모두 동일한 파일 식별자를 기준으로 수행되어야 합니다.
보호되지 않은 베이스라인과 각 보호된 릴리스 후보 버전 모두에 대해 파일 다이제스트, 패키지 이름, 버전, 서명 인증서 다이제스트, 빌드 소스, 보호 구성 버전, 채널 처리 순서를 기록하는 것이 좋습니다. 재빌드, 재서명 또는 채널 수정이 발생하면 새로운 후보 식별자가 생성되므로 영향을 받는 검증 단계를 다시 수행해야 합니다.
릴리스 결정은 검증된 범위, 미수행 범위, 실패 범위라는 세 가지 결론을 명확히 명시해야 합니다. 디바이스, 시스템 또는 비즈니스 데이터가 부족한 영역은 '검증 불가'로 표시하고 다른 버전이나 디바이스의 성공 결과를 차용하지 않은 채 카나리아 릴리스 범위를 제한해야 합니다.
| 게이트 | 증거 | 허용되지 않는 대체 수단 | 실행 조치 |
|---|---|---|---|
| 후보 식별자 | 다이제스트, 버전, 서명, 구성 및 빌드 소스. | 동일한 파일명 또는 구두 확인. | 전파를 중단하고 아티팩트를 재수정합니다. |
| 기능적 일관성 | 주요 입출력 경로와 예외 경로의 비교. | 단순히 홈 화면이나 단일 데모를 여는 행위. | 범위를 좁혀 가장 초기의 차이 지점을 파악합니다. |
| 성능 예산 | 동일 조건 하에서의 시작 시간 및 주요 경로 분포. | 다른 디바이스에서 추출한 단일 평균값. | 고빈도 경로를 롤백하거나 티어를 조정합니다. |
| 호환성 매트릭스 | 대상 시스템, ABI, 디바이스 유형 및 서드파티 경로. | 에뮬레이터 또는 단일 신규 시스템 버전. | 검증 불가로 플래그를 지정하고 릴리스를 제한합니다. |
| 릴리스 종료 | 업그레이드, 서명, 채널, 모니터링 및 롤백 훈련. | 재서명 후 생성된 다른 패키지. | 영향을 받는 게이트를 재실행합니다. |
VMP 범위를 직접 확장해서는 안 되는 시나리오
팀이 핵심 자산을 명확히 정의하지 못했거나 안정적인 릴리스 후보가 없거나 대상 시스템 매트릭스를 충족하지 못하거나 심지어 보호되지 않은 베이스라인조차 없는 경우, 범위를 무리하게 확장하면 귀속 불가능한 변수만 증가시킵니다. 올바른 조치는 검증 공백을 높은 커버리지로 덮는 것이 아니라 자산 정의와 테스트 조건을 완성하는 것입니다.
리플렉션, 직렬화, 동적 클래스 로딩, 핫픽스, 플러그인 프레임워크, JNI 등록, 서드파티 자체 검증 및 시작 단계 SDK 는 이름, 코드 레이아웃, 로딩 순서 또는 예외 동작에 대한 암묵적 의존성을 가질 수 있습니다. 이러한 요소들이 보호 대상에서 완전히 배제되어야 하는 것은 아니지만, 별도로 목록화하여 실제 비즈니스 진입점에서 검증해야 합니다.
서버에서 처리 가능한 고위험 결정은 최종 권한 부여를 서버 측에서 수행하는 것을 우선시해야 합니다. 클라이언트 측 VMP 는 필요한 로컬 연산과 결정 자료를 보호할 수 있지만, 런타임 환경이 영구적으로 신뢰할 수 있음을 보장하지는 않으며 유효한 클라이언트 자격 증명의 남용을 단독으로 방지할 수도 없습니다.
최종 범위는 단일 미팅에서 도출된 영구적인 결론이 아닙니다. 비즈니스 로직, 컴파일 체인, SDK 및 대상 시스템이 변경됨에 따라 자산 가치, 실행 빈도 및 호환성 경계를 재평가해야 합니다.
- 범위를 확장하기 전에 기준선을 수립하십시오.
- 롤백 계획 없이 폭발 반경 (blast radius) 을 확장하지 마십시오.
- 암시적 종속성이 있는 경로에 대해서는 별도의 그룹을 생성하십시오.
- 서버에서 관리 가능한 결정을 클라이언트에만 맡기지 마십시오.
증거 및 적용 범위
이 섹션에서는 문서화된 플랫폼 사실, 엔지니어링 판단, 확인되지 않은 제품 주장으로 일반화할 수 없는 제한 사항을 구분합니다.
| 기사판정 | 사실 또는 공학적 근거 | 적용 범위 |
|---|---|---|
| VMP 는 보안 아키텍처를 대체하는 수단이 아니라 위협 기반의 다층 방어 (defense-in-depth) 로 활용되어야 합니다. | OWASP MASVS-RESILIENCE 는 복원력을 향상시키기 위한 통제 수단으로 난독화, 변조 방지 및 정적/동적 분석 방지를 명시하지만, 보안은 여전히 검증 가능한 설계, 암호화 및 서버 측 검증에 의존함을 강조합니다. | 본 표준은 통제 목표를 정의하며, 특정 제품이나 구성이 해당 목표를 달성했음을 증명하지는 않습니다. |
| 스타트업 경로에는 독립적인 성능 기준선이 필요합니다. | Android 는 공식적으로 스타트업을 콜드, 웜, 핫 상태로 분류하며 TTID 와 TTFD 를 사용하여 첫 번째 프레임 표시 시간과 완전 상호작용 가능 시간을 구분합니다. | 공식 지표 정의가 특정 프로젝트의 실제 릴리스 후보 (release candidate) 및 대상 기기에서의 측정을 대체할 수는 없습니다. |
| 서명 및 업그레이드 연속성은 독립적으로 승인되어야 합니다. | Android 문서에 따르면 모든 APK 에 서명이 필요하며, 플랫폼은 서명 신원을 사용하여 설치된 앱의 업데이트가 동일한 키 소유자로부터 왔는지 여부를 판단합니다. | 서명 일관성은 릴리스 신원 체인의 일부만 증명할 뿐이며, 비즈니스 로직이 남용되지 않았음을 증명하지는 않습니다. |
| 플랫폼 무결성 신호를 서버 측 정책에 통합해야 합니다. | Play Integrity 는 앱, 기기, 계정 및 환경과 관련된 판정 결과를 반환하므로 백엔드가 위험 등급에 따라 대응할 수 있습니다. | 신호는 배포 환경에 따라 사용 불가능하거나 제한될 수 있으므로 단일 판정 결과를 절대적인 신뢰로 간주해서는 안 됩니다. |
| 함수, 기기 및 구성과 분리된 범용 성능 오버헤드 수치는 존재하지 않습니다. | VMP 비용은 실행 빈도, 스레드 수, 코드 구조, 보호 구현 방식, 컴파일러 및 디바이스 환경에 비례하므로, 결론은 반드시 동일한 조건 하의 통제된 비교를 통해 도출해야 합니다. | 이는 엔지니어링 판단이며, Yudun 이나 기타 제품에 대한 실증적 성능 주장이 아닙니다. |
엔지니어링 질문
보호 범위가 넓을수록 항상 리버스 엔지니어링 비용이 증가합니까?
커버리지 증가는 일부 부분에서 분석 노력을 높일 수 있지만 성능, 호환성, 회귀 비용도 확대시킵니다. 공격자의 ROI에 진정으로 영향을 미치는 것은 고가치 경로가 효과적으로 보호되는지 여부와 서명, 무결성 검사, 서버 측 정책이 폐쇄 루프를 형성하는지 여부입니다.
스타트업 함수에 VMP 적용이 절대 금지됩니까?
절대 금지되지는 않습니다. 다만 스타트업 단계의 장애는 폭발 반경 (blast radius) 이 크고 모니터링이 아직 초기화되지 않았을 수 있습니다. 따라서 콜드 스타트업 기준치 설정, 명확한 예산 수립, 대상 시스템 매트릭스 정의 및 신속한 롤백 계획 수립이 선행되어야 합니다.
어떻게 함수의 고가치 여부를 판단합니까?
해당 함수를 리버스 엔지니어링하거나 수정할 경우 인증 우회, 알고리즘 복제, 프로토콜 악용 또는 직접적인 비즈니스 손실이 발생하는지 평가하십시오. 동시에 해당 로직이 온디바이스 (on-device) 에서 유지되어야 하며 독립적인 회귀 테스트가 가능한지 확인해야 합니다.
현재 릴리스 후보 (release candidate) 가 없는 상태에서 최종 적용 범위를 확정할 수 있습니까?
예비 자산 등급 분류와 개념 증명 (PoC) 목록은 작성 가능하나, 성능, 호환성 또는 최종 보호 효과에 대해서는 사전에 보장할 수 없습니다. 최종 적용 범위는 실제 릴리스 후보를 통한 비교 검증 결과를 바탕으로 확정해야 합니다.
VMP 적용 후에도 서버 측 위험 제어 기능이 필요합니까?
네, 필요합니다. 클라이언트 측 보호는 분석 및 변조 비용을 증가시키지만, 계정 인증, 거래 처리, 권한 부여 및 고위험 자원 접근에 대한 최종 결정은 버전, 계정 정보 및 위험 신호를 종합하는 서버에서 이루어져야 합니다.
자신의 앱에서 이를 테스트하고 싶으신가요?
Yudun PoC 및 호환성 평가를 위한 릴리스 후보, 대상 시스템 및 중요한 비즈니스 경로를 제출하세요.