# 실패한 국가 배후 추정 공격 해부

> Clean Markdown view of GeekNews topic #30873. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=30873](https://news.hada.io/topic?id=30873)
- GeekNews Markdown: [https://news.hada.io/topic/30873.md](https://news.hada.io/topic/30873.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-06-27T11:03:59+09:00
- Updated: 2026-06-27T11:03:59+09:00
- Original source: [grack.com](https://grack.com/blog/2026/06/25/dissecting-a-failed-nation-state-attack/)
- Points: 1
- Comments: 1

## Topic Body

- 캐나다의 한 개발자가 가짜 VC 인터뷰를 가장한 **백도어 유도 공격**을 받았고, 공격 흐름은 crates.io 패키지 관리자를 노린 것으로 의심될 만큼 개발자 업무에 맞춰져 있었음
- 미끼 저장소는 “Ticket Harbor”라는 TypeScript 앱처럼 보였지만, `patch-package`와 `typescript+5.9.2.patch`로 **TypeScript 실행 경로**에 악성 코드를 숨김
- 삽입된 스텁은 base64와 XOR 난독화를 풀어 `new Function(...)`으로 실행되고, `operators/3.png`의 숨은 청크와 WASM 스텁을 거쳐 1.68MB짜리 **2단계 페이로드**를 별도 Node 프로세스로 띄움
- 최종 페이로드 “PinpinRAT”은 RSA-2048 키쌍과 AES-256-CBC 세션 키를 만들고, 호스트 지문 수집, 파일 업로드·다운로드, 프로세스 실행, 파일시스템 조작, DNS 질의, 자가 제거를 지원함
- 저장소를 실행했다면 즉시 네트워크를 끊고 다른 기기에서 자격 증명을 교체해야 하며, 쿠키와 비밀번호 보호 비밀까지 **탈취됐을 가능성**을 전제로 대응해야 함

---

### 가짜 인터뷰로 시작된 개발자 표적 공격
- 공격자는 “Lua Ventures” 소속이라고 주장하는 가짜 인물로 접근함
  - Lua Ventures는 싱가포르 기반 DeFi 분야 VC로 소개됐지만, 실제로는 이미 활동을 중단한 곳이었음
  - 인물명은 실제 동명이인들과 혼동될 수 있어 공개되지 않음
- 이메일은 그럴듯했고, 평범하지만 정상처럼 보이는 LinkedIn 프로필 링크도 포함돼 있었음
- 자문을 찾는 투자사로 **Lyrasing**과 **Roadpay**를 언급함
  - 두 회사는 기본적인 웹 존재감이 있어 가짜라기보다 초기 단계 회사처럼 보였음
  - Roadpay 사이트의 [archive.org 스냅샷](https://web.archive.org/web/20260626011734/https://roadpay.cc/en)도 남아 있음
- 이메일 왕복 뒤 Google Meet 통화까지 이어짐
  - 통화 상대는 독일식 억양이 있는 남성이었고, 이동 중이라고 말함
  - 통화 자체에는 뚜렷하게 이상한 점이 없었음

### “테스트 과제”로 위장한 실행 트리거
- 통화 뒤 공격자는 “테스트”를 제안하며 저장소를 보냄
- 저장소는 “Ticket Harbor”라는 **페리 티켓팅 앱**처럼 꾸며져 있었음
- 포함된 `task.txt`는 지루하지만 그럴듯한 과제 목록을 담고 있었고, 마지막에 실행 지시가 들어 있었음
  - 저장소의 typecheck, 테스트 스위트, 관련 desktop/server 빌드 명령을 실행하라는 내용
- 이 지시가 실제 감염 트리거였음
  - `npm run typecheck`, `build`, `dev`처럼 TypeScript가 실행되거나 `typescript.js`를 import하는 순간 페이로드가 실행될 수 있었음

### TypeScript 패치에 숨은 실행 체인
- 첫 경고 신호는 저장소가 **TypeScript 과제**처럼 보였다는 점이었음
  - 요청 내용이 아키텍처 분석보다 TypeScript 채용 과제에 가까웠음
  - 저장소를 Claude에 넣어 빠르게 확인한 결과, `patch-package` 관련 이상 징후가 드러남
- `patches/` 디렉터리가 비정상적으로 많았음
  - 일부 패치는 정상처럼 보여 실제 페이로드를 숨기는 노이즈 역할을 함
  - 예시로 `sumchecker+3.0.1.patch`, `@electron+get+2.0.3.patch`, `extract-zip+2.0.1.patch`가 포함됨
- 핵심 악성 코드는 `typescript+5.9.2.patch`에 있었음
  - `typescript.js`와 `_tsc.js` 맨 위에 즉시 실행 스텁을 삽입함
  - 스텁은 base64 문자열을 디코드하고, 각 바이트를 키 `73`으로 XOR 복호화한 뒤 `new Function(...)`으로 실행함
  - `require`, `Buffer`, `WebAssembly`, `process`, `__dirname`이 실행 함수에 전달됨
- 실행 체인은 여러 단계를 거침
  - 네 개의 `postinstall` 훅이 `patch-package`를 실행함
  - 그중 하나는 patch 파일에 `git update-index --skip-worktree`를 적용해 `git status`에서 숨김
  - 로더는 `operators/3.png` 파일 뒤에 붙은 숨은 청크를 읽음
  - 커스텀 `wAsm` 청크의 작은 WASM 스텁을 실행함
  - 1.68MB짜리 난독화된 2단계 페이로드를 조용한 별도 Node 프로세스로 실행함
- 공격 코드는 실행 후 흔적을 줄이도록 설계됨
  - `git skip-worktree`로 패치를 숨김
  - 드로퍼가 첫 실행 뒤 patch 파일에서 자신이 삽입한 줄을 삭제함
  - 2단계 임시 디렉터리는 실행 시 자가 삭제됨

### PinpinRAT의 기능
- 최종 페이로드는 “PinpinRAT”으로 지칭됨
  - 내부 문자열 때문에 붙은 이름이며, 다른 이름으로 알려졌을 가능성은 배제되지 않음
  - 온라인에서 다른 참조는 확인되지 않음
- 페이로드는 여러 난독화 계층 안에 들어 있었음
  - obfuscator.io
  - 추가 base64 계층 두 개
- RAT는 시작 시 호스트 지문을 수집해 유출함
  - 기본 IP 주소와 전체 IP 목록
  - `os.userInfo().username`의 사용자명
  - 호스트명
  - OS type, release, platform, architecture
  - 프로세스 PID와 전체 `process.argv`
  - Node 버전
- 암호화 구조도 포함함
  - 로컬에서 RSA-2048 키쌍 생성
  - 무작위 AES-256 세션 키 `aes_psk` 생성
  - 이후 트래픽은 AES-256-CBC로 암호화되고 HMAC-SHA256 무결성 태그가 붙음
- 지원 명령은 **원격 접근 트로이목마** 수준의 기능을 제공함
  - `env`: `process.env`를 JSON 문자열로 만들어 전송
  - `upload`: 임의 파일 경로를 읽어 유출
  - `download`: 공격자가 제공한 바이트를 쓰기 가능한 경로에 기록
  - `spawn`: 선택적 shell 확장과 함께 임의 프로세스 실행
  - `ls`, `cd`, `pwd`, `cp`, `mv`: 일반 파일시스템 조작
  - `dns`: 지정한 resolver를 통해 임의 이름 해석
  - `dismantle`: 자가 제거

### 침해 지표와 즉시 대응
- 페이로드가 담긴 이미지는 [VirusTotal](https://www.virustotal.com/gui/file/7af7864333f5d6dec2a137e2c123019dea27cae8c30b0f293b310c969635c90e/detection)에서 어떤 AV 엔진에도 탐지되지 않았음
- 실행한 경우 즉시 시스템을 네트워크에서 분리해야 함
- 자격 증명은 다른 기기에서 교체해야 함
  - 쿠키와 비밀번호로 보호된 비밀도 침해된 것으로 간주해야 함
- PinpinRAT 관련 **침해 지표**는 다음과 같음
  - C2: `89.124.107.161:80`
  - Windows 예약 작업: `PinpinWrappedJs`
  - macOS 프로세스 위장: `com.apple.WebKit.Networking`
  - 환경 변수: `NODT_PAYLOAD_PATH`, `NODT_PAYLOAD_ARGS`
  - PNG 청크 가드: `WASMPACK` (`wAsm`)
  - `PINPIN_NO_AUTOSTART=1`: persistence 중단
  - `mutex.js`를 포함한 cronjob: RAT 권한이 있을 때만 존재할 수 있으며, macOS에는 없을 수 있음
  - `typescript.js` 앵커 문자열: `12ff4b51`, `ticket-harbor-tsc-shim-anchor`
  - 페이로드가 포함된 `typescript+5.9.2.patch`
  - 아티팩트 디렉터리:
    - macOS: `~/Library/Caches/runtime-cache/.cache-&lt;randomhex&gt;/`
    - Linux: `/tmp/.cache-&lt;randomhex&gt;/`
    - Windows: `%TEMP%\.cache-&lt;randomhex&gt;\`
    - 내부에 `payload.js`와 `mutex.js`가 들어 있음

### 뒤늦게 보인 경고 신호
- 메시지에는 자세히 보면 **LLM 흔적**으로 보이는 표현이 있었음
- LinkedIn 프로필은 첫눈에는 정상처럼 보였지만, 학위·자격 나열이 어색했고 실제 활동도 없었음
- 웹사이트의 소셜 미디어 링크는 실제 이력이 있었지만, 이름이 2025년 11월에 바뀌었음
  - 게시물은 구체성이 낮고 회사들에 대한 모호한 칭찬에 가까웠음
- 회사 웹사이트들은 화려했지만 실제 존재감은 거의 없었음
- 공격자는 정식 캘린더 초대를 보내지 않고 시간과 Google Meet만 전달함
  - 통화 중 카메라는 계속 꺼져 있었고 이동 중이라고 말함
- 싱가포르 기반 VC, CEST 시간대 활동, 캐나다 개발자 대상 접근, 미국 고객을 겨냥한 `.cc` 도메인이 함께 나타남
  - 멀리 있는 조직의 신뢰성을 확인하기가 더 어려웠음
- 개별 신호만으로는 명확하지 않았지만, 여러 **노란불**이 함께 쌓이면 빨간불로 볼 수 있는 패턴이었음

### 공격 배후와 범위
- 배후를 확정할 수는 없음
- 공격은 개발자를 겨냥했고, 가짜 인물, 설득력 있는 커버 스토리, 여러 가짜 웹사이트, 인내심 있는 일정, 정교한 `git` 함정을 포함함
- 2026년에 여러 행위자가 사용하는 “가짜 인터뷰 사기” 흐름과 맞닿아 있음
- Reddit의 Rust 커뮤니티에서도 [비슷하게 표적이 됐다는 사례](https://www.reddit.com/r/rust/comments/1ug9pzn/anatomy_of_a_failed_nationstate_attack/)가 언급됨
- 같은 방식이 Rust 저장소의 함정 `build.rs` 스크립트로 구성됐다면 속아 넘어갔을 수 있을 만큼 개발자 워크플로에 밀착돼 있었음

## Comments



### Comment 60450

- Author: neo
- Created: 2026-06-27T11:04:00+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/j2ua4f/anatomy_failed_nation_state_attack) 
- 제목에서 **국가 배후 공격자**일 수 있다고 추측한 게 혼란스러움. 여기엔 그 정도의 준비나 복잡성이 꼭 필요해 보이는 부분이 없음  
  가능성은 상상할 수 있지만, 다른 시나리오와 비슷한 정도로만 그럴듯해 보임
  - 이런 **정교한 사기**는 자원이 많이 들어서 꽤 드물기 때문인 듯함. 정교한 사기를 보면 국가 배후일지도 모른다고 느끼기 쉬움  
    그래도 거의 확실히 국가 배후 공격자는 아닐 것 같음. 이런 유형의 공격은 이제 그렇게 어렵지 않음

- 일주일 전 내 블로그 글에서 설명한 가상의 사례와 이번 공격이 비슷한 건 정말 우연임: [the hypothetical I describe in my blog post from a week ago](https://manishearth.github.io/blog/2026/06/17/the-future-of-the-con-is-already-here/)  
  기술에 밝은 전문가도 속을 수 있는 예시로, 그럴듯해 보이는 몇 가지 공격 중 하나를 골랐을 뿐임. 사람을 노린 여러 **정교한 사기**가 늘어나는 건 봤지만, **면접 사기**라는 흐름이 진행 중인지는 몰랐음. 그래서 이번 공격을 알게 되니 좀 섬뜩했음
  - 정말 섬뜩함. 그 글에 대한 [Lobsters discussion](https://lobste.rs/s/5majlp/future_con_is_already_here_it_s_just_not) 링크도 있음

- 지난주 Lua Ventures의 D____ S_____에게서 똑같은 식의 **면접 제안**을 받았음. 대부분의 채용 담당자 스팸처럼 무시했는데, 그러길 잘했음
  - Rust 쪽 사람인지 궁금함. **Rust 커뮤니티**의 주요 인물들이 Lua의 표적이 됐는데, Rust에만 국한된 건지 더 넓은지 알고 싶음

- 며칠 전이나 몇 주 전에 이런 제출글이 있었던 것 같음
  - 아마 이 글일 수도 있음: https://blog.daviddodda.com/how-i-almost-got-hacked-by-a-job-interview?  
    비슷한 글이 여러 개 있었던 느낌임

- “진짜 이메일처럼 보였다”는 게 놀라움. 너무 명백히 **LLM 생성 문장**이라서 두 번째 문장부터 의심했을 것 같음
  - 내게는 그렇게 명백하지 않았음. 그냥 **LinkedIn식 문체**처럼 느껴졌음. 그것도 종종 LLM이 쓴 것처럼 들리지만, 냄새가 너무 비슷해서 둘을 구분할 능력이 있는지 잘 모르겠음
