基于windows的内存分页机制,进程间的隔离让我们无法直接读写其他进程的地址空间,又因为copy on write让我们即使patch了系统dll也无法影响其他进程。但是这一根内存条就插在主板上,就不能有个方法能看到内容么? 在裸机上如果没有定制的外设是无解了,但是在虚拟化的框架下,这一切都显得再正常不过。
在虚拟化的框架下,客户机的“内存条”实际上是宿主机上申请的一段普通内存,如果我们能够找到GVA与HVA之间的映射关系,就可以绕开任何限制,直接在宿主机上读写任意位置的客户机内存。
我们先暂停vm后,通过KVM_GET_SREGS即可获取cr3寄存器。
gs寄存器在R0下存放的是KPCR,在R3下存放的是TEB
通过偏移计算KTHREAD->KPROCESS->EPROCESS->active_process_links获得这个进程双链表结构,通过遍历active_process_links我们可以获取当前系统所有进程,包括每个进程的CR3。
关于windows的分页机制,文档很多不赘述直接贴出部分代码
在能够获取所有进程cr3后,加上页表解析,可以轻松的在host上读写任意guest内存。当我们尝试在host抹掉guest进程notepad中的ntdll的PE头后,由于系统dll的特殊性加上直接修改了物理内存,系统也随之陷入一片混乱
https://github.com/tenclass/mvisor 使用右ctrl+F8唤起debug窗口,目前仅支持win10 guest。
machine_
-
>Pause();
bool
success
=
false;
for
(auto vcpu : machine_
-
>vcpus()) {
struct kvm_sregs sregs;
if
(ioctl(vcpu
-
>fd(), KVM_GET_SREGS, &sregs) <
0
)
MV_PANIC(
"KVM_GET_REGS failed"
);
...
machine_
-
>Pause();
bool
success
=
false;
for
(auto vcpu : machine_
-
>vcpus()) {
struct kvm_sregs sregs;
if
(ioctl(vcpu
-
>fd(), KVM_GET_SREGS, &sregs) <
0
)
MV_PANIC(
"KVM_GET_REGS failed"
);
...
...
if
((sregs.cs.base &
3
) !
=
0
) {
MV_LOG(
"current vcpu=%d is in usermode"
, vcpu
-
>vcpu_id());
continue
;
}
auto kpcr
=
(uint8_t
*
)GuestVAToHostAddress((uint64_t)sregs.gs.base, sregs.cr3);
...
...
if
((sregs.cs.base &
3
) !
=
0
) {
MV_LOG(
"current vcpu=%d is in usermode"
, vcpu
-
>vcpu_id());
continue
;
}
auto kpcr
=
(uint8_t
*
)GuestVAToHostAddress((uint64_t)sregs.gs.base, sregs.cr3);
...
/
/
0xb080
bytes (sizeof)
struct _KPCR
{
union
{
struct _NT_TIB NtTib;
/
/
0x0
struct
{
union _KGDTENTRY64
*
GdtBase;
/
/
0x0
struct _KTSS64
*
TssBase;
/
/
0x8
ULONGLONG UserRsp;
/
/
0x10
struct _KPCR
*
Self;
/
/
0x18
struct _KPRCB
*
CurrentPrcb;
/
/
0x20
struct _KSPIN_LOCK_QUEUE
*
LockArray;
/
/
0x28
VOID
*
Used_Self;
/
/
0x30
};
};
union _KIDTENTRY64
*
IdtBase;
/
/
0x38
ULONGLONG Unused[
2
];
/
/
0x40
UCHAR Irql;
/
/
0x50
UCHAR SecondLevelCacheAssociativity;
/
/
0x51
UCHAR ObsoleteNumber;
/
/
0x52
UCHAR Fill0;
/
/
0x53
ULONG Unused0[
3
];
/
/
0x54
USHORT MajorVersion;
/
/
0x60
USHORT MinorVersion;
/
/
0x62
ULONG StallScaleFactor;
/
/
0x64
VOID
*
Unused1[
3
];
/
/
0x68
ULONG KernelReserved[
15
];
/
/
0x80
ULONG SecondLevelCacheSize;
/
/
0xbc
ULONG HalReserved[
16
];
/
/
0xc0
ULONG Unused2;
/
/
0x100
VOID
*
KdVersionBlock;
/
/
0x108
VOID
*
Unused3;
/
/
0x110
ULONG PcrAlign1[
24
];
/
/
0x118
struct _KPRCB Prcb;
/
/
0x180
};
/
/
0x700
bytes (sizeof)
struct _KPRCB
{
ULONG MxCsr;
/
/
0x0
UCHAR LegacyNumber;
/
/
0x4
UCHAR ReservedMustBeZero;
/
/
0x5
UCHAR InterruptRequest;
/
/
0x6
UCHAR IdleHalt;
/
/
0x7
struct _KTHREAD
*
CurrentThread;
/
/
0x8
struct _KTHREAD
*
NextThread;
/
/
0x10
struct _KTHREAD
*
IdleThread;
/
/
0x18
UCHAR NestingLevel;
/
/
0x20
UCHAR ClockOwner;
/
/
0x21
union
{
UCHAR PendingTickFlags;
/
/
0x22
struct
{
UCHAR PendingTick:
1
;
/
/
0x22
UCHAR PendingBackupTick:
1
;
/
/
0x22
};
};
UCHAR IdleState;
/
/
0x23
ULONG Number;
/
/
0x24
ULONGLONG RspBase;
/
/
0x28
ULONGLONG PrcbLock;
/
/
0x30
CHAR
*
PriorityState;
/
/
0x38
CHAR CpuType;
/
/
0x40
CHAR CpuID;
/
/
0x41
union
{
USHORT CpuStep;
/
/
0x42
struct
{
UCHAR CpuStepping;
/
/
0x42
UCHAR CpuModel;
/
/
0x43
};
};
ULONG MHz;
/
/
0x44
ULONGLONG HalReserved[
8
];
/
/
0x48
USHORT MinorVersion;
/
/
0x88
USHORT MajorVersion;
/
/
0x8a
UCHAR BuildType;
/
/
0x8c
UCHAR CpuVendor;
/
/
0x8d
UCHAR LegacyCoresPerPhysicalProcessor;
/
/
0x8e
UCHAR LegacyLogicalProcessorsPerCore;
/
/
0x8f
ULONGLONG TscFrequency;
/
/
0x90
ULONG CoresPerPhysicalProcessor;
/
/
0x98
ULONG LogicalProcessorsPerCore;
/
/
0x9c
ULONGLONG PrcbPad04[
4
];
/
/
0xa0
struct _KNODE
*
ParentNode;
/
/
0xc0
ULONGLONG GroupSetMember;
/
/
0xc8
UCHAR Group;
/
/
0xd0
UCHAR GroupIndex;
/
/
0xd1
UCHAR PrcbPad05[
2
];
/
/
0xd2
ULONG InitialApicId;
/
/
0xd4
ULONG ScbOffset;
/
/
0xd8
ULONG ApicMask;
/
/
0xdc
VOID
*
AcpiReserved;
/
/
0xe0
ULONG CFlushSize;
/
/
0xe8
ULONGLONG PrcbPad11[
2
];
/
/
0xf0
struct _KPROCESSOR_STATE ProcessorState;
/
/
0x100
struct _XSAVE_AREA_HEADER
*
ExtendedSupervisorState;
/
/
0x6c0
ULONG ProcessorSignature;
/
/
0x6c8
ULONG ProcessorFlags;
/
/
0x6cc
ULONGLONG PrcbPad12a;
/
/
0x6d0
ULONGLONG PrcbPad12[
3
];
/
/
0x6d8
};
/
/
0xb080
bytes (sizeof)
struct _KPCR
{
union
{
struct _NT_TIB NtTib;
/
/
0x0
struct
{
union _KGDTENTRY64
*
GdtBase;
/
/
0x0
struct _KTSS64
*
TssBase;
/
/
0x8
ULONGLONG UserRsp;
/
/
0x10
struct _KPCR
*
Self;
/
/
0x18
struct _KPRCB
*
CurrentPrcb;
/
/
0x20
struct _KSPIN_LOCK_QUEUE
*
LockArray;
/
/
0x28
VOID
*
Used_Self;
/
/
0x30
};
};
union _KIDTENTRY64
*
IdtBase;
/
/
0x38
ULONGLONG Unused[
2
];
/
/
0x40
UCHAR Irql;
/
/
0x50
UCHAR SecondLevelCacheAssociativity;
/
/
0x51
UCHAR ObsoleteNumber;
/
/
0x52
UCHAR Fill0;
/
/
0x53
ULONG Unused0[
3
];
/
/
0x54
USHORT MajorVersion;
/
/
0x60
USHORT MinorVersion;
/
/
0x62
ULONG StallScaleFactor;
/
/
0x64
VOID
*
Unused1[
3
];
/
/
0x68
ULONG KernelReserved[
15
];
/
/
0x80
ULONG SecondLevelCacheSize;
/
/
0xbc
ULONG HalReserved[
16
];
/
/
0xc0
ULONG Unused2;
/
/
0x100
VOID
*
KdVersionBlock;
/
/
0x108
VOID
*
Unused3;
/
/
0x110
ULONG PcrAlign1[
24
];
/
/
0x118
struct _KPRCB Prcb;
/
/
0x180
};
/
/
0x700
bytes (sizeof)
struct _KPRCB
{
ULONG MxCsr;
/
/
0x0
UCHAR LegacyNumber;
/
/
0x4
UCHAR ReservedMustBeZero;
/
/
0x5
UCHAR InterruptRequest;
/
/
0x6
UCHAR IdleHalt;
/
/
0x7
struct _KTHREAD
*
CurrentThread;
/
/
0x8
struct _KTHREAD
*
NextThread;
/
/
0x10
struct _KTHREAD
*
IdleThread;
/
/
0x18
UCHAR NestingLevel;
/
/
0x20
UCHAR ClockOwner;
/
/
0x21
union
{
UCHAR PendingTickFlags;
/
/
0x22
struct
{
UCHAR PendingTick:
1
;
/
/
0x22
UCHAR PendingBackupTick:
1
;
/
/
0x22
};
};
UCHAR IdleState;
/
/
0x23
ULONG Number;
/
/
0x24
ULONGLONG RspBase;
/
/
0x28
ULONGLONG PrcbLock;
/
/
0x30
CHAR
*
PriorityState;
/
/
0x38
CHAR CpuType;
/
/
0x40
CHAR CpuID;
/
/
0x41
union
{
USHORT CpuStep;
/
/
0x42
struct
{
UCHAR CpuStepping;
/
/
0x42
UCHAR CpuModel;
/
/
0x43
};
};
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2024-9-27 13:39
被Justgoon编辑
,原因: