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 |