python系统安全工具软件汇编一线开发 [2021]余弦定理检测文件相似度 & 病毒样本基因检测 本余弦定理有如下应用场景: 1.相似度计算 2.信息推送 在网络安全领域,主要就是样本基因检测,或者叫做样本相似度计算,他的公式长这样: ![](https://key08.com/usr/uploads/2021/08/2243488000.png) 请注意,之所以叫做余弦定理,是因为,他就是求一个三角形的角,并且在N维这个定理也成立 ![](https://key08.com/usr/uploads/2021/08/3451125394.png) 样本相似度检测,以两个风灵月影为例,属于同一个家族: ![](https://key08.com/usr/uploads/2021/08/947620823.png) # 编码 通过pefile库,读入文件,然后逐个比对字节码,参数A为字节码相同的,参数B为字节码不同的: ```cpp def get_peinfo_by_cos(pSource,pTarget): source = pefile.PE(pSource) target = pefile.PE(pTarget) source_map,source_sizeof_code,source_base_of_code = get_pe_info(source) target_map,target_sizeof_code,target_base_of_code = get_pe_info(target) a1_dict = {} a2_dict = {} for iter in range(source_sizeof_code): v1 = iter + source_base_of_code v2 = iter + source_base_of_code + 1 if source_map[v1:v2] in a1_dict.keys(): a1_dict[source_map[v1:v2]] = a1_dict[source_map[v1:v2]] + 1 else: a1_dict[source_map[v1:v2]] = 0 for iter in range(target_sizeof_code): v1 = iter + target_base_of_code v2 = iter + target_base_of_code + 1 if target_map[v1:v2] in a2_dict.keys(): a2_dict[target_map[v1:v2]] = a2_dict[target_map[v1:v2]] + 1 else: a2_dict[target_map[v1:v2]] = 0 str1_vector=[] str2_vector=[] for key in a1_dict: str1_count = a1_dict[key] str1_vector.append(str1_count) for key in a2_dict: str2_count = a2_dict[key] str2_vector.append(str2_count) str1_map = map(lambda x: x*x,str1_vector) str2_map = map(lambda x: x*x,str2_vector) str1_mod = reduce(lambda x, y: x+y, str1_map) str2_mod = reduce(lambda x, y: x+y, str2_map) str1_mod = math.sqrt(str1_mod) str2_mod = math.sqrt(str2_mod) vector_multi = reduce(lambda x, y: x + y, map(lambda x, y: x * y, str1_vector, str2_vector)) # 计算余弦值 cos = float(vector_multi)/(str1_mod*str2_mod) return cos ``` 其中,两个是相似的,两个是不相似的,两个是恶意样本家族 来试试: ![](https://key08.com/usr/uploads/2021/08/1402924204.png) 简单粗暴,并且有效. 完整代码: 阅读全文 2021-08-19 huoji 1 条评论
系统安全C/C++汇编 [2021]Windows PatchGuard KiErrata671Present 在一次偶然中我发现了KiErrata671Present,它这个看起来长这样: ![](https://key08.com/usr/uploads/2021/08/1055346649.png) 人畜无害 但是看调用: ![](https://key08.com/usr/uploads/2021/08/1257889702.png) 第一眼看不出什么 让我们慢慢解释一下: ![](https://key08.com/usr/uploads/2021/08/1678044808.png) 请注意,ida反汇编的代码是没有try和catch的,在汇编里面,你可以看得到如下的代码: ![](https://key08.com/usr/uploads/2021/08/1437456579.png) 通俗的解释一下 1.去掉页面保护 2.给KiErrata671Present + 0x2的位置写0xC3 让其从1返回为0 3.执行KiErrata671Present 4.恢复页面保护 这样做会有什么效果: 一些hypervisor中的EPT/NPT hook技术会让页面读写执行分离实现无痕hook,如果在有EPT/NPT HOOK的情况下并且这个函数正好与某些保护页面在同一页的情况下,第2步(给KiErrata671Present + 0x2的位置写0xC3 让其从1返回为0)不会被写入执行页面,导致执行结果依然是1,从而让其检测到hypervisor,不过这也只是猜测,因为目前有几个不确定: 1. 这个是1809的东西,为什么目前没有1809的ept hook出错的报告 2. 这个东西是如何调用的,会在哪调用,哪些页面会有这个东西,目前来说并不知道 阅读全文 2021-08-18 huoji 5 条评论
python一线开发 [2021]从0开始的tensorflow2.0 (三) LSTM 假设给出如下需求: 我给你几个行为 A B C D E F 要求知道A B C D E 推测出F 这种使用场景就能使用LSTM,关于LSTM本文就不废话了,因为网上介绍一大堆了,直接上干货: 首先我们需要将数据 A B C D E F 转为编号:0 1 2 3 4 6 其次,对其进行扁平归一化,并且划分训练和测试数据: ```cpp train_path = './result_list.csv' data_frame = pd.read_csv(train_path) data_frame['activity'] = data_frame['activity'].astype('float32') scaler = StandardScaler() data_frame['activity'] = scaler.fit_transform( data_frame['activity'].values.reshape(-1, 1), scaler.fit(data_frame['activity'].values.reshape(-1, 1))) train_size = int(len(data_frame['activity']) * 0.75) trainlist = data_frame['activity'][:train_size] testlist = data_frame['activity'][train_size:] ``` 读出来应该是: 0 1 2 3 4 5 .... 然后构造滑块,成0 1 2 3 4(X), 5(Y)的样子: ```cpp look_back = 64 trainX, trainY = create_dataset(trainlist, look_back, None) testX, testY = create_dataset(testlist, look_back, train_size) ``` 注意网上的create_dataset代码都过时了,大部分你直接抄就会报错,用我的就行: ```cpp def create_dataset(dataset, look_back, start_index): dataX, dataY = [], [] for i in range(len(dataset)-look_back-1): a = dataset[i:(i+look_back)] dataX.append(a) if start_index != None: dataY.append(dataset[start_index + i + look_back]) else: dataY.append(dataset[i + look_back]) return np.array(dataX), np.array(dataY) ``` 记得要reshap一下: ```cpp trainX = trainX.reshape(trainX.shape[0], trainX.shape[1], 1) testX = testX.reshape(testX.shape[0], testX.shape[1], 1) ``` 之后直接训练即可: ```cpp model = keras.Sequential() model.add(keras.layers.LSTM(128, input_shape=(look_back, 1), return_sequences=True)) model.add(keras.layers.LSTM(256)) model.add(keras.layers.Dense(1)) model.compile(optimizer=keras.optimizers.Adam(), loss='mae', metrics=['MeanSquaredError']) model.fit(trainX, trainY, epochs=26, batch_size=128) model.save('./model_lstm.h5') ``` 测试: ![](https://key08.com/usr/uploads/2021/08/1454514772.png) 阅读全文 2021-08-14 huoji 0 条评论
系统安全二进制安全渗透复现 [2021]process herpaderping原理 看了看国外这个process Herpaderping这个东西,被国内某些人吹的玄乎的要死,有点尬, 核心原理如下,杀毒软件用processcreatenotifycallback监视进程创建,然后做杀毒操作之类的,但是这个是有个问题: ![](https://key08.com/usr/uploads/2021/08/674615226.png) 这个回调需要有线程进入才会激活,没有自然是不会有信息的 所以国外这个作者,这样利用了磁盘缓存来绕过processcreatenotifycallback: 1. 打开一个黑文件和白文件 2. 把白文件的内容写到黑文件里面 3. NtCreateSection映射黑文件的内容【关键】 4. 创建白文件的进程,进程内存区段填写第三步映射黑文件的内容,此时不会触发processcreatenotifycallback 5. 给黑文件填充随机垃圾字符【关键】,并且修复参数通过写PEB 6. 创建线程启动第四步的进程 7. 再次启动进程.你会发现,黑文件代码顶着白文件的壳跑,并且杀毒软件不认为有异常 **所以为什么会这样,原因出在硬盘读写设计中,是有一层缓存的,缓存和硬盘内容不一定会实时同步,一般是在有完全关闭文件的操作后才会跟硬盘内容同步** 本次注入利用了,把白文件的内容写到黑文件里面的时候缓存并不会更新。 启动进程的时候,用的是NtCreateSection的内存,也就是缓存的内存,在启动线程去执行线程的时候,由于磁盘文件和内存镜像不同,走完processcreatenotifycallback后直接CloseFile关闭文件了(这里是系统自己关闭的) 现在就有了一个奇怪的文件 硬盘内容是白文件的内容、缓存里面是黑文件的代码,执行这个文件的时候, 由于部分其他的属性不是来自缓存而且来自于硬盘的,所以导致了,一个黑文件看起来顶着一个白文件跑..... 当然重启后缓存没了,这个黑文件就没了,就成白文件了 > ps: 很久之前我注意到了一个现象(18年左右写反作弊的时候),在修改SECTION_OBJECT_POINTERS->FILE_OBJECT的时候,我以为他是内存行为,关闭文件就没了,实际上他会有个操作系统缓存,也就是说你改了这玩意后,下次启动文件,他还是会访问缓存.导致我查了很久资料才发现这玩意居然是全局缓存共享的tm的 知道原理后,就很容易检测了,检测方法如下: 创建进程回调里面检查缓存是否与磁盘文件一致,不一致可以认为是搞破坏的(一般也不会不一致),sysmon里面 EventID 25的镜像被替换就是这样做的 阅读全文 2021-08-12 huoji 0 条评论
python工具软件 [2021]python批量比较校验两个文件夹里面的文件md5 网上的东西都不怎么靠谱,这里发一个自己写的,用来快速确认有没有后门之类的东西 ```python import base64 import hashlib import os g_origin_path = "【目录】" g_target_path = "【目录】" def get_file_md5(filepath): f = open(filepath, 'rb') md5obj = hashlib.md5() md5obj.update(f.read()) hash = md5obj.hexdigest() f.close() return str(hash).upper() for root, dirs, files in os.walk(g_origin_path): for file in files: origin_file_path = os.path.join(root, file) strlist = origin_file_path.split('\\') target_file_path = g_origin_path + '\\'.join(strlist[5:]) if os.path.exists(target_file_path) == False: print("多出文件: {} ".format(target_file_path)) continue origin_file_md5 = get_file_md5(origin_file_path) target_file_md5 = get_file_md5(target_file_path) #print(origin_file_md5, target_file_md5) if origin_file_md5 != target_file_md5: print("md5不同 路径: {} src: {} target: {}".format( target_file_path, origin_file_md5, target_file_md5)) ``` 阅读全文 2021-08-02 huoji 0 条评论
系统安全二进制安全汇编 [2021]PatchGuard的 sub_1403DA6F0 回调研究(二) [上一文章](https://key08.com/index.php/2021/06/28/1190.html "上一文章") 中,我们介绍了PG的回调,本篇文章将会大概介绍一下这个回调所调用的sub_1403DA6F0的一些内容: 阅读全文 2021-08-01 huoji 0 条评论
系统安全工具软件二进制安全C/C++一线开发 [2021]检测Cobalt Strike只使用40行代码 无文件落地的木马主要是一段可以自定位的shellcode组成,特点是没有文件,可以附加到任何进程里面执行。一旦特征码被捕获甚至是只需要xor一次就能改变特征码.由于传统安全软件是基于文件检测的,对目前越来越多的无文件落地木马检查效果差. **基于内存行为特征的检测方式,可以通过检测执行代码是否在正常文件镜像区段内去识别是否是无文件木马.由于cobaltstrike等无文件木马区段所在的是private内存,所以在执行loadimage回调的时候可以通过堆栈回溯快速确认是否是无文件木马** 检测只需要40行代码: 1. 在loadimagecallback上做堆栈回溯 2. 发现是private区域的内存并且是excute权限的code在加载dll,极有可能,非常有可能是无文件木马或者是shellcode在运行 核心代码如下: 阅读全文 2021-07-25 huoji 0 条评论