fastdd의 64비트 버전이 업데이트 되었습니다.

Download


<사용 방법>
"fastdd64 [덤프할 파일 이름]"


fastdd에 대한 설명은 여기를 참조해주세요.

알림) fastdd32, 64의 실행파일 및 드라이버 바이너리의 디지털서명은 Four&Six Tech.의 지원을 받아 수행되었습니다. http://4n6tech.com




rawcopy v1.0은 프로세스에 의해 핸들이 잠긴 상태의 파일을 복사하기 위해 제작되었습니다. 예를 들어 레지스트리 하이브 파일이나 페이지파일(pagefile.sys), 하이버네이션파일(hiberfil.sys) 등은 시스템에 의해 사용 중이기 때문에 복사할 수 없습니다. 이러한 경우에 rawcopy를 통해 복사를 수행하시면 됩니다. 특히나 페이지파일이나 하이버네이션파일은 라이브포렌식이나 메모리분석 시에 유용히 사용되기 때문에 활용가치가 높다고 생각됩니다.

구현 원리를 말씀드리자면, 파일시스템 모듈이 볼륨을 직접 오픈하고 파일시스템 구조를 직접 파싱하여 파일의 데이터 영역에 접근합니다. 지원하는 파일시스템은 FAT16, 32 그리고 NTFS 입니다. 프로그램은 간단해 보이지만 내부적으로는 복잡한 과정을 거칩니다.

download

<사용법>
rawcopy srcfile destfile


다운로드 받으시면 실행파일과 dll 파일이 나옵니다. dll 파일은 직접 개발한 파일시스템 모듈이기 때문에 반드시 필요합니다. 그냥 함께두고 실행하세요.

개인적인 용도로 사용하기 위해 단순하게 제작하였습니다. 만약 버그 발견 시에는 리플로 리포팅해주시면 적극 반영하도록 하겠습니다. 그리고 만약 디렉토리 복사를 원하시면... 쉘스크립트를 이용하세요.. ;p



개인적인 사정으로 인해 현재 포스팅 중단 중입니다. :(
시간되는 대로 다시 시작하도록 하지요.



오늘 'Paradox Conference 2011'에서 윈도우즈 물리 메모리 포렌식과 관련하여 발표를 하고 왔습니다. 아래는 발표자료 다운로드 링크입니다.

Download


재미있었는지는 모르겠지만, 경청해주신 많은 분들께 감사드립니다.



윈도우즈 시스템에서의 물리 메모리는 일반적으로 win32dd 또는 mdd 등의 도구를 이용하여 수집합니다. 이러한 도구들은 여러가지 방법을 이용하여 물리 메모리에 접근하게 되는데, 이번 포스팅은 윈도우즈 시스템에서 물리 메모리에 접근하여 이를 덤프하는 방법에 대한 글입니다.



1. \Device\PhysicalMemory를 이용한 방법

'\Device\PhysicalMemory' 개체는 물리 메모리에 접근하기 위해 사용되는 개체이며, 가장 일반적으로 사용되는 방법입니다. 이 방법을 사용하는 대표적인 도구가 바로 mdd입니다. (win32dd는 이 방법 및 앞으로 설명될 다른 방법들을 옵션으로 제공합니다.)

mdd는 '\Device\PhysicalMemory' 섹션의 핸들을 커널레벨에서 얻어온 뒤, 이를 유저레벨에서 특정 메모리주소에 맵핑 후 접근하는 방식을 취하고 있습니다. win32dd는 커널레벨에서 모든 작업을 한다는 점이 다릅니다.

아래는 mdd의 커널 드라이버 소스 중 일부입니다.

UNICODE_STRING usPhysicalMemory;
OBJECT_ATTRIBUTES oa;
 
RtlInitUnicodeString( &usPhysicalMemory, L"\\Device\\PhysicalMemory"); 

InitializeObjectAttributes( &oa, &usPhysicalMemory,
        OBJ_CASE_INSENSITIVE,
        NULL, NULL );   
status = ZwOpenSection( &hPhysicalMemory, SECTION_MAP_READ, &oa );
if( !NT_SUCCESS(status) )
{
  DbgPrint("Failed to open %wZ! Status %p\n", usPhysicalMemory, status);
  hPhysicalMemory = NULL;
  goto done;
}
DbgPrint("Opened section handle %p in driver\n", hPhysicalMemory);
 
*(HANDLE*)pIrp->AssociatedIrp.SystemBuffer = hPhysicalMemory;
pIrp->IoStatus.Information = 4;
status = 0;


mdd는 위의 코드를 이용하여 물리 메모리의 핸들을 얻어온 뒤, MapViewOfFile() 함수를 이용하여 가상 주소에 맵핑하여 이를 파일에 쓰는 작업을 합니다.


2. MmGetPhysicalMemoryRanges()를 이용한 방법

다음 방법은 undocumented kernel function인 MmGetPhysicalMemoryRanges()를 이용한 방법입니다. 이 함수는 PHYSICAL_MEMORY_RANGE 구조체 배열의 시작 주소를 리턴하는데, 그 원형은 다음과 같습니다.

typedef struct _PHYSICAL_MEMORY_RANGE {
    PHYSICAL_ADDRESS BaseAddress;
    LARGE_INTEGER NumberOfBytes;
} PHYSICAL_MEMORY_RANGE, *PPHYSICAL_MEMORY_RANGE;

NTKERNELAPI
PPHYSICAL_MEMORY_RANGE
MmGetPhysicalMemoryRanges (
    VOID
    );

PHYSICAL_MEMORY_RANGE의 BaseAddress와 NumberOfBytes 필드를 MmMapIoSpace() 함수의 파라메터로 이용하여 가상 주소로  맵핑할 수 있습니다. MmMapIoSpace() 함수의 원형은 다음과 같습니다.


PVOID 
MmMapIoSpace( 
    IN PHYSICAL_ADDRESS PhysicalAddress,
    IN ULONG NumberOfBytes,
    IN MEMORY_CACHING_TYPE CacheType 
    );

유의하실 점은, PHYSICAL_MEMORY_RANGE 구조체의 마지막 노드는 BaseAddress와 NumberOfBytes 필드가 null이라는 것입니다.


3. MmMapMemoryDumpMdl()을 이용한 방법

MmMapMemoryDumpMdl() 함수는 undocumented kernel function이며 크래시 덤프를 위해 사용되는 함수입니다. win32dd가 기본적으로 이 함수를 이용하며, 그 원형은 다음과 같습니다.

typedef struct _MDL {
    struct _MDL *Next;
    CSHORT Size;
    CSHORT MdlFlags;
    struct _EPROCESS *Process;
    PVOID MappedSystemVa;
    PVOID StartVa;
    ULONG ByteCount;
    ULONG ByteOffset;
} MDL, *PMDL;

NTKERNELAPI
VOID
MmMapMemoryDumpMdl (
    __inout PMDL MemoryDumpMdl
    );

MDL 구조체는 특정 물리 메모리 주소를 서술하기 위한 구조체이며, MmMapMemoryDumpMdl()의 입출력 파라메터로 사용됩니다. 가상 주소로의 맵핑을 원하는 Page Frame Number를 MDL 구조체의 뒤의 4바이트에 넣으면, MappedSystemVa 필드에 맵핑된 주소가 리턴되어 출력됩니다. 이를 이용하여 함수를 작성해보면 다음과 같습니다.


typedef struct _MY_MDL {
 MDL Mdl;
 DWORD_PTR PageFrameNumber;
} MY_MDL, *PMY_MDL;

PVOID GetMappedAddr(
        IN ULONG PageFrameNumber
        )
{
 MY_MDL mymdl;
 mymdl.Mdl.Next = NULL;
 mymdl.Mdl.Size = 0x20; // MDL size 0x1C + 4 bytes
 mymdl.Mdl.MappedSystemVa = NULL;
 mymdl.Mdl.StartVa = NULL;
 mymdl.Mdl.ByteCount = SIZE_MEM_PAGE; // 4096 bytes
 mymdl.Mdl.ByteOffset = 0;
 mymdl.PageFrameNumber = PageFrameNumber;

 MmMapMemoryDumpMdl(&mymdl.Mdl);

 return mymdl.Mdl.MappedSystemVa;
}

입력을 위한 물리 페이지 번호의 범위는 ZwQuerySystemInformation 함수를 이용하여 구합니다. 참고로 리턴되는 주소는 항상 0xFFBF0000를 가리키며, 이는 크래시 덤프 드라이버를 위해 예약된 주소와 일치입니다.

유의해야 할 부분은, 위 주소를 ZwWriteFile 함수로 직접 접근해 파일로 출력해서는 안되며, ExAllocatePoolWithTag 등의 함수로 할당 받은 영역으로 memcpy로 복사 후 이용해야 한다는 점입니다. (직접 접근하는 순간 BSOD를...)



맺음말 : 얼마전 제가 공개한 Fastdd는 바로 MmMapMemoryDumpMdl() 함수를 이용하였습니다. 제가 테스트 해본 결과로는 지금까지 공개된 윈도우즈 물리 메모리 덤프도구 중에서는 가장 빠릅니다. 필요하신 분들의 많은 활용이 있었으면 합니다. 





오늘 새로운 도구를 소개해드립니다.
윈도우즈에서 물리 메모리를 덤프할 수 있는 'Fastdd v1.0'입니다.




win32dd를 역공학 분석하는 도중, 지금까지 외부에 알려지지 않았던 메모리 덤프 방식을 사용하는 것을 발견하여 이를 이용해 간단히 도구를 만들어 보았습니다.

자체 테스트 결과 win32dd보다 빠른 속도로 메모리를 수집할 수 있었습니다. 물리 메모리는 시간의 흐름에 따라 데이터의 변화량이 증가하기 때문에 수집 속도가 빠를 수록 메모리 분석에 유리합니다.

다운로드는 아래 링크를 참조해주세요.


<사용 방법>
"fastdd [덤프할 파일 이름]"


본 도구는 비영리적 목적에 한해 마음대로 사용하셔도 됩니다. 다만 소스코드는 제공해드리지 않습니다. 사실 별다른 기술이 들어가서 그런게 아니라.. 급하게 대충 만든거라 소스가 지저분해서요..ㅋㅋ 

x64 버젼도 개발하고 싶지만, 코드사이닝 문제로 비용이 발생하기 때문에 아마 무료로 푸는건 힘들 것 같고 내부적인 용도로만 사용할 것 같습니다. 사실 x64로 컴파일하는건 일도 아니긴 하죠. 

(수정) x64 버젼은 여기를 참조해주세요.


어찌되었든 차후에 시간이 되는대로 메모리 수집 도구들이 사용하는 방법들에 대해서 정리하여 포스팅하도록 하겠습니다. 그럼 이만.. :)

알림) fastdd32, 64의 실행파일 및 드라이버 바이너리의 디지털서명은 Four&Six Tech.의 지원을 받아 수행되었습니다. http://4n6tech.com



* 알림 : 본 포스트는 '2010 한국정보보호학회 동계학술대회'에 발표된 논문인 "A Study on Riskiness and Countermeasures of Personal Identifiable Information in Physical Memory"의 리뷰입니다.


물리 메모리에는 우리가 생각치 못한 많은 개인 정보들이 남아있습니다. 주민등록번호, 계좌번호, ID 및 패스워드 등이 그 대상입니다. 따라서 물리 메모리 포렌식의 가장 기본이 되는 분석 방법은 '문자열 검색'입니다. 너무나도 단순한 방법이고 어찌보면 수천만개씩이나 존재할지 모르는 문자열들 중에 중요한 정보를 찾는 것은 비효율적이기 때문에 old-fashioned method라고 치부될지 모르지만, 분명한 것은 어쨌든 중요한 정보가 '존재'한다는 것이고 이를 효율적으로 추출하는 것은 조사관의 몫이라는 것입니다.

이 논문은 물리 메모리 덤프에 존재하는 웹포털 사이트의 ID 및 패스워드를 추출하는 방법에 관한 논문입니다. 그 방법은 상당히 단순합니다. 물리 메모리 내에 존재하는 문자열 중 웹사이트로 전달하기 위한 POST Method와 관련한 문자열을 추출하고 이를 사이트 별 특징에 따라 정규표현식으로 ID와 패스워드를 추출하는 것입니다.

사실 누구나 생각해볼 수 있고 해외에서는 이와 같은 방식으로 웹사이트, 메신저 등의 계정 정보를 추출하는 방법에 대해 셀수 없이 논의되어 왔지만, 국내에서 자주 사용되는 웹사이트를 대상으로 하였을 때는 상당히 치명적이라는 사실이 와닿습니다.

메모리에 남아있는 모 사이트의 ID 및 패스워드
위와 같은 결과는 각 사이트들이 제공하는 보안로그인(일반적으로 1-3단계 제공)을 적용하더라도 똑같은 결과를 얻을 수 있습니다. 즉, 암호화하여 계정 정보를 전송한다고 하더라도 암호화되기 전의 데이터를 초기화 하지 않으면 메모리에 그대로 남아있게 된다는 것입니다.

물론 모든 사이트에 적용 가능한 방법은 아니며, 국내 모 포털사이트의 경우에는 보안로그인 여부와 관계없이 사용된 ID 및 패스워드를 초기화하여 관련 정보가 남지 않습니다. (하지만 불행하게도 90% 이상의 웹사이트는 위험 상태에 노출되어있습니다.)

Physical Memory Dump Explorer에 추가된 웹 패스워드 추출 기능

위 그림은 제가 만든 분석 도구인 Physical Memory Dump Explorer(a.k.a MEMA)에 새롭게 추가된 기능입니다. 실제 기능을 위한 모듈은 논문의 저자로부터 받아서 해결하였습니다. 결과를 통해 알 수 있듯이 상당히 많은 웹사이트들이 그 대상이 됨을 알 수 있습니다. 

간단히 논문 및 결과를 살펴보았습니다만, 모두가 메모리에 중요 정보가 남는다는 사실을 알면서도 "설마 누군가 들여다보겠어?"라는 생각으로 공용PC에서의 사용을 쉽게 생각하고 있는 것 같습니다. 참고로 실제 공용PC에서 메모리 덤프를 하여 프로그램을 돌려본 결과..... 역시 공용PC의 사용은 조심하시는게 좋겠습니다.