분석일: 2025-08-26 (초기) / 2026-02-13 (심층 재분석)
분석자: 주식회사 아크링크 ([비공개] 대표)
분석 목적: 피싱/스미싱 [피해자 정보 비공개] 위한 악성앱 분석
보고서 버전: v3.0 (ML Gold Standard)
총 분석 Phase: 10
항목 · 내용
**파일명** · Chinso.apk
**패키지명** · com.novabeex.smartpulse
**앱 이름** · Chinso
**메인 패키지** · com.novabeex.smartpulse
**Application 클래스** · com.novabeex.smartpulse.Myapplication
**Version Code** · 4110
**Version Name** · 4.1.0
**Target SDK** · 34 (Android 14)
**Min SDK (원본)** · 29 (Android 10)
**Min SDK (패치)** · 21 (Android 5.0)
**Compile SDK** · 34
**프레임워크** · Native Android (Kotlin 1.9)
**패밀리** · Wavegrid 변종
**아이콘** · @mipmap/logoicon
**위협 등급** · **EXTREME**
항목 · 수량
**smali/ 파일 수** · 7,914
**smali_classes2/ 파일 수** · 1,725
**총 smali 파일** · 9,639
**핵심 패키지 (novabeex) 파일** · 19
**Activity 수** · 2
**Callback 클래스** · 3
Chinso는 ML(YLOVE)의 원형 패밀리인 Wavegrid와 동일한 구조적 특성을 공유한다:
· `[비공개] 접두사를 사용하는 RuoYi 기반 C2 서버
· webapp/login, webapp/saveAddressBook, webapp/image/ 엔드포인트 체계
· HTTP 200 = 실패 역로직 초대코드 인증 (T001)
· FastJSON 기반 응답 파싱 (com.alibaba.fastjson)
· BlankJ AndroidUtilCode 라이브러리 (에뮬레이터 탐지)
· SharedPreferences 기반 상태 관리 (IFFIRST, UUIDVALUE, INVITECODE, ISUPLOAD)
단, ML의 com.tushiweih.wavegrid 패키지와 달리 com.novabeex.smartpulse라는 독자적 패키지명을 사용하며, 이는 Wavegrid 코드베이스의 재패키징(변종 생성)을 의미한다.
패키지 · 위치 · 용도
`com/novabeex/smartpulse` · smali/ · 핵심 악성 로직 (19 파일)
`com/alibaba/fastjson` · smali/ · JSON 파싱 (C2 응답 처리)
`com/blankj/utilcode` · smali/ · Android 유틸리티 (157 파일, 에뮬레이터 탐지 포함)
`com/google` · smali/ · Google 라이브러리
`com/gyf/immersionbar` · smali/ · 상태바/네비게이션바 커스터마이징
`com/permissionx` · smali/ · 권한 요청 라이브러리
`com/zhouyou/http` · smali/ · HTTP 네트워크 라이브러리
`okhttp3` · smali_classes2/ · OkHttp HTTP 클라이언트
`retrofit2` · smali_classes2/ · REST API 클라이언트 (미사용 추정)
`top/zibin/luban` · smali_classes2/ · Luban 이미지 압축
# · 권한 · 위험도 · 피해 시나리오
1 · `READ_CONTACTS` · **위험** · 피해자의 연락처(이름, 전화번호) 전체를 탈취하여 지인 대상 2차 피싱에 활용. 탈취된 연락처로 "OO님이 보냈습니다" 형태의 스미싱 메시지 발송
2 · `READ_PHONE_STATE` · **위험** · IMEI, 기기 모델, 통신사 정보를 수집하여 [피해자 정보 비공개] 고유 식별. 동일 피해자의 재접근 시 추적에 활용
3 · `READ_PHONE_NUMBERS` · **위험** · [피해자 정보 비공개] 전화번호를 직접 탈취. 보이스피싱 시 "본인 확인" 명목으로 악용하거나, 번호 기반 금융사기에 활용
4 · `READ_MEDIA_IMAGES` · **위험** · 갤러리의 사진을 탈취하여 신분증 사진, 개인 사진 등 민감 이미지 유출. 협박/사칭 소재로 악용 가능 (API 33+)
5 · `READ_MEDIA_VIDEO` · **위험** · 동영상 파일 탈취. 개인 영상을 협박 수단으로 악용 가능 (API 33+)
6 · `READ_EXTERNAL_STORAGE` · **위험** · API 32 이하에서 외부 저장소의 모든 파일 접근. 문서, 사진, 다운로드 파일 무차별 탈취
7 · `WRITE_EXTERNAL_STORAGE` · **위험** · 외부 저장소에 파일 쓰기 (탈취 데이터 임시 저장, 이미지 압축 캐시 `/Ask` 디렉토리)
8 · `INTERNET` · 일반 · C2 서버와 통신
9 · `ACCESS_NETWORK_STATE` · 일반 · 네트워크 연결 상태 확인
10 · `MOUNT_UNMOUNT_FILESYSTEMS` · 일반 · 파일시스템 마운트/언마운트
미선언 권한 · 관련 Dormant 코드 · 위험
`READ_SMS` · j62.g() SMS 수집 코드 존재 · 코드 활성화 시 SMS 전체 탈취 가능
j62.smali에 완전한 SMS 수집 코드가 존재하지만 AndroidManifest.xml에 READ_SMS 권한이 미선언 상태. 서버 명령으로 권한 추가 + 메서드 호출 경로 활성화 시 SMS 탈취 가능. T040 Dormant Code 패턴 참조 (섹션 13).
다른 Wavegrid 변종(Q, j0z)과 달리 READ_PHONE_NUMBERS 권한을 별도로 요청하며, CAMERA 대신 READ_EXTERNAL_STORAGE를 중심으로 한 파일 탈취 전략을 사용한다. 이는 사진 촬영보다 기존 저장 파일 대량 탈취에 초점을 맞춘 변종임을 시사한다.
```
SecondActivity 진입
↓
[API 33+ 분기]
├─ READ_MEDIA_IMAGES 요청
├─ READ_MEDIA_VIDEO 요청
└─ 이후 READ_CONTACTS → READ_PHONE_NUMBERS → READ_PHONE_STATE
[API 32- 분기]
├─ READ_EXTERNAL_STORAGE 요청
└─ 이후 READ_CONTACTS → READ_PHONE_NUMBERS → READ_PHONE_STATE
↓
[모든 권한 허용 시]
w0() 호출 → 데이터 수집 시작
[권한 거부 시]
x0() → "서비스 이용 알림" 다이얼로그 반복 표시
```
Activity · 클래스 경로 · 설명
`MainActivity` · `com.novabeex.smartpulse.view.MainActivity` · 런처 Activity. 초대코드 입력 화면
`SecondActivity` · `com.novabeex.smartpulse.view.SecondActivity` · 메인 화면. 권한 요청 및 데이터 탈취 수행
# · 클래스 · smali 파일 · 줄 수 · 역할
1 · `Myapplication` · `smali/com/novabeex/smartpulse/Myapplication.smali` · 70 · Application 진입점. C2 URL 설정
2 · `MainActivity` · `smali/com/novabeex/smartpulse/view/MainActivity.smali` · 394 · 초대코드 입력 UI, 로그인 API 호출
3 · `MainActivity$a` · `smali/com/novabeex/smartpulse/view/MainActivity$a.smali` · 197 · 로그인 콜백. HTTP 역로직 처리
4 · `SecondActivity` · `smali/com/novabeex/smartpulse/view/SecondActivity.smali` · 806 · 권한 요청, 연락처/미디어 수집 총괄
5 · `SecondActivity$a` · `smali/com/novabeex/smartpulse/view/SecondActivity$a.smali` · 144 · 이미지 Luban 압축 → 업로드 콜백
6 · `SecondActivity$b` · `smali/com/novabeex/smartpulse/view/SecondActivity$b.smali` · 196 · 연락처 업로드 성공/실패 콜백
7 · `di0` · `smali/di0.smali` · 198 · 네트워크 싱글톤. SSL bypass, 파일 업로드
8 · `j62` · `smali/j62.smali` · 831 · **DataHelper** - 9개 데이터 수집 메서드
9 · `pv1` · `smali/pv1.smali` · 939 · SharedPreferences 래퍼 (SPUtils)
10 · `fi0` · `smali/fi0.smali` · - · SSL trust-all 팩토리 생성
11 · `qx` · `smali/qx.smali` · - · OkHttp 래퍼 싱글톤
12 · `CollectBeanDTO` · `smali/com/novabeex/smartpulse/bean/CollectBeanDTO.smali` · - · 연락처 데이터 모델
13 · `InfoBeanDTO` · `smali/com/novabeex/smartpulse/bean/InfoBeanDTO.smali` · - · 미디어 정보 모델
14 · `ResultSuccessCallBack` · `smali/com/novabeex/smartpulse/bean/ResultSuccessCallBack.smali` · 9 · 콜백 인터페이스
```
[사용자 앱 설치]
↓
[Myapplication.onCreate()]
C2 URL 설정: "[비공개]
OkHttp(qx) 싱글톤 초기화
↓
[MainActivity.onCreate()]
SharedPrefs 확인: IFFIRST 플래그
├─ IFFIRST == true → 즉시 SecondActivity 이동
└─ IFFIRST == false → 초대코드 입력 화면 표시
↓
[초대코드 입력 → o0() 호출]
POST webapp/login { name: 초대코드, cId: UUID }
↓
[MainActivity$a 콜백]
FastJSON 파싱 → code 필드 추출
├─ code != 200 → 성공 (역로직 T001)
│ └─ SharedPrefs 저장: UUIDVALUE, INVITECODE, IFFIRST=true
│ └─ r0() → SecondActivity 전환
└─ code == 200 → 실패 (에러 메시지 표시)
↓
[SecondActivity.onCreate()]
s0(0) → 권한 요청 시작
↓
[권한 허용 시 → w0()]
TelephonyManager.getLine1Number() → 전화번호 수집
├─ C0() → 연락처 수집 + webapp/saveAddressBook POST
└─ B0() → 미디어 스캔 + Luban 압축 + webapp/image/ POST
↓
[SecondActivity$b 콜백 (연락처)]
├─ 성공: ISUPLOAD=true, "synSuc" 가짜 에러 다이얼로그
└─ 실패: Toast 에러 메시지
↓
[SecondActivity$a 콜백 (이미지)]
각 이미지별 Thread 생성 → di0.a() 멀티파트 업로드
```
레벨 · 대상 · 상태 · 예시
패키지명 · `com.novabeex.smartpulse` · **미난독화** · 원본 패키지명 유지
Activity명 · `MainActivity`, `SecondActivity` · **미난독화** · 의미 있는 이름
유틸리티 클래스 · R8 축소 · **난독화** · `di0`, `fi0`, `j62`, `pv1`, `qx`
콜백 클래스 · 내부 클래스 · **난독화** · `MainActivity$a`, `SecondActivity$a/$b`
Bean 클래스 · DTO · **미난독화** · `CollectBeanDTO`, `InfoBeanDTO`
메서드명 · R8 축소 · **부분 난독화** · `o0()`, `r0()`, `w0()`, `C0()`, `B0()`
필드명 · R8 축소 · **부분 난독화** · 상수는 유지, 지역변수는 축소
난독화 강도: 낮음 (R8 기본 축소만 적용, ProGuard 커스텀 규칙 없음)
항목 · 내용
**도메인** · [비공개]
**Base URL** · `[비공개]
**프로토콜** · HTTPS (SSL 검증 비활성화)
**서버 프레임워크** · RuoYi (Spring Boot 기반)
**TLD** · `.work` (저비용 TLD, 위험도 높음)
**공유 C2** · LOVEM (동일 C2 [비공개] 확인)
.work TLD는 일반적인 .com이나 .net과 달리 등록 비용이 낮고 인증 절차가 간소하여 악성 인프라에 자주 사용된다. Wavegrid 패밀리 전체에서 .online, .store, .work 등 저비용 TLD를 일관되게 사용하는 패턴이 관찰된다.
# · 엔드포인트 · 메소드 · 파라미터 · 용도 · 코드 위치
1 · `[비공개] · POST · `{name: 초대코드, cId: UUID}` · 초대코드 인증 · di0.d, MainActivity.o0()
2 · `[비공개] · POST · HashMap (5 fields) · 연락처+기기정보 업로드 · di0.e, SecondActivity.C0()
3 · `[비공개] · POST · File (multipart/image/*) · 미디어 파일 업로드 · di0.f, SecondActivity$a.f()
Myapplication.smali (Line 59):
```smali
const-string v0, "[비공개]
invoke-virtual {p0, v0}, Lqx;->M(Ljava/lang/String;)Lqx;
```
di0.smali (Static Fields):
```smali
.field public static final b:Ljava/lang/String; = "[비공개]"
.field public static final c:Ljava/lang/String; = "[비공개]
.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/"
```
SecondActivity.C0() 메서드에서 구성하는 HashMap:
필드명 · 값 소스 · 설명
`userName` · SharedPrefs INVITECODE · 초대코드 ([피해자 정보 비공개])
`model` · 하드코딩 `"android"` · 기기 플랫폼
`bjPhone` · `TelephonyManager.getLine1Number()` · [피해자 정보 비공개]
`operatorName` · `j62.h()` → `TelephonyManager.getSimOperatorName()` · 통신사명
`phoneContent` · `j62.c()` → FastJSON 직렬화 · 연락처 JSON 배열
요청 형태 (추정):
```json
{
> [비공개]
"model": "android",
"bjPhone": "010-**-**",
"operatorName": "SKTelecom",
"phoneContent": "[{\"displayName\":\"홍길동\",\"content\":\"010-**-**\"}, ...]"
}
```
di0.a() 메서드 - OkHttp Multipart:
```
URL: [비공개]
Content-Type: multipart/form-data
Part: "image/*" content type
Body: Luban 압축된 이미지 파일
```
업로드 파이프라인:
```
B0() → j62.b() MediaStore 스캔
→ InfoBeanDTO 리스트 (경로, 이름, 날짜)
→ Luban.with(context).load(path)
.setCompressListener(SecondActivity$a)
.launch()
→ SecondActivity$a.f() 콜백
→ new Thread() { di0.a(file, inviteCode) }
→ OkHttp multipart POST
```
위치: com/blankj/utilcode/util/d.smali (DeviceUtils)
BlankJ AndroidUtilCode 라이브러리의 에뮬레이터 탐지 기능을 내장:
y() 메소드 - 종합 탐지 (8가지 시그니처):
```
1. Build.FINGERPRINT: "generic" 시작 여부
2. Build.FINGERPRINT: "vbox", "test-keys" 포함 여부
3. Build.MODEL: "google_sdk", "Emulator", "Android SDK built for x86" 포함
4. Build.MANUFACTURER: "Genymotion" 포함
5. Build.BRAND/DEVICE: "generic" 시작
6. Build.PRODUCT: "google_sdk" 일치
7. TelephonyManager.getNetworkOperatorName(): "android" 일치
8. 전화 다이얼 Intent 처리 가능 여부
```
z() 메소드 - CPU 아키텍처 탐지:
```
· /proc/cpuinfo에서 "intel" 또는 "amd" 문자열 존재 여부
· x86 에뮬레이터(예: LD플레이어, BlueStacks) 탐지 목적
```
위치: MainActivity.smali → MainActivity$a.smali
서버로 POST 요청 후 응답의 code 필드를 검증하는 방식. HTTP 200 = 실패라는 역로직을 사용한다.
```smali
const/16 v2, 0xc8 # 200
if-ne v0, v2, :cond_2 # 200이 아니면 → 실패(cond_2) 이동
```
이 역로직의 의미: 올바른 초대코드를 입력하면 서버가 200이 아닌 응답(성공 응답)을 반환하고, 잘못된 코드는 200(에러 메시지 포함)으로 응답한다.
원본 minSdkVersion: 29 (Android 10)
API 29 이상에서만 사용 가능한 메서드들을 사용하여 구형 에뮬레이터에서의 실행을 차단:
# · 메서드 · API 레벨 · 위치
1 · `Activity.registerActivityLifecycleCallbacks()` · 29+ · androidx/lifecycle
2 · `Window.setStatusBarContrastEnforced()` · 29+ · ImmersionBar.smali
3 · `Window.setNavigationBarContrastEnforced()` · 29+ · ImmersionBar.smali
위치: di0.smali:96-106
```smali
const/4 v2, 0x0 # null
invoke-static {v2, v2, v2}, Lfi0;->c(...) # null, null, null
move-result-object v3
check-cast v3, Ljavax/net/ssl/SSLSocketFactory;
invoke-static {v2, v2, v2}, Lfi0;->c(...)
move-result-object v2
check-cast v2, Ljavax/net/ssl/X509TrustManager;
invoke-virtual {v1, v3, v2}, Lokhttp3/g$b;->E(...)
```
효과: 모든 HTTPS 인증서를 무조건 신뢰하여 MITM 공격에 취약. 동시에 공격자 입장에서는 자체 서명 인증서로도 C2 서버 운영 가능.
데이터 유형 · 수집 메서드 · DTO 클래스 · 전송 API · 상태
**연락처** · j62.c() · `InfoBeanDTO` (displayName, content) · `webapp/saveAddressBook` · **활성**
**미디어 경로** · j62.b() · `InfoBeanDTO` (path) · `webapp/image/` · **활성**
**전화번호** · `getLine1Number()` · HashMap 직접 · `webapp/saveAddressBook` · **활성**
**통신사명** · j62.h() · HashMap 직접 · `webapp/saveAddressBook` · **활성**
**이미지 압축** · j62.a() + j62.i() · File · `webapp/image/` · **활성**
**연락처 (상세)** · j62.d() · `CollectBeanDTO` (name, number) · - · **Dormant**
**연락처 (직접)** · j62.e() · `CollectBeanDTO` (name, number) · - · **Dormant**
**이미지 (정렬)** · j62.f() · `InfoBeanDTO` (path) · - · **Dormant**
**SMS** · j62.g() · - · - · **Dormant**
```java
// j62.c() - ContactsContract.CommonDataKinds.Phone 쿼리
// 수집 필드: DISPLAY_NAME, NUMBER
public class InfoBeanDTO {
public String displayName; // 연락처 이름
public String content; // 전화번호
public String path; // (미디어 경로용)
public String date; // (날짜용)
public String type; // (타입용)
}
```
```java
// j62.b() - MediaStore.Images.Media.EXTERNAL_CONTENT_URI 쿼리
// 수집 필드: _data (파일 경로)
public class InfoBeanDTO {
public String path; // 이미지 절대 경로
}
```
```
1. SecondActivity.w0()
→ getLine1Number() 전화번호 수집
→ C0() 호출
→ j62.c() 연락처 수집 → FastJSON 직렬화
→ HashMap 5필드 구성 (userName, model, bjPhone, operatorName, phoneContent)
→ POST webapp/saveAddressBook
2. SecondActivity.w0()
→ B0() 호출
→ j62.b() 미디어 스캔 → InfoBeanDTO 리스트
→ 각 파일별 Luban 압축 (top.zibin.luban)
→ SecondActivity$a.f() 콜백
→ new Thread() { di0.a(file, inviteCode) }
→ multipart POST webapp/image/{inviteCode}
3. 업로드 완료
→ SecondActivity$b 콜백 (code==200)
→ ISUPLOAD=true 저장 (중복 전송 방지)
→ "synSuc" 가짜 에러 다이얼로그 표시
```
· 1회성 전송: ISUPLOAD 플래그로 최초 1회만 수집/전송
· 권한 허용 직후 즉시 수행
· 이미지는 개별 Thread로 병렬 업로드 (Thread-per-image 패턴)
패치 항목 · 파일 · 수정 내용 · 결과
minSdkVersion · apktool.yml · 29 → 21 · 적용
초대코드 역전 · MainActivity$a.smali:150 · `if-ne` → `if-eq` · 적용
결과: 크래시 발생 - registerActivityLifecycleCallbacks (API 29+)
패치 항목 · 파일 · 수정 내용
registerActivityLifecycleCallbacks · androidx/lifecycle 관련 smali · 메서드 호출 제거 (return-void)
setStatusBarContrastEnforced · ImmersionBar.smali · 메서드 호출 제거
결과: 크래시 발생 - setStatusBarContrastEnforced 추가 호출 발견
패치 항목 · 파일 · 수정 내용
setNavigationBarContrastEnforced · ImmersionBar.smali · 메서드 호출 제거
최종 결과: 정상 실행 (PID: 5219)
```smali
if-ne v0, v2, :cond_2 # 200이 아니면 실패로 이동
if-eq v0, v2, :cond_2 # 200이면 실패로 이동 (역전!)
```
효과: 잘못된 초대코드 입력 → 서버 200 응답 → 패치로 if-eq 분기 → cond_2(실패) 이동 → 실패 분기를 건너뛰고 성공 로직 실행 → SecondActivity 진입
항목 · 상태
Android 9 호환 · 성공 (minSdk 29 → 21)
초대코드 우회 · 성공 (if-ne → if-eq)
API 29+ 제거 · 성공 (3개 메서드)
APK 빌드/서명 · 성공 (Chinso_modified_v2.apk)
LD Player 실행 · 성공 (PID: 5219)
유전자 · 값 · 정규화 · 설명
permission_count · 7 · 0.5833 · 위험 권한 7개
dangerous_perm_ratio · 0.7 · 0.7 · 10개 중 7개 위험
data_exfil_count · 4 · 0.6667 · 연락처+전화번호+통신사+미디어
phase_count · 10 · 0.3636 · 10단계 분석
contacts_access · 1 · 1.0 · 연락처 접근
camera_access · 0 · 0.0 · 카메라 미접근
sms_access · 0.5 · 0.5 · SMS 코드 존재 (Dormant)
storage_access · 1 · 1.0 · 저장소 접근
phone_access · 1 · 1.0 · 전화상태 접근
location_access · 0 · 0.0 · 위치 미접근
network_access · 0 · 0.0 · 네트워크 미접근
media_images · 1 · 1.0 · 이미지 탈취
media_video · 1 · 1.0 · 비디오 권한 요청
media_audio · 0 · 0.0 · 오디오 미접근
c2_known · 1 · 1.0 · C2 서버 확인됨
tld_type · 2 · 0.6667 · .work (저비용 TLD)
api_endpoint_count · 3 · 0.25 · 3개 API
uses_https · 1 · 1.0 · HTTPS 사용 (검증 비활성화)
ssl_bypass · 1 · 1.0 · SSL 검증 비활성화
multi_c2 · 0 · 0.0 · 단일 C2
has_jiagu · 0 · 0.0 · Jiagu 미사용
has_invitation_code · 1 · 1.0 · 초대코드 사용
bypass_level · 3 · 1.0 · 완전 우회
protection_level · 1 · 0.3333 · 낮은 보호
framework_code · 1 · 0.0 · Native Android
is_wavegrid · 1 · 1.0 · Wavegrid 패밀리
threat_level_code · 3 · 1.0 · EXTREME
analysis_depth · 0.4348 · 0.3636 · 심층 분석
dormant_code · 4 · 0.8 · 4개 Dormant 메서드
비교 대상 · 거리 · 관계
FileM · 0.0213 · **거의 동일** (최근접)
FileQ · 0.0213 · **거의 동일** (최근접)
LOVEM · 0.0856 · **근거리** (동일 C2)
QN · 0.2314 · 근거리
Q · 0.3211 · 중거리
j0z · 0.3756 · 중거리
ML (YLOVE) · 0.4375 · 원거리
분석: Chinso는 FileM/FileQ와 유전적으로 거의 동일(0.0213)하다. 이는 동일한 코드베이스에서 패키지명만 변경하여 배포한 것으로 추정된다. LOVEM과는 C2 서버([비공개])를 공유하며, 이는 동일 공격 그룹이 동시 운영하는 인프라임을 시사한다. ML과의 거리(0.4375)는 같은 패밀리이지만 세대 차이가 있음을 나타낸다.
카테고리 · 점수 · 설명
**개인정보** · 70/100 · 연락처, 전화번호, 기기정보, 통신사 탈취 + Dormant SMS 위험
**금융** · 45/100 · 전화번호 기반 금융사기 가능성
**미디어** · 65/100 · 사진/동영상 탈취, Luban 압축으로 대량 전송 효율화
**통신** · 40/100 · 연락처 기반 2차 피싱 확산
**기기** · 25/100 · IMEI 등 기기 식별 정보, UUID 생성
**감시** · 20/100 · 1회성이지만 Dormant SMS 활성화 시 지속 감시 가능
v2.0에서 HIGH → v3.0에서 EXTREME으로 상향 조정.
사유: Dormant SMS 코드(j62.g) 발견 + SSL 인증서 검증 비활성화 + LOVEM과의 C2 공유로 인프라 규모 확인
```
1단계: 피해자가 스미싱 링크 통해 Chinso APK 설치
(성인 앱으로 위장 - "성인입장" 버튼)
2단계: 초대코드 입력 (공격자가 사전 제공)
3단계: "서비스 이용 알림" 권한 요청 다이얼로그
(거부 시 반복 표시로 피로감 유도)
4단계: 권한 허용 즉시:
· getLine1Number() → 전화번호 수집
· j62.c() → 연락처 전체 수집
· j62.b() → 갤러리 이미지 전체 스캔
· j62.h() → 통신사명 수집
5단계: C2로 데이터 전송:
· webapp/saveAddressBook ← 연락처+전화번호+통신사
· webapp/image/{code} ← 이미지 (Luban 압축, Thread-per-image)
6단계: "synSuc" 가짜 에러 다이얼로그 표시
("알 수 없는 오류로 인해..." → 피해자가 앱 삭제 유도)
7단계: 탈취된 연락처로 지인 대상 2차 피싱 문자 발송
```
```
도메인: [비공개]
Base URL: [비공개]
TLD: .work (저비용, 악성 인프라 선호)
```
```
POST [비공개]
POST [비공개]
POST [비공개]
```
```
패키지명: com.novabeex.smartpulse
Application: com.novabeex.smartpulse.Myapplication
MainActivity: com.novabeex.smartpulse.view.MainActivity
SecondActivity: com.novabeex.smartpulse.view.SecondActivity
```
```
원본: Chinso.apk
패치 v1: Chinso_modified.apk
패치 v2 (최종): Chinso_modified_v2.apk
```
```
di0 → NetworkUploadSingleton (C2 통신, SSL bypass)
j62 → DataHelper (데이터 수집 9개 메서드)
pv1 → SPUtils (SharedPreferences 래퍼)
fi0 → SSLTrustAllFactory (SSL 검증 비활성화)
qx → OkHttpSingleton (HTTP 클라이언트)
```
```
IFFIRST: 최초 인증 여부 (boolean) - 재실행 시 초대코드 건너뛰기
UUIDVALUE: 기기 UUID (string) - [피해자 정보 비공개] 식별
INVITECODE: 사용된 초대코드 (string) - 공격자
본 보고서는 주식회사 아크링크 Deep-Coding 보안연구소가 피싱·몸캠피싱 피해자 구제를 목적으로 작성했습니다. 전체 열람·피해 상담: arklink.co.kr