'DLL'에 해당되는 글 4건

  1. 2015.02.17 아래한글 DLL 하이재킹 취약점 보안 업데이트
  2. 2010.08.26 DLL 하이재킹 취약점으로 인한 악성코드 감염 주의
  3. 2009.09.01 DLL Injection 은 어떻게 이루어지는가? (1)
2015.02.17 18:50

아래한글 DLL 하이재킹 취약점 보안 업데이트

□ 개요
 o 한글과컴퓨터社의 한글 등 오피스 프로그램에서 DLL 하이재킹 취약점이 발견됨 [1]
   - 사용자가 특수하게 조작된 DLL 파일과 동일한 디렉토리 경로에 존재하는 정상파일을 한글 프로그램을 통하여 열람 및 추가 기능을 사용 할 경우, 임의코드가 실행될 수 있는 취약점이 존재
 o 영향 받는 버전의 사용자는 악성코드 감염에 취약할 수 있으므로 해결방안에 따라 보안 업데이트를 권고함

□ 해당 시스템
 o 영향 받는 소프트웨어

□ 해결 방안
  o 한글과컴퓨터 홈페이지에서 보안업데이트 파일을 직접 다운로드 받아 설치하여 영향 받지 않는 버전(보안#26)으로 업데이트

  o 한글과컴퓨터 자동 업데이트를 통해 최신버전으로 업데이트
    - 시작 → 모든 프로그램 → 한글과컴퓨터 → 한글과컴퓨터 자동 업데이트

□ 문의사항
  o 한국인터넷진흥원 인터넷침해대응센터: 국번없이 118

□ 기타
  o 이번 보안 업데이트에서 보완된 취약점은 KrCERT 홈페이지를 통해 ‘조민기’님께서 제공해주셨습니다.

[참고사이트] 
[1] http://www.hancom.co.kr/downLoad.downPU.do?mcd=001



Trackback 0 Comment 0
2010.08.26 11:55

DLL 하이재킹 취약점으로 인한 악성코드 감염 주의

□ 개요

   o 일부 응용프로그램에서 로드하는 라이브러리 파일의 경로를 부적절하게 검증함으로 인해 
     원격코드실행 취약점이 발생 [1, 3, 4, 5, 10]
   o 공격자는 취약한 프로그램을 사용하는 파일을 USB 이동저장매체, 압축 해제된 파일, WebDav, 
     원격 네트워크 공유 등을 통해 열도록 유도하여, 동일한 경로의 악의적인 라이브러리 파일이
     로드되어 실행되게 함으로써 악성코드를 유포할 수 있음 [1, 6, 7]
   o 취약점을 공격하는 개념증명코드가 공개되었고 다수의 응용프로그램이 취약할 것으로 
     추정[2, 5]되므로, 개발자의 취약점 점검 조치 및 사용자의 각별한 주의가 요구됨

□ 해당 시스템
   o 영향 받는 소프트웨어 [1, 5]
     - 외부 라이브러리를 안전하지 않은 방식으로 로드하는 응용프로그램
       ※ LoadLibrary() 및 LoadLibraryEx()에서 라이브러리 파일의 절대 경로를 인자로 전달하지 
          않은 경우 취약점이 발생할 수 있음

□ 권장 조치 방안
   o 해당 취약점은 취약한 응용프로그램을 개발한 제작사에서 보안 업데이트를 발표해야할
     사안으로, 응용프로그램 개발자는 다음과 같은 조치를 권장함
     - 응용프로그램이 취약한지 여부를 "DLL Hijacking Audit Tool[11]"로 판단
     - Microsoft의 MSDN 사이트에서 DLL 검색 순서[8] 및 DLL 보안[9]에 관한 문서를 참고하고,
       외부 라이브러리를 안전하게 로드할 수 있도록 해당 취약점을 패치
   o 일반 사용자는 취약점을 통한 공격을 완화시키기 위해 다음과 같은 설정 적용
     - Microsoft 기술자료 2264107[12]를 참고하여 WebDAV와 원격 네트워크 공유로부터
       라이브러리가 로딩되지 않도록 설정
     - WebClient 서비스를 비활성화
       * 시작 → 실행 → services.msc 입력 후 확인 → WebClient 서비스 속성 → 시작 유형을
         "사용 안 함"으로 설정 및 서비스 중지 선택 후 확인
     - 방화벽에서 TCP 139, 145 포트 차단
       ※ WebClient에 종속적이거나 해당 포트를 사용하는 윈도우 서비스나 응용프로그램을 사용하는
           시스템은, 기능상 장애가 발생할 수 있음
   o 취약점에 의한 피해를 줄이기 위하여 사용자는 다음과 같은 사항을 준수해야함
     - 파일공유 기능 등을 사용하지 않으면 비활성화하고 개인방화벽을 반드시 사용
     - 사용하고 있는 백신프로그램의 최신 업데이트를 유지하고, 실시간 감시기능을 활성화
     - 신뢰되지 않는 웹 사이트의 방문 자제
     - 출처가 불분명한 이메일의 링크 클릭하거나 첨부파일 열어보기 자제


□ 용어 정리
   o DLL(Dynamic Link Library, 동적 연결 라이브러리): 동시에 하나 이상의 프로그램에서 사용될
     수 있는 코드와 데이터를 포함한 라이브러리로, DLL을 사용하면 프로그램을 분리된 구성 요소로 
     모듈화하여 작성할 수 있음
   o WebDAV(Web Distributed Authoring and Versioning): 웹 기반으로 파일의 생성, 복사,
     이동 및 삭제와 같은 기능이 수행되는 방식을 정의하는 HTTP 확장
     
□ 기타 문의사항
   o 한국인터넷진흥원 인터넷침해대응센터: 국번없이 118

□ 참고사이트
   [1] http://www.microsoft.com/technet/security/advisory/2269637.mspx
   [2] http://www.theregister.co.uk/2010/08/20/windows_code_execution_vuln/
   [3] http://isc.sans.edu/diary.html?storyid=9445
   [4] http://acrossecurity.blogspot.com/2010/08/binary-planting-update-day-6.html
   [5] http://www.acrossecurity.com/advisories.htm
   [6] http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
   [7] http://blog.rapid7.com/?p=5325
   [8] http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx
   [9] http://msdn.microsoft.com/en-us/library/ff919712(VS.85).aspx
   [10] http://blog.zoller.lu/2010/08/cve-2010-xn-loadlibrarygetprocaddress.html
   [11] https://www.metasploit.com/redmine/projects/framework/repository/raw/external/
source/DLLHijackAuditKit.zip

   [12] http://support.microsoft.com/kb/2264107


Trackback 0 Comment 0
2009.09.01 09:37

DLL Injection 은 어떻게 이루어지는가?

루트킷을 비롯하여 바이러스, 악성코드 등 여러 분야에 두루 쓰이는 기법이 DLL Injection입니다. 윈도우즈 OS에 한정되어 적용되는 것이지만, 윈도우즈 자체의 점유율이 높은 이유로 아주 효과적으로 공격자가 원하는 작업을 수행할 수 있는 방법이죠. 최근 루트킷에 대해 공부하면서 이 DLL Injection이 어떻게 이루어지는 알게 된 것을 정리해봅니다.

DLL? 그게 뭐야?

DLL은 윈도우즈 OS에서 사용되는 동적 연결 라이브러리 실행 파일입니다. 말이 어렵죠? 간단하게 말해서, 실행할 수 있는 아주 작은 프로그램의 단위라고 이해하시면 되겠습니다.

라이브러리라는 말은 아시나요? 영어로 Library, 도서관이라는 뜻이죠? 프로그램이 작업을 수행할 때 이 라이브러리를 참조하게 됩니다. 라이브러리에 포함된 함수, 구조체, (추천하는 방법은 아니지만) 변수 등등을 이용하는 것이죠. 우리가 프로그래밍을 할 때 (C 언어 기준으로) 헤더 파일을 집어넣습니다. stdio.h, string.h 같은 표준 헤더부터, cimg.h, curl.h 같은 사용자 정의 헤더까지 다양하죠. 이런 것을 정적 라이브러리라고 합니다. 프로그램 자체에 포함되는 라이브러리죠.

[그림 1] RocketDock 이 이용하는 많은 DLL 파일들

이에 반해 동적 연결 라이브러리는 [그림 1]에서처럼 프로그램과는 별도로 존재합니다. 가장 많이 볼 수 있는 kernel32.dll, user32.dll, gdi32.dll 등이 동적 연결 라이브러리 파일입니다. 프로그램은 필요할 때 이 DLL을 호출해서 그 안에 있는 함수를 이용하지요.

왜 이렇게 따로 하냐구요? 이렇게 함으로써 두 가지 이익을 얻을 수 있기 때문입니다.

첫 째는 프로그램이 메모리에 적재되는 용량을 줄일 수 있다는 점입니다. 프로그램 자체에 처음부터 들어 있는 게 아니라, 필요할 때 호출하는 방식이기 때문에 메모리에 항상 적재되어 있을 필요가 없지요.

두 번째는 DLL의 코드가 변경되어도 원래의 함수 이름이나 인자가 그대로라면, 프로그램을 다시 컴파일하거나 링킹을 할 필요가 없다는 점입니다. 정적 라이브러리는 변경될 때마다 매번 컴파일하고 링킹을 새로 해야하니 DLL은 정말 편리한 녀석이죠. [그림 1]에서 StackDocklet.dll을 이용하는 것을 볼 수 있죠? 플러그인을 이렇게 DLL 파일로 지원할 수도 있습니다. StackDocklet.dll의 내부 코드가 변경되어도 함수의 형태만 유지된다면 RocketDock 자체를 새로 컴파일할 필요는 없겠죠?

간단하게 DLL이 무엇인지 알아보았는데요. 다음에는 DLL이 어떻게 호출되는지, DLL Injection이 어떻게 이루어지는지를 정리해보겠습니다.

참고 문헌

Visual C++ DLL :: http://msdn.microsoft.com/ko-kr/library/1ez7dh12(VS.80).aspx
Dynamic-link library :: http://en.wikipedia.org/wiki/Dynamic-link_library

AppInit_DLLs 값 조작

DLL Injection에는 여러 방법이 있습니다. 그중 루트킷에 이용되는 세 가지 방법을 알아보겠는데요. 첫 번째로 레지스트리를 조작하는 방법입니다.

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs

regedit에서 위 주소의 레지스트리 값을 확인해보면, 보통은 값이 비어있습니다. 그런데 어떠한 값이 들어있다면, 그리고 그것이 자신이 모르는 어떤 파일이라면, 그것은 악성 코드일 가능성이 있습니다. 이 레지스트리 값이 무엇이냐구요? 바로 이 값이 DLL Injection에 참조되는 레즈스트리 값입니다.

윈도우즈의 많은 어플리케이션들이 user32.dll을 호출합니다. 이 DLL에는 창관리자를 호출하는 API 함수들이 있습니다. 윈도우즈가 기본적으로 GUI 환경이고 그 때문에 어플리케이션들도 user32.dll을 호출하기 마련이죠.

[그림 1] user32.dll이 AppInit_DLLs를 참조하는 개요

그런데 이 user32.dll은 특별한 기능을 가지고 있습니다. [그림 1]에서처럼 user32.dll은 LoadLibrary() 함수를 이용하여 AppInit_DLLs 안에 지정된 DLL들을 호출합니다. 이 때 LoadLibrary()의 인자값으로 DLL_PROCESS_ATTACH를 지정해주기 때문에 프로세스 중간에 DLL이 들어갈 수 있는 것입니다.

공격자가 이 레지스트리 값을 악의적으로 변경한다면 악성코드를 프로세스에 심을 수 있죠. 대신 이것이 적용될려면 재부팅이 필요합니다. 그러나 레지스트리 값이 변경되기 이전에 메모리에 적재된 프로세스일 경우에 재부팅이 필요한 것이지, 변경 된 이후에 메모리에 적재될 프로세스라면 굳이 재부팅이 안 되더라도 DLL이 삽입됩니다.

Email-Worm.Win32.Warezov.nf 이라는 웜이 AppInit_DLLs 값을 변경하여 DLL Injection을 시도하는 한 예입니다. 이것은 이메일의 첨부파일이 실행되면 악성 DLL을 C:\WINDOWS\system32에 생성합니다. 그리고 AppInit_DLLs 값을 변경하여 이후에 user32.dll을 호출하는 프로세스에 악성 DLL을 삽입하죠. 이 웜에 대한 자세한 내용은 아래 참고 문헌을 읽어주세요.

하지만 이 방법은 해당 레지스트리 값만 조사하면 금방 탐지될 수 있는 단점이 있습니다. 보통 정상적인 경우라면 위에서도 언급했듯이 값이 비어있기 때문이죠. 그렇더라도 레지스트리가 무엇인지 모르는 윈도우즈 사용자가 대부분이기 때문에 이것만으로도 꽤 치명적이라 할 수 있습니다.

참고 문헌

루트킷 : 윈도우 커널 조작의 미학, Greg Hoglund, James Butler, 2007, 에이콘
부팅할때 읽는 주요 파일 :: http://fd.igrus.kr/?mid=Study&document_srl=1013
Email-Worm.Win32.Warezov.nf 정보 :: http://blog.daum.net/virusmyths/6041710

SetWindowsHookEx ()

이번에는 윈도우즈에서 정상적으로 지원하는 후킹 함수를 이용하는 방법을 알아보겠습니다. 윈도우즈는 OS와 프로세스 간에 메시지를 주고받는데요. 키보드를 누른다던지, 마우스를 클릭한다던지, 디버깅에 관한 메시지라던지 그런 것들을요. 그리고 그렇게 주고받는 메시지를 후킹할 수 있는 함수도 제공하고 있습니다.

[그림 1] SetWindowsHookEx() 함수의 개요

SetWindowsHookEx() 함수가 그것이죠. [그림 1]처럼 이 함수에 삽입할 DLL의 Handler, 즉 주소와 함수의 주소를 인자로 넣음으로써 메모리에 올라간 프로세스에 삽입하게 됩니다.

SetWindowsHookEx (WH_KEYBOARD, KeyHookProc, hModule, NULL);

위 예처럼 함수를 작성합니다. hModule은 삽입할 DLL의 주소입니다. 이것은 LoadLibrary() 함수로 구할 수 있죠.

그리고 KeyHookProc은 DLL의 함수인데, GetProcAddress() 함수로 구할 수 있고, CallBack 함수로 등록할 수도 있습니다. 주의할 것은 KeyHookProc는 CallNextHookEx() 함수를 반환해야 한다는 것입니다. 후킹이 끝나고 나서 원래의 작업을 하기 위해서죠. 만약, 원래의 작업을 하지 않는다면, 사용자는 무엇인가가 잘목되었다는 것을 알 수 있고 자칫하면 블루스크린을 띄울 수도 있거든요.

[그림 1]에서 보면 네 번째 인자로 dwThreadId가 지정되어 있는데, 이것은 DLL을 삽입하려는 쓰레드의 ID입니다. GetCurrentThreadId() 함수로 구할 수 있습니다. 이 값이 0이라면, 현재 윈도우즈 데스크탑의 모든 쓰레드가 대상이 되죠.

[그림 2] idHook 테이블

첫 번째 인자가 남았는데 이것이 후킹할 메시지입니다. OS와 여기에 지정된 메시지를 주고받는 쓰레드를 후킹하지요. 이 인자에 들어갈 수 있는 값은 [그림 2]에 정리되어 있습니다. 키보드, 마우스, 디버깅, 쉘과 관련된 15개의 메시지들이 있습니다. 이 메시지들에 대해 더 자세한 내용은 아래 참고 문헌에 나와 있으니 여기서는 생략하겠습니다.

마지막으로 작업이 모두 끝나면 메모리 반환을 위해서 UnhookWindowsHookEx() 함수로 후킹을 풀어줘야 합니다.

아래는 SetWindowsHookEx() 함수를 이용하는 예제 소스입니다.

#include <windows.h>

#pragma data_seg(".npdata")     HINSTANCE hModule=NULL;     HHOOK hKeyHook=NULL;     HWND hWndBeeper=NULL; #pragma data_seg() #pragma comment (linker, "/SECTION:.npdata,RWS")
LRESULT CALLBACK
KeyHookProc(int nCode, WPARAM wParam, LPARAM lParam) {     if (nCode>=0)     {         SendMessage(hWndBeeper,WM_USER+1,wParam,lParam);     }     return CallNextHookEx(hKeyHook,nCode,wParam,lParam); }

extern "C" __declspec(dllexport) void InstallHook(HWND hWnd) {     hWndBeeper=hWnd;     hKeyHook=SetWindowsHookEx(WH_KEYBOARD,KeyHookProc,hModule,NULL); }
extern "C" __declspec(dllexport) void UninstallHook() {     UnhookWindowsHookEx(hKeyHook); }
BOOL WINAPI
DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID lpRes) {     switch (fdwReason)     {         case DLL_PROCESS_ATTACH:             hModule=hInst;             break;         case DLL_PROCESS_DETACH:             break;     }     return TRUE; }

참고 문헌

루트킷 : 윈도우 커널 조작의 미학, Greg Hoglund, James Butler, 2007, 에이콘
SetWindowsHookEx Function :: http://msdn.microsoft.com/library/ms644990.aspx
SetWindowsHookEx() 함수를 이용한 방법 :: http://blog.naver.com/amanahnr/90032952064


CreatRomoteThread ()

DLL Injection의 마지막 세 번째 방법은 CreatRemoteThread() 함수를 이용하는 것입니다. 가장 많이 쓰이는 방법이라서 관련 문서도 쉽게 찾을 수 있죠.

[그림 1] CreatRemoteThread() 의 개요

CreatRemoteThread() 함수는 이름 그대로 쓰레드를 만드는 API 함수입니다. 원격은 다른 프로세스에서 쓰레드를 생성하기 때문에 붙은 것이죠. [그림 1]과 같은 구조로 구성되어 있고, 윈도우즈 NT 계열에서 지원합니다.

첫 번째 인자인 hProcess는 쓰레드를 생성할 프로세스를 가리킵니다. 윈도우즈에서 제공하는 OpenProcess()  API 함수를 이용해서 구할 수 있으며, PID(Process ID) 값을 이용합니다. OpenProcess()의 원형은 아래와 같습니다.

HANDLE WINAPI OpenProcess(
  __in  DWORD dwDesiredAccess,
  __in  BOOL bInheritHandle,
  __in  DWORD dwProcessId
);

네 번째 인자, lpStartAddress는 LoadLibrary() 함수를 가리킵니다. LoadLibray()를 이용하여 DLL을 삽입하기 때문이죠. 원래는 쓰레드를 생성할 프로세스에서의 LoadLibray()를 가리켜야 하지만, 윈도우즈는 각 프로세스의 kernel32.dll의 베이스주소를 일정하게 관리하기 때문에 DLL Loader에서 사용하는 kernel32.dll의 LoadLibray()를 가리키더라도 문제 없다고 합니다. LoadLibray()의 주소는 GetProcAddress()를 이용합니다. 원형은 아래와 같습니다.

FARPROC WINAPI GetProcAddress(
  __in  HMODULE hModule,
  __in  LPCSTR lpProcName
);

다섯 번째 인자인 lpParameter는 프로세스 안에서 쓰레드가 위치할 메모리 영역을 가리킵니다. CreateRemoteThread()는 프로세스 안에 쓰레드를 생성하는 것이므로 쓰레드를 위한 메모리를 별도로 생성해주어야 하지요. 이 때 사용하는 API 함수가 VirtualAllockEx()와 WriteProcessMemory()입니다. VirtualAllockEx()가 메모리를 할당하면, WriteProcessMemory()로 쓰는 것이죠. 각각의 원형은 아래와 같습니다.

LPVOID WINAPI VirtualAllocEx(
  __in      HANDLE hProcess,
  __in_opt  LPVOID lpAddress,
  __in      SIZE_T dwSize,
  __in      DWORD flAllocationType,
  __in      DWORD flProtect
);

BOOL WINAPI WriteProcessMemory(
  __in   HANDLE hProcess
,
  __in   LPVOID lpBaseAddress
,
  __in   LPCVOID lpBuffer
,
  __in   SIZE_T nSize
,
  __out  SIZE_T
*lpNumberOfBytesWritten
);

나머지 인자들은 lp*는 NULL로, dw*는 0으로 넣습니다. 이 중에서 dwCreationFlags에 0을 넣는 것은 쓰레드가 생성되는 즉시 실행하라는 뜻입니다.

전체적으로 정리해보죠. OpenProcess()로 DLL을 집어넣을 프로세스를 구합니다. 그리고 GetProcAddress()로 DLL을 로드하는 LoadLibrary()의 주소를 구합니다. 마지막으로 VirtualAllockEx()로 DLL이 위치할 메모리를 할당하고 WriteProcessMemory()로 쓰게 됩니다. 이 모든 것들을 CreateRemoteThread()의 인자값으로 넣어서 DLL Loader에서 실행합니다. 이러면 DLL Injection이 된 것입니다. 간단하죠?

하지만 이 방법은 간단한 대신 쉽게 탐지되기도 합니다. CreateRemoteThread()를 호출하면 CreatThreat()가 호출되고, 그 안에서 다시 BaseThreadStartThunk()가 호출된다고 합니다. 이 BaseThreadStartThunk()를 후킹해서 lpStartAddress가 위에서 설명한 대로 LoadLibray()나 GetProcAddress()를 가리킨다면 DLL Injection이라고 간주하는 것이죠.

참고 문헌

루트킷 : 윈도우 커널 조작의 미학, Greg Hoglund, James Butler, 2007, 에이콘
CreateRemoteThread Function :: http://msdn.microsoft.com/en-us/library/ms682437(VS.85).aspx
OpenProcess Function :: http://msdn.microsoft.com/en-us/library/ms684320(VS.85).aspx
GetProcAddress Function :: http://msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx
VirtualAllocEx Function :: http://msdn.microsoft.com/en-us/library/aa366890(VS.85).aspx
WriteProcessMemory Function :: http://msdn.microsoft.com/en-us/library/ms681674(VS.85).aspx
Shield from DLL-Injection :: http://nerd.egloos.com/2940078


출처 : http://hisjournal.net/blog


Trackback 0 Comment 1
  1. DLL Injection 2009.09.01 09:42 address edit & del reply

    LoadLibraryA 와 CreateRemoteThreadㅁ API 를 이용한 DLL Injection 방법이 있고
    SetWindowsHookExA 로도 DLL Injection 이 가능합니다
    CreateRemoteThread 를 이용한 DLL Injection 방법 : << 해보세요 즉석에서 대충만들어서 안될수도 있따만 ㅎㄷ;;;


    Public Function Inject_Dll(Strdll As String, StrProcID As String)
    Dim LoadlibAdr As Long, RemThread As Long, LngModule As Long, LngProcess As Long, LngBytes As Long, LngThreadID As Long
    On Error GoTo ErrTrap
    LngProcess = OpenProcess(PROCESS_ALL_ACCESS, False, CLng(StrProcID)) '프로세스를 엽니다
    LoadlibAdr = GetProcAddress(GetModuleHandle("kernel32.dll";), "LoadLibraryA";) 'dll 주소 가져옴
    LngModule = VirtualAllocEx(LngProcess, 0, Len(Strdll), MEM_COMMIT, PAGE_READWRITE) '메모리를 읽고 쓰기가 가능하게 만듦
    WriteProcessMemory LngProcess, ByVal LngModule, ByVal Strdll, Len(Strdll), LngBytes ' 메모리를 씁니다(dll 공간)
    RemThread = CreateRemoteThread(LngProcess, ByVal 0, 0, ByVal LoadlibAdr, ByVal LngModule, 0, LngThreadID) 'DLL Injecting
    WaitForSingleObject RemThread, INFINITE
    CloseHandle LngProcess ' 핸들 닫아야함 안그럼 Memory Leak 현상이 일어날거임.
    CloseHandle RemThread ' 역시 이것도 뭐..
    MsgBox "성공 - 작업을 완료햇습니다.", vbInformation, "완료"
    Exit Function
    ErrTrap:
    MsgBox "실패.", vbCritical, "오류"
    End Function