0. 목차
Contents
1. 소개
HWP 한글 문서형 악성코드는 문서파일 열람시 악성코드에 감염되는 유형으로 주로 한글 프로그램을 사용하는 공공기관이나 가상화폐 관련 기업 등의 대상을 공격하는 타깃형 공격이 2010년 이후부터 꾸준히 발생하였다.
과거에는 한글 프로그램 자체의 취약점을 노린 공격이 가장 많았지만 한글 프로그램에서 지원하는 EPS(Encapsulated PostScript)
파일을 이용한 공격방식이 대부분 사용하고 있다. EPS파일을 이용한 공격은 악성 행위를 수행하는 EPS파일을 한글 문서 내에 삽입하여 유포하는 것이다.
EPS 파일의 기능에 따라 이용한 공격 방식은 다음과 같이 크게 두 가지로 구분된다.
① EPS 파일 뷰어 또는 인터프리터에서 발생하는 취약점을 공격하는 EPS파일
② 파일 객체 생성 등 정상적인 포스트스크립트 문법을 이용해 악성 파일을 생성하는 EPS파일
이번에 분석하는 내용은 2번에 해당되지만 1번의 내용은 잠깐 설명하고 넘어가도록 하겠다.
1번에 해당되는 내용은 2017년 6월 최초 발견 이후로도 계속적으로 제작 및 유포되고 있는 한글 문서에 삽입되는 EPS파일 처리에서 발생하는 취약점을 이용한 것이다. 취약점이 발생하는 부분은 EPS파일 인터프리터인 고스트스크립트(Ghostscript)
프로그램이다.(CVE-2017-8291)
현재는 한컴에서 2017년 02월 23일에 해당 취약점에 관련된 보안 패치를 하여 포스트스크립트로 작성된 EPS파일을 한글 문서에 사용할 수 없으나 여전히 동일한 취약점을 이용한 공격방식이 계속되고 있다. 그만큼 성공률이 높고 아직 패치가 적용되지 않는 한글 프로그램을 사용하는 사용자들이 많다는 뜻이다.
1.1 CVE-2017-8291
CVE-2017-8291
취약점을 이용한 악성 EPS 파일은 포스트스크립트의 메모리 관리 방식과 특정 연산자의 내부 실행 방식에서 발생하는 Type Confusion
버그를 이용하여 익스플로잇한다.
익스플로잇 과정을 이해하고 설명하려면 너무 길어지므로 간략히 정리하고 넘어가겠다...
고스트스크립트 인터프리터가 .eqproc
함수에서 두 개의 객체 타입을 고려하지 않고 비교하여 취약점이 발생하고 이를 통해 피연산자 스택의 메모리 변조(Memory Corruption)
를 허용하여 악의적인 포스트스크립트 파일로 스택을 변조함으로써 임의 코드를 실행할 수 있다. 한글 프로그램이 설치된 환경이면 취약점은 고스트스크립트 기능이 구현된 라이브러리 파일인 gsdll32.dll
에서 발생한다.
해당 취약점과 익스과정을 자세히 살펴보려면 다음 링크에서 참고)
1.2 한글 파일 구조
그럼 한글 파일을 분석하기 위해 한글 파일 포맷에 대해서 간략하게 알아보자
'한글 2002'부터 '한글 2018'까지 현재 출시된 한글 프로그램은 기본적으로 5.0버전의 한글 문서 파일 형식으로 한글 파일(.hwp)를 생성한다.
한글 문서 파일 형식 5.0은 OLE(Object Linking and Embedding)
파일을 기반으로 하여 여러 개의 Storage
와 Stream
으로 구성되어 있다.
또한, 파일 크기를 최소화하기 위하여 압축 기능을 사용하는데 그림 관련 데이터를 포함한 일부 스트림은 파일의 크기를 줄이기 위해 zlib
으로 압축해서 저장하는 방식을 사용한다.
하나의 스트림에는 일반적인 바이너리나 레코드 구조로 데이터가 저장되고 스트림에 따라 압축 및 암호화되기도 한다. 위 표를 살펴보면 주목해야될 스토리지로 바이너리 데이터를 의미하는 BinData
라는 스토리지가 존재하는데 여기에 그림 또는 OLE Object
가 스트림으로 zlib
으로 압축되어 저장되어 진다.
이처럼 한글 문서에 그림 파일을 삽입할 수 있는데 삽입 가능한 파일 포맷중에 EPS 파일이 포함되어 있다. 그리고 한글 파일에 포함된 EPS 파일은 BinData 스토리지에 각각의 스트림으로 zlib으로 압축되어 저장하게 된다.
1.3 EPS파일 로드 과정
EPS파일이 BinData 스토리지에 저장되는 것은 알았는데 한글 문서를 열면 어떻게 실행되는 것인지 알아보도록 하자
EPS(Encapsulated PostScript)
파일은 포스트스크립트(PostScript)
프로그래밍 언어로 작성된 규격화된 파일로 단일 그래픽 이미지를 표현한다. 쉽게 설명하면 포스트스크립트언어에서 사용되는 그래픽 파일 포맷이며 고품질 인쇄 및 출력을 목적으로 한다.
이처럼 EPS파일을 화면에 표현하기 위해 인터프리터가 필요하며 한글 프로그램에서는 인터프리터인 고스트스크립트(Ghostscript)
를 내장하고 있다.
기본적으로 위와 같이 4개의 파일로 구성되어 있으며 인터프리팅 기능을 하는 핵심 파일은 gsdll32.dll
라이브러리이다. 이외에 실행파일들은 라이브러리 함수를 호출하는 역할을 하며 한컴에서 제작한 gbb.exe
파일을 제외하면 모두 공개된 고스트스크립트 소스로 컴파일된 파일이다.
gbb.exe
: 한컴에서 제작한 포스트스크립트 인터프리터로 gsdll32.dll 로드해서 동작
gsdll32.dll
: 고스트스크립트 인터프리터 핵심 라이브러리
gswin32.exe
: 고스트스크립트 인터프리터 GUI버전으로 gsdll32.dll 로드해서 동작
gswin32c.exe
: 고스트스크립트 인터프리터 커맨드 버전으로 gsdll32.dll 로드해서 동작
1) Process
한글 프로그램은 문서를 읽는 과정에서 EPS 이미지가 포함된 페이지가 로드될 때 이를 화면에 표현하기 위해 고스트스크립트 인터프리터인 gbb.exe
파일과 gswin32c.exe
파일이 순차적으로 실행된다. 즉, Hwp.exe
프로세스는 Child Process로 gbb.exe
와 gswin32c.exe
프로세스를 실행할 때 표현 대상인 EPS파일을 실행 인자로 전달하여 그래픽 이미지를 화면에 표시한다.
참고로 위에서 언급했듯이 EPS파일(스트림)
은 BinData Storage
에 .zlib
으로 압축되어 저장되어 있기 때문에 Hwp.exe
프로세스는 먼저 .zlib
압축을 풀어 임시 파일로 생성하고, 생성된 임시 파일을 고스트스크립트 인터프리터가 처리할 수 있도록 생성된 임시 파일 경로를 인자로 전달한다.
2) 추가 설명
Hwp.exe
프로세스는 단순히 고스트스크립트를 호출하고 작업 이후 종료 여부에 관해서만 확인하며 고스트스크립트 내부에 일어나는 일에 대해서는 관여하지 않는다. 인터프리터도 EPS 파일의 포스트스크립트 코드를 처리한 뒤 최종 표현하며, 단독으로 EPS 파일 실행이 가능하다.
(즉, 이 말은 한글 프로그램이 설치되지 않은 환경에서도 고스트스크립트에 EPS파일을 실행인자로 주면 마찬가지로 악성 기능이 동작한다.)
+) EPS파일이 문서의 첫 번째가 아닌 다른 페이지에 삽입된 경우 해당 페이지가 화면에 로드될 때 고스트스크립트가 실행되어 동작하지만 실제 악성 한글 파일의 대부분은 문서를 열자마자 악의적인 기능이 동작하도록 첫 번째 페이지에 삽입되어 있다.
3) 요약
Hwp.exe
프로세스가 EPS파일을 처리할 때 .zlib
으로 압축되어 있는 EPS파일(스트림)을 압축해제하고 임시 파일을 만들어 해당 파일 경로를 인자로 고스트스크립트 인터프리터인 gbb.exe
, gswin32c.exe
프로세스를 호출하면서 전달하며, 두 프로세스는 취약점이 존재하는 gsdll32.dll
라이브러리 로드하여 사용한다. 이 때, Type Confusion
취약점이 터지는 .eqproc
함수를 사용하게 된다.
2. 분석환경
3. 분석
위에서는 고스트스크립트의 취약점을 이용하는 EPS파일에 대한 내용이지만 여기서 분석하는 대상은 고스트스크립트 취약점을 이용하는 것이 아닌 파일 객체 생성 등 정상적인 포스트스크립트 문법을 이용해 악성 파일을 생성하는 PS파일에 해당되는 내용이다.
3.1 문서 확인
분석하는 대상은 실제 악성 행위를 하지 않으며 문서 열람시 시작프로그램 폴더에 메시지 박스를 띄우는 프로그램을 생성하여 시스템 재부팅 후에도 자동으로 실행하는 기능을 한다.
- 문서를 열어보면 뭔가 작업을 진행하는지 약간의 시간이 걸리고 난 다음 문서의 내용을 확인할 수 있다.
- 문서의 내용은 위와 같이 별거 없어보인다.
- 하지만 사진 위에 엄청 확대해서 보면 빨간색 박스 안에 조그마한 밑줄이 보인다. 저것이 바로 메시지박스 프로그램을 생성하는 EPS파일이다.
- 실제로 고스트스크립트 취약점을 이용한 악성코드들은 저렇게 사용자들이 식별할 수 없도록 작게 축소 시키거나 숨겨놓는다.
- 최종적으로
hwpTray.exe
파일이 시작프로그램 디렉터리에 저장되며 시스템 재부팅시에 자동으로hwpTray.exe
파일이 실행되어 위와 같이MessageBox
를 띄우게 된다.
3.2 PS파일 추출
이제 SSView(Structed Storage Viewer)
를 이용하여 해당 문서 파일에 숨겨진 EPS파일을 추출해보도록 하자
(참고로 누리랩에서 개발한 한글 문서 파일의 취약점을 점검할 수 있는 HWPScan2
를 사용하고자 하였으나 현재 제품 업그레이드를 위해 일시적으로 다운로드를 못하도록 하여 SSView를 사용하였다.)
- 해당 문서를 SSView에 올려보면
BinData Storage
에 두 개의 파일을 확인할 수 있다. 앞서 언급했듯이BinData Storage
에는 그림 또는 OLE Object가 스트림으로 zlib으로 압축되어 저장되어진다.(그리고 삽입가능한 파일 포맷에는 EPS파일이 포함된다.)
- 현재
BIN0001.ps
파일은 zlib으로 압축되어 있으므로 먼저 해당 ps파일을 추출하자
BIN0001.ps.stream
파일이 zlib으로 압축되어 있음을 확인
따라서, 압축해제를 위해 다음 파이썬 코드를 실행시켜주자
import zlib
flist = ["BIN0001.ps.stream"]
for item in flist:
with open(item, "rb") as f:
buf = f.read()
unzlibed = zlib.decompress(buf, -9)
with open(item+".unzlib", "wb") as f:
f.write(unzlibed)
(hwpscan2
에서는 바로 Decompress
기능을 통해 위와 같은 파이썬 코드를 안짜도 걍 바로 추출 및 압축 해줌ㅠㅠ)
- 위 파이썬 코드를 실행시켜주면
BIN0001.ps.stream.unzlib
파일이 생성되는데 이거를 다시010 Editor
에 올려주면 위와 같은 그림을 볼 수 있다.
- 빨간색 박스는 포스트스크립트로 짜여진 것을 알 수 있고 노란색 박스의 처음 헥사 값을 보면
PE Signature
인4D5A(MZ)
인 것을 통해 PE파일임을 알 수 있다.
3.3 포스트 스크립트 분석
포스트스크립트는 Adobe에서 개발한 페이지 기술 언어이다. 포스트스크립트 인터프리터는 연산의 기본 단위가 되는 객체(Object)를 대상으로 일정한 규칙에 따라 읽고 처리한다.
여기서는 포스트 스크립트에 대한 문법을 자세히 다루지는 않을 것이다... 왜냐면 나도 처음 접하는 언어이기 때문에 깊게 들어가면 시간이..... 부족할 것 같다.
PostScript 문법 참고자료)
%
: 주석 처리하는 용도
/
: 변수를 지정하기 위해 사용
{ }
: 프로시저를 구분 짓는 용도이며 객체를 별도의 데이터 단위로 처리
- aa라는 변수에 readhexstring을 통해 "7456D70"라는 헥사 값을 문자열로 변경 하는 것 같다.
- 그리고 p2에서도 동일하게 readhexstring을 사용하여 헥사 값을 문자열로 변경한다.
- 이거를 간단하게 파이썬으로 문자열로 변환하면 오른쪽 사진과 같이 된다.
- 마지막으로 Getenv함수에
"temp"
를 전달해 임시 디렉터리 경로를 획득하고 loop문에서"Startup\hwpTray.exe"
파일을 생성한다.
- 그리고 마지막 부분에
exec
를 이용하여 객체를 실행할 수 있도록 한다.
솔직히 위 내용을 완벽히 이해하지는 못했으나 대충 시작프로그램 디렉터리 경로를 획득하여 밑에 있는 바이너리를 hwpTray.exe
파일로 저장하는 것 같다.
3.4 PE파일 분석
- 밑에 PE 시그니쳐 4D5A(MZ)부터 복사하여 HxD에 올린 다음 main.exe파일로 저장한다.
- 32Bit PE파일임을 확인
- IDA에 올려보면 start함수를 따라가서 main함수를 찾을 수 있지만 처음에 hwpTray.exe파일이 실행하면 "pwn!"이라는 문자열을 출력하는 메시지 박스를 띄우므로
Shift + F12
를 눌러 먼저 문자열을 검색한다.
int __cdecl sub_403B70(char a1)
{
LPSTR v1; // ebx
CHAR v2; // al
int v3; // esi
HMODULE v4; // eax
LPSTR v6; // edx
CHAR v7; // al
struct _STARTUPINFOA StartupInfo; // [esp+1Ch] [ebp-5Ch]
char *v9; // [esp+6Ch] [ebp-Ch]
v9 = &a1;
sub_4019A0();
v1 = GetCommandLineA();
GetStartupInfoA(&StartupInfo);
....
v3 = 10;
if ( StartupInfo.dwFlags & 1 )
v3 = StartupInfo.wShowWindow;
v4 = GetModuleHandleA(0);
return sub_401460((int)v4, 0, (int)v1, v3);
}
- main함수로 추정되는 함수에서 sub_401460()을 호출하게 되는데
int __stdcall sub_401460(int a1, int a2, int a3, int a4)
{
MessageBoxA(0, "cdpython", "pwn!", 0);
return 0;
}
- 여기서 MessageBoxA()를 호출하게 된다.
3.5 행위 분석
Process Monitor
를 이용하여 문서 열람 시 행위를 분석해보자
1) 필터 적용 1
- Process Name → is →
hwp.exe
- Path → Contains →
hwpTray.exe
확인 결과)
- Hwp.exe의 자식 프로세스인 gbb.exe와 gswin32c.exe를 실행하는 것을 확인
2) 필터 적용 2
- Process Name → is →
gswin32.exe
,gbb.exe
확인 결과)
gbb.exe
프로세스가 시작프로그램 디렉터리 밑에hwpTray.exe
파일을 생성하는 것을 확인
Uploaded by Notion2Tistory v1.1.0