User 권한(Ring 3)의 프로그램에서 _ETHREAD 주소(및 커널 메모리를 읽을 수 있다면 _EPROCESS 주소) 구하는 방법
우선, _ETHREAD 주소는 해당 프로세스가 열고 있는 Thread Handle 값을 통해 알 수 있습니다. 따라서 다음의 코드를 이용하면,
C# - 프로세스의 모든 핸들을 열람
; https://www.sysnet.pe.kr/2/0/12080
개별 프로세스가 열고 있는 Thread 핸들을 알 수 있고 아래의 글에 설명했던 것처럼,
Windows 10 - Process Explorer로 확인한 Handle 정보를 windbg에서 조회
; https://www.sysnet.pe.kr/2/0/12099
해당 핸들의 Object Address가 가리키는 값은 Thread인 경우 _ETHREAD에 해당하므로 유저 권한(Ring 3)의 프로그램도 _ETHREAD 주솟값을 알 수 있게 됩니다. 실제로 "
Local Kernel Debug 모드"로 실행한 Windbg로 이를 확인할 수 있습니다.
가령, Process Explorer에서 확인한 스레드의 핸들 정보가 아래와 같을 때,
Type: Thread
Object Address: 0xFFFFC38DA331F080
thread id == 9384
Windbg에서 해당 주소로 _ETHREAD 타입으로 덤프해 보면 다음과 같은 식의 결과를 얻을 수 있습니다.
lkd> dt _ETHREAD 0xFFFFC38DA331F080
nt!_ETHREAD
+0x000 Tcb : _KTHREAD
+0x600 CreateTime : _LARGE_INTEGER 0x01d5c46f`f88ebbe1
+0x608 ExitTime : _LARGE_INTEGER 0xffffc38d`a331f688
+0x608 KeyedWaitChain : _LIST_ENTRY [ 0xffffc38d`a331f688 - 0xffffc38d`a331f688 ]
+0x618 PostBlockList : _LIST_ENTRY [ 0xffffa207`c46f2300 - 0xffffa207`c46f2a20 ]
+0x618 ForwardLinkShadow : 0xffffa207`c46f2300 Void
+0x620 StartAddress : 0xffffa207`c46f2a20 Void
+0x628 TerminationPort : (null)
+0x628 ReaperLink : (null)
+0x628 KeyedWaitValue : (null)
+0x630 ActiveTimerListLock : 0
+0x638 ActiveTimerListHead : _LIST_ENTRY [ 0xffffc38d`a331f6b8 - 0xffffc38d`a331f6b8 ]
+0x648 Cid : _CLIENT_ID
+0x658 KeyedWaitSemaphore : _KSEMAPHORE
+0x658 AlpcWaitSemaphore : _KSEMAPHORE
+0x678 ClientSecurity : _PS_CLIENT_SECURITY_CONTEXT
+0x680 IrpList : _LIST_ENTRY [ 0xffffc38d`a331f700 - 0xffffc38d`a331f700 ]
+0x690 TopLevelIrp : 0
+0x698 DeviceToVerify : (null)
+0x6a0 Win32StartAddress : 0x00007ff7`1c3b0100 Void
+0x6a8 ChargeOnlySession : (null)
+0x6b0 LegacyPowerObject : (null)
+0x6b8 ThreadListEntry : _LIST_ENTRY [ 0xffffc38d`a37f7738 - 0xffffc38d`a3d74508 ]
+0x6c8 RundownProtect : _EX_RUNDOWN_REF
+0x6d0 ThreadLock : _EX_PUSH_LOCK
+0x6d8 ReadClusterSize : 7
+0x6dc MmLockOrdering : 0n0
+0x6e0 CrossThreadFlags : 0x5442
+0x6e0 Terminated : 0y0
+0x6e0 ThreadInserted : 0y1
+0x6e0 HideFromDebugger : 0y0
+0x6e0 ActiveImpersonationInfo : 0y0
+0x6e0 HardErrorsAreDisabled : 0y0
+0x6e0 BreakOnTermination : 0y0
+0x6e0 SkipCreationMsg : 0y1
+0x6e0 SkipTerminationMsg : 0y0
+0x6e0 CopyTokenOnOpen : 0y0
+0x6e0 ThreadIoPriority : 0y010
+0x6e0 ThreadPagePriority : 0y101
+0x6e0 RundownFail : 0y0
+0x6e0 UmsForceQueueTermination : 0y0
+0x6e0 IndirectCpuSets : 0y0
+0x6e0 DisableDynamicCodeOptOut : 0y0
+0x6e0 ExplicitCaseSensitivity : 0y0
+0x6e0 PicoNotifyExit : 0y0
+0x6e0 DbgWerUserReportActive : 0y0
+0x6e0 ForcedSelfTrimActive : 0y0
+0x6e0 SamplingCoverage : 0y0
+0x6e0 ReservedCrossThreadFlags : 0y00000000 (0)
+0x6e4 SameThreadPassiveFlags : 0
+0x6e4 ActiveExWorker : 0y0
+0x6e4 MemoryMaker : 0y0
+0x6e4 StoreLockThread : 0y00
+0x6e4 ClonedThread : 0y0
+0x6e4 KeyedEventInUse : 0y0
+0x6e4 SelfTerminate : 0y0
+0x6e4 RespectIoPriority : 0y0
+0x6e4 ActivePageLists : 0y0
+0x6e4 SecureContext : 0y0
+0x6e4 ZeroPageThread : 0y0
+0x6e4 WorkloadClass : 0y0
+0x6e4 ReservedSameThreadPassiveFlags : 0y00000000000000000000 (0)
+0x6e8 SameThreadApcFlags : 8
+0x6e8 OwnsProcessAddressSpaceExclusive : 0y0
+0x6e8 OwnsProcessAddressSpaceShared : 0y0
+0x6e8 HardFaultBehavior : 0y0
+0x6e8 StartAddressInvalid : 0y1
+0x6e8 EtwCalloutActive : 0y0
+0x6e8 SuppressSymbolLoad : 0y0
+0x6e8 Prefetching : 0y0
+0x6e8 OwnsVadExclusive : 0y0
+0x6e9 SystemPagePriorityActive : 0y0
+0x6e9 SystemPagePriority : 0y000
+0x6e9 AllowUserWritesToExecutableMemory : 0y0
+0x6e9 AllowKernelWritesToExecutableMemory : 0y0
+0x6e9 OwnsVadShared : 0y0
+0x6ec CacheManagerActive : 0 ''
+0x6ed DisablePageFaultClustering : 0 ''
+0x6ee ActiveFaultCount : 0 ''
+0x6ef LockOrderState : 0 ''
+0x6f0 AlpcMessageId : 0
+0x6f8 AlpcMessage : (null)
+0x6f8 AlpcReceiveAttributeSet : 0
+0x700 AlpcWaitListEntry : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
+0x710 ExitStatus : 0n0
+0x714 CacheManagerCount : 0
+0x718 IoBoostCount : 0
+0x71c IoQoSBoostCount : 0
+0x720 IoQoSThrottleCount : 0
+0x724 KernelStackReference : 1
+0x728 BoostList : _LIST_ENTRY [ 0xffffc38d`a331f7a8 - 0xffffc38d`a331f7a8 ]
+0x738 DeboostList : _LIST_ENTRY [ 0xffffc38d`a331f7b8 - 0xffffc38d`a331f7b8 ]
+0x748 BoostListLock : 0
+0x750 IrpListLock : 0
+0x758 ReservedForSynchTracking : (null)
+0x760 CmCallbackListHead : _SINGLE_LIST_ENTRY
+0x768 ActivityId : (null)
+0x770 SeLearningModeListHead : _SINGLE_LIST_ENTRY
+0x778 VerifierContext : (null)
+0x780 AdjustedClientToken : (null)
+0x788 WorkOnBehalfThread : (null)
+0x790 PropertySet : _PS_PROPERTY_SET
+0x7a8 PicoContext : (null)
+0x7b0 UserFsBase : 0
+0x7b8 UserGsBase : 0
+0x7c0 EnergyValues : 0xffffc38d`a331f8a0 _THREAD_ENERGY_VALUES
+0x7c8 CmDbgInfo : (null)
+0x7d0 SelectedCpuSets : 0
+0x7d0 SelectedCpuSetsIndirect : (null)
+0x7d8 Silo : 0xffffffff`fffffffd _EJOB
+0x7e0 ThreadName : (null)
+0x7e8 SetContextState : (null)
+0x7f0 LastExpectedRunTime : 0x2e3ae
+0x7f4 HeapData : 0xe02c0000
+0x7f8 OwnerEntryListHead : _LIST_ENTRY [ 0xffffc38d`a331f878 - 0xffffc38d`a331f878 ]
+0x808 DisownedOwnerEntryListLock : 0
+0x810 DisownedOwnerEntryListHead : _LIST_ENTRY [ 0xffffc38d`a331f890 - 0xffffc38d`a331f890 ]
// Windows 10
// GetThreadDescription, SetThreadDescription
정상적으로 구해진 값인지 확인하기 위해 _CLIENT_ID를 덤프해 보면,
lkd> dt _CLIENT_ID 0xFFFFC38DA331F080+0x648
nt!_CLIENT_ID
+0x000 UniqueProcess : 0x00000000`000024d8 Void
+0x008 UniqueThread : 0x00000000`000024a8 Void
UniqueThread의 값이 0x24a8 == 0n9384인 걸로 봐서 ETHREAD 구조체가 맞습니다.
아쉽게도 ETHREAD 주소는 이렇게 구할 수 있지만 EPROCESS 주소는 구할 수 없습니다. 왜냐하면, 대개의 프로그램이 자신의 프로세스 Handle을 일부러 열고 있는 경우가 많지 않으므로 "Process" 타입의 핸들이 "
C# - 프로세스의 모든 핸들을 열람" 코드로는 열거가 안 됩니다.
대신 _ETHREAD에 담긴 EPROCESS를 찾는 방법이 있습니다. _ETHREAD의 0번째 offset에 위치한 구조체가 _KTHREAD인데 이것을 덤프해 보면,
lkd> dt _KTHREAD 0xFFFFC38DA331F080
nt!_KTHREAD
+0x000 Header : _DISPATCHER_HEADER
+0x018 SListFaultAddress : (null)
...[생략]...
+0x21c QueuePriority : 0n0
+0x220 Process : 0xffffc38d`a3d74080 _KPROCESS
+0x228 UserAffinity : _GROUP_AFFINITY
...[생략]...
+0x5e0 ThreadTimerDelay : 0
+0x5e4 ThreadFlags2 : 0n0
+0x5e4 PpmPolicy : 0y00
+0x5e4 ThreadFlags2Reserved : 0y000000000000000000000000000000 (0)
+0x5e8 TracingPrivate : [1] 0
+0x5f0 SchedulerAssist : (null)
+0x5f8 AbWaitObject : (null)
_KPROCESS에 해당하는 포인터를 가지고 있으므로 (_ETHREAD와 _KTHREAD의 관계와 동일하므로) _EPROCESS 주소를 구한 것이나 다름없습니다.
lkd> dt _EPROCESS 0xffffc38d`a3d74080
nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x2e0 ProcessLock : _EX_PUSH_LOCK
+0x2e8 UniqueProcessId : 0x00000000`000024d8 Void
+0x2f0 ActiveProcessLinks : _LIST_ENTRY [ 0xffffc38d`9e9f2370 - 0xffffc38d`a3dd1370 ]
+0x300 RundownProtect : _EX_RUNDOWN_REF
+0x308 Flags2 : 0xd000
+0x308 JobNotReallyActive : 0y0
+0x308 AccountingFolded : 0y0
+0x308 NewProcessReported : 0y0
+0x308 ExitProcessReported : 0y0
+0x308 ReportCommitChanges : 0y0
+0x308 LastReportMemory : 0y0
+0x308 ForceWakeCharge : 0y0
+0x308 CrossSessionCreate : 0y0
+0x308 NeedsHandleRundown : 0y0
+0x308 RefTraceEnabled : 0y0
+0x308 PicoCreated : 0y0
+0x308 EmptyJobEvaluated : 0y0
+0x308 DefaultPagePriority : 0y101
+0x308 PrimaryTokenFrozen : 0y1
+0x308 ProcessVerifierTarget : 0y0
+0x308 RestrictSetThreadContext : 0y0
+0x308 AffinityPermanent : 0y0
+0x308 AffinityUpdateEnable : 0y0
+0x308 PropagateNode : 0y0
+0x308 ExplicitAffinity : 0y0
+0x308 ProcessExecutionState : 0y00
+0x308 EnableReadVmLogging : 0y0
+0x308 EnableWriteVmLogging : 0y0
+0x308 FatalAccessTerminationRequested : 0y0
+0x308 DisableSystemAllowedCpuSet : 0y0
+0x308 ProcessStateChangeRequest : 0y00
+0x308 ProcessStateChangeInProgress : 0y0
+0x308 InPrivate : 0y0
+0x30c Flags : 0x144d0c03
+0x30c CreateReported : 0y1
+0x30c NoDebugInherit : 0y1
+0x30c ProcessExiting : 0y0
+0x30c ProcessDelete : 0y0
+0x30c ManageExecutableMemoryWrites : 0y0
+0x30c VmDeleted : 0y0
+0x30c OutswapEnabled : 0y0
+0x30c Outswapped : 0y0
+0x30c FailFastOnCommitFail : 0y0
+0x30c Wow64VaSpace4Gb : 0y0
+0x30c AddressSpaceInitialized : 0y11
+0x30c SetTimerResolution : 0y0
+0x30c BreakOnTermination : 0y0
+0x30c DeprioritizeViews : 0y0
+0x30c WriteWatch : 0y0
+0x30c ProcessInSession : 0y1
+0x30c OverrideAddressSpace : 0y0
+0x30c HasAddressSpace : 0y1
+0x30c LaunchPrefetched : 0y1
+0x30c Background : 0y0
+0x30c VmTopDown : 0y0
+0x30c ImageNotifyDone : 0y1
+0x30c PdeUpdateNeeded : 0y0
+0x30c VdmAllowed : 0y0
+0x30c ProcessRundown : 0y0
+0x30c ProcessInserted : 0y1
+0x30c DefaultIoPriority : 0y010
+0x30c ProcessSelfDelete : 0y0
+0x30c SetTimerResolutionLink : 0y0
+0x310 CreateTime : _LARGE_INTEGER 0x01d5c46f`f88ebbd1
+0x318 ProcessQuotaUsage : [2] 0x33f8
+0x328 ProcessQuotaPeak : [2] 0x72f8
+0x338 PeakVirtualSize : 0x00000201`09cc6000
+0x340 VirtualSize : 0x00000201`09846000
+0x348 SessionProcessLinks : _LIST_ENTRY [ 0xffffc38d`9e9f23c8 - 0xffffc38d`a3dd13c8 ]
+0x358 ExceptionPortData : 0xffffc38d`a2359a80 Void
+0x358 ExceptionPortValue : 0xffffc38d`a2359a80
+0x358 ExceptionPortState : 0y000
+0x360 Token : _EX_FAST_REF
+0x368 MmReserved : 0
+0x370 AddressCreationLock : _EX_PUSH_LOCK
+0x378 PageTableCommitmentLock : _EX_PUSH_LOCK
+0x380 RotateInProgress : (null)
+0x388 ForkInProgress : (null)
+0x390 CommitChargeJob : (null)
+0x398 CloneRoot : _RTL_AVL_TREE
+0x3a0 NumberOfPrivatePages : 0x219
+0x3a8 NumberOfLockedPages : 0
+0x3b0 Win32Process : 0xffffecaa`047c5ab0 Void
+0x3b8 Job : (null)
+0x3c0 SectionObject : 0xffffa207`c46084d0 Void
+0x3c8 SectionBaseAddress : 0x00007ff7`1c390000 Void
+0x3d0 Cookie : 0x41dbe064
+0x3d8 WorkingSetWatch : (null)
+0x3e0 Win32WindowStation : 0x00000000`00000098 Void
+0x3e8 InheritedFromUniqueProcessId : 0x00000000`000019bc Void
+0x3f0 OwnerProcessId : 0x19be
+0x3f8 Peb : 0x000000f9`6bae1000 _PEB
+0x400 Session : 0xffff8f00`26f44000 _MM_SESSION_SPACE
+0x408 Spare1 : (null)
+0x410 QuotaBlock : 0xffffc38d`9fca5bc0 _EPROCESS_QUOTA_BLOCK
+0x418 ObjectTable : 0xffffa207`c439ac80 _HANDLE_TABLE
+0x420 DebugPort : (null)
+0x428 WoW64Process : (null)
+0x430 DeviceMap : 0xffffa207`c23223d0 Void
+0x438 EtwDataSource : 0xffffc38d`a3b5c650 Void
+0x440 PageDirectoryPte : 0
+0x448 ImageFilePointer : 0xffffc38d`a440b1a0 _FILE_OBJECT
+0x450 ImageFileName : [15] "notepad.exe"
+0x45f PriorityClass : 0x2 ''
+0x460 SecurityPort : (null)
+0x468 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
+0x470 JobLinks : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
+0x480 HighestUserAddress : 0x00007fff`ffff0000 Void
+0x488 ThreadListHead : _LIST_ENTRY [ 0xffffc38d`a331f738 - 0xffffc38d`a3c76978 ]
+0x498 ActiveThreads : 4
+0x49c ImagePathHash : 0xb28cc291
+0x4a0 DefaultHardErrorProcessing : 1
+0x4a4 LastThreadExitStatus : 0n0
+0x4a8 PrefetchTrace : _EX_FAST_REF
+0x4b0 LockedPagesList : (null)
+0x4b8 ReadOperationCount : _LARGE_INTEGER 0x0
+0x4c0 WriteOperationCount : _LARGE_INTEGER 0x0
+0x4c8 OtherOperationCount : _LARGE_INTEGER 0x10
+0x4d0 ReadTransferCount : _LARGE_INTEGER 0x0
+0x4d8 WriteTransferCount : _LARGE_INTEGER 0x0
+0x4e0 OtherTransferCount : _LARGE_INTEGER 0x0
+0x4e8 CommitChargeLimit : 0
+0x4f0 CommitCharge : 0x2d0
+0x4f8 CommitChargePeak : 0x311
+0x500 Vm : _MMSUPPORT_FULL
+0x640 MmProcessLinks : _LIST_ENTRY [ 0xffffc38d`9e9f26c0 - 0xffffc38d`a3dd16c0 ]
+0x650 ModifiedPageCount : 0x16
+0x654 ExitStatus : 0n259
+0x658 VadRoot : _RTL_AVL_TREE
+0x660 VadHint : 0xffffc38d`a3e6c500 Void
+0x668 VadCount : 0x5e
+0x670 VadPhysicalPages : 0
+0x678 VadPhysicalPagesLimit : 0
+0x680 AlpcContext : _ALPC_PROCESS_CONTEXT
+0x6a0 TimerResolutionLink : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
+0x6b0 TimerResolutionStackRecord : (null)
+0x6b8 RequestedTimerResolution : 0
+0x6bc SmallestTimerResolution : 0
+0x6c0 ExitTime : _LARGE_INTEGER 0x0
+0x6c8 InvertedFunctionTable : (null)
+0x6d0 InvertedFunctionTableLock : _EX_PUSH_LOCK
+0x6d8 ActiveThreadsHighWatermark : 7
+0x6dc LargePrivateVadCount : 0
+0x6e0 ThreadListLock : _EX_PUSH_LOCK
+0x6e8 WnfContext : 0xffffa207`c460a8c0 Void
+0x6f0 ServerSilo : (null)
+0x6f8 SignatureLevel : 0 ''
+0x6f9 SectionSignatureLevel : 0 ''
+0x6fa Protection : _PS_PROTECTION
+0x6fb HangCount : 0y000
+0x6fb GhostCount : 0y000
+0x6fb PrefilterException : 0y0
+0x6fc Flags3 : 0x40c000
+0x6fc Minimal : 0y0
+0x6fc ReplacingPageRoot : 0y0
+0x6fc Crashed : 0y0
+0x6fc JobVadsAreTracked : 0y0
+0x6fc VadTrackingDisabled : 0y0
+0x6fc AuxiliaryProcess : 0y0
+0x6fc SubsystemProcess : 0y0
+0x6fc IndirectCpuSets : 0y0
+0x6fc RelinquishedCommit : 0y0
+0x6fc HighGraphicsPriority : 0y0
+0x6fc CommitFailLogged : 0y0
+0x6fc ReserveFailLogged : 0y0
+0x6fc SystemProcess : 0y0
+0x6fc HideImageBaseAddresses : 0y0
+0x6fc AddressPolicyFrozen : 0y1
+0x6fc ProcessFirstResume : 0y1
+0x6fc ForegroundExternal : 0y0
+0x6fc ForegroundSystem : 0y0
+0x6fc HighMemoryPriority : 0y0
+0x6fc EnableProcessSuspendResumeLogging : 0y0
+0x6fc EnableThreadSuspendResumeLogging : 0y0
+0x6fc SecurityDomainChanged : 0y0
+0x6fc SecurityFreezeComplete : 0y1
+0x6fc VmProcessorHost : 0y0
+0x700 DeviceAsid : 0n0
+0x708 SvmData : (null)
+0x710 SvmProcessLock : _EX_PUSH_LOCK
+0x718 SvmLock : 0
+0x720 SvmProcessDeviceListHead : _LIST_ENTRY [ 0xffffc38d`a3d747a0 - 0xffffc38d`a3d747a0 ]
+0x730 LastFreezeInterruptTime : 0
+0x738 DiskCounters : 0xffffc38d`a3d74900 _PROCESS_DISK_COUNTERS
+0x740 PicoContext : (null)
+0x748 EnclaveTable : (null)
+0x750 EnclaveNumber : 0
+0x758 EnclaveLock : _EX_PUSH_LOCK
+0x760 HighPriorityFaultsAllowed : 0
+0x768 EnergyContext : 0xffffc38d`a3d74928 _PO_PROCESS_ENERGY_CONTEXT
+0x770 VmContext : (null)
+0x778 SequenceNumber : 0x102
+0x780 CreateInterruptTime : 0xcde9d1df
+0x788 CreateUnbiasedInterruptTime : 0xcde9d1df
+0x790 TotalUnbiasedFrozenTime : 0
+0x798 LastAppStateUpdateTime : 0xcde9d1df
+0x7a0 LastAppStateUptime : 0y0000000000000000000000000000000000000000000000000000000000000 (0)
+0x7a0 LastAppState : 0y000
+0x7a8 SharedCommitCharge : 0x650
+0x7b0 SharedCommitLock : _EX_PUSH_LOCK
+0x7b8 SharedCommitLinks : _LIST_ENTRY [ 0xffffa207`c4a44438 - 0xffffa207`c4a449d8 ]
+0x7c8 AllowedCpuSets : 0
+0x7d0 DefaultCpuSets : 0
+0x7c8 AllowedCpuSetsIndirect : (null)
+0x7d0 DefaultCpuSetsIndirect : (null)
+0x7d8 DiskIoAttribution : (null)
+0x7e0 DxgProcess : 0xffffa207`c3acea60 Void
+0x7e8 Win32KFilterSet : 0
+0x7f0 ProcessTimerDelay : _PS_INTERLOCKED_TIMER_DELAY_VALUES
+0x7f8 KTimerSets : 0
+0x7fc KTimer2Sets : 0
+0x800 ThreadTimerSets : 4
+0x808 VirtualTimerListLock : 0
+0x810 VirtualTimerListHead : _LIST_ENTRY [ 0xffffc38d`a3d74890 - 0xffffc38d`a3d74890 ]
+0x820 WakeChannel : _WNF_STATE_NAME
+0x820 WakeInfo : _PS_PROCESS_WAKE_INFORMATION
+0x850 MitigationFlags : 0x21
+0x850 MitigationFlagsValues : <anonymous-tag>
+0x854 MitigationFlags2 : 0
+0x854 MitigationFlags2Values : <anonymous-tag>
+0x858 PartitionObject : 0xffffc38d`99697f80 Void
+0x860 SecurityDomain : 0x00000001`00000074
+0x868 ParentSecurityDomain : 0x00000001`00000074
+0x870 CoverageSamplerContext : (null)
+0x878 MmHotPatchContext : (null)
여기서 문제는, _ETHREAD의 주솟값이 커널 영역이기 때문에 User 권한의 프로그램이 저런 식으로 덤프를 하며 _EPROCESS의 주소를 찾아낼 수는 없습니다.
굳이, 방법을 찾아낸다면 일부러 Process Handle을 Duplicate하는 사용자 코드를 대상 프로세스에 Injection시킨 후에 핸들을 열람하거나, 커널 영역의 메모리 읽기를 대행해 주는 Device Driver를 제작하는 정도가 될 것입니다.
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]