SMALL
이것저것 구조체 필요한 부분만 알맞게 정의해서 vad 파싱해서 이름 가져왔다.
#pragma once extern "C"{ #include "ntddk.h" } // 타입 정의////////////// typedef unsigned long DWORD; typedef DWORD *PDWORD; typedef unsigned char BYTE; typedef BYTE *PBYTE; typedef unsigned short WORD; typedef unsigned long ULONG; //////////////////////////// typedef struct _SUBSECTION // 0x20 { struct _CONTROL_AREA* ControlArea; // +0x0(0x4) struct _MMPTE* SubsectionBase; // +0x4(0x4) struct _SUBSECTION* NextSubsection; // +0x8(0x4) ULONG PtesInSubsection; // +0xc(0x4) ULONG UnusedPtes; // +0x10(0x4) struct _MM_AVL_TABLE* GlobalPerSessionHead; // +0x10(0x4) ULONG u; // +0x14(0x4) ULONG StartingSector; // +0x18(0x4) ULONG NumberOfFullSectors; // +0x1c(0x4) } SUBSECTION, *PSUBSECTION; #pragma pack(push,1) typedef struct _EX_FAST_REF { union { PVOID Object; ULONG_PTR RefCnt : 3; ULONG_PTR Value; }; } EX_FAST_REF, *PEX_FAST_REF; #pragma pack(pop) typedef struct _CONTROL_AREA // 0x50 { struct _SEGMENT* Segment; // +0x0(0x4) struct _LIST_ENTRY DereferenceList; // +0x4(0x8) ULONG NumberOfSectionReferences; // +0xc(0x4) ULONG NumberOfPfnReferences; // +0x10(0x4) ULONG NumberOfMappedViews; // +0x14(0x4) ULONG NumberOfUserReferences; // +0x18(0x4) ULONG u; // +0x1c(0x4) ULONG FlushInProgressCount; // +0x20(0x4) struct _EX_FAST_REF FilePointer; // +0x24(0x4) }CONTROL_AREA, *PCONTROL_AREA; typedef struct _SEGMENT // 0x38 { struct _CONTROL_AREA* ControlArea; // +0x0(0x4) ULONG TotalNumberOfPtes; // +0x4(0x4) ULONG SegmentFlags; // +0x8(0x4) ULONG NumberOfCommittedPages; // +0xc(0x4) ULONGLONG SizeOfSegment; // +0x10(0x8) union { struct _MMEXTEND_INFO* ExtendInfo; // +0x18(0x4) void* BasedAddress; // +0x18(0x4) }; UINT32 SegmentLock; // +0x1c(0x4) ULONG u1; // +0x20(0x4) ULONG u2; // +0x24(0x4) struct _MMPTE* PrototypePte; // +0x28(0x4) //ULONGLONG ThePtes[0x1]; // +0x30(0x8) }SEGMENT, *PSEGMENT; typedef struct _MMVAD_FLAGS { ULONG CommitCharge : 19; ULONG NoChange : 1; ULONG VadType : 3; ULONG MemCommit : 1; ULONG Protection : 5; ULONG Spare : 2; ULONG PrivateMemory : 1; } MMVAD_FLAGS, *PMMVAD_FLAGS; typedef struct // 0x14 { ULONG u1; // +0x0(0x4) struct _MMADDRESS_NODE* LeftChild; // +0x4(0x4) struct _MMADDRESS_NODE* RightChild; // +0x8(0x4) ULONG StartingVpn; // +0xc(0x4) ULONG EndingVpn; // +0x10(0x4) }MMADDRESS_NODE, *PMMADDRESS_NODE; typedef struct _MM_AVL_TABLE { MMADDRESS_NODE BalancedRoot; ULONG DepthOfTree : 5; ULONG Unused : 3; ULONG NumberGenericTableElements : 24; PVOID NodeHint; PVOID NodeFreeHint; } MM_AVL_TABLE, *PMM_AVL_TABLE; typedef struct _MMVAD_FLAGS2 { ULONG FileOffset : 24; ULONG SecNoChange : 1; ULONG OneSecured : 1; ULONG MultipleSecured : 1; ULONG ReadOnly : 1; ULONG LongVad : 1; ULONG ExtendableFile : 1; ULONG Inherit : 1; ULONG CopyOnWrite : 1; } MMVAD_FLAGS2, *PMMVAD_FLAGS2; #define Name_Offset 0x16c #define ActiveProcessLinks 0xb8 #define VAD_ROOT_OFFSET 0x278 typedef struct _MMVAD // 10 elements, 0x50 bytes (sizeof) { UINT32 unnamed_tag; /*0x00 - 0x03 [4바이트]*/ struct _MMVAD* LeftChild; /*0x04 - 0x07 [4바이트]*/ struct _MMVAD* RightChild; /*0x08 - 0x0b [4바이트]*/ UINT32 StartingVpn; /*0x0c - 0x0f [4바이트]*/ UINT32 EndingVpn; /*0x10 - 0x13 [4바이트]*/ UINT32 u; /*0x14 - 0x17 [4바이트]*/ UINT32 _EX_PUSH_LOCK; /*0x18 - 0x1b [4바이트]*/ UINT32 u5; /*0x1c - 0x1f [4바이트]*/ UINT32 u2; /*0x20 - 0x23 [4바이트]*/ PSUBSECTION Subsection; /*0x24 - 0x27 [4바이트]*/ UINT32 FirstPrototypePte; UINT32 LastContiguousPte; UINT32 ViewLinks; UINT32 VadsProcess; }MMVAD, *PMMVAD;
#pragma once extern "C" { #include "refer_vad.h" #include "wdm.h" #include "ndis.h" #include "Ntifs.h" } VOID PrintTree(MMVAD* Root); PEPROCESS GetEprocess(PCHAR szProcessName); VOID ListVAD(PMMVAD pParentVad); VOID OnUnload(_In_ PDRIVER_OBJECT DriverObject); extern "C" NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT pDriverObject, _In_ PUNICODE_STRING pRegistryPath); VOID ListVAD(PMMVAD pParentVad) { PMMVAD pVadLeft = NULL; PMMVAD pVadRight = NULL; if (pParentVad == 0x0) return; PrintTree(pParentVad); pVadLeft = (PMMVAD)pParentVad->LeftChild; pVadRight = (PMMVAD)pParentVad->RightChild; if (pVadLeft != 0x0) { ListVAD(pVadLeft); } if (pVadRight != 0x0) { ListVAD(pVadRight); } return; } extern "C" NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT pDriverObject, _In_ PUNICODE_STRING pRegistryPath) { UNREFERENCED_PARAMETER(pDriverObject); UNREFERENCED_PARAMETER(pRegistryPath); PMM_AVL_TABLE pVad_Root = NULL; PMMVAD pVad_Parent = NULL; DbgPrint("Driver Load!\n"); //원하는 Process의 이름에서 EPROCESS 포인터 PEPROCESS target_EPROC = GetEprocess("calc.exe"); DbgPrint("Target_EPROC : %08x\n", target_EPROC); //vadroot 주소84760a48 pVad_Root = (PMM_AVL_TABLE)((unsigned char*)target_EPROC + VAD_ROOT_OFFSET); //eprocess+vad_root_offset만큼에서 TABLE의 포인터를 가지고온다. DbgPrint("VadRoot Address : %08x\n", pVad_Root); //TABLE에서 BalanceRoot의 값을 가지고 온다. DbgPrint("VadRoot[TABLE] BalanceRoot Address : %08x\n", &(pVad_Root->BalancedRoot)); //!process 명령어를 통해서 확인하는 VadRoot 값은 pVad_Root->BalancedRoot.RightChild와 같은 값이다. //나머지 VadRoot가 아닌 값은 null 값이다. //위와 같이 null 값을 확인해서 진짜 사용되는? VadRoot 값을 가져온다. if (pVad_Root->BalancedRoot.RightChild) { DbgPrint("VadRoot[TABLE] BalanceRoot.Right Address : %08x\n", pVad_Root->BalancedRoot.RightChild); pVad_Parent = (PMMVAD)pVad_Root->BalancedRoot.RightChild; } if (pVad_Root->BalancedRoot.LeftChild) { DbgPrint("VadRoot[TABLE] BalanceRoot.Left Address : %08x\n", pVad_Root->BalancedRoot.LeftChild); pVad_Parent = (PMMVAD)pVad_Root->BalancedRoot.LeftChild; } ListVAD(pVad_Parent); pDriverObject->DriverUnload = OnUnload; //pDriverObject->DriverUnload = OnUnload; return STATUS_SUCCESS; } VOID OnUnload( _In_ PDRIVER_OBJECT DriverObject ) { DbgPrint("UnLoad!!!\n"); } PEPROCESS GetEprocess(PCHAR szProcessName) { PEPROCESS pEPROC = (PEPROCESS)PsGetCurrentProcess(); PLIST_ENTRY pHead, pNode; unsigned char* PROC = NULL; //첫 링크를 획득 한다. //EPRCOESS + OFFSET을 해서 PLIST의 값들을 구함 pHead = pNode = (PLIST_ENTRY)((unsigned char*)pEPROC + ActiveProcessLinks); do { //다시 프로세스를 비교하기 위해서 EPROCESS 첫 포인터로 귀환 PROC = (unsigned char*)((unsigned char*)pNode - ActiveProcessLinks); //Target Process 확인 if (strcmp(szProcessName, (const char*)((unsigned char*)PROC + Name_Offset)) == 0) { DbgPrint("Find Target Process!!\n"); break; } pNode = pNode->Flink; } while (pNode->Flink != pHead); return (PEPROCESS)PROC; } VOID PrintTree(MMVAD* Root) { PSUBSECTION pSubsection = NULL; PCONTROL_AREA pCONTROL_AREA = NULL; PEX_FAST_REF pFilePointer = NULL; POBJECT_NAME_INFORMATION Str = (POBJECT_NAME_INFORMATION)ExAllocatePool(PagedPool, 800); ULONG RetLen = 0; if (!Str || !Root) return; RtlZeroMemory(Str, 800); if (MmIsAddressValid(Root->Subsection) && MmIsAddressValid(Root->Subsection->ControlArea)) { // DbgPrint("a\n"); if (MmIsAddressValid((PVOID)Root->Subsection->ControlArea->FilePointer.Value)) { // DbgPrint("b\n"); PFILE_OBJECT pFileObj = (PFILE_OBJECT)((Root->Subsection->ControlArea->FilePointer.Value >> 3) << 3); if (MmIsAddressValid(pFileObj)) { NTSTATUS Status = ObQueryNameString(pFileObj, Str, 800, &RetLen); if (NT_SUCCESS(Status)) { //KdPrint(("Base:%08X Size:%dKb ", Root->Subsection->ControlArea->Segment->BasedAddress, \ //(Root->Subsection->ControlArea->Segment->SizeOfSegment) / 0x1000)); KdPrint(("Name:%ws\n", Str->Name.Buffer)); } else { KdPrint(("!%08X\n", Status)); } //DbgPrint("c\n"); //DbgPrint("pFileObj address : %08x\n", pFileObj); } } } }
여기저기 참조하고.. 구조체 사용하는 부분만 올바르게 정의하고... 막 해서 vad tree에서 이름 파싱 하는 코드.
해당 코드를 이용해서 dll detection하거나 cr3 확인해서 virtual address -> physical address 구하는 코드 확장
#참고
해당 코드를 빌드 할때 타입 재정의 error가 나오는데 한 두줄만 수정하면 된다.
typedef struct _EPROCESS *PEPROCESS;
typedef struct _ETHREAD *PETHREAD;
해당 타입으로 해주면 된다.
#include "Ntifs.h" 에서 위와 같은 타입의 정의가 달라서 나는 애러이다.
LIST
'reversing > rootkit' 카테고리의 다른 글
rootkit- syscall [2] (0) | 2017.05.04 |
---|---|
rootkit- syscall [1] (0) | 2017.05.04 |
DLL Injection Detect[2] (0) | 2016.09.05 |
[WHY] 역공학 분야를 공부하는 이유 (0) | 2016.08.27 |
DPC (0) | 2016.08.19 |