二进制安全C/C++汇编一线开发 [2021]解读HyperPlatform的MMU(memory management unit)虚拟化 ## MMTR windows和linux系统在启动的过程中,会分配一段叫做"低内存"(low-level-memory)的保留内存区域,地址范围是在0x1000-0xA0000 这一段区间内,用于各种bios的操作。在此期间有一个操作是bios会通过这里面的字段信息设置对应的物理内存的地址范围属性,这叫做 "MTRRS -memory-type range register"(内存范围类别注册) 为什么要这样做呢? 答案: 告訴CPU在解析或者说操作内存的时候应该用什么手段。一般情况下,内存都是应该是被设置为有cache来帮助CPU操作内存的,这样的话整个系统的效率就会比较高。但是某些设备所使用的内存却比较特殊,比如说Frame buffer就是一种很好的例子。那么软件(一般情况下是BIOS)就需要配置CPU的相关寄存来申明那些范围的内存在处理的时候需要做什么样的动作(这就是类型)。总的来说它们允许CPU优化不同类型的内存如RAM,ROM和帧缓冲内存(frame buffer),内存操作映射I / O设备。这种做法简化了内存控制系统的硬件设计引脚。 根据intel手册,内存有以下的类型: ![](https://key08.com/usr/uploads/2021/05/4142820640.png) MTRR机制允许多达96个内存范围(memory ranges)在物理内存的定义,它定义了一系列的MSRs,这些寄存器分别去说明MSR定义中包含的那段内存的具体类型 ## MMU 现在的计算机基本上都带了一个叫做MMU(memory management unit)的东西,这个东西你可以理解为内存管理机制(虽然有点偏离意思),他主要负责内存访问、读写权限控制、虚拟地址到物理地址转换。 **请注意这里有个小知识点,虚拟内存的块我们叫做页(page),而物理内存的块我们叫做帧(frame)** intel把虚拟内存分为一个一个4KB的页面(可以是其他大小),物理内存分为一个一个4KB的帧,之后在此基础上设置了TLB机制(后备缓冲区,简单理解为是一种CPU缓存就行) 物理与虚拟地址转换图: ![](https://key08.com/usr/uploads/2021/05/4219135422.png) 如果你还是不理解物理地址与虚拟地址这些的关系,可以参考一下大学课本《计算机组成原理》这本书,里面有详细的介绍 ## EPT EPT是intel的CPU的一个名词,全名 Extended Page Table(NPT跟这个差不多),或者叫做SLAT,他最简单的理解就是: 以前: 物理内存 -> MMU -> 虚拟内存 EPT开启: guest access物理内存 -> EPT -> MMU -> 虚拟内存 阅读全文 2021-05-28 huoji 0 条评论
工具软件二进制安全C/C++汇编一线开发 [2021]基于hypervisor的HIPS架构 从0到1 四 (SSDT hook) # 前言 还记我们系列的标题吗? HIPS,作为系统监控,我们需要监控所有的syscall调用。这个部分会由hypervisor完成. ssdt hook是一个古老古老的东西了,还记得我以前入门就是很多人把ssdt hook看做是核心机密,现在已经烂大街了.我们的ssdt hook不同于传统的"内联hook",我们准确的说叫做msr hook.回忆一下amd64里面syscall的方式,看看AMD手册的介绍: 在AMD64体系下,为了解决之前int调用方式的不足,从而推出了syscall指令作为进入内核入口的指令,syscall在AMD64体系下调用的方式 ![](https://key08.com/usr/uploads/2021/05/3936827292.png) 可以看到,最终RIP的值会等与MSR_LSTAR相等,而在微软体系里,MSR_LSTAR存放着kisystemcall64的函数地址 因此,我们需要hook这个msr_star 阅读全文 2021-05-25 huoji 1 条评论
python一线开发 [2021]手撸机器学习入门之jaya算法 总所周知,所谓机器学习就是一个解方程给x求y的过程罢了. 这是一篇入门的算法代码,又叫做jaya算法(不是java!!!),网上没什么资料,以下是自己python写的. ```python import math import random import matplotlib.pyplot as plt import numpy as np g_group_size = 5000 g_var_weight = 2 g_max_iteration = 100 g_array_f = [0 for i in range(0, g_group_size)] g_array_best = [0 for i in range(0, g_group_size)] g_array_worst = [0 for i in range(0, g_group_size)] g_array_pop_new = [[0 for i in range(0, g_var_weight)] for i in range(0, g_group_size)] #g_number_a = -2 * math.pi #g_number_b = 2 * math.pi #g_number_a = -5.12 #g_number_b = 5.12 g_number_a = -100 g_number_b = 100 g_result = [] array_pop = [[0 for i in range(0, g_var_weight)] for i in range(0, g_group_size)] def fn_objective(pArray): result = 0 for i in range(0, g_var_weight): # result += pArray[i] * pArray[i] # result += math.sin(pArray[i]) * math.pow(math.e, math.pow(1 - math.cos(result), 2)) + math.cos(result) * math.pow(math.e, math.pow(1 - math.sin(pArray[i]), 2)) + math.pow(pArray[i] - result, 2) # result += -(1 + math.cos(12 * math.sqrt(math.pow(pArray[i], 2) + math.pow(result, 2)))) / (0.5 * (math.pow(pArray[i], 2) + math.pow(result, 2)) + 2) result += math.pow(pArray[i], 2) + 2 * math.pow(result, 2) - 0.3 * math.cos(3 * math.pi * pArray[i]) - 0.4 * math.cos(4 * math.pi * result) + 0.7 return result def fn_clean_array(pArray): for i in range(0, g_group_size): for z in range(0, g_var_weight): if pArray[i][z] < g_number_a: pArray[i][z] = g_number_a if pArray[i][z] > g_number_b: pArray[i][z] = g_number_b return pArray for i in range(0, len(array_pop)): for z in range(0, len(array_pop[i])): array_pop[i][z] = random.uniform(g_number_a, g_number_b) g_array_f[i] = fn_objective(array_pop[i]) print("array_pop: ") print(array_pop) print("g_array_f: ") print(g_array_f) iter_num = 1 min_index = 0 max_index = 0 while iter_num <= g_max_iteration: min_value = min(g_array_f) min_index = g_array_f.index(min_value) - 1 g_array_best = array_pop[min_index] max_value = max(g_array_f) max_index = g_array_f.index(max_value) - 1 g_array_worst = array_pop[max_index] for i in range(0, g_group_size): for z in range(0, g_var_weight): wrost_number = g_array_worst[z] - math.fabs(array_pop[i][z]) best_number = g_array_best[z] - math.fabs(array_pop[i][z]) g_array_pop_new[i][z] = array_pop[i][z] + \ random.random() * best_number - wrost_number g_array_pop_new = fn_clean_array(g_array_pop_new) f_new = 0 for i in range(0, len(g_array_pop_new)): f_new = fn_objective(g_array_pop_new[i]) if f_new < g_array_f[i]: g_array_f[i] = f_new for z in range(g_var_weight): array_pop[i][z] = g_array_pop_new[i][z] min_value = min(g_array_f) min_index = g_array_f.index(min_value) g_array_best = array_pop[min_index] print("min number {} ".format(g_array_f[min_index])) print("x=") print(g_array_best) #g_result.insert(0, g_array_f[min_index]) g_result.append(g_array_f[min_index]) iter_num += 1 x = np.arange(0, len(g_result)) y = np.array(g_result) plt.title("jaya") plt.xlabel("min number") plt.ylabel("y") plt.plot(x, y) plt.show() ``` 请注意有一些公式需要很大的族群范围才能收敛 论文里面的收敛图: ![](https://key08.com/usr/uploads/2021/05/2290756614.png) 这边的: ![](https://key08.com/usr/uploads/2021/05/3846208643.png) 阅读全文 2021-05-24 huoji 0 条评论
二进制安全C/C++汇编Shellcode [2021]微软存在的一处内存泄露 在做EFI驱动的时候,会发现有疑似内存泄露,但不知道为什么.经过很久的调试,发现并不是EFI的代码的问题.而是微软自己的问题! 微软自己存在一处内存泄露.只不过EFI驱动多次调用这个API进行通讯导致从不明显的泄露成了明显的泄露 阅读全文 2021-05-21 huoji 0 条评论
系统安全C/C++汇编Shellcode [2021]微软如何检测到hypervisor以及如何预防 微软挺奇怪的,什么事都要管一腿.总所周知 win 1809后hypervisor的一些功能比如msr hook(通过替换msr_lstar寄存器)的方案已经无了.怎么无的呢?除了kva shadow的问题,还有如下几个问题: 翻开微软的内核,有如下函数 KiErrata361Present KiErrataSkx55Present KiErrata704Present ... 这些函数有如下特点: 1. 名字莫名其妙 2. 调用者也莫名其妙,比如KiErrata361Present在一个IDA分析都要半个小时的函数里面调用. 3. 大部分都是微软检测虚拟机的函数 KiErrata704Present: 他长这样: 阅读全文 2021-05-13 huoji 1 条评论
二进制安全C/C++汇编Shellcode一线开发 [2021]基于hypervisor的HIPS架构 从0到1 三 (进入虚拟化方式总结) 这部分是我在2021年的某场信息安全作品赛时候时候所写的。考虑到以后可能这个东西比赛完就没价值了.于是放在这里做备份吧. 阅读全文 2021-05-13 huoji 0 条评论