Flirting 138 상세 분석 보고서

Flirting_138.apk 심층 분석 보고서

분석일: 2026-02-12 ~ 2026-02-13

분석자: 주식회사 아크링크 ([비공개] .ai, deep-scan.ai)

분석 목적: 피싱/스미싱 [피해자 정보 비공개] 위한 악성앱 분석

보고서 버전: v3.0 (ML Gold Standard 심층 재분석)

분석 등급: ML Gold Standard (전수 분석)

총 분석 Phase: 16

1. 앱 기본 정보

항목 · 내용

**파일명** · Flirting_138.apk

**표시 이름** · Flirting

**패키지명** · com.snjcjs.snnqq.appqouwyc

**내부 패키지** · com.xyx.sms

**앱 패밀리** · Wavegrid 3세대 (SMS)

**Compile SDK** · 32 (Android 12)

**프레임워크** · Java + OkHttp3 + Fastjson + Gson + Huawei ScanKit + Huawei ML Kit

**위장 유형** · 데이팅/플러팅 앱

**위험 등급** · **EXTREME**

1.1 패키지 구조 개요

```

com.snjcjs.snnqq.appqouwyc ← 외부 패키지 (위장용, 랜덤 문자열)

└── com.xyx.sms ← 내부 패키지 (실제 악성 코드)

├── LoginActivity ← 초대코드 입력 + 검증 (역전 로직)

├── MainActivity ← 메인 화면 (위장 UI)

├── ContactActivity ← 연락처 데이터 수집

├── AlbumActivity ← 앨범/이미지 수집

├── UploadActivity ← 핵심: 데이터 탈취 오케스트레이터

├── BaseApp ← Application 초기화

├── adapter/ ← UI 어댑터 3종

│ ├── AlbumAdapter ← 앨범 목록 표시

│ ├── MainAdapter ← 메인 리스트 표시

│ └── SmsAdapter ← SMS 목록 표시

├── bean/ ← 데이터 모델 4종

│ ├── ContactBean ← {name, number}

│ ├── SmsBean ← {content, date, displayName, path, type}

│ ├── NewsBean ← 위장 뉴스 데이터

│ └── WeatherBean ← 위장 날씨 데이터

├── servise/ ← 백그라운드 서비스 (오타: "servise")

│ └── UploadService ← 5초 주기 SMS 재수집 서비스

├── utils/ ← 유틸리티 6종

│ ├── Constant ← API 경로 상수 4개

│ ├── DialogUtil ← 로딩 다이얼로그

│ ├── GlideEngine ← 이미지 로딩

│ ├── HttpUtils ← HTTP 통신 (C2 URL 하드코딩)

│ ├── ReadContactUtils ← 데이터 수집 메서드 7개

│ └── SPUtils ← SharedPreferences 래퍼

└── view/

└── GeneralDialog ← 커스텀 다이얼로그

```

1.2 코드베이스 통계

항목 · 수량

**총 smali 파일** · 7,484

**smali/ (1차)** · 6,691

**smali_classes2/ (2차)** · 793

**핵심 클래스 (com.xyx.sms)** · 76

**Activity** · 5개

**Service** · 1개

**Provider** · 3개

**데이터 모델** · 4개

**유틸리티 클래스** · 6개

**어댑터** · 3개

1.3 라이브러리/SDK 분석

패키지 · 라이브러리 · 용도 · 악용 가능성

com/alibaba · FastJSON · JSON 직렬화/역직렬화 · 데이터 전송 포맷

com/blankj · AndroidUtilCode · 유틸리티 (에뮬레이터 탐지) · **에뮬레이터 탐지**

com/bumptech · Glide · 이미지 로딩 캐시 · 위장 UI 이미지

com/google · Gson · JSON 파싱 · 서버 응답 파싱

com/huawei · ScanKit [비공개] · QR 코드 스캔 · **미사용** (라이브러리만 포함, 호출 코드 없음)

com/huawei · ML Kit [비공개] · 컴퓨터 비전 · **미사용** (빌드 템플릿 잔재)

com/luck · PictureSelector · 이미지/동영상 선택 · 미디어 탈취

com/xyz · (별도 패키지) · 불명 (난독화) · 분석 필요

top/zibin · Luban · 이미지 압축 · **탈취 전 이미지 압축**

okhttp3 · OkHttp3 · HTTP 클라이언트 · C2 통신

kotlin · Kotlin stdlib · Kotlin 런타임 · -

2. 권한 분석

2.1 AndroidManifest 선언 권한

# · 권한 · 위험도 · 악용 목적

1 · `READ_CONTACTS` · **Critical** · 연락처 전체 탈취

2 · `READ_PHONE_STATE` · **High** · 기기 정보 수집

3 · `READ_EXTERNAL_STORAGE` · **High** · 사진/파일 탈취

4 · `INTERNET` · Normal · C2 서버 통신

5 · `ACCESS_NETWORK_STATE` · Normal · 네트워크 상태 확인

2.2 런타임 권한 요청 (코드 내 숨겨진 권한)

LoginActivity.requestPermission() (line 129-144):

```

android.permission.READ_SMS ← AndroidManifest에 없음!

android.permission.READ_PHONE_NUMBERS ← AndroidManifest에 없음!

android.permission.READ_PHONE_STATE

android.permission.READ_CONTACTS

```

UploadActivity.requestAllPermission() (line 151-155):

```

android.permission.READ_PHONE_STATE

android.permission.READ_CONTACTS

android.permission.READ_EXTERNAL_STORAGE

```

UploadActivity.requestPermission(String): 개별 권한 요청 (contactP=0x66, smsP=0x65, albumP=0x6A)

2.3 권한 분석 결론

실제 요청 권한 7개 (Manifest 5개 + 런타임 추가 2개):

권한 · Manifest · 런타임 · 목적

READ_CONTACTS · O · O · 연락처 전수 탈취

READ_PHONE_STATE · O · O · IMEI/전화번호

READ_EXTERNAL_STORAGE · O · O · 사진/미디어 탈취

INTERNET · O · - · C2 서버 통신

ACCESS_NETWORK_STATE · O · - · 네트워크 확인

**READ_SMS** · **X** · O · **SMS 전수 탈취**

**READ_PHONE_NUMBERS** · **X** · O · **전화번호 수집**

특이사항: READ_SMS와 READ_PHONE_NUMBERS가 AndroidManifest에 없지만 런타임으로 요청. compileSdkVersion 32에서는 런타임 요청만으로도 동작 가능 (targetSdkVersion에 의존).

3. 코드 구조 전수 분석

3.1 Wavegrid 3세대 (SMS 계열) 특징

Flirting_138은 Wavegrid 3세대 중 [비공개] 클러스터 변종:

세대 · 대표 앱 · 내부 패키지 · 특징

Gen1 · ML, Chinso · com.tushiweih.wavegrid / com.cryonix.wavegrid · RuoYi C2, 기본 구조

Gen1.5 · QF (EchoVerse) · com.cryonix.wavegrid · Kotlin + DataStore 사용

Gen3 · **Flirting_138**, ze, zine, nyang · **com.xyx.sms** · SMS 수집, 명시적 Activity

3.2 난독화 수준 분석

컴포넌트 · 난독화 수준 · 설명

Activity 이름 · **없음** · LoginActivity, ContactActivity 등 의미 명확

메서드 이름 · **없음** · getContact, uploadAllData 등

필드 이름 · **없음** · phoneNumber, contactList, smslist

문자열 · **없음** · C2 URL, API 경로 평문

패키지 · **부분** · 외부 패키지만 랜덤 (com.snjcjs.snnqq.appqouwyc)

ProGuard · **미적용** · .source 디렉티브 유지 ("LoginActivity.java" 등)

**총합** · **LOW** (2/10) · 거의 난독화하지 않음

3.3 LoginActivity 전수 분석

초대코드 검증 흐름 (4단계 콜백 체인)

```

사용자 → [초대코드 입력] → btn_save 클릭

└→ LoginActivity$1.onClick()

├── 빈값 체크 → Toast "초대 코드를 입력하십시오."

├── UUID 생성 (최초 1회)

├── HashMap 생성: {name: inviteCode, cId: uuid}

└→ Thread → LoginActivity$1$1.run()

└→ HttpUtils.postGson("webapp/login", map, callback)

└→ LoginActivity$1$1$1.onSuccess(code, body)

└→ runOnUiThread → LoginActivity$1$1$1$1.run()

├── code != 200 → ✅ 성공 처리

│ ├── SPUtils.put("UUID", uuid)

│ ├── SPUtils.put("invite_code", code)

│ ├── Toast "success"

│ └── startMain() → UploadActivity (데이터 탈취 시작!)

└── code == 200 → ❌ 실패 처리

├── JSON "msg" 파싱

└── Toast 에러 메시지 표시

```

역전 로직 상세 (LoginActivity$1$1$1$1.smali:53-57)

```smali

iget v0, p0, ...->val$code:I # v0 = JSON response "code" 값

const/16 v1, 0xc8 # v1 = 200

if-eq v0, v1, :cond_0 # code == 200이면 :cond_0(실패)로 점프

--- 이 아래가 code != 200 경로 = "성공" 처리 ---

```

RuoYi 표준: code=200 = 성공, code=500 = 실패

Wavegrid 역전: code=200 → 에러 메시지 표시, code≠200 → "success" + 데이터 탈취 진행

우회 패치 방법

```smali

원본 (LoginActivity$1$1$1$1.smali:57)

if-eq v0, v1, :cond_0

패치 (역전 → 정상화)

if-ne v0, v1, :cond_0

```

is_first 플래그

LoginActivity.onCreate():

· SPUtils에서 is_first 읽기 → true면 startMain() 직접 호출 (초대코드 건너뜀)

· 즉, 한번 로그인 성공하면 이후 초대코드 입력 없이 바로 데이터 탈취

login() 메서드 (Fallback)

LoginActivity.login() — GET 요청으로 webapp/login 호출 후 WeatherBean으로 파싱. 이 메서드는 초대코드 방식과 별개로, 날씨 API 위장 엔드포인트로의 연결 시도를 보여줌. 홈화면 데이터를 가져오는 데 사용.

3.4 UploadActivity 전수 분석

데이터 수집 오케스트레이션

UploadActivity는 데이터 탈취의 중앙 통제자:

```

UploadActivity.onCreate()

├── invite_code 복원 (SPUtils)

├── is_upload 상태 확인 (중복 업로드 방지)

├── 4개 버튼 초기화:

│ ├── btn_sync → sysncPermission() → uploadAllData()

│ ├── btn_sms → READ_SMS 권한 → getSmsDataUpload()

│ ├── btn_contact → READ_CONTACTS 권한 → getContactDataUpload()

│ └── btn_album → READ_EXTERNAL_STORAGE 권한 → getAlbumDataUpload()

└── uploadAllData()

├── TelephonyManager → phoneNumber 수집

├── getContactDataUpload() ← 연락처 업로드

└── getAlbumDataUpload() ← 이미지 업로드

```

권한 요청 코드 분석 (onRequestPermissionsResult)

UploadActivity는 한글 다이얼로그로 권한을 재요청:

코드(requestCode) · 권한 · 다이얼로그 텍스트

0x64 (100) · 전체 · "문자 메시지、연락처、연락처、파일"

0x65 (101) · READ_SMS · "문자 메시지"

0x66 (102) · READ_CONTACTS · "연락처"

0x6A (106) · READ_EXTERNAL_STORAGE · "파일"

3.5 UploadService 전수 분석 — 5초 주기 재수집

핵심 특성

```

UploadService.onCreate()

├── context = getApplicationContext()

├── TelephonyManager.getLine1Number() → phoneNumber (전화번호 자동 수집!)

└── countDown() → 5초 타이머 시작

UploadService.onStartCommand()

└── return START_STICKY (=1) ← 시스템 kill 후 자동 재시작!

UploadService.countDown()

└── new CountDownTimer(5000ms, 1000ms) ← 5초 간격, 1초 틱

└── onFinish() → getSmsDataUpload() → countDown() (무한 루프!)

```

START_STICKY의 위험성

onStartCommand()가 START_STICKY (1)을 반환:

· 시스템이 메모리 부족으로 서비스를 kill해도 자동 재시작

· 사용자가 앱을 강제 종료해도 서비스가 다시 살아남

· 5초마다 SMS를 재수집하여 새 SMS도 실시간으로 탈취

SMS 재수집 데이터 구조

```json

{

> [비공개]

"bjPhone": "피해자_전화번호",

"content": "[{\"content\":\"SMS내용\",\"displayName\":\"발신자\",\"date\":\"timestamp\",\"type\":\"1\"}]"

}

```

→ POST webapp/saveSms (Constant.sms_url)

4. 데이터 수집 흐름 전수 분석

4.1 ReadContactUtils — 7개 데이터 수집 메서드 + 호출 관계

# · 메서드 · 반환 타입 · 데이터 소스 · 호출 위치 · 상태

1 · `getContact()` · List\<SmsBean\> · ContactsContract.Phone.CONTENT_URI · UploadActivity.getContactDataUpload() · **활성**

2 · `getContacts()` · List\<ContactBean\> · ContactsContract.Contacts.CONTENT_URI · 없음 · **미사용**

3 · `getContactss()` · List\<ContactBean\> · content://com.android.contacts/data/phones · 없음 · **미사용**

4 · `getImg()` · List\<SmsBean\> · MediaStore.Images.EXTERNAL_CONTENT_URI · 없음 · **미사용**

5 · `getAlbum()` · List\<SmsBean\> · MediaStore.Images.EXTERNAL_CONTENT_URI · UploadActivity.getAlbumDataUpload() · **활성**

6 · `getMsgs()` · List\<SmsBean\> · content://sms/ · UploadActivity, UploadService, MainActivity · **활성**

7 · `getOperatorName()` · String · TelephonyManager · UploadActivity.getContactDataUpload() · **활성**

활성 4개 / 미사용 4개 — 7개 메서드 중 절반이 죽은 코드.

부가 메서드:

· compressImage(): JPEG 100KB 이하로 압축 (10% 단위 품질 감소) — 미사용

· saveFile(): 외부 캐시 /Ask 디렉토리에 저장 (JPEG 품질 80%) — 미사용, 디렉토리명 /Ask/는 다른 프로젝트에서 복사한 코드 잔재

설계 결함: SmsBean 남용

getContact()는 연락처 데이터를 SmsBean에 저장:

· display_name → SmsBean.displayName

· 전화번호 → SmsBean.content

전용 ContactBean이 존재함에도 SmsBean을 재사용. 초기 개발 시 SMS 데이터 모델로 시작하여 연락처까지 확장한 흔적.

getMsgs() 날짜 필터 미작동

```java

Calendar calendar = Calendar.getInstance();

calendar.add(Calendar.DAY_OF_WEEK, -1); // 1일 전 계산

// ... 하지만 이 값을 query의 selection 조건에 전달하지 않음!

Cursor cursor = contentResolver.query(Uri.parse("content://sms/"), null, null, null, null);

```

날짜 계산은 수행하지만 쿼리에 조건으로 넣지 않아 전체 SMS를 수집.

4.2 데이터 전송 구조

연락처 업로드 (getContactDataUpload)

```

ReadContactUtils.getContact() → contactList

HashMap 생성:

"userName" → invite_code (SPUtils)

"model" → "android"

"bjPhone" → phoneNumber (TelephonyManager)

"operatorName" → getOperatorName() (통신사명)

"phoneContent" → JSONObject.toJSONString(contactList) ← 연락처 전체!

Thread → HttpUtils.postGson("webapp/saveAddressBook", map, callback)

```

SMS 업로드 (getSmsDataUpload)

```

ReadContactUtils.getMsgs() → smslist

HashMap 생성:

"userName" → invite_code

"bjPhone" → phoneNumber

"content" → JSONObject.toJSONString(smslist) ← SMS 전체!

Thread → HttpUtils.postGson("webapp/saveSms", map, callback)

```

이미지 업로드 (getAlbumDataUpload)

```

ReadContactUtils.getAlbum() → albumList

for each SmsBean:

Luban.with(context)

.load(smsBean.path) ← 원본 이미지 경로

.setCompressListener(...)

.launch() ← Luban 압축 후

HttpUtils.postFile(activity, "webapp/image/" + code, compressedFile, callback)

```

4.3 데이터 탈취 타임라인

```

[T+0s] 앱 설치 + 실행

[T+5s] 초대코드 입력 → 서버 검증 (역전 로직)

[T+10s] UploadActivity 진입 → 권한 요청 다이얼로그

[T+15s] 권한 허용 시 즉시:

├── 연락처 전수 수집 → POST /webapp/saveAddressBook

├── 이미지 수집 + Luban 압축 → POST /webapp/image/{code}

└── UploadService 시작

[T+20s] UploadService: 5초마다 SMS 수집 → POST /webapp/saveSms

[T+∞] START_STICKY로 영구 실행 → 새 SMS 실시간 탈취

```

5. 네트워크/C2 분석

5.1 C2 서버 정보

항목 · 내용

**도메인** · [비공개]

**Base URL** · `[비공개]

**프로토콜** · **HTTP (평문 통신!)**

**프레임워크** · RuoYi (Spring Boot)

**C2 위치** · HttpUtils.smali:7 (static field)

5.2 API 엔드포인트 전수 추출

# · 메서드 · 엔드포인트 · 용도 · 요청 본문

1 · POST · `[비공개] · 초대코드 검증 · `{name, cId}`

2 · POST · `[비공개] · 연락처 업로드 · `{userName, model, bjPhone, operatorName, phoneContent}`

3 · POST · `[비공개] · SMS 업로드 · `{userName, bjPhone, content}`

4 · POST · `[비공개] · 이미지 업로드 · multipart/form-data `{file, path, success_action_status}`

기존 보고서 대비 발견: webapp/saveSms 엔드포인트가 기존 보고서에서 누락되어 있었음.

5.3 요청/응답 구조

Login 요청

```json

POST [비공개]

Content-Type: application/json; charset=utf-8

{"name": "초대코드", "cId": "UUID"}

```

Login 응답 (역전 로직)

```json

// 서버 측 "실패" → 클라이언트 "성공" (code ≠ 200)

{"code": 500, "msg": "..."}

// 서버 측 "성공" → 클라이언트 "실패" (code = 200)

{"code": 200, "msg": "유효하지 않은 초대코드"}

```

연락처 업로드 요청

```json

POST [비공개]

Content-Type: application/json; charset=utf-8

{

> [비공개]

"model": "android",

"bjPhone": "010-XXXX-XXXX",

"operatorName": "SKT",

"phoneContent": "[{\"name\":\"홍길동\",\"number\":\"010-**-**\"}, ...]"

}

```

이미지 업로드 요청

```http

POST [비공개]

Content-Type: multipart/form-data

file: [compressed_image.jpg]

other_field: value

```

5.4 네트워크 보안 설정

network_security_config.xml에서 cleartext 트래픽 허용:

· 모든 데이터가 암호화 없이 평문으로 전송

· 공격자뿐 아니라 ISP, 공유 WiFi 사용자도 탈취 데이터 감청 가능

· 이중 피해 위험: [피해자 정보 비공개] 공격자 외 제3자에게도 노출

5.5 HttpUtils 통신 패턴

메서드 · 용도 · 실행 방식 · 특징

`postFile()` · 파일 업로드 · **비동기** (enqueue) · OkHttp Callback

`postGson()` · JSON 전송 · **동기** (execute) · 별도 Thread에서 호출

`postJSONObject()` · JSON 전송 (테스트용) · **동기** (execute) · 하드코딩 테스트 데이터

postJSONObject 특이사항: "西红柿炒鸡蛋" (토마토 달걀볶음) 하드코딩 — 개발자 테스트 코드가 제거되지 않음 → 개발 수준 낮음.

6. 방어기제 상세 분석

6.1 초대코드 검증

항목 · 상세

**구현 위치** · LoginActivity$1$1$1$1.smali:53-57

**검증 방식** · 서버 측 (webapp/login POST)

**역전 로직** · `if-eq` (code==200 → 실패)

**우회 방법** · `if-eq` → `if-ne` 패치

**우회 상태** · **완료** (Result/ 폴더)

6.2 에뮬레이터 탐지

항목 · 상세

**구현 위치** · com/blankj/utilcode/util/DeviceUtils.smali

**탐지 방식** · BlankJ DeviceUtils.isEmulator()

**호출 위치** · com.xyx.sms 패키지에서는 미호출 (라이브러리만 포함)

**우회 방법** · `isEmulator()` → `return false` 삽입

**우회 상태** · **완료**

특이사항: BlankJ 라이브러리가 포함되어 있으나, com.xyx.sms 패키지 내에서 isEmulator를 직접 호출하는 코드가 발견되지 않음. 다른 경로에서 호출될 가능성 있음.

6.3 QR 코드 초대코드 입력

항목 · 상세

**구현** · Huawei ScanKit [비공개] (AndroidManifest에 등록)

**용도** · 초대코드를 QR 형태로 전달 (의도)

**Activity** · com.huawei.hms.hmsscankit.ScanKitActivity

**실제 사용** · **미사용** — com.xyx.sms 패키지에서 ScanKit API 호출 코드 0건

결론: ScanKit은 빌드 템플릿에 포함된 라이브러리이며, 이 변종에서는 구현되지 않음. 초대코드는 순수 EditText(et_code) 수동 입력 방식.

6.4 SharedPreferences 기반 상태 관리

파일명: share_data

키 · 타입 · 용도

`is_first` · Boolean · 최초 실행 여부 (true면 초대코드 건너뜀)

`is_upload` · Boolean · 업로드 완료 여부 (btn_sync 비활성화)

`UUID` · String · 기기 식별 UUID

`invite_code` · String · 입력한 초대코드

`nick` · String · 닉네임 (미사용)

6.5 BaseApp 초기화 분석 — Android 8.0+ 서비스 결함

Application 클래스 구조 (BaseApp.smali)

```java

public class BaseApp extends Application {

@Override

public void onCreate() {

super.onCreate();

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

private int activityNumber = 0; // 선언만, 사용 안 함

@Override

public void onActivityStopped(Activity activity) {

Log.e("tag", "ActivityLifecycleCallbacksAdapter:前台 --> 后台");

Intent intent = new Intent(getApplicationContext(), UploadService.class);

if (Build.VERSION.SDK_INT < 26) { // Android 8.0 미만만!

getApplicationContext().startService(intent);

}

}

});

}

}

```

Android 8.0+ 백그라운드 서비스 결함

핵심 발견: if (SDK_INT < 26) 조건으로 인해 Android 8.0 이상 기기에서 백그라운드 서비스 재시작이 작동하지 않음.

Android 버전 · 서비스 동작 · 영향

7.1 이하 · `startService()` 정상 호출 → UploadService 재시작 · SMS 5초 재수집 지속

8.0 이상 · 조건 불충족 → 서비스 미시작 · **최초 1회 수집만 가능**

startForegroundService() 호출이 누락되어 있으며, activityNumber 필드도 선언만 되고 증감 코드가 없음 — 미완성 코드.

중국어 디버그 로그

BaseApp에 중국어 로그가 하드코딩:

· 后台 --> 前台 (백그라운드→포그라운드)

· 前台 --> 后台 (포그라운드→백그라운드)

→ 개발자의 1차 언어가 중국어임을 확증.

6.6 패치 결과

파일 · 위치

Flirting_138_signed_new.apk · Result/

7. 개발자 프로파일링 — 16개 코딩 실수

7.1 실수 목록

# · 유형 · 위치 · 상세

1 · **servise** (오타) · `com.xyx.sms.servise` · 패키지명, Manifest 모두 오타 고정

2 · **dissmiss** (오타) · `DialogUtil.smali` · 메서드명 `dissmiss()`, ss 이중

3 · **sysncPermission** (오타) · `UploadActivity.smali` · sync→sysnc 오타

4 · **xyx vs xyz** 혼용 · 패키지 구조 · 실제 코드 `com.xyx.sms`, R 클래스 `[비공개].sms`

5 · **SmsBean 남용** · ReadContactUtils · 연락처를 SmsBean에 저장 (ContactBean 존재)

6 · **연락처 3중 구현** · ReadContactUtils · getContact, getContacts, getContactss 중 1개만 사용

7 · **날짜 필터 미작동** · getMsgs() · Calendar 계산 후 query에 미적용

8 · **Kotlin template 리터럴** · getMsgs() · `"address:${address}"` 치환 안 됨

9 · **테스트 코드 미삭제** · postJSONObject() · "西红柿炒鸡蛋" 전체 메서드 잔류

10 · **빈 URL** · LoginActivity · `url("")` 빈 문자열로 이미지 업로드 시도

11 · **success111 디버그** · LoginActivity$3 · `Log.e("success111", ...)` 디버그 태그

12 · **/Ask/ 디렉토리** · saveFile() · 다른 프로젝트에서 복사한 코드

13 · **activityNumber 미사용** · BaseApp$1 · 선언만 하고 증감 없음

14 · **Android 8.0+ 미처리** · BaseApp$1 · `startForegroundService()` 누락

15 · **phoneNumber 빈 문자열** · UploadActivity · TelephonyManager 후 `phoneNumber = ""` 대입

16 · **동기 네트워크** · postJSONObject() · `execute()` 동기 호출 — ANR 위험

7.2 개발자 프로파일

항목 · 추정

**1차 언어** · 중국어 (后台/前台 로그, 西红柿炒鸡蛋 테스트, 返回= 로그)

**기술 수준** · 초급~중급 (16개 코딩 실수, 미완성 코드 다수)

**개발 방식** · 기존 템플릿 복사 + 수정 (ScanKit 미사용, /Ask/ 잔재, xyx/xyz 혼용)

**보안 의식** · 매우 낮음 (난독화 2/10, HTTP 평문, 테스트 코드 미삭제)

**개발 환경** · Android Studio + Java (Kotlin 미사용, kotlin stdlib는 의존성으로만)

**코드 리뷰** · 없음 (servise, dissmiss 등 명백한 오타 미수정)

7.3 코드 복사 증거

증거 · 출처 추정

`/Ask/` 디렉토리 · "Ask" 프로젝트에서 saveFile() 복사

ScanKit 라이브러리 (미사용) · QR 기능이 있는 다른 변종에서 템플릿 복사

`[비공개].sms` R 클래스 · 원래 패키지명이 `[비공개].sms`였다가 `xyx`로 변경 시 R 누락

Kotlin template 문법 · Kotlin 프로젝트에서 getMsgs() 로그 코드 복사

8. 교차 비교 분석 — xxayjgagagxxg 클러스터

8.1 진화 계보

```

ze (원형) Flirting_138 (업

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