Process Listing
Handle?
- 자원에 대한 '추상적인' 참조
- 어플리케이션이 다른 시스템에서 관리되는 메모리 블록이나 객체를 참조할 때 사용
- 파일 디스크립터, 파이프, 소켓, DB 연결 소켓, PID 등등
Objcet Handle
- 커널 오브젝트에 접근하기 위해 만들어진 핸들
- 커널 리소스에 직접 접근하는 대신, 핸들을 통해 간접적으로 참조할 수 있음.
- 커널 오브젝트가 생성되면 생성된 오브젝트를 가리키기 위해 오브젝트 핸들이 반환됨.
- 프로세스가 초기화 되었을 때 각 프로세스별로 사용할 수 있는 오브젝트 핸들 테이블이 할당되어 테이블의 형태로 오브젝트 핸들을 관리.
- 프로세스마다 독립적으로 관리됨.
Kernel Object Handle Table
- 커널 오브젝트의 핸들 정보를 저장하는 테이블
- 핸들을 통해 커널 오브젝트를 찾아갈 수 있게 정보를 저장함.
- 부모-자식 프로세스의 경우 상속도 됨
- EPROCESS 구조 내 ObjectTable 필드가 HANDLE_TABLE 구조로 이루어져 있음.
//Windows 10 | 2016 2104 21H1 (May 2021 Update) x64
struct _HANDLE_TABLE
{
ULONG NextHandleNeedingPool; //0x0
LONG ExtraInfoPages; //0x4
volatile ULONGLONG TableCode; //0x8
struct _EPROCESS* QuotaProcess; //0x10
struct _LIST_ENTRY HandleTableList; //0x18
ULONG UniqueProcessId; //0x28
union
{
ULONG Flags; //0x2c
struct
{
UCHAR StrictFIFO:1; //0x2c
UCHAR EnableHandleExceptions:1; //0x2c
UCHAR Rundown:1; //0x2c
UCHAR Duplicated:1; //0x2c
UCHAR RaiseUMExceptionOnInvalidHandleClose:1; //0x2c
};
};
struct _EX_PUSH_LOCK HandleContentionEvent; //0x30
struct _EX_PUSH_LOCK HandleTableLock; //0x38
union
{
struct _HANDLE_TABLE_FREE_LIST FreeLists[1]; //0x40
struct
{
UCHAR ActualEntry[32]; //0x40
struct _HANDLE_TRACE_DEBUG_INFO* DebugInfo; //0x60
};
};
};
PspCidTable
- 모든 프로세스와 스레드의 CID를 관리하는 핸들 테이블
- 현재 시스템의 모든 프로세스와 스레드의 cid 관련된 정보가 들어있다
- PspReferenceCidTableEntry 함수 내부에서 PspCidTable 참조해 오는 것 확인됨.
-
PspReferenceCidTableEntry+16 48 83 EC 40 sub rsp, 40h PspReferenceCidTableEntry+1a 48 8B 05 9F 60 69 00 mov rax, cs:PspCidTable PspReferenceCidTableEntry+21 0F B6 EA movzx ebp, dl
- PspReferenceCidTableEntry+1a 에서 오프셋이 나온다.
- RIP+OFFSET 으로 값을 찾아올 위치의 주소값이 정해지므로, (PspReferenceCidTableEntry+21) + 0x69609f 의 결과가 ****커널 메모리상 PspCidTable의 실제 주소값이 된다.
- 즉, +0x1d 위치에서 4바이트를 가져와 오프셋을 구한 다음 PspReferenceCidTableEntry+21 에 더하면 된다.
-
//WINDBG nt!PspReferenceCidTableEntry+0x1a: fffff805`5f06652a 488b059f606900 mov rax,qword ptr [nt!PspCidTable (fffff805`5f6fc5d0)] fffff805`5f066531 0fb6ea movzx ebp,dl
-
- 주소값은 이렇게 가져오는데, 그럼 이제 프로세스나 다른 핸들의 정보는 어떻게 뽑아내면 될까? Win7 용으로 만들어진 코드를 찾아 분석해본다.
- PspCidTable을 찾아오는 함수.
-
RtlInitUnicodeString(&sysRoutineName, L"PsLookupProcessByProcessId"); PUCHAR pFun = (PUCHAR)MmGetSystemRoutineAddress(&sysRoutineName); if (pFun) { do { if(!MmIsAddressValid(pFun) || !MmIsAddressValid((PUCHAR)pFun + 6)) { return NULL; } if (*(PSHORT)pFun == 0X3D8B && *((PUCHAR)pFun + 6) == 0Xe8) { unsigned int pspCidTable = *((unsigned int *)((PUCHAR)pFun + 2)); DbgPrint("%x", pspCidTable); return (void*)pspCidTable; //break; }
- PsLookupProcessByProcessId() 함수의 바이트코드에서 PspCidTable을 찾아오는걸로 보이는데, Windows7 시절에는 함수 내부에 주소값이 바로 박혀져 있었기 때문.
- Windows8 이후부터는 PspReferenceCidTableEntry() 에서 반환받아 사용하므로, PspReferenceCidTableEntry()의 바이트코드에서 PspCidTable을 찾아오면 될듯.
-
- TableCode의 레이어 레벨 분리
-
PHANDLE_TABLE pspCidTable = *pPspCidTable; ULONG level = pspCidTable->TableCode & 3; //Take 2 digits, draw the number of sentenced stem. PUCHAR tableBase = (PUCHAR)pspCidTable->TableCode - level; switch(level) { case 0: { EnumLevel1Tabel((PUCHAR)tableBase); } break; case 1: { EnumLevel2Tabel((PULONG)tableBase); } break; case 2: { EnumLevel3Tabel((PULONG)tableBase); } }
- PspCidTable의 HANDLE_TABLE구조는 TableCode를 가지고 있는데, 여기서 레이어 레벨을 분리해낸다.
- TableCode&3 을 연산하여 레이어 레벨을 얻어내고, 얻어낸 값만큼 빼면 table base가 나온다. 이 tablebase를 인자로 레이어에 따라 다른 함수를 돌리게 된다.
- 0 : Layer Level1, 1: Level2, 2:Level3
-
- Level1의 경우
-
void EnumLevel1Tabel(PUCHAR pLevel1Table) { DbgPrint("Table1:%x\n", pLevel1Table); PHANDLE_TABLE_ENTRY phte = (PHANDLE_TABLE_ENTRY)pLevel1Table; for (ULONG i = 0; i < 512; i++) //512 is the number of items, units: handle_table_entry { PEPROCESS pProcess = (PEPROCESS)phte->Object; POBJECT_TYPE objType; objType = *PsProcessType; pProcess = (PEPROCESS)((ULONG)pProcess & 0xfffffff8); //I don't know what to do. if (pProcess != NULL && objType == ObGetObjectType(pProcess)) { DbgPrint("Process Name:%s\n", (PUCHAR)pProcess + 0x16c); } phte++; } }
- 인자로 넘긴 주소값은 _HANDLE_TABLE_ENTRY 구조체의 주소값이 된다.
- Windows7 때는 Object 멤버를 참조하여 AND 연산을 진행 , PEPROCESS 구조체 주소값을 뽑아낼 수 있었다.
- Windows8 이후부터는 구조체 형태가 바뀌어 새로 분석이 필요함. 이는 후술
- _HANDLE_TABLE_ENTRY 구조체의 포인터가 연달아 붙어있는 형태이기 때문에 ++ 연산을 진행해 다음 주소값으로 넘어가 연속적으로 구조체를 참조할 수 있어 전체 프로세스의 탐색이 가능하다.
-
- level2, 3의 경우
-
void EnumLevel2Tabel(PULONG pLevel2Table) { DbgPrint("EnumLevel2Tabel:%x\n", pLevel2Table); for (ULONG i = 0; i < 1024; i++) //1024 is the number of secondary tablets, unit: Phandle_Table_ENTRY { if (*pLevel2Table != 0) { EnumLevel1Tabel((PUCHAR)*pLevel2Table); } else { break; } pLevel2Table++; } } void EnumLevel3Tabel(PULONG pLevel3Table) { DbgPrint("EnumLevel3Tabel:%x\n", pLevel3Table); for (ULONG i = 0; i < 32; i++) //32 is the number of three-level entry, unit: Phandle_Table_ENTRY * { if (*pLevel3Table != 0) { EnumLevel2Tabel((PULONG)*pLevel3Table); } else { break; } pLevel3Table++; } }
- level 2와 3의 경우 포인터를 따라가면 또 다른 테이블의 포인터가 있는 식으로 구성된다.
- 따라서 단순히 포인터를 참조하고 하위 레이어의 동작을 수행하면 되는 단순한 동작.
- 마찬가지로 포인터가 연달아 존재하므로 ++연산으로 다음번 포인터를 참조할 수 있음.
-
- win7 기준 코드이기때문에 , 해당 프로세스를 참고만 하고 구조는 다시 분석해서 적용이 필요할듯.
- PspCidTable을 찾아오는 함수.
PspCidTable의 Table Base 연산
- 이전에 찾은 구조는 Windows7 기준이기 때문에 지금과는 좀 차이점이 있다.
- 일단 PspCidTable 를 찾아오는 과정부터 다름
- win7 : PsLookupProcessByProcessId()
- win8이후 : PsLookupProcessByProcessId() → PspReferenceCidTableEntry()
- _HANDLE_TABLE_ENTRY 구조체가 다름
- TableCode 멤버에서 레이어를 분리하고 포인터를 연산하는 방식이 다름
- 따라서 새로 분석을 진행하여 현재 환경에 맞게 재구성이 필요함.
- 일단 PspCidTable 를 찾아오는 과정부터 다름
- 공통적으로, PspCidTable의 하위 2바이트에서 Layer Level을 찾아내는 과정이 있다.
- 00,01,11 일때 각각 레이어 레벨 1,2,3이 된다.
- 하위 2바이트는 이를 위한 비트이므로 레이어를 찾은 다음 제외한다.
- PspReferenceCidTableEntry() 함수 내에 PspCidTable을 연산하는 루틴이 들어있다.
-
mov rdi, [rsi] sar rdi, 10h and rdi, 0FFFFFFFFFFFFFFF0h
- 0x10 바이트만큼 sar 연산 진행 후 0xFFFFFFFFFFFFFFF0과 AND 연산 진행
- 오른쪽 산술 시프트 연산이기 때문에 , 새로 만들어지는 상위 비트들이 1로 채워진다.
- 즉, 상위 4바이트를 F로 채우고 하위 4바이트는 버리는 것.
-
원리 - 디버깅
- PspCidTable 로 부터 EPROCESS와 PID를 찾는 ****과정을 디버거에서 수동으로 따라가보자.
1. PspCidTable
1: kd> dq PspCidTable
fffff805`5f6fc5d0 ffff8a00`98664dc0 ffff9b8f`95cf5980
fffff805`5f6fc5e0 00000000`00000000 00010000`00000000
fffff805`5f6fc5f0 00000000`00001000 00000000`00000000
fffff805`5f6fc600 00000000`00000000 00009e09`00000000
fffff805`5f6fc610 00000000`00000000 00000000`00000000
fffff805`5f6fc620 00000000`00000000 00000000`00000000
fffff805`5f6fc630 0000002e`00000000 00000000`00000000
fffff805`5f6fc640 ffff9b8f`95cfe4e0 fffff805`5fa46000
- PspCidTable 심볼이 있는 fffff805`5f6fc5d0 주소를 참조하면 테이블이 나오는데, 나오는 주소인 ffff8a00`98664dc0
1: kd> dt_HANDLE_TABLE ffff8a00`98664dc0
nt!_HANDLE_TABLE
+0x000 NextHandleNeedingPool : 0x2000
+0x004 ExtraInfoPages : 0n0
+0x008 TableCode : 0xffff8a00`9c6bc001
+0x010 QuotaProcess : (null)
+0x018 HandleTableList : _LIST_ENTRY [ 0xffff8a00`98664dd8 - 0xffff8a00`98664dd8 ]
- ffff8a00`98664dc0 을 HANDLE_TABLE 구조로 정렬해보면 +0x8 위치의 TableCode 멤버를 찾을 수 있다.
- 0xffff8a00`9c6bc001 의 마지막 2바이트는 1이므로, 2단계 레이어라고 볼 수 있다.
- 0xffff8a00`9c6bc000 주소를 찾아가면 2단계 레이어 테이블을 찾을 수 있다.
1: kd> dq 0xffff8a00`9c6bc000
ffff8a00`9c6bc000 **ffff8a00`986b2000** ffff8a00`9c6bd000
ffff8a00`9c6bc010 ffff8a00`9ce55000 ffff8a00`9d6ac000
ffff8a00`9c6bc020 ffff8a00`9dbfe000 ffff8a00`9e9fb000
ffff8a00`9c6bc030 ffff8a00`9f1ff000 ffff8a00`a017c000
ffff8a00`9c6bc040 00000000`00000000 00000000`00000000
2. 레이어 테이블
- 2단계와 3단계 레이어 테이블은 다음 단계 레이어 테이블의 주소를 담고 있다. 위 테이블의 경우 8개의 1단계 레이어 테이블 주소를 가지고 있는 셈.
- x64기반 시스템에서 각 레이어 테이블의 크기는 0x1000(4096)bytes 이고, 1단계 테이블은 16바이트씩의 _HANDLE_TABLE_ENTRY 구조를 가진다 ****
- 이 부분 정확하게 추가적인 분석이 필요함
- 0xffff8a00`986b2000 주소를 찾아가면 1단계 레이어 테이블을 찾을 수 있다.
1: kd> dq ffff8a00`986b2000
ffff8a00`986b2000 00000000`00000000 00000000`00000000
ffff8a00`986b2010 **9b8f95c9`0040fdfd** 00000000`00000000
ffff8a00`986b2020 9b8f999b`e0800001 00000000`00000000
ffff8a00`986b2030 9b8f95cc`d080fff5 00000000`00000000
ffff8a00`986b2040 9b8f95d5`7080fff5 00000000`00000000
ffff8a00`986b2050 9b8f95d2`4080fff5 00000000`00000000
ffff8a00`986b2060 9b8f95d9`b080fff5 00000000`00000000
ffff8a00`986b2070 9b8f95c8`4580fff5 00000000`00000000
3. 주소값 연산
- 1단계 레이어 테이블은 프로세스 혹은 PID에 따라 인덱싱되는데, 각 데이터는 EPROCESS 혹은 ETHREAD 구조체의 주소값이 연산 과정을 거친것이다.
- (data >> 10) & 0xFFFFFFFFFFFFFFF0 연산을 거친 결과가 최종 주소값이 된다.
- 레이어 테이블의 각 데이터에는 규칙이 있는데, PID 와 TID에 따라 레이어 테이블 순서와 행 순서가 결정된다 .
- ( 2단계 레이어테이블 순서 * 0x400 ) + (1단계 레이어 테이블 행 순서 * 0x4 )
- 9b8f95c9`0040fdfd → 1번째 레이어 테이블, 1번째 행 → PID : 4
1: kd> dt_EPROCESS FFFF9B8F95C90040 UniqueProcessId nt!_EPROCESS +0x440 UniqueProcessId : 0x00000000`00000004 Void
- 9b8f999b`e0800001 → 1번째 레이어 테이블, 2번째 행 → TID : 8
1: kd> dt_ETHREAD FFFF9B8F999BE080 Cid.UniqueThread nt!_ETHREAD +0x478 Cid : +0x008 UniqueThread : 0x00000000`0000000**8** Void
- 9b8f991b`3300ffe3 → 2번째 레이어 테이블, 1번째 행 → TID : 404
1: kd> dt_ETHREAD FFFF9B8F991B3300 Cid.UniqueThread nt!_ETHREAD +0x478 Cid : +0x008 UniqueThread : 0x00000000`00000**404** Void
- 9b8f97ea`4080fffb → 3번째 레이어 테이블, 1번째 행 → TID : 804
1: kd> dt_ETHREAD FFFF9B8F97EA4080 Cid.UniqueThread nt!_ETHREAD +0x478 Cid : +0x008 UniqueThread : 0x00000000`00000**804** Void
- PID가 92(0x5c)인 Registry 프로세스 → 1번째 레이어 테이블, 17번째 행
1: kd> dq ffff8a00`986b2180 ffff8a00`986b2180 9b8f95db`d0800001 00000000`00000000 ffff8a00`986b2190 **9b8f95dc`e080fff5** 00000000`00000000 ffff8a00`986b21a0 9b8f95cd`7080fff5 00000000`00000000
1: kd> dt_EPROCESS FFFF9B8F95DAC080 UniqueProcessId nt!_EPROCESS +0x440 UniqueProcessId : 0x00000000`000000**5c** Void
- 따라서, 레이어 테이블 전체를 순회하면 모든 프로세스와 모든 쓰레드의 정보를 받아올 수 있다.
- 연산을 거친 주소값이 EPROCESS 구조체인지, ETHREAD 구조체인지만 판정할 수 있으면 된다.
- 주소에 접근하지 않아도, 인덱스 번호를 통해 해당 주소가 가리킬 PID 혹은 TID를 미리 알 수 있다.
- 따라서 , PID 를 통해 프로세스 정보를 가져오는 함수를 사용하면 연산을 거쳐 원래 주소에 접근할 필요 없이 프로세스를 가져올 수'는' 있다.
- 지금은 실습을 위해 연산을 통해 EPROCESS 주소를 가져와 데이터를 뽑아내는걸로 한다.
- PsLookupProcessByProcessId() 함수의 동작과 유사하다.
- PspReferenceCidTableEntry() 함수를 실행해 PspCidTable 에 접근한다.
- 이후 전달받은 PID에 맞는 순서에 위치한 데이터를 가져오는것으로 보인다.
- 이 경우 PspCidTable를 직접 참조하기 때문에 Link등의 변조에 영향을 받지 않아 DKOM등의 ProcessHide에 무관하게 프로세스를 찾아올 수 있게된다.
구상
- PspReferenceCidTableEntry() 함수의 바이트 코드로부터 PspCidTable 가져옴
- MmGetSystemRoutineAddress() 함수 이용해 실제 주소 가져오기
- 함수 시작주소 +0x1d 위치에서 4바이트 오프셋 가져옴
- 함수 시작주소 + 21 + 오프셋 = PspCidTable 주소
- PspCidTable 포인터 참조하여 테이블에 접근
- 포인터 따라간 다음 0x3과 비트연산, 레이어 테이블 단계 찾기
- 레이어 테이블 단계에 따라 다른 동작 실행
- 레이어 테이블에서 EPROCESS 값 디코딩
- (data >> 0x10) & 0xFFFFFFFFFFFFFFF0
- EPROCESS + 0x440에 PID 존재
- EPROCESS or ETHREAD
- ETHREAD인 경우 해당 값이 0xFFFFFFFC 이상임.
- EPROCESS→PID 와 EPROCESS→ImageFileName 찾아 출력.
실습
- PspCidTable의 실제 주소 구하는 코드 작성
- MmGetSystemRoutineAddress 함수에서 PspReferenceCidTableEntry 직접 참조 불가.
-
PsLookupProcessByProcessId+24 E8 77 01 00 00 call PspReferenceCidTableEntry PsLookupProcessByProcessId+29 48 8B D8 mov rbx, rax
- 따라서 PsLookupProcessByProcessId먼저 찾아간 다음 바이트코드에서 오프셋 가져와 PsLookupProcessByProcessId+29 과 연산해야함.
- PsLookupProcessByProcessId+25 에서 4바이트 만큼이 오프셋
//PspReferenceCidTableEntry 찾기위해 바이트코드에서 상대주소 오프셋 찾아옴. tmpAddr = (PVOID*)((ULONGLONG)PsLookupProcessByProcessId + 0x25); FuncOffset = (int)*tmpAddr; //PspReferenceCidTableEntry 주소 연산 PspReferenceCidTableEntry = (PVOID)((ULONGLONG)PsLookupProcessByProcessId + 0x29 + FuncOffset);
**** PsLookupProcessByProcessId : FFFFF80649466370 **** **** Offset addr : FFFFF80649466395 **** **** PspReferenceCidTableEntry addr : FFFFF80649466510 **** **** offset : 0000000000000177 **** //WinDBG 6: kd> x nt!PsLookupProcessByProcessId fffff806`49466370 nt!PsLookupProcessByProcessId (void) 6: kd> dw FFFFF80649466395 fffff806`49466395 0177 0000 6: kd> x nt!PspReferenceCidTableEntry fffff806`49466510 nt!PspReferenceCidTableEntry (void)
- 주소값들 제대로 가져옴
- PspReferenceCidTableEntry 함수 바이트코드에서 PspCidTable 오프셋 가져오기
- PspReferenceCidTableEntry+1d 에서 4바이트 가져옴
- PspReferenceCidTableEntry+21 과 오프셋 연산 ****
//PspCidTable 상대주소 오프셋 찾아옴 tmpAddr = (PVOID*)((ULONGLONG)PspReferenceCidTableEntry + 0x1d); FuncOffset = (int)*tmpAddr; PspCidTableOffset = (ULONGLONG) ((ULONGLONG)PspReferenceCidTableEntry + 0x21 + FuncOffset); DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "**** PspCidTable: %llx **** \\n", PspCidTableOffset);
**** PspCidTable: fffff80649afc5d0 **** ///Windbg 3: kd> dq !PspCidTable fffff806`49afc5d0 ffffba02`61a805c0 ffffa901`e1cfde80
- 주소값 제대로 가져옴
- PspCidTable 참조하여 EPROCESS 주소 가져오기
- PspCidTable 포인터 + 8 위치에 TableCode위치함.
TableCode = (PVOID*)((ULONGLONG)(*PspCidTable) + 0x8); DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "**** TableCode: %p **** \\n", TableCode);
**** TableCode: FFFFBA0261A805C8 **** //WinDBG 0: kd> dq FFFFBA0261A805C8 ffffba02`61a805c8 ffffba02`656fb001
- TableCode 연산하여 테이블레이어 단계 구분
-
//TableCode에서 LayerLevel 분리 LayerLevel = (ULONGLONG)(*TableCode) & 3; TableAddr = (PVOID*)( (ULONGLONG)(*TableCode) - LayerLevel); DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "**** TableAddr: %p **** \\n", TableAddr);
**** TableAddr: FFFFBA02656FB000 ****
- 테이블 레이어 2단계→ 1단계순으로 타고 내려가야함
- 레이어 단계별로 다르게 동작하는 함수 구성
- 2,3단계 함수는 반복문 돌면서 하위단계로 넘겨주는 역할
- 데이터가 테이블에 연속적으로 존재하니, 유효한 주소를 가져오지 못하는 시점에서 반복문이 중단되면 될듯.
- 1단계 함수는 반복문 돌면서 테이블 데이터 읽어와서 EPROCESS 출력
- 1단계 테이블 하나에 들어갈 수 있는 PID/TID 의 최대 수치는 0x400
- 따라서, 0x100행→256행까지만 들어갈 수 있으므로 최대 256회만 반복 돌면 됨.
- 1단계 함수 돌면서 찾아온 데이터 디코딩해서 EPROCESS 주소 찾아오기
-
retResult = (PVOID)( ( (ULONGLONG)((ULONGLONG)*EncodeAddr >> 0x10 ) + 0xFFFF000000000000 ) & 0xFFFFFFFFFFFFFFF0);
-
**** Target addr : ffffba0261ab2010 **** **** Target val : a901e1c62080fb91 **** ---- DECODE : ffffa901e1c62080 ----
- 읽어온 주소의 UniqueProcessId(0x440) 멤버 참조하여 0xFFFFFFFC 보다 작으면 EPROCESS로 판정
if(*TargetAddress){ TargetProcess = DecodeTableData(TargetAddress); PID = (ULONGLONG) * ((PVOID*)((ULONGLONG)TargetProcess + 0x440)); if(PID < 0xFFFFFFFC) DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "**** Target PID : %llx **** \\n",PID); }
**** Target PID : 4 ****
- PsGetProcessId 함수를 이용하는 경우, HANDLE 타입이기 때문에 4바이트값 밖에 가져오지 못함. 0xE0000000 이상 반환되는 경우로 필터링 조건 변경.
**** PID : 4 **** **** PID : e1d57a38 **** **** PID : e1d8a4b8 **** **** PID : e1cd74b8 ****
PID = PsGetProcessId(TargetProcess); DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "**** PID : %lx **** \\n", PID); if ((ULONG)PID < 0xE0000000) { ~~~
- PspCidTable 포인터 + 8 위치에 TableCode위치함.
- 찾은 EPROCESS 구조체의 PID와 ImageFileName 가져와 출력
-
if (PID < 0xFFFFFFFC) { PName = (UCHAR*)((ULONGLONG)TargetProcess + 0x5a8); DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "**** PNAME : %s PID : %llx **** \\n", PName,PID); }
**** PNAME : System PID : 4 ****
- PsGetProcessImageFileName() 함수 이용하는 방법
//PsGetProcessImageFileName 함수 원형 선언 typedef UCHAR*(*NTAPI PsGetProcessImageFileName_t)( PEPROCESS Process ); PsGetProcessImageFileName_t(PsGetProcessImageFileName) = nullptr; ~~~~ if ((ULONG)PID < 0xE0000000) { PName = PsGetProcessImageFileName(TargetProcess); DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "**** PNAME : %s PID : %llx **** \\n", PName, PID); }
-
- 전체 프로세스 목록 출력
-
**** PNAME : System PID : 4 **** **** PNAME : Registry PID : 8c **** **** PNAME : svchost.exe PID : 194 **** **** PNAME : smss.exe PID : 1b8 **** **** PNAME : dwm.exe PID : 1e4 **** **** PNAME : svchost.exe PID : 208 **** ~~~~~~~~ **** PNAME : svchost.exe PID : 2378 **** **** PNAME : msedge.exe PID : 239c **** **** PNAME : svchost.exe PID : 242c **** **** PNAME : dllhost.exe PID : 24f4 **** **** PNAME : cmd.exe PID : 272c **** **** PNAME : conhost.exe PID : 2734 **** **** PNAME : ShellExperienc PID : 2790 **** **** PNAME : RuntimeBroker. PID : 27e0 ****
-
- 1860(0x744) 프로세스 숨긴 후 전체 프로세스 목록 출력
-
**** PNAME : svchost.exe PID : 68c **** **** PNAME : svchost.exe PID : 6c8 **** **** PNAME : notepad.exe PID : 744 **** **** PNAME : svchost.exe PID : 750 **** **** PNAME : svchost.exe PID : 76c ****
- 잘 나오는것 확인됨
구현 완료
추가로 해 볼것
- NtQuerySystemInformation의 handle(0x40) 반환값 이용해 동일 기능 구현
GITHUB
https://github.com/synod2/Kernel_Hooking/tree/main/Window Device Driver/MyDriver6
참고 문서
https://shhoya.github.io/windows_hwndobject.html
https://ko.wikipedia.org/wiki/핸들_(컴퓨팅)
https://docs.microsoft.com/ko-kr/windows/win32/sysinfo/handles-and-objects - MSDN 핸들
https://wonjayk.tistory.com/270 - window handle object
http://egloos.zum.com/sweeper/v/2814944
https://titanwolf.org/Network/Articles/Article?AID=d8c016a4-1610-46c5-a751-deb46dd7a97a
http://pds8.egloos.com/pds/200805/13/51/about_windows_handle.pdf - PspCidTable
https://driverentry.tistory.com/entry/PspCidTable-HANDLETABLEENTRY-ObjectPointerBits - PspCidTable
http://egloos.zum.com/nerd/v/2592677 - PspCidTable
https://blog.pages.kr/587 - PspCidTable
http://www.vijaymukhi.com/seccourse/june2606/pspctbl.htm - PspCidTable
https://www.programmerall.com/article/69211807726/ - PspCidTable
https://www.unknowncheats.me/forum/3021549-post36.html - PspCidTable
https://www.codenong.com/cs106975071/- PspCidTable TableCode 연산루틴
https://www.freesion.com/article/7384815990/- PspCidTable TableCode 연산루틴