这次来说说如何简单的使用KSM来解决非法Hook的问题。
比如游戏中. 攻击->判断攻击中->发包->完毕 直接Hook导致多倍发包,严重影响游戏平衡。常用的CRc也很好被针对。这里就要提一下利用VT ept技术来解决这个问题了
首先创建一个EPTP 并且把其中在该应用需要被保护的代码段的所有gpa的权限全部改为ept only exec
参数 ksm pid cr3 模块基地址va 被保护的大小(这是之前的demo很不靠谱最好不要用这个方案 测试可行性还行)
static inline int create_sa_task(struct ksm *k, pid_t pid, u64 pgd,u64 base,u64 size)
{
struct sa_task *task;
int i;

task = mm_alloc_pool(sizeof(*task));
if (!task)
return ERR_NOMEM;
task->isunload = FALSE;
task->pgd = pgd;
task->pid = pid;
task->base = base;
task->size = size;
task->phy = mm_alloc_page();
memset(task->phy, 0xcc, PAGE_SIZE);
INIT_LIST_HEAD(&task->pages);
spin_lock_init(&task->lock);
for (i = 0; i < KSM_MAX_VCPUS; ++i) task->eptp[i] = EPT_MAX_EPTP_LIST;

spin_lock(&k->task_lock);
list_add(&task->link, &k->task_list);
spin_unlock(&k->task_lock);
return 0;
}

void ksm_sandbox_handle_cr3(struct vcpu *vcpu, u64 cr3)
{
struct ksm *k;
struct sa_task *task;
u16 *eptp;

k = vcpu_to_ksm(vcpu);
spin_lock(&k->task_lock);
task = __find_sa_task_pgd(k, cr3 & PAGE_PA_MASK);根据当前的CR3看看是否已经被添加到task
spin_unlock(&k->task_lock);

if (task) {存在
eptp = &task->eptp[cpu_nr()];获取eptp
if (*eptp == EPT_MAX_EPTP_LIST)
BUG_ON(!ept_create_ptr(&vcpu->ept, EPT_ACCESS_EXEC, eptp));创建新的eptp 权限为ept only exec 读写时将陷入ept ve

vcpu->last_switch = task;//保存到Last task
vcpu->eptp_before = vcpu_eptp_idx(vcpu);//这是当前的
if (!task->isunload)
{
vcpu_switch_root_eptp(vcpu, *eptp);//切换Eptp
}

} else if (vcpu->last_switch) {//是否存在last task
vcpu_switch_root_eptp(vcpu, vcpu->eptp_before);//切换到之前的
vcpu->last_switch = NULL;
}
}
这样就在切换到指定的CR3时创建了针对该CR3的 Eptp

bool ksm_sandbox_handle_ept(struct ept_ve_around *ve)
{
struct sa_task *task;
struct cow_page *page;
struct ve_except_info *info;
struct vcpu *vcpu;
struct ept *ept;
struct ksm *k;
u64 *epte;
u64 mhpa;
vcpu = ve->vcpu;
ept = &vcpu->ept;
info = ve->info;
k = vcpu_to_ksm(vcpu);

spin_lock(&k->task_lock);
task = __find_sa_task_eptp(k, info->eptp);
spin_unlock(&k->task_lock);
if (!task) {
ve->eptp_next = EPTP_DEFAULT;
BREAK_ON(1);
return true;
}

epte = ept_pte(EPT4(ept, info->eptp), info->gpa);
BUG_ON(!epte);
//DbgPrint("EPTP SANDBOXER GLA:/n", info->gla);

if (task->isunload )
{
DbgPrint("保护模块已关闭 READ:/n", info->gla);
//goto unload;
}

if (info->gla>(task->base+(PAGE_SIZE*10)) && info->gla<(task->base+ task->size))
{
//在被保护的模块内

if (info->exit & EPT_ACCESS_READ){
if((PsGetCurrentProcessId()!=4 )&& (PsGetCurrentProcessId()!=task->pid )){
// DbgPrint("保护模块内 GLA READ:/n", info->gla);
__set_epte_ar_inplace(epte, EPT_ACCESS_RW);

gpa_to_hpa(vcpu, va_to_pa(task->phy), &mhpa);
__set_epte_pfn(epte, mhpa >> PAGE_SHIFT);

}
else
{
__set_epte_ar_inplace(epte, EPT_ACCESS_RW);
gpa_to_hpa(vcpu, info->gpa, &mhpa);
__set_epte_pfn(epte, mhpa >> PAGE_SHIFT);
}

}
top:
if (info->exit & EPT_ACCESS_WRITE) {

if ((PsGetCurrentProcessId() != 4) &&( PsGetCurrentProcessId() != task->pid)) {
//DbgPrint("保护模块内 GLA Write:/n", info->gla);
__set_epte_ar_inplace(epte, EPT_ACCESS_RW);

gpa_to_hpa(vcpu, va_to_pa(task->phy), &mhpa);
__set_epte_pfn(epte, mhpa >> PAGE_SHIFT);

}
else
{
__set_epte_ar_inplace(epte, EPT_ACCESS_RW);
gpa_to_hpa(vcpu, info->gpa, &mhpa);
__set_epte_pfn(epte, mhpa >> PAGE_SHIFT);
}

}
if (info->exit & EPT_ACCESS_EXEC) {
// DbgPrint("保护模块内 GLA EXEC:/n", info->gla);
__set_epte_ar_inplace(epte, EPT_ACCESS_EXEC);
gpa_to_hpa(vcpu, info->gpa, &mhpa);
__set_epte_pfn(epte, mhpa >> PAGE_SHIFT);
}

vcpu->epte = epte;
vcpu->krip = vcpu->ip;
vcpu->gpa = info->gpa;
ToggleMTF(TRUE);

}
else
{
unload:
//被保护模块之外
__set_epte_ar_inplace(epte, EPT_ACCESS_ALL);
}

ve->invalidate = true;
return true;
}


博客管理员