목차
1. 개요
1.1) 분석 파일 정보
2. 상세 분석
2.1) pdf 파일 생성
2.2) dll 파일 생성
2.3) .rdata 섹션 임베딩 후 파싱
2.4) 동적 분석
2.4.1) 악성 dll 로드 과정
2.4.2) config.dat 분석
2.4.3) 지속 메커니즘
2.4.4) ADS 생성
2.4.5) config.dat 언패킹
2.5) config.dat 상세 분석
2.5.1) export 호출
2.5.2) ADS 체크
2.5.3) 지속 메커니즘 등록
2.5.4) C2 연결
2.5.5) C2 명령 수신
3. 결론

1. 개요
최근(5월) 북한 연계 해킹 그룹의 공격으로 CJ올리브네트웍스의 디지털 인증서 파일이 유출된 정황이 확인됐다. 보안 업계는 지난달 말 공개된 악성파일에서 해당 회사의 서명 정보가 발견됐다고 밝혔다.
CJ올리브네트웍스는 CJ그룹의 IT 인프라를 관리하는 계열사로, 이번 유출은 SK텔레콤 유심 정보 해킹 등 최근 잇따른 대기업 계열사 대상 사이버 공격 흐름의 연장선에 있다. 디지털 인증서는 소프트웨어가 특정 기업에서 제작되었다는 사실을 증명하는 수단으로, 정상 서명이 있으면 보안 솔루션의 탐지를 회피하기 쉽다. 따라서 공격자가 기업의 인증서를 악용하면 악성코드가 정상 프로그램처럼 위장되어 배포될 위험이 커진다.


북한발 악성파일에서 CJ올리브네트웍스 소유로 보이는 디지털 서명이 발견되면서 해당 인증서의 유출·악용 가능성에 대한 우려가 제기되었다. 일부 보고서는 공격에 ‘김수키’ 관련 그룹이 연루되었을 가능성을 지적했으며, 보안업체는 이 서명을 악용해 특정 연구기관을 노린 정황을 공개했다. CJ올리브네트웍스는 해당 인증서를 즉시 폐기했고 현재 유효하지 않다고 밝혔다.
1.1) 분석 파일 정보
해당 악성코드는 국내 유명 기업의 디지털 인증서로 서명된 상태여서 안티바이러스 등의 탐지를 회피하려는 정황이 발견되고, Windows용 SCR(스크린세이버) 포맷의 실행파일이지만, 아이콘을 조작해 PDF 문서처럼 보이도록 위장해 사용자의 클릭을 유도한다.
| C2 | gsegse.dasfesfgsegsefsede.o-r[.]kr |
| File name | 20250428 플랜아이 작업계획서 및 작업완료서_기계연 이명화.scr |
| MD5 | 7ec88818697623a0130b1de42fa31335 |
| SHA-256 | 123aefe0734da130b475bfdad6c3ebe49688569ab8310e71ec5252ec46cb67eb |
| File type | Win32 EXE |
| File size | 5.83 MB (6118288 bytes) |
| First Submission | 2025-04-30 07:05:20 UTC |

본 분석에서는 원본 파일인 20250428 플랜아이 작업계획서 및 작업완료서_기계연 이명화.scr을 sample.exe로 파일명을 변경한 후 분석을 진행하였다.

정적 문자열 분석 및 도구 스캔 결과, 해당 악성코드는 Go 언어 기반으로 작성된 것으로 확인된다.
2. 상세 분석
2.1) pdf 파일 생성

빌드 시 Go의 파일 임베딩 기능을 활용해 image/icon.png(미끼 PDF 파일)을 실행 파일 내부에 그대로 포함시킨다. 프로그램이 실행되면 임베딩된 PDF 데이터를 메모리에서 바로 읽어 실제 PDF 파일로 생성한다. 생성 과정에서 동일한 파일이 이미 존재할 경우, 기존 파일을 자가 삭제 한 뒤 새롭게 생성하도록 구현되어 있다.

PDF 파일이 존재하지 않을 경우 새롭게 PDF 파일을 생성한 뒤, RunCmd 함수를 통해 해당 PDF를 자동으로 실행하도록 동작한다.


해당 파일 삭제 루틴에서는 실행 중인 파일의 핸들 이름을 변경한 뒤 삭제를 수행한다. 일반적으로 실행 중인 EXE 파일은 운영체제에 의해 파일 핸들이 잠금(Lock) 상태가 되기 때문에, DeleteFile() 같은 함수 호출만으로는 삭제에 실패하는데 열려 있는 실행 파일 핸들에 대해 파일명 및 경로를 무효화하는 방식으로 이름을 변경하면 원래의 파일 이름과 실제 경로가 더 이상 존재하지 않기 때문에 파일이 이미 삭제된 것처럼 보이게 된다.
이후 프로세스 종료 시점에 OS가 내부적으로 파일을 정리하면서 최종적으로 삭제가 된다.
2.2) dll 파일 생성

image/image.png에 임베딩된 악성 DLL 파일을 내부 메모리에서 읽어온 뒤, PDF 생성 루틴과 동일한 방식으로 C:\Users\Public 경로에 생성된다. 이후 생성된 DLL은 RunCmd 함수를 통해 rundll32.exe로 로드되어 실행되도록 구성되어 있다.
2.3) .rdata 섹션 임베딩 후 파싱

앞서 설명한 PDF와 DLL 파일은 실행 파일의 .rdata 섹션에 임베딩되어 있으며, 런타임 시 embed.FS.ReadFile() 함수를 통해 메모리에서 읽어와 파일로 생성된다.
2.4) 동적 분석
2.4.1) 악성 dll 로드 과정



내부적으로 CreateFileW() 함수를 호출하여 config.dat 파일을 생성한 뒤, WriteFile()을 통해 DLL 데이터가 기록된다. 이후 PDF 파일은 다음과 같은 명령을 통해 실행된다.
cmd.exe /c start "" "C:\Users\*****\Desktop\sample.pdf"
DLL 파일은 다음 명령을 통해 rundll32.exe로 로드되며, config.dat에 기록된 DLL의 export 함수인 hello가 실행되도록 구성되어 있다.
rundll32.exe C:\Users\Public\config.dat hello

rundll32.exe의 로드된 모듈 리스트를 확인하면 config.dat가 정상적으로 로드된 것을 확인할 수 있으며, 이후 C:\Users\Public 경로에 해당 DLL 모듈이 실제로 존재하는 것도 확인할 수 있다.
2.4.2) config.dat 분석
| File name | config.dat |
| MD5 | 580d7a5fdf78dd3e720b2ce772dc77e9 |
| SHA-256 | 7047efbd15b20086933a3e41f23252d3f8b049b913b2c05af520a3233368f700 |
| File type | Win32 DLL |
| File size | 3.58 MB (3749376 bytes) |
| Creation Time | 2025-04-28 13:45:48 UTC |

config.dat는 DLL 파일 형태이며, 파일명은 httpSpy.dll로 확인된다. 또한 Export Table을 확인하면 hello 함수가 존재하는 것을 확인할 수 있다.

Import Address Table를 조회한 결과, C2 통신에 필요한 WINHTTP.dll에서 WinHttpOpen, WinHttpOpenRequest, WinHttpSendRequest 등과 같은 함수들이 참조되고 있는 것을 확인할 수 있다.
2.4.3) 지속 메커니즘

C2와 지속적인 연결을 유지하기 위해 지속 메커니즘 루틴이 실행된다. 권한 수준에 따라 동작이 달라지며,
- 사용자 권한으로 실행될 경우, 그림 16의 아래 이미지와 같이 HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\MSEdgeInstaller 레지스트리에 등록된다.
- 관리자 권한으로 실행될 경우, 그림 16의 위 이미지와 같이 sc.exe를 사용하여 MicrosoftEdgeInstaller 서비스에 등록된다.

서비스 목록을 확인하면, MicrosoftEdgeInstaller라는 서비스가 존재하며, 해당 서비스에 cmd /c rundll32.exe C:\Users\Public\config.dat hello 명령이 등록되어 있는 것을 확인할 수 있다.
2.4.4) ADS 생성

config.dat은 C2 주소를 은닉하기 위해 Alternate Data Stream(ADS) 을 생성하여 C2 주소를 파싱해 온다. 내부적으로 CreateFileW()를 통해 config.dat:DATA_CONF 스트림을 생성하고, WriteFile() 함수로 복호화된 C2 주소를 해당 ADS에 작성한다.


PowerShell에서 Get-Item -Stream * 명령을 사용해 확인한 결과, DATA_CONF ADS 스트림이 존재하는 것이 확인된다.
notepad.exe <경로>:DATA_CONF 명령을 통해 스트림에 기록된 내용을 열어본 결과, 다음과 같은 C2 주소가 저장되어 있는 것을 확인할 수 있다.
hxxp://gsegse.dasfesfgsegsefsede.o-r[.]kr/login.php

2.4.5) config.dat 언패킹

분석 과정에서 해당 DLL 파일은 분석을 방해하기 위해 패커로 패킹된 것으로 추정된다. PEP(Packing Entry Point)로 진입 시 이어지는 난독화된 코드 블록이 존재한다. 특이한 점은 일반적인 패킹된 바이너리와는 차이점이 있었다. 그림 15)를 확인해보면 패킹된 바이너리임에도 IAT(Import Address Table) 영역이 변경되거나 난독화되지 않았고, 문자열 및 실행 코드 영역만 암호화되어 있었다는 점이다. 주요 루틴으로 사용되는 VirtualAlloc() -> VirtualProtect() 루틴도 관찰되지 않았다.이는 기존 상용 패커에서 흔히 관찰되는 방식과는 차이를 보이는 부분이다.
또한 PE 뷰어 도구에 내장된 휴리스틱 탐지 기능에서도 어떠한 알려진 패커 흔적도 탐지되지 않았다. 이러한 점을 종합하였을 때, Kimsuky 그룹이 자체적으로 제작한 커스텀 패커를 사용하여 배포했을 가능성이 높다고 판단된다.
(물론 상용 패커의 경우에도 기능별 옵션 설정이 가능한 SDK 형태로 제공되긴한다. 예를 들어, IAT 난독화나 섹션 암호화, VM 실행 방지와 같은 기능을 사용자가 선택적으로 활성화하거나 비활성화할 수 있다. 또한 사용된 상용 패커가 비교적 최신 버전이거나 최근 릴리즈된 변종일 경우, 패턴 DB가 최신화 되지 않아 휴리스틱 기반 탐지 기능이 해당 패커를 식별하지 못했을 가능성 역시 존재한다.)


패킹된 바이너리 상태에서는 정상적인 분석이 어려워 수동 언패킹을 진행하였다. 우선 rundll32.exe를 통해 대상 DLL을 메모리에 로드하여 런타임 시 패커가 암호화된 원본 코드를 .text영역에 복호화 시킨 다는 점을 노려, Scylla 플러그인을 사용해 config.dll의 OEP(Original Entry Point) 를 찾아 수동으로 지정해준 뒤, Import Address Table 를 재구성해 정상적으로 동작(Runnable)은 불가능하나 정적 분석이 가능한 형태의 바이너리를 추출하는 데 성공하였다. 수동 언패킹 과정을 거친 후, 해당 DLL의 파일 크기가 약 2,400 KB 정도 증가한 것을 확인할 수있다.
2.5) config.dat 상세 분석
2.5.1) export 호출

hello 익스포트 함수는 CreateThread()를 통해 실행되며, 내부적으로 총 7개의 주요 루틴을 순차적으로 수행한다.

초기화 과정에서는 동작에 필요한 kernel32.dll, user32.dll, wininet.dll, winhttp.dll 등 주요 모듈을 로드한다.
2.5.2) ADS 체크

CreateFileW()를 사용하여 config.dat:DATA_CONF 스트림의 존재 여부를 확인하며, 파일 핸들이 INVALID_HANDLE_VALUE일 경우 수동으로 DATA_CONF 스트림을 생성하는 루틴이 실행된다.
이미 존재하는 경우에는 ReadFile()을 통해 스트림 내용을 읽어 기록한다.

config.dat:DATA_CONF 스트림이 존재하지 않을 경우, .data 섹션에 하드코딩된 g_config 값을 RC4 알고리즘으로 복호화한다. 이때 사용되는 키는 RGdcsedfd@#%dg9ser3$#$^@34sdfxl이며, 복호화가 완료되면 ConfigToAds() 함수를 호출하여 복호화된 C2 정보를 ADS 스트림(DATA_CONF)에 생성 및 기록한다.
2.5.3) 지속 메커니즘 등록

관리자 권한으로 실행 될 시 sc.exe를 실행하여 MicrosoftEdgeInstaller라는 이름의 서비스를 생성하고, 서비스의 실행 명령을 cmd /c rundll32.exe <파일경로> hello 형태로 등록하여 지속성을 확보한다.

사용자 권한으로 실행될 경우에는 HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\MSEdgeInstaller
레지스트리 경로에 항목을 생성하여 지속성을 확보한다.
2.5.4) C2 연결

ADS로 생성된 DATA_CONF 스트림에서 C2 주소를 읽어온 후, 해당 주소로 POST 요청을 전송하여 C2 서버와 통신하며, 서버로부터 전달되는 명령을 수신해 실행한다.
2.5.5) C2 명령 수신

C2와 연결을 수립한 후 서버로부터 전달받아 수행하는 명령들을 바이너리 분석을 통해 확인한 결과, 주요 명령들을 정리하면 다음과 같다.
| Command | Action | info |
| d | 원격 CMD 명령 실행 | execCMD()로 C2가 보낸 문자열을 CMD 명령으로 실행. 결과는 C2에 전송 |
| e | 파일 다운로드 (C2 → PC) | DownloadFile() 호출. C2 서버에서 파일을 받아 로컬에 저장 |
| f | 파일 업로드 (PC → C2) | UploadFile() 호출. 지정된 파일을 C2로 업로드 |
| g | 프로세스 생성(CreateProcessW) | CreateProcessW()로 실행 시도 . C2에서 받은 문자열을 명령행으로 실행, 창 숨김 모드(wShowWindow=0) |
| h | 사용자 토큰 기반 프로세스 생성 | CreateProcessAsUser()로 실행 시도 |
| i | 파일 삭제 | 파일경로를 받고 DeleteFileW()로 지정된 파일 삭제 |
| j | 임시 파일 생성 후 스크린 샷 | TempFile 생성 → 스크린샷 캡처 → 스크린샷 파일을 C2로 업로드 → 파일 삭제 |
| k | 환경 정보(C2 구조체) 전송 | C2 구조체 (구성 데이터)를 전송 |
| l | Config 수정(DATA_CONF) | Config (DATA_CONF 데이터)를 업데이트 |
| m | 임의 서버로 TCP 연결 | 지정된 IP/PORT로 connect() 시도, 프록시 역할 |
| n | Sleep 명령 | 프로그램 일시 중지 |
| o | 파일 타임스탬프 변조 | src의 생성/수정/접근 시간을 dst 파일에 복사, 안티포렌식 행위 |
| p | 내부 정리/종료 | 언인스톨 / 종료 |
| q | 동작 없음 | 아무 작업도 하지 않음. Heartbeat 또는 Keep-alive 용도 추정 |
| r | cmd 명령 처리 | C2가 보낸 문자열을 CMD 명령으로 실행 , "d" 명령과 동작 동일 |
| s | DLL 인젝션 | PID,DLL 경로를 C2에서 받고 VirtualAllocEx + WriteProcessMemory + CreateRemoteThread(LoadLibraryW)로 DLL Injection 수행. |
| default | 오류 처리 | 위 명령에 매칭되지 않는 경우 "fail" 응답. |
3. 결론
본 사례의 Go언어 기반 악성코드는 CJ 올리브네트웍스 명의의 코드서명 인증서가 탈취되어 악성코드 서명에 악용된 점이 가장 큰 특징이다. 감염 직후에는 한국기계연구원 문서로 위장한 미끼 PDF를 출력하여 정상 문서로 오인하도록 위장 동작을 수행하며, 실제 악성 기능 수행을 위해 추가 DLL을 드랍 후 로딩하는 구조로 동작한다.
또한 공격자는 NTFS ADS(Alternate Data Stream) 을 활용해 C2 주소를 파일 시스템에서 은닉하고, 실행 시 해당 스트림에서 C2 정보를 로드하도록 설계하였다. 이를 통해 사용자 눈에 보이지 않는 형태로 C2 정보를 은닉할 뿐만 아니라, 스트림 내용만 교체하면 공격자가 손쉽게 인프라를 변경할 수 있는 유연성도 확보하게 된다.

정상 파일로 위장하거나, 인증서를 악용해 신뢰성을 가장하는 경우가 많으므로 출처가 불분명한 실행 파일은 항상 주의해야 한다. 특히 Windows에서 확장자 표시를 활성화하여 실행 파일(.exe, .dll 등)을 명확히 구분하는 것이 중요하며, 신뢰할 수 없는 첨부파일이나 다운로드 파일 실행을 최소화해야 한다.
'Reversing > Malware Analysis' 카테고리의 다른 글
| [Shuyal Stealer] Telegram API를 악용하는 악성코드 (0) | 2025.12.05 |
|---|---|
| [Agent Tesla] 악성메일로 유포되는 .NET 기반 악성코드 분석 (0) | 2025.11.22 |
| [Lumma Stealer] Heaven's Gate 기법을 활용한 악성코드(2) (1) | 2025.11.08 |
| [Lumma Stealer] clickfix 기법을 활용한 악성코드 유포(1) (1) | 2025.10.04 |
| [BPFDoor] 악성코드 분석 - 패킷 필터를 악용하는 악성코드 (0) | 2025.09.19 |