버전: v2.0
분석일: 2026-02-26
분석가: Deep-Coding 보안연구소 (주식회사 아크링크)
분석 수준: ML-Complete (Quantum-Nano)
앱 식별자: yolo
파일명: YOLO (app_name: "YOLO")
YOLO는 WaveGrid Gen3 Pre-R8 계열의 악성 데이터 탈취 앱으로, C2 도메인 [비공개]를 사용한다. 이 도메인은 SL-060 (C2 Domain Rotation) 패턴의 중간 회전 도메인으로, [비공개](원본) → [비공개] → [비공개](최신)로 이어지는 도메인 회전의 2번째 단계이다.
핵심 발견 사항:
· C2: `[비공개] (SL-060 중간 도메인)
· API: webapp/* 네임스페이스 (SL-062 — zcloud_2, Sfile과 동일)
· 권한: 11개 (SEND_SMS 포함 — 데드 권한, SN-040)
· SEND_SMS 실제 사용 0건 — SmsManager/sendTextMessage 호출 없음
· MessengerUtils 존재 — zcloud_2에 없던 클래스가 추가됨
· Huawei ScanKit + MLKit SDK 번들 (앱 코드 미사용 — SL-063 재확인)
· 4채널 단방향 전송: SMS + 연락처 + 사진(Luban 압축) + 전화번호
· 19세 미만 이용 불가 경고 UI — 성인용 앱으로 위장
· 별도 AlbumActivity, ContactActivity 존재 (zcloud_2에는 미존재)
· compileSdkVersion=32 (zcloud_2의 33보다 낮음 — 역설적 빌드 번호)
항목 · 값
**패키지명** · `[비공개]`
**내부 패키지** · `com.example.sms`
**앱 이름** · YOLO
**compileSdkVersion** · 32
**minSdkVersion** · 26 (추정)
**targetSdkVersion** · 32
**권한 수** · 11개 (SEND_SMS 포함)
**smali 파일 수** · 6,678개
**DEX 수** · 2개 (classes.dex + classes2.dex)
**파일 크기** · 11.06 MB
**파일 SHA256** · (auto_analysis.json 참조)
**패밀리** · WaveGrid Gen3 Pre-R8 (v4-A')
**C2 서버** · `[비공개]
**초대코드** · NQAQ, YHCC
**배포 도메인** · `[비공개]`
```
[비공개] (원본, zcloud_2 vCode=7)
↓
[비공개] (중간, YOLO — 본 분석)
↓
[비공개] (최신, Sfile vCode=21145)
```
YOLO는 도메인 회전의 2번째 단계에 위치한다. zcloud.website에서 zcloud1.website로의 전환은 도메인 차단/만료 대응으로 추정되며, "zcloud" 브랜딩을 유지한 점이 특징적이다. 이후 love19.store로의 전환에서는 "zcloud" 브랜딩을 완전히 폐기했다.
```smali
.field public static base_url:Ljava/lang/String; = "[비공개]
```
# · 권한 · 위험 · 용도
1 · INTERNET · Normal · C2 통신
2 · ACCESS_NETWORK_STATE · Normal · 네트워크 상태
3 · READ_SMS · Dangerous · SMS 탈취
4 · **SEND_SMS** · Dangerous · **데드 권한 (SN-040)**
5 · READ_CONTACTS · Dangerous · 연락처 탈취
6 · READ_PHONE_STATE · Dangerous · IMEI, 전화번호
7 · READ_PHONE_NUMBERS · Dangerous · 전화번호
8 · READ_EXTERNAL_STORAGE · Dangerous · 사진 탈취
9 · READ_MEDIA_IMAGES · Dangerous · 사진 (API 33+)
10 · READ_MEDIA_AUDIO · Dangerous · 오디오 (API 33+)
11 · READ_MEDIA_VIDEO · Dangerous · 비디오 (API 33+)
```bash
grep SEND_SMS: 0건
grep SmsManager: 0건
grep sendTextMessage: 0건
```
SEND_SMS는 AndroidManifest.xml에 선언되어 있으나 앱 코드에서 단 한 번도 사용되지 않는다. 이는 Sfile에서도 동일하게 관찰된 패턴(SN-040)으로, 템플릿에 남아있는 미사용 권한이다. zcloud_2에서는 아예 선언되지 않았으므로, SEND_SMS 추가는 zcloud_2 이후 어느 시점에 발생했다.
권한 · zcloud_2 · YOLO · 차이
SEND_SMS · 없음 · 있음(데드) · YOLO에서 추가
나머지 10개 · 동일 · 동일 · 변화 없음
```
com.example.sms/
├── LoginActivity.smali (+ $1, $1$1, $1$1$1$1, $2, $2$1, $3)
├── MainActivity.smali (+ $1, $2, $3, $4)
├── UploadActivity.smali (+ $1~$9)
├── AlbumActivity.smali (+ $1, $1$1, $1$2, $1$2$1)
├── ContactActivity.smali (+ $1, $2)
├── BaseApp.smali (+ $1)
├── BuildConfig.smali
├── R.smali (+ $color, $drawable, $id, $layout, $mipmap, $string, $style, $xml)
├── adapter/
│ ├── AlbumAdapter.smali (+ $1, $ItemListener, $ViewHolder)
│ ├── MainAdapter.smali (+ $1, $ItemListener, $ViewHolder)
│ └── SmsAdapter.smali (+ $1, $ItemListener, $ViewHolder)
├── bean/
│ ├── ContactBean.smali
│ ├── OnSuccess.smali (interface)
│ ├── SmsBean.smali
│ ├── NewsBean.smali (+ $Result, $Result$News)
│ └── WeatherBean.smali (+ $Result, $Result$Weather)
├── servise/
│ └── UploadService.smali (+ $1, $2, $3, $3$1)
├── utils/
│ ├── HttpUtils.smali (+ $1)
│ ├── ReadContactUtils.smali
│ ├── SPUtils.smali (+ $SharedPreferencesCompat)
│ ├── DialogUtil.smali
│ └── GlideEngine.smali (+ $1, $InstanceHolder)
└── view/
└── GeneralDialog.smali
```
클래스 · YOLO · zcloud_2 · 분석
AlbumActivity · 있음 · 없음 · 별도 앨범 관리 화면
ContactActivity · 있음 · 없음 · 별도 연락처 화면
BaseApp · 있음 · 없음 · Application 서브클래스
NewsBean · 있음 · 없음 · 뉴스/날씨 위장 데이터
WeatherBean · 있음 · 없음 · 날씨 위장 데이터
GeneralDialog · 있음 · 없음 · 커스텀 다이얼로그
GlideEngine · 있음 · 없음 · 이미지 로딩 엔진
YOLO(6,678) vs zcloud_2(6,884): YOLO가 206개 적음에도 더 많은 클래스를 보유.
요인 · 설명
compileSdkVersion 차이 · YOLO=32, zcloud_2=33 → API 33 미디어 관련 코드 미생성
라이브러리 차이 · zcloud_2에 더 많은 3rd-party 라이브러리 포함
Huawei SDK 버전 · 동일하지만 빌드 시점 차이로 생성 smali 달라질 수 있음
이 역설적 관계는 Gen3 Pre-R8 계열이 단순 선형 진화가 아님을 시사한다. 기능 추가와 라이브러리 변경이 독립적으로 발생.
```smali
.class public Lcom/example/sms/LoginActivity;
.super Landroidx/appcompat/app/AppCompatActivity;
.field private btn_save:Landroid/widget/TextView;
.field private et_code:Landroid/widget/EditText;
.field private uuid:Ljava/lang/String;
```
```smali
const-string v1, "webapp/login"
```
· GET 요청 (zcloud_2와 동일)
· 비동기 enqueue() 사용 (zcloud_2와 동일)
· UUID 기반 기기 식별 (SPUtils)
```smali
const-string v2, "" # 빈 URL — 데드코드
```
· zcloud_2와 동일한 빈 URL 데드코드
· 그러나 YOLO는 HashMap에 "path", "success_action_status"="200" 포함 — OSS/클라우드 업로드 잔재
· zcloud_2보다 더 완전한 형태의 데드코드 → 원본 템플릿에 가까움
YOLO의 uploadImgnew()가 zcloud_2보다 더 완전한 형태를 가진다:
· YOLO: HashMap("path", "success_action_status") + "application/octet-stream" MIME
· zcloud_2: 빈 URL만 존재, HashMap 없음
이는 코드 정리(stripping)가 zcloud_2에서 더 많이 진행되었음을 의미한다. 하지만 zcloud_2의 versionCode가 7(더 낮음)이므로, 단순 버전 순서가 아닌 빌드 분기(branch)의 존재를 시사한다.
SL-064 Build Branch Divergence: 동일 Gen3 Pre-R8 계열 내에서 빌드 분기가 발생하여 독립적으로 코드가 진화한 패턴.
```smali
const-wide/16 v2, 0x1388 # 5000ms
const-wide/16 v4, 0x3e8 # 1000ms
```
· 5초 CountDownTimer 무한 루프 — zcloud_2와 완전 동일
· getSmsDataUpload(): userName(invite_code) + bjPhone + content(SMS JSON)
· onStartCommand: START_STICKY (const/4 p1, 0x1)
· 별도 Thread에서 postGson("webapp/saveSms") 실행
```json
{
> [비공개]
"bjPhone": "010-XXXX-XXXX", // getLine1Number()
"content": "[...]" // getMsgs() → toJSONString()
}
```
완전히 동일한 페이로드 구조.
내부 클래스 · 역할 (추정)
$1~$4 · UI 이벤트 핸들러 (버튼 클릭)
$5, $5$1, $5$1$1 · 사진 업로드 (webapp/image/)
$6, $6$1, $6$1$1 · 연락처 업로드 (webapp/saveAddressBook)
$7, $7$1, $7$1$1 · SMS 업로드 (webapp/saveSms)
$8 · 추가 핸들러
$9 · 추가 핸들러
zcloud_2의 UploadActivity($1~$7)보다 내부 클래스 2개 더 많음 ($8, $9 추가).
```
LoginActivity.smali:74 → "webapp/login"
LoginActivity$1$1.smali → "webapp/login"
UploadService$3.smali:57 → "webapp/saveSms"
UploadActivity$5$1.smali → "webapp/image/"
UploadActivity$6.smali:57 → "webapp/saveAddressBook"
UploadActivity$7.smali:57 → "webapp/saveSms"
```
zcloud_2와 완전 동일한 API 엔드포인트.
```xml
<!-- AndroidManifest.xml:49-53 -->
<service android:exported="false" android:name="com.blankj.utilcode.util.MessengerUtils$ServerService">
<intent-filter>
<action android:name="[비공개].messenger"/>
</intent-filter>
</service>
```
항목 · YOLO · zcloud_2
MessengerUtils · 있음 · **없음**
action명 · [비공개].messenger · -
용도 · IPC 메시지 전달 · -
com.blankj.utilcode 패키지: 중국 안드로이드 유틸리티 라이브러리 (AndroidUtilCode). MessengerUtils는 프로세스 간 통신을 위한 유틸리티. 악성 기능과 직접 관련 없으나, 빌드 환경 추적에 활용 가능.
```xml
<meta-data android:name="huawei_module_scankit_local" android:value="1030100"/>
<meta-data android:name="com.huawei.hms.client.service.name:scan" android:value="scan:[비공개]"/>
<meta-data android:name="com.huawei.hms.client.service.name:ml-computer-camera-inner" android:value="ml-computer-camera-inner:[비공개]"/>
```
SDK · zcloud_2 · YOLO
ScanKit · [비공개] · [비공개]
MLKit · [비공개] · [비공개]
동일 SDK 버전 = 동일 빌드 환경/템플릿에서 생성된 증거.
3개 앱에서 동일한 Huawei SDK 잔류 확인:
· zcloud_2: ScanKit [비공개] + MLKit [비공개]
· YOLO: ScanKit [비공개] + MLKit [비공개]
· (추가 확인 필요) 다른 Gen3 Pre-R8 앱들
패키지명 com.example.sms, 클래스명 LoginActivity/UploadService 등 원본 그대로. Gen3 Pre-R8 특징.
Build.FINGERPRINT, Build.MODEL, "goldfish", "sdk" 등 탐지 코드 부재.
su, Superuser, Magisk 관련 코드 부재.
서버 측 초대코드 검증만 존재 (NQAQ, YHCC).
```smali
.field public static base_url:Ljava/lang/String; = "[비공개]
```
모든 데이터가 HTTP cleartext로 전송. network_security_config.xml에서 cleartextTrafficPermitted="true" 확인.
초대코드+전화번호가 URL 파라미터로 노출. 서버 access log에 기록됨.
OkHttpClient 기본 생성. 인증서 검증 커스터마이징 없음.
SMS, 연락처, 전화번호 모두 암호화 없이 JSON으로 전송.
UploadService가 외부 앱에서 시작 가능.
uploadImgnew()의 빈 URL 데드코드. 원본 템플릿 흔적.
항목 · zcloud_2 · **YOLO** · Sfile
C2 도메인 · [비공개] · **[비공개]** · [비공개]
SL-060 위치 · 원본 · **중간** · 최신
versionCode · 7 · (확인 필요) · 21145
smali 수 · 6,884 · **6,678** · 7,469
권한 수 · 10 · **11** · 11
SEND_SMS · 없음 · **있음(데드)** · 있음(데드)
MessengerUtils · 없음 · **있음** · 있음
AlbumActivity · 없음 · **있음** · 확인 필요
ContactActivity · 없음 · **있음** · 확인 필요
BaseApp · 없음 · **있음** · 확인 필요
Huawei SDK · 있음 · **있음(동일)** · 미확인
compileSdkVersion · 33 · **32** · 확인 필요
uploadImgnew 데드 · 빈 URL · **HashMap+빈URL** · 있음
operatorName · 있음 · 있음(추정) · 있음
19세 경고 · 미확인 · **있음** · 미확인
YOLO는 zcloud_2 이후 빌드임에도 역설적 특성을 보인다:
지표 · zcloud_2 · YOLO · 선형 모델 예측 · 실제
compileSdkVersion · 33 · 32 · 33+ · **역행**
smali 수 · 6,884 · 6,678 · 6,884+ · **감소**
uploadImgnew 데드코드 · 빈 URL만 · HashMap+빈URL · 동일 또는 제거 · **더 완전**
SEND_SMS 권한 · 없음 · 있음(데드) · 없음 유지 · **추가됨**
MessengerUtils · 없음 · 있음 · 없음 유지 · **추가됨**
AlbumActivity · 없음 · 있음 · 없음 유지 · **추가됨**
ContactActivity · 없음 · 있음 · 없음 유지 · **추가됨**
BaseApp · 없음 · 있음 · 없음 유지 · **추가됨**
UploadService action · com.example.sms · com.example.mydemo · sms 유지 · **다른 네임스페이스**
이는 SL-064 Build Branch Divergence를 뒷받침한다: Gen3 Pre-R8은 단일 선형 발전이 아닌, 복수 빌드 분기에서 독립적으로 진화한 변종 그룹이다.
YOLO의 mydemo 네임스페이스와 낮은 compileSdkVersion은 이 앱이 zcloud_2보다 이전 시점에 분기된 별도 빌드임을 시사한다:
```
┌─ Branch A (compileSdk=32, mydemo) → YOLO
원본 템플릿 ──────┤
└─ Branch B (compileSdk=33, sms) → zcloud_2
↓
Sfile ([비공개])
```
Branch A는 원본 템플릿의 mydemo 네임스페이스를 유지하면서 MessengerUtils, AlbumActivity 등을 추가. Branch B는 sms 네임스페이스로 변경하면서 코드를 정리(smali 증가).
카테고리 · zcloud_2 · YOLO · 차이 · 원인 추정
MessengerUtils 관련 · 0 · ~50-80 · +50-80 · YOLO에 MessengerUtils 추가
AlbumActivity · 0 · ~30-50 · +30-50 · YOLO에 AlbumActivity 추가
ContactActivity · 0 · ~30-50 · +30-50 · YOLO에 ContactActivity 추가
BaseApp · 0 · ~10-20 · +10-20 · YOLO에 BaseApp 추가
SEND_SMS 관련 · ~20-30 · ~20-30 · 0 · 선언만, 코드 없음
Huawei SDK · ~300 · ~300 · 0 · 동일 버전
zcloud_2 고유 · ~200+ · 0 · -200+ · Branch B에서 추가된 코드
**총계** · **6,884** · **6,678** · **-206** · 분기별 독립 진화
YOLO가 4개 클래스(MessengerUtils, AlbumActivity, ContactActivity, BaseApp)를 추가하면서도 총 smali 수가 적은 것은, Branch B(zcloud_2)에서 다른 영역의 코드가 더 추가되었음을 의미한다. 이 ~200개 차이가 zcloud_2의 자체 빌드 최적화 또는 독립 기능 추가 결과이다.
필드 · 타입 · 소스 · 설명
userName · String · SPUtils("invite_code") · 공격자 식별
bjPhone · String · getLine1Number() · [피해자 정보 비공개]
content · String(JSON) · getMsgs() → toJSONString() · SMS 목록
필드 · 타입 · 소스 · 설명
userName · String · SPUtils("invite_code") · 공격자 식별
model · String · 하드코딩 "android" · 플랫폼
bjPhone · String · getLine1Number() · [피해자 정보 비공개]
operatorName · String · getSimOperatorName() · 통신사명
phoneContent · String(JSON) · getContact() → toJSONString() · 연락처
필드 · 타입 · 소스 · 설명
file · Binary · Luban 압축 파일 · 이미지
other_field · String · 하드코딩 "value" · 플레이스홀더
· 마젠타/핑크 원형 로고 (하트 심볼 + "YOLO!" 텍스트)
· "YOLO!" 브랜딩
· "19 세미만의 청소년이 이용할 수 없습니다" — 성인용 앱 위장
· 초대코드 입력 필드
· 스크린샷: screenshot_login.png
19세 경고는 소셜 엔지니어링 기법: 성인 콘텐츠 기대감을 유발하여 권한 허용을 유도. 실제로는 데이터 탈취 앱.
```
┌──────────────────────────────────────────────┐
│ 1. LoginActivity (앱 시작) │
│ ┌──────────────────────────┐ │
│ │ ● YOLO! (마젠타+하트) │ │
│ │ "19 세미만의 청소년이 │ │
│ │ 이용할 수 없습니다" │ │
│ │ [초대코드 입력] │ │
│ │ [확인] 버튼 │ │
│ └──────────────────────────┘ │
│ │ │
│ ▼ (초대코드 검증 성공) │
│ 2. UploadActivity (권한 요청) │
│ - READ_SMS 권한 요청 │
│ - READ_CONTACTS 권한 요청 │
│ - READ_PHONE_STATE 권한 요청 │
│ - READ_PHONE_NUMBERS 권한 요청 │
│ │ │
│ ▼ (권한 허용) │
│ 3. UploadService 시작 │
│ - 5초 CountDownTimer 무한 루프 │
│ - SMS 수집 → C2 전송 │
│ - 연락처 전체 → C2 전송 │
│ - 갤러리 사진 → Luban 압축 → C2 전송 │
│ │ │
│ ▼ │
│ 4. 데이터 탈취 완료 (백그라운드 지속) │
│ - START_STICKY로 서비스 재시작 │
│ - 사용자 인지 없이 지속 동작 │
└──────────────────────────────────────────────┘
```
항목 · zcloud_2 · YOLO · Sfile
앱 이름 · zcloud · **YOLO** · Sfile
로고 색상 · 미확인 · **마젠타/핑크** · 미확인
19세 경고 · 미확인 · **있음** · 미확인
로고 심볼 · 미확인 · **하트** · 미확인
위장 전략 · 클라우드 서비스? · **성인 소셜** · 파일 관리?
메시지 수신/처리용 Handler 서브클래스.
5초 카운트다운. onFinish()에서 SMS 수집 + 새 타이머 시작 → 무한 루프.
```smali
const-string v2, "webapp/saveSms"
invoke-static {v2, v0, v1}, Lcom/example/sms/utils/HttpUtils;->postGson(...)
```
UploadService$3 내부의 OnSuccess 콜백. zcloud_2에는 없는 추가 내부 클래스.
```smali
GsonBuilder.disableHtmlEscaping().create().toJson(map) # 전송
JSONObject.parseObject(response).getInteger("code") # 응답
```
· Gson (전송) + FastJSON/alibaba (응답) — zcloud_2와 동일
유형 · 값
C2 도메인 · `[비공개]`
C2 URL · `[비공개]
API · `[비공개]
API · `[비공개]
API · `[비공개]
API · `[비공개]
배포 도메인 · `[비공개]`
유형 · 값
패키지명 · `[비공개]`
내부 패키지 · `com.example.sms`
앱 이름 · YOLO
초대코드 · NQAQ, YHCC
행위 · 설명
SMS 읽기 · content://sms/inbox 접근
연락처 읽기 · content://contacts 접근
전화번호 수집 · TelephonyManager.getLine1Number()
통신사명 수집 · TelephonyManager.getSimOperatorName()
사진 탈취 · MediaStore → Luban 압축 → C2 업로드
5초 폴링 · CountDownTimer(5000, 1000) 무한 루프
SEND_SMS (데드) · 권한 선언만 존재, 코드 미사용
항목 · 결과
환경 · DeepCoding_API35 (API 35, x86_64)
설치 · 성공 (Streamed Install)
실행 · LoginActivity 정상 시작
UI · YOLO! 로고 (마젠타+하트), 19세 경고, 초대코드 입력
ANR · "Process system isn't responding" (에뮬레이터 리소스)
logcat · 111,671줄 수집
· screenshot_launch.png: 앱 시작 (ANR)
· screenshot_login.png: YOLO! 로고 + 19세 경고 + 초대코드 UI
앱 · C2 · SL-060 위치 · SEND_SMS · MessengerUtils
zcloud_2 · [비공개] · 원본 · 없음 · 없음
**YOLO** · [비공개] · **중간** · **있음(데드)** · **있음**
Sfile · [비공개] · 최신 · 있음(데드) · 있음
```
도메인 회전: [비공개] → [비공개] → [비공개]
서버: RuoYi (prod-api 패턴)
API: webapp/* 네임스페이스 (3개 앱 모두 동일)
SDK: Huawei ScanKit [비공개] + MLKit [비공개] (2개 앱 확인)
```
전술 · 기법 · ID
Initial Access · Phishing (초대코드 + 19세 위장) · T1566
Collection · SMS 수집 · T1636.004
Collection · 연락처 수집 · T1636.003
Collection · 미디어 파일 수집 · T1533
Collection · 전화번호/통신사 · T1426
Exfiltration · HTTP C2 · T1048
Persistence · Service (START_STICKY) · T1624
Defense Evasion · 성인용 앱 위장 · T1036.005
🔬 기법 점검:
· 시도한 기법: QN-038 (Pre-R8 식별), WF-059 (패밀리 분류), SL-060 (도메인 회전 중간 단계), SL-062 (API 네임스페이스), SL-063 (Dead SDK Residue 재확인), SN-040 (SEND_SMS 데드 권한)
· 확장된 기법: SL-060 확장 (3단계 도메인 회전 시퀀스 완성), SL-063 확장 (크로스 레퍼런스로 동일 빌드 환경 증명)
· 신규 기법: SL-064 Build Branch Divergence — 동일 Gen3 Pre-R8 계열 내에서 빌드 분기 발생 증거. compileSdkVersion, smali 수, 데드코드 완전도의 비선형 관계.
· 한계 발견: versionCode 미확인 (aapt 출력 필요). AlbumActivity/ContactActivity 내부 로직 미비교.
혁신 점검:
· 새 아이디어/시도: uploadImgnew() 데드코드 형태 비교로 빌드 분기 추론 (SL-064)
· 결과: 성공 — YOLO의 데드코드가 zcloud_2보다 더 완전한 형태 → 코드 정리 수준 차이 확인
· 기법 카탈로그 반영: SL-064 Build Branch Divergence 신규 등재
· 다음 앱에서 시도할 아이디어: pilates/tender/mfil
본 보고서는 주식회사 아크링크 Deep-Coding 보안연구소가 피싱·몸캠피싱 피해자 구제를 목적으로 작성했습니다. 전체 열람·피해 상담: arklink.co.kr