(果然分析不下去了,这个样本涉及的内容太广,我得去补充补充知识再来接着分析了)
最近发现这个模块比较有趣,还是个x64上的,正好可以练习一下x64的汇编,写下来有个更好的理解。由于个人能力有限,这个过程可能会持续几个月,或者更长,不知道能不能弄完。下面通过一些汇编片段来学习它的编程思路及技巧。
仅供参考,如有错误欢迎指出。
1,获取系统信息,函数原型:
ULONG64 GetSystemInformation(ULONG InformationClass,PVOID64 Data);
InformationClass是系统信息的类型,Data指向存储成功获得的信息的地址。
解释:默认Buffer大小为0x4000,然后调用ZwQuerySystemInformation根据返回的数指决定接下的处理;成功返回系统信息内容。
2, 附加进程
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
USHORT UniqueProcessId;//进程号
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
NTSTATUS
ZwQueryObject(
__in_opt HANDLE Handle,
__in OBJECT_INFORMATION_CLASS ObjectInformationClass,
__out_bcount_opt(ObjectInformationLength) PVOID ObjectInformation,
__in ULONG ObjectInformationLength,
__out_opt PULONG ReturnLength
);
typedef enum _OBJECT_INFORMATION_CLASS {
ObjectBasicInformation,
ObjectNameInformation,//1
ObjectTypeInformation,
ObjectTypesInformation,
ObjectHandleFlagInformation,
ObjectSessionInformation,
ObjectSessionObjectInformation,
MaxObjectInfoClass
} OBJECT_INFORMATION_CLASS;
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION
函数原型:NTSTATUS AttachProcess(PKPROCESS Process,PRKAPC_STATE ApcState);
解释:首先判断ProcessId是否合法,如果合法,(最开始的部分这里)AllocatePool1()--->ApcState,PsLookupProcessByProcessId---->Process,
KeStackAttachProcess(Process,ApcState);如果不合法,GetSystemInformation--->HandleInformation,解析获得句柄信息,
KeStackAttachProcess,ZwQueryObject---->NameInformation,KeUnstackDetachProcess,比较对象名是否为"\Windows\ApiPort",
如果相同,保存当前句柄信息中进程号,接着执行最开始的部分;否则继续解析句柄信息。
2019-08-03
3, NTSTATUS CallDriverEntryInMemory(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath);
解释:根据DriverObject里的相关信息,在内存中创建一份新的镜像,然后找到pe文件入口也就是DriverEntry并调用。如果返回status_success,就把这份新镜像的"MZ","PE"标示给抹掉并强制返回status_cancelled;如果返回不是status_success ,就把新镜像给释放掉并把原错误返回。当新驱动的DriverEntry成功执行后,可以看到rootkit作者对一些敏感信息做了处理。这份新的镜像应该还在内存中运行,而由于CallDriverEntryInMemory返回status_cancelled给最开始的DriverEntry,导致驱动异常退出。
2019-08-04
typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY64
{ PVOID64 Section;
PVOID64 MappedBase;
PVOID64 ImageBase;//0X10
ULONG ImageSize;//0X18
ULONG Flag;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[0x100];//0X28
}SYSTEM_MODULE_INFORMATION_ENTRY64,
2019-08-08
4,获取进程的文件镜像名称
BOOLEAN GetProcessImageNameByProcessId(ULONG ProcessId,WCHAR* buffer,ULONG BufferLength);
解释:第一步会起一个线程计算出ImageFileName在_EPROCESS结构中的偏移,第二步根据ProcessId获取其EPROCESS然后将ImageFileName拷贝。
VOID GetImageFileNameOffsetInEPROCESS(PVOID StartContext)
一般情况下驱动运行的当前进程是system进程,通过内存中数据比对来确认ImageFileName的偏移。
2019-08-09
5,(进程间)内存读写
NTSTATUS ReadWriteMemory(HANDLE ProcessHandle,PVOID64 Address,PVOID64 buffer,
ULONG64 LenthToReadWrite,ULONG64 LengthReadWritten,BOOLEAN ReadOrWrite);
.text:0000000000030A54 ; =============== S U B R O U T I N E =======================================
.text:0000000000030A54
.text:0000000000030A54
.text:0000000000030A54 ReadWriteMemory proc near ; CODE XREF: ReadMemory+16p
.text:0000000000030A54 ; WriteMemory+16p
.text:0000000000030A54 ; DATA XREF: ...
.text:0000000000030A54
.text:0000000000030A54 Object = qword ptr -98h
.text:0000000000030A54 HandleInformation= qword ptr -90h
.text:0000000000030A54 var_88 = dword ptr -88h
.text:0000000000030A54 var_84 = dword ptr -84h
.text:0000000000030A54 var_80 = qword ptr -80h
.text:0000000000030A54 var_78 = qword ptr -78h
.text:0000000000030A54 var_70 = qword ptr -70h
.text:0000000000030A54 var_68 = byte ptr -68h
.text:0000000000030A54 arg_18 = dword ptr 20h
.text:0000000000030A54 arg_20 = qword ptr 28h
.text:0000000000030A54 arg_28 = dword ptr 30h
.text:0000000000030A54
.text:0000000000030A54 push rsi
.text:0000000000030A56 push rdi
.text:0000000000030A57 push r12
.text:0000000000030A59 push r13
.text:0000000000030A5B push r14
.text:0000000000030A5D push r15
.text:0000000000030A5F sub rsp, 88h
.text:0000000000030A66 mov r13d, r9d ; length
.text:0000000000030A69 mov r15, r8
.text:0000000000030A6C mov r14, rdx
.text:0000000000030A6F xor r12d, r12d
.text:0000000000030A72 mov [rsp+0B8h+var_80], r12
.text:0000000000030A77 xor esi, esi
.text:0000000000030A79 mov [rsp+0B8h+var_78], rsi
.text:0000000000030A7E mov [rsp+0B8h+arg_18], esi
.text:0000000000030A85 mov [rsp+0B8h+var_88], esi
.text:0000000000030A89 test r9d, r9d
.text:0000000000030A8C jnz short loc_30A95
.text:0000000000030A8E xor eax, eax
.text:0000000000030A90 jmp loc_30C46
.text:0000000000030A95 ; ---------------------------------------------------------------------------
.text:0000000000030A95
.text:0000000000030A95 loc_30A95: ; CODE XREF: ReadWriteMemory+38j
.text:0000000000030A95 mov [rsp+0B8h+HandleInformation], rsi ; HandleInformation
.text:0000000000030A9A lea rax, [rsp+0B8h+var_70] ; ProcessObject
.text:0000000000030A9F mov [rsp+0B8h+Object], rax ; Object
.text:0000000000030AA4 xor r9d, r9d ; AccessMode
.text:0000000000030AA7 xor r8d, r8d ; ObjectType
.text:0000000000030AAA xor edx, edx ; DesiredAccess
.text:0000000000030AAC call cs:ObReferenceObjectByHandle
.text:0000000000030AB2 test eax, eax
.text:0000000000030AB4 js loc_30C46
.text:0000000000030ABA call cs:IoGetCurrentProcess
.text:0000000000030AC0 cmp [rsp+0B8h+var_70], rax
.text:0000000000030AC5 jz loc_30BAE ; target process is the current process
.text:0000000000030ACB mov [rsp+0B8h+Object], rsi ; Irp
.text:0000000000030AD0 xor r9d, r9d ; ChargeQuota
.text:0000000000030AD3 xor r8d, r8d ; SecondaryBuffer
.text:0000000000030AD6 mov edx, r13d ; Length
.text:0000000000030AD9 mov rcx, r15 ; VirtualAddress
.text:0000000000030ADC call cs:IoAllocateMdl
.text:0000000000030AE2 mov rsi, rax
.text:0000000000030AE5 mov [rsp+0B8h+var_78], rax
.text:0000000000030AEA test rax, rax
.text:0000000000030AED jnz short loc_30AF9
.text:0000000000030AEF mov edi, 0C000009Ah ; status_insufficient_resources
.text:0000000000030AF4 jmp loc_30BF5
.text:0000000000030AF9 ; ---------------------------------------------------------------------------
.text:0000000000030AF9
.text:0000000000030AF9 loc_30AF9: ; CODE XREF: ReadWriteMemory+99j
.text:0000000000030AF9 lea rdx, [rsp+0B8h+var_68]
.text:0000000000030AFE mov rcx, [rsp+0B8h+var_70]
.text:0000000000030B03 call cs:KeStackAttachProcess ; attach to target process
.text:0000000000030B09 mov [rsp+0B8h+arg_18], 1 ; attached.
.text:0000000000030B14
.text:0000000000030B14 loc_30B14: ; DATA XREF: .text:0000000000067260o
.text:0000000000030B14 xor r8d, r8d
.text:0000000000030B17 cmp [rsp+0B8h+arg_28], r8d
.text:0000000000030B1F setnz r8b ; Operation
.text:0000000000030B23 xor edx, edx ; AccessMode
.text:0000000000030B25 mov rcx, rsi ; MemoryDescriptorList
.text:0000000000030B28 call cs:MmProbeAndLockPages ; IoWriteAccess=0x1
.text:0000000000030B2E mov [rsp+0B8h+var_88], 1
.text:0000000000030B36 mov dword ptr [rsp+0B8h+HandleInformation], 10h ; Priority
.text:0000000000030B3E mov dword ptr [rsp+0B8h+Object], 0 ; BugCheckOnFailure
.text:0000000000030B46 xor r9d, r9d ; BaseAddress
.text:0000000000030B49 xor edx, edx ; AccessMode
.text:0000000000030B4B lea r8d, [r9+1] ; CacheType
.text:0000000000030B4F mov rcx, rsi ; MemoryDescriptorList
.text:0000000000030B52 call cs:MmMapLockedPagesSpecifyCache
.text:0000000000030B58 mov r12, rax ; mapped!
.text:0000000000030B5B mov [rsp+0B8h+var_80], rax
.text:0000000000030B60 test rax, rax
.text:0000000000030B63 jnz short loc_30B73 ; 1 to read,0 to write!
.text:0000000000030B65 mov edi, 0C000009Ah
.text:0000000000030B6A mov [rsp+0B8h+var_84], edi
.text:0000000000030B6E jmp loc_30BF5
.text:0000000000030B73 ; ---------------------------------------------------------------------------
.text:0000000000030B73
.text:0000000000030B73 loc_30B73: ; CODE XREF: ReadWriteMemory+10Fj
.text:0000000000030B73 cmp [rsp+0B8h+arg_28], 0 ; 1 to read,0 to write!
.text:0000000000030B7B jz short loc_30B8D
.text:0000000000030B7D mov r8, r13 ; Size
.text:0000000000030B80 mov rdx, r14 ; Src
.text:0000000000030B83 mov rcx, rax ; Dst
.text:0000000000030B86 call memcpy
.text:0000000000030B8B jmp short loc_30B9C
.text:0000000000030B8D ; ---------------------------------------------------------------------------
.text:0000000000030B8D
.text:0000000000030B8D loc_30B8D: ; CODE XREF: ReadWriteMemory+127j
.text:0000000000030B8D mov r8, r13 ; Size
.text:0000000000030B90 mov rdx, rax ; Src
.text:0000000000030B93 mov rcx, r14 ; Dst
.text:0000000000030B96 call memcpy
.text:0000000000030B9B nop
.text:0000000000030B9C
.text:0000000000030B9C loc_30B9C: ; CODE XREF: ReadWriteMemory+137j
.text:0000000000030B9C ; DATA XREF: .text:0000000000067260o
.text:0000000000030B9C xor edi, edi
.text:0000000000030B9E jmp short loc_30BF5
.text:0000000000030BA0 ; ---------------------------------------------------------------------------
.text:0000000000030BA0
.text:0000000000030BA0 loc_30BA0: ; DATA XREF: .text:0000000000067260o
.text:0000000000030BA0 mov edi, eax
.text:0000000000030BA2 mov r12, [rsp+0B8h+var_80]
.text:0000000000030BA7 mov rsi, [rsp+0B8h+var_78]
.text:0000000000030BAC jmp short loc_30BF5
.text:0000000000030BAE ; ---------------------------------------------------------------------------
.text:0000000000030BAE
.text:0000000000030BAE loc_30BAE: ; CODE XREF: ReadWriteMemory+71j
.text:0000000000030BAE xor edi, edi
.text:0000000000030BB0
.text:0000000000030BB0 loc_30BB0: ; DATA XREF: .text:0000000000067270o
.text:0000000000030BB0 cmp [rsp+0B8h+arg_28], edi
.text:0000000000030BB7 jz short loc_30BC9
.text:0000000000030BB9 mov r8, r13 ; Size
.text:0000000000030BBC mov rdx, r14 ; Src
.text:0000000000030BBF mov rcx, r15 ; Dst
.text:0000000000030BC2 call memcpy
.text:0000000000030BC7 jmp short loc_30BD7
.text:0000000000030BC9 ; ---------------------------------------------------------------------------
.text:0000000000030BC9
.text:0000000000030BC9 loc_30BC9: ; CODE XREF: ReadWriteMemory+163j
.text:0000000000030BC9 mov r8, r13 ; Size
.text:0000000000030BCC mov rdx, r15 ; Src
.text:0000000000030BCF mov rcx, r14 ; Dst
.text:0000000000030BD2 call memcpy
.text:0000000000030BD7
.text:0000000000030BD7 loc_30BD7: ; CODE XREF: ReadWriteMemory+173j
.text:0000000000030BD7 mov rax, [rsp+0B8h+arg_20]
.text:0000000000030BDF test rax, rax
.text:0000000000030BE2 jz short loc_30BE7
.text:0000000000030BE4 mov [rax], r13d;LengthReadWritten
.text:0000000000030BE7
.text:0000000000030BE7 loc_30BE7: ; CODE XREF: ReadWriteMemory+18Ej
.text:0000000000030BE7 jmp short loc_30BF5
.text:0000000000030BE9 ; ---------------------------------------------------------------------------
.text:0000000000030BE9
.text:0000000000030BE9 loc_30BE9: ; DATA XREF: .text:0000000000067270o
.text:0000000000030BE9 mov edi, eax
.text:0000000000030BEB mov r12, [rsp+0B8h+var_80]
.text:0000000000030BF0 mov rsi, [rsp+0B8h+var_78]
.text:0000000000030BF5
.text:0000000000030BF5 loc_30BF5: ; CODE XREF: ReadWriteMemory+A0j
.text:0000000000030BF5 ; ReadWriteMemory+11Aj ...
.text:0000000000030BF5 test r12, r12
.text:0000000000030BF8 jz short loc_30C06
.text:0000000000030BFA mov rdx, rsi ; MemoryDescriptorList
.text:0000000000030BFD mov rcx, r12 ; BaseAddress
.text:0000000000030C00 call cs:MmUnmapLockedPages
.text:0000000000030C06
.text:0000000000030C06 loc_30C06: ; CODE XREF: ReadWriteMemory+1A4j
.text:0000000000030C06 cmp [rsp+0B8h+var_88], 0
.text:0000000000030C0B jz short loc_30C16 ; is attached?
.text:0000000000030C0D mov rcx, rsi ; MemoryDescriptorList
.text:0000000000030C10 call cs:MmUnlockPages
.text:0000000000030C16
.text:0000000000030C16 loc_30C16: ; CODE XREF: ReadWriteMemory+1B7j
.text:0000000000030C16 cmp [rsp+0B8h+arg_18], 0 ; is attached?
.text:0000000000030C1E jz short loc_30C2B
.text:0000000000030C20 lea rcx, [rsp+0B8h+var_68]
.text:0000000000030C25 call cs:KeUnstackDetachProcess
.text:0000000000030C2B
.text:0000000000030C2B loc_30C2B: ; CODE XREF: ReadWriteMemory+1CAj
.text:0000000000030C2B test rsi, rsi
.text:0000000000030C2E jz short loc_30C39
.text:0000000000030C30 mov rcx, rsi ; Mdl
.text:0000000000030C33 call cs:IoFreeMdl
.text:0000000000030C39
.text:0000000000030C39 loc_30C39: ; CODE XREF: ReadWriteMemory+1DAj
.text:0000000000030C39 mov rcx, [rsp+0B8h+var_70] ; Object
.text:0000000000030C3E call cs:ObfDereferenceObject
.text:0000000000030C44 mov eax, edi
.text:0000000000030C46
.text:0000000000030C46 loc_30C46: ; CODE XREF: ReadWriteMemory+3Cj
.text:0000000000030C46 ; ReadWriteMemory+60j
.text:0000000000030C46 add rsp, 88h
.text:0000000000030C4D pop r15
.text:0000000000030C4F pop r14
.text:0000000000030C51 pop r13
.text:0000000000030C53 pop r12
.text:0000000000030C55 pop rdi
.text:0000000000030C56 pop rsi
.text:0000000000030C57 retn
.text:0000000000030C57 ReadWriteMemory endp
.text:0000000000030C57
解释:首先判断LengthToReadWrite是否合法,接着调用ObReferenceObjectByHandle获得ProcessHandle所指的进程对象,并 将该对象与当前进程对象比较。如果相等就表示接下来的内存读写都在同一进程环境下,可以直接memcpy;否则,先IoAllocateMdl(buffer,****),再KeStackAttachProcess,接MmProbeAndLockPages(*,*,IoWriteAccess/IoReadAccess)+MmMapLockedPagesSpecifyCache,最后根据读写请求在memcpy中调整Address和buffer的位置。重点注意:在目标进程不是当前进程时,先要在当前进程中将buffer与mdl对应起来,再附加到目标进程(可以试验一下,调换先后循序)。如果是读请求,MmProbeAndLockPages(*,*,IoWriteAccess),'读'是从目标进程读,然后写到buffer中,这里IoWriteAccess是对于buffer的;写请求相反。
2019-8-12
(win10 1903)
typedef enum _ndis_request_type
{
NdisRequestQueryInformation=0,
NdisRequestSetInformation=1,
NdisRequestQueryStatistics=2,
NdisRequestOpen=3,
NdisRequestClose=4,
NdisRequestSend=5,
NdisRequestTransferData=6,
NdisRequestReset=7,
NdisRequestGeneric1=8,
NdisRequestGeneric2=9,
NdisRequestGeneric3=10,
NdisRequestGeneric4=11,
NdisRequestMethod=12
}NDIS_REQUEST_TYPE,*PNDIS_REQUEST_TYPE;
typedef struct _ndis_request
{
UCHAR MacReserved[32]; //0X0
NDIS_REQUEST_TYPE RequestType; //0X20
NDIS_REQUEST::DATA Data; //0X28
UCHAR NdisReserved[72]; //0X48
union //0X90
{
UCHAR CallMgrReserved[16];
UCHAR ProtocolReserved[16];
};
UCHAR MiniportReserved[16]; //0xa0
}NDIS_REQUEST,*PNDIS_REQUEST;
typedef struct _NDIS_REQUEST::_DATA
{
union
{
NDIS_REQUEST::DATA::QUERY_INFORMATION QUERY_INFORMATION;
NDIS_REQUEST::DATA::SET_INFORMATION SET_INFORMATION;
};
}NDIS_REQUEST::DATA;*NDIS_REQUEST::PDATA;
typedef sturct _ndis_request::_data::_set_information
{
ULONG Oid;//0x0
PVOID64 InformationBuffer;//0x8
ULONG InformationBufferLength;//0x10;
ULONG BytesRead;//0x14
ULONG BytesNeeded;//0x18
}NDIS_REQUEST::DATA::SET_INFORMATION,*NDIS_REQUEST::DATA::PSET_INFORMATION;
typedef struct _ndis_request::_data::_query_information
{
ULONG Oid;//0x0
PVOID64 InformationBuffer;//0x8
ULONG InformationBufferLength;//0x10;
ULONG BytesWritten;//0x14
ULONG BytesNeeded;//0x18
}NDIS_REQUEST::DATA::QUERY_INFORMATION;*NDIS_REQUEST::DATA::PQUERY_INFORMATION;
2019-08-14
6,线程执行
8F4 ; void __stdcall StartRoutine(PVOID StartContext)
.text:000000000001A8F4 StartRoutine proc near ; DATA XREF: RunInThread+8Bo
.text:000000000001A8F4 ; .pdata:000000000008F2A0o ...
.text:000000000001A8F4 push rbx
.text:000000000001A8F6 push rbp
.text:000000000001A8F7 push rsi
.text:000000000001A8F8 push rdi
.text:000000000001A8F9 push r12
.text:000000000001A8FB push r13
.text:000000000001A8FD push r14
.text:000000000001A8FF push r15
.text:000000000001A901 sub rsp, 28h
.text:000000000001A905 mov r13, rcx
.text:000000000001A908 call KeGetCurrentThread ; returns pkthread.
.text:000000000001A90D mov r14, [r13+0] ; sub_***
.text:000000000001A911 mov r15, [r13+8] ; ProcessId
.text:000000000001A915 mov rbx, rax
.text:000000000001A918 xor eax, eax
.text:000000000001A91A mov rsi, rax
.text:000000000001A91D mov rdi, rax
.text:000000000001A920 mov r12, rax
.text:000000000001A923 mov rbp, rax
.text:000000000001A926 call rand;产生随机数据用来填充到_ethread中的StartAddress
.text:000000000001A92B mov rdx, cs:off_69080
.text:000000000001A932 movsxd r8, eax
.text:000000000001A935 xor eax, eax
.text:000000000001A937 add r8, [rdx+10h]
.text:000000000001A93B xor ecx, ecx
.text:000000000001A93D lock cmpxchg cs:qword_7E250, rcx
.text:000000000001A946 jz short loc_1A957
.text:000000000001A948 mov rsi, cs:qword_7E250
.text:000000000001A94F mov r12, [rsi+rbx];保存原来的StartAddress到r12
.text:000000000001A953 mov [rsi+rbx], r8
.text:000000000001A957
.text:000000000001A957 loc_1A957: ; CODE XREF: StartRoutine+52j
.text:000000000001A957 xor eax, eax
.text:000000000001A959 lock cmpxchg cs:qword_7E258, rcx
.text:000000000001A962 jz short loc_1A973
.text:000000000001A964 mov rdi, cs:qword_7E258
.text:000000000001A96B mov rbp, [rdi+rbx]
.text:000000000001A96F mov [rdi+rbx], r8 ; fill StartAddress in _ethread with random data
.text:000000000001A973
.text:000000000001A973 loc_1A973: ; CODE XREF: StartRoutine+6Ej
.text:000000000001A973 mov rcx, r13
.text:000000000001A976 call FreePool
.text:000000000001A97B mov rcx, r15 ; ProcessId
.text:000000000001A97E call r14 ;执行真正的线程 函数
.text:000000000001A981 xor ecx, ecx
.text:000000000001A983 cmp r12, rcx
.text:000000000001A986 jz short loc_1A98C
.text:000000000001A988 mov [rsi+rbx], r12;还原StartAddress
.text:000000000001A98C
.text:000000000001A98C loc_1A98C: ; CODE XREF: StartRoutine+92j
.text:000000000001A98C cmp rbp, rcx
.text:000000000001A98F jz short loc_1A995
.text:000000000001A991 mov [rdi+rbx], rbp
.text:000000000001A995
.text:000000000001A995 loc_1A995: ; CODE XREF: StartRoutine+9Bj
.text:000000000001A995 mov ecx, eax
.text:000000000001A997 add rsp, 28h
.text:000000000001A99B pop r15
.text:000000000001A99D pop r14
.text:000000000001A99F pop r13
.text:000000000001A9A1 pop r12
.text:000000000001A9A3 pop rdi
.text:000000000001A9A4 pop rsi
.text:000000000001A9A5 pop rbp
.text:000000000001A9A6 pop rbx
.text:000000000001A9A7 jmp cs:PsTerminateSystemThread
.text:000000000001A9A7 StartRoutine endp
解释:PsCreateSystemThread时通过StartContext传入参数块,在StartRoutine中将当前线程的_ethread中StartAddress用随机数填充(估计是为了隐蔽),然后调用StartContext中的函数,最后还原。
2019-08-15
VOID STDCALL KeInitializeApc(PKAPC Apc,
PKTHREAD Thread,
KAPC_ENVIRONMENT TargetEnvironment,
PKERNEL_ROUTINE KernelRoutine,
PKRUNDOWN_ROUTINE RundownRoutine,
PKNORMAL_ROUTINE NormalRoutine,
KPROCESSOR_MODE Mode,
PVOID Context);
BOOLEAN NTAPI KeInsertQueueApc(PKAPC Apc,
PVOID SystemArgument1,PVOID SystemArgument2,
KPRIORITY PriorityBoost);