本帖最后由 Panel 于 2023-3-27 20:10 编辑
浅谈一类反调试的方法
概述:通过修改指定进程的ERPROCESS中某个成员的值达到保护进程不被附加的效果
原理:EPROCESS->FLAG2->ProtectedProcess标志着进程是否需要保护,就像它的名字一样
环境:Windows 7 x86 sp1
实验开始:
0x1:EPROCESS结构是啥?
EPROCESS是Windows进程在0环的一个储存进程信息的结构体,里面大致包含了进程的创建时间、结束时间、进程ID等等信息。
以下是EPROCESS结构的内存布局信息:
//0x2c0 bytes (sizeof)
struct _EPROCESS
{
struct _KPROCESS Pcb; //0x0
struct _EX_PUSH_LOCK ProcessLock; //0x98
union _LARGE_INTEGER CreateTime; //0xa0
union _LARGE_INTEGER ExitTime; //0xa8
struct _EX_RUNDOWN_REF RundownProtect; //0xb0
VOID* UniqueProcessId; //0xb4
struct _LIST_ENTRY ActiveProcessLinks; //0xb8
ULONG ProcessQuotaUsage[2]; //0xc0
ULONG ProcessQuotaPeak[2]; //0xc8
volatile ULONG CommitCharge; //0xd0
struct _EPROCESS_QUOTA_BLOCK* QuotaBlock; //0xd4
struct _PS_CPU_QUOTA_BLOCK* CpuQuotaBlock; //0xd8
ULONG PeakVirtualSize; //0xdc
ULONG VirtualSize; //0xe0
struct _LIST_ENTRY SessionProcessLinks; //0xe4
VOID* DebugPort; //0xec
union
{
VOID* ExceptionPortData; //0xf0
ULONG ExceptionPortValue; //0xf0
ULONG ExceptionPortState:3; //0xf0
};
struct _HANDLE_TABLE* ObjectTable; //0xf4
struct _EX_FAST_REF Token; //0xf8
ULONG WorkingSetPage; //0xfc
struct _EX_PUSH_LOCK AddressCreationLock; //0x100
struct _ETHREAD* RotateInProgress; //0x104
struct _ETHREAD* ForkInProgress; //0x108
ULONG HardwareTrigger; //0x10c
struct _MM_AVL_TABLE* PhysicalVadRoot; //0x110
VOID* CloneRoot; //0x114
volatile ULONG NumberOfPrivatePages; //0x118
volatile ULONG NumberOfLockedPages; //0x11c
VOID* Win32Process; //0x120
struct _EJOB* volatile Job; //0x124
VOID* SectionObject; //0x128
VOID* SectionBaseAddress; //0x12c
ULONG Cookie; //0x130
ULONG Spare8; //0x134
struct _PAGEFAULT_HISTORY* WorkingSetWatch; //0x138
VOID* Win32WindowStation; //0x13c
VOID* InheritedFromUniqueProcessId; //0x140
VOID* LdtInformation; //0x144
VOID* VdmObjects; //0x148
ULONG ConsoleHostProcess; //0x14c
VOID* DeviceMap; //0x150
VOID* EtwDataSource; //0x154
VOID* FreeTebHint; //0x158
union
{
struct _HARDWARE_PTE PageDirectoryPte; //0x160
ULONGLONG Filler; //0x160
};
VOID* Session; //0x168
UCHAR ImageFileName[15]; //0x16c
UCHAR PriorityClass; //0x17b
struct _LIST_ENTRY JobLinks; //0x17c
VOID* LockedPagesList; //0x184
struct _LIST_ENTRY ThreadListHead; //0x188
VOID* SecurityPort; //0x190
VOID* PaeTop; //0x194
volatile ULONG ActiveThreads; //0x198
ULONG ImagePathHash; //0x19c
ULONG DefaultHardErrorProcessing; //0x1a0
LONG LastThreadExitStatus; //0x1a4
struct _PEB* Peb; //0x1a8
struct _EX_FAST_REF PrefetchTrace; //0x1ac
union _LARGE_INTEGER ReadOperationCount; //0x1b0
union _LARGE_INTEGER WriteOperationCount; //0x1b8
union _LARGE_INTEGER OtherOperationCount; //0x1c0
union _LARGE_INTEGER ReadTransferCount; //0x1c8
union _LARGE_INTEGER WriteTransferCount; //0x1d0
union _LARGE_INTEGER OtherTransferCount; //0x1d8
ULONG CommitChargeLimit; //0x1e0
volatile ULONG CommitChargePeak; //0x1e4
VOID* AweInfo; //0x1e8
struct _SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo; //0x1ec
struct _MMSUPPORT Vm; //0x1f0
struct _LIST_ENTRY MmProcessLinks; //0x25c
VOID* HighestUserAddress; //0x264
ULONG ModifiedPageCount; //0x268
union
{
ULONG Flags2; //0x26c
struct
{
ULONG JobNotReallyActive:1; //0x26c
ULONG AccountingFolded:1; //0x26c
ULONG NewProcessReported:1; //0x26c
ULONG ExitProcessReported:1; //0x26c
ULONG ReportCommitChanges:1; //0x26c
ULONG LastReportMemory:1; //0x26c
ULONG ReportPhysicalPageChanges:1; //0x26c
ULONG HandleTableRundown:1; //0x26c
ULONG NeedsHandleRundown:1; //0x26c
ULONG RefTraceEnabled:1; //0x26c
ULONG NumaAware:1; //0x26c
ULONG ProtectedProcess:1; //0x26c
ULONG DefaultPagePriority:3; //0x26c
ULONG PrimaryTokenFrozen:1; //0x26c
ULONG ProcessVerifierTarget:1; //0x26c
ULONG StackRandomizationDisabled:1; //0x26c
ULONG AffinityPermanent:1; //0x26c
ULONG AffinityUpdateEnable:1; //0x26c
ULONG PropagateNode:1; //0x26c
ULONG ExplicitAffinity:1; //0x26c
};
};
union
{
ULONG Flags; //0x270
struct
{
ULONG CreateReported:1; //0x270
ULONG NoDebugInherit:1; //0x270
ULONG ProcessExiting:1; //0x270
ULONG ProcessDelete:1; //0x270
ULONG Wow64SplitPages:1; //0x270
ULONG VmDeleted:1; //0x270
ULONG OutswapEnabled:1; //0x270
ULONG Outswapped:1; //0x270
ULONG ForkFailed:1; //0x270
ULONG Wow64VaSpace4Gb:1; //0x270
ULONG AddressSpaceInitialized:2; //0x270
ULONG SetTimerResolution:1; //0x270
ULONG BreakOnTermination:1; //0x270
ULONG DeprioritizeViews:1; //0x270
ULONG WriteWatch:1; //0x270
ULONG ProcessInSession:1; //0x270
ULONG OverrideAddressSpace:1; //0x270
ULONG HasAddressSpace:1; //0x270
ULONG LaunchPrefetched:1; //0x270
ULONG InjectInpageErrors:1; //0x270
ULONG VmTopDown:1; //0x270
ULONG ImageNotifyDone:1; //0x270
ULONG PdeUpdateNeeded:1; //0x270
ULONG VdmAllowed:1; //0x270
ULONG CrossSessionCreate:1; //0x270
ULONG ProcessInserted:1; //0x270
ULONG DefaultIoPriority:3; //0x270
ULONG ProcessSelfDelete:1; //0x270
ULONG SetTimerResolutionLink:1; //0x270
};
};
LONG ExitStatus; //0x274
struct _MM_AVL_TABLE VadRoot; //0x278
struct _ALPC_PROCESS_CONTEXT AlpcContext; //0x298
struct _LIST_ENTRY TimerResolutionLink; //0x2a8
ULONG RequestedTimerResolution; //0x2b0
ULONG ActiveThreadsHighWatermark; //0x2b4
ULONG SmallestTimerResolution; //0x2b8
struct _PO_DIAG_STACK_RECORD* TimerResolutionStackRecord; //0x2bc
};
0x2:重要成员介绍
EPROCESS->FLAG2->ProtectedProcess:标志进程是否处于保护,置1标志为保护
EPROCESS->FLAG->ProcessDelete:标志进程是否已经被销毁,置1标志为已经被销毁
还有几个类似成员这里不一一列出,目前咱们只需要用到这两个中的一个就可以实现
0x3:实现逻辑
①将指定进程的EPROCESS->FLAG2的值复制出来;
②将复制出来的EPROCESS->FLAG2->ProtectedProcess置为1;
③再将将复制出来的EPROCESS->FLAG2写回EPROCESS->FLAG2.
0x4:实现代码
#include <ntddk.h>
#include <string.h>
union
{
ULONG Flags2; //0x26c
struct
{
ULONG JobNotReallyActive : 1; //0x26c
ULONG AccountingFolded : 1; //0x26c
ULONG NewProcessReported : 1; //0x26c
ULONG ExitProcessReported : 1; //0x26c
ULONG ReportCommitChanges : 1; //0x26c
ULONG LastReportMemory : 1; //0x26c
ULONG ReportPhysicalPageChanges : 1; //0x26c
ULONG HandleTableRundown : 1; //0x26c
ULONG NeedsHandleRundown : 1; //0x26c
ULONG RefTraceEnabled : 1; //0x26c
ULONG NumaAware : 1; //0x26c
ULONG ProtectedProcess : 1; //0x26c
ULONG DefaultPagePriority : 3; //0x26c
ULONG PrimaryTokenFrozen : 1; //0x26c
ULONG ProcessVerifierTarget : 1; //0x26c
ULONG StackRandomizationDisabled : 1; //0x26c
ULONG AffinityPermanent : 1; //0x26c
ULONG AffinityUpdateEnable : 1; //0x26c
ULONG PropagateNode : 1; //0x26c
ULONG ExplicitAffinity : 1; //0x26c
}Flags;
}ALLFlags;
/*
Windows7 x86
*/
VOID UnloadDriver(PDRIVER_OBJECT pDriver)
{
DbgPrintEx(77, 0, "卸载成功\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegPath)
{
PEPROCESS pSelfEProcess = PsGetCurrentProcess();
DbgPrintEx(77, 0, "进程名称%s\n",(PUCHAR)pSelfEProcess+0x16c);
PLIST_ENTRY pProcessList = (PUCHAR)pSelfEProcess + 0xb8;
PLIST_ENTRY pSelfEPLocation = pProcessList;
ANSI_STRING aDst;
ANSI_STRING aGet;
CHAR* string1 = "123.exe";
CHAR* string2 = "123.exe";
INT result = 1;
RtlInitAnsiString(&aDst, string1);
do
{
DbgPrintEx(77, 0, "[db]:进程名:%s\n", (PUCHAR)pProcessList - 0xb8 + 0x16c);
string2 = (PUCHAR)pProcessList - 0xb8 + 0x16c;
RtlInitAnsiString(&aGet, string2);
result = RtlCompareString(&aDst, &aGet, FALSE);
if (!result)
{
pSelfEProcess = (PUCHAR)pProcessList - 0xb8;
break;
}
pProcessList = pProcessList->Blink;
} while (pProcessList->Blink != pSelfEPLocation);
PMDL pMDL = IoAllocateMdl(pSelfEProcess, PAGE_SIZE, NULL, NULL, NULL);
PVOID pVirsualForMdl = NULL;
BOOLEAN bIsLocked = FALSE;
__try
{
//锁定不分页
MmProbeAndLockPages(pMDL, KernelMode, IoWriteAccess);
bIsLocked = TRUE;
//将物理地址映射出来
pVirsualForMdl = MmMapLockedPagesSpecifyCache(pMDL, KernelMode, MmNonCached, NULL, FALSE, NormalPoolPriority);
}
__except (1)
{
if (!bIsLocked)
{
IoFreeMdl(pMDL);
}
}
RtlCopyMemory(&ALLFlags, (PUCHAR)pVirsualForMdl + 0x26c, sizeof(ALLFlags));
ALLFlags.Flags.ProtectedProcess = 1;
RtlCopyMemory((PUCHAR)pVirsualForMdl + 0x26c, &ALLFlags, sizeof(ALLFlags));
MmUnmapLockedPages(pVirsualForMdl, pMDL);
MmUnlockPages(pMDL);
IoFreeMdl(pMDL);
pDriver->DriverUnload = UnloadDriver;
}
0x5:代码注意点
因为没去查看EPROCESS的内存是否可读写,所以这里使用了MDL把物理地址从新映射到一块可写不分页内存来进行读写,使用 完记得解除映射和释放MDL就行.
0x6:效果图
0x7:总结
以上的实现只是修改了EPROCESS结构体中的一个成员,还可以修改其他成员的标志去实现类似效果.
浅谈,大牛请路过!
|