본문 바로가기

reversing/rootkit

DLL Injection Detect[3]

SMALL

이것저것 구조체 필요한 부분만 알맞게 정의해서 vad 파싱해서 이름 가져왔다.




refer_vad.h
#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;


main.cpp
#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