IDA로 분석 후 올리로 확인하면 되지만 너무 귀찮고 매번 쫏아가서 확인하기도 귀찮고...해서 열심히 찾아봤지만
API가 아닌 사용자 정의 함수(USER Function)에 대한 모니터링 도구가 없었다.
그래서 하나 만들어 써야겠다는 생각에 만들었는데 제법(?) 쓸만하다.. ㅋㅋㅋ
만든 도구인데...
간단히 설명하면...
1. 분석하고자 하는 대상 프로세스를 선택 후
2. 내부에서 사용하는 DLL 리스트를 확인. 이 후 분석하고자 하는 DLL를 선택하면, 내부 im/export 함수 목록과 기본 정보가 출력하며, 등록되지 않은 다른 함수들도 출력(내부에서 사용자가 구현한, 또는 im/export 되지 않은 함수들)
3. 원하는 대상을 클릭 시 해당 함수 내부에서 호출 또는 점프하는 주소를 출력
4. 주소값 확인 후 모니터링 대상에 추가 후 모니터링 ( 모니터링 주소값은 임의로 추가 가능)
아직 버그가 몇개 남아있어서 수정중이긴 하지만 지금도 나름 쓸만해보인다...극히 개인적인 생각.. ㅋㅋ
API와 같은 함수들은 파라미터들을 확인하고 원하는 값을 뽑는게 가능하지만, 사용자 정의 함수는 파라미터이 몇개인지 알 도리가 없으므로(물론 IDA와 같은 좋은 도구들은 어떻게 찾는지 모르지만, 뽑아줌...하지만 난 모름..ㅋ) 파라미터 3개까지만 각 자료형별로 출력하도록 했다.
어차피 이건 Memget Project에 포함되있는 기능이고, 해당 파라미터가 만약 포인터 또는 구조체일 경우 주소를 덤프떠보면 뭐가 나오지 않을까? ...
분석은 vm상의 가상 머신과 로컬머신 두대로 하였으며 윈도우 커널 디버깅을 위해 windbg를 사용했음.
커널모드에는 여러 가지로 구성된다. 그중 눈에 띄는것은 Graphic처리에 관련된 GDI와 win32k.sys 파일이다. 문제는 GDI가 커널 내부로 들어온것인다. 이것은 좋을수도 있고 나쁠수도있다. 물론 안정성 측면의 문제도 집고 넘어가야 하지만 몇가지 의구심이 들수도있다. 이것을 만든 제작자는 안정성에 확신이있어서 GDI를 커널내부로 넣었다고한다. 하지만 종종 win32k.sys의 leak로 인한 블루스크린을 볼수있다.
예전에 Windows GDI Local Privilege Escalation(11/06/2006) 에 GDI문제점으로 야기된바 있다. 하지만 더 중요한건 패치가 늦다는것이다. 패치날짜가 4/3/2007 일으로써 거의 근 5개월만에 패치가 되었다. 이것은 win32k.sys파일안에 취약점이 존재하는데 이를 보면 gpHmgrSharedHandleSection은 GDI 오브젝트 핸들 안에있는 10바이트의 테이블이다. 이것은 다음의 형식을 가지고있다.
+00h PTR GDI object data (kernel data) pointer
+04h WORD Process ID
+06h WORD some flags
+08h WORD high word of GDI handle
+0Ah BYTE type
01h = DC 0Ah = Font
02h = Surface? 0Ch = Font Chunk?
03h = 3D Surface? 0Eh = Color Transform Object
04h = Region 10h = Brush
05h = Bitmap 15h = Metafile?
06h = Client Object? 16h = EnumFontStyle?
07h = Path 1Ch = Driver Object
08h = Palette 1Eh = Spool Object
09h = Color Space
+0Bh BYTE more flags
+0Ch PTR user data pointer
악의가 있는 사용자는 GDI 오브젝트를 새로 만들수있다. 이것은 핸들과 관련된 핵심 데이터 지시자를 수정할 수 있고 이것을 win32k.sys에 적용하기위해 그 오브젝트를 사용한다.
예를 들면 새로운 부분을 만들 수 있고, 핸들 테이블 엔트리를 수정하고, display context에 영역을 더하면서 사용자는 win32k.sys의 커널 매모리를 원하는 위치로 복사할수있다.
그러면 코드를가지고 취약성을 확인해보도록해보겠다.
GDI Kernel structure vulnerability의 취약점으로 GDITableEntry의 구조체는 다음과 같다
typedef struct
{
DWORD pKernelInfo;
WORD ProcessID;
WORD _nCount;
WORD nUpper;
WORD nType;
DWORD pUserInfo;
} GDITableEntry;
위에 상세 정의보다는 추상적이지만 실제로 이 구조체를 사용하여 값을 수정하고 오류를 발생시킬수가있다. 이 취약점의 전체적인 내용은 윈도우를 생성시킨후 그 윈도우의 열려진 객체에 접근하여 시작위치를 가져오게된다. 그리고 Ntdll.dll를 로드한후 핸들 DLL모듈과 함수를가지고 그에대한 프로시져 주소를 가져오고 그 주소에 미리지정한 구조체형식으로 세션의 정보를가져온다. 이 정보는 위에 구조체로 정의한 GDITableEntry의 정보도 포함되어있으며 이 정보에 악의적인 코드를 삽입함으로써 실행시 치명적인 오류를 발생하게된다.
즉 간단히 말하면 이 취약점은 잘못된 세션이 hMapFile 맵상의 초기값을 바꾸기를 시도함으로써 BSOD(Blue Screen of Death)가 발생한다.
0x2에 의한 win32k의 SSDT의 API's입장을 바꿔 부름으로써 현재의 프로세스의 GDITable를 수정할수있다. 0x2에서 메모리를 NtAllocateVirtualMemory와 함께 할당하고 새로만든 패이로드를 할당할수있다.
lkd> dps bf998300 L 2.
bf998300 bf934921 win32k!NtGdiAbortDoc.
bf998304 bf94648d win32k!NtGdiAbortPath.
after :
lkd> dps bf998300 L 2.
bf998300 00000002.
bf998304 bf94648d win32k!NtGdiAbortPath.
공격코드의 실행전과 실행후의 모습을 보여주고있다.
이 코드의 동작과정을 보면 프로세스에 원격 메모리 핸들링을 할당하고 이 프로세스 핸들의 주소에 쉘 코드를 올리게 된다. 그리고 win32k imagebase와 SSDT사이에 올리게된다.
이에 대한 주소는 다음과 같다.
bf998300 bf934921 win32k!NtGdiAbortDoc
그리고 GDITableEntry 내에 있는 브러쉬를 새로 생성한다. 그리고 위의 취약점과 동일하게 이에대한 주소를 가져오고 process id 값을 얻어온다. 그리고 현재 동작중인 GDI Process의 GDITable를 저장하고 새로이 생성한 것으로 바꾸게된다. 공격이 완료되면 현재 브러쉬를 지우고 이전의 것으로 돌리게된다.
위의 정보를 보면 a0002b44여기서 잘못된 접근이 일어난것을 알수있다. 첫 번째 취약점과는 달리 00000000으로 채우고있다. 이것은 Microsoft 보안 공지 MS07-017-GDI의 취약점으로 인한 원격 코드 실행 문제점 (925902)으로도 문제가되었다. 이 취약점은 windows xp,2000,2003,vista에 이르기까지 windows의 전체적으로 피해를 입을수있다.