LyScript 针对内存读写函数的封装功能并不多,只提供了内存读取和内存写入函数的封装,本篇文章将继续对API进行封装,实现一些在软件逆向分析中非常实用的功能,例如内存交换,内存区域对比,磁盘与内存镜像比较,特征码检索等功能。

LyScript项目地址:https://github.com/lyshark/LyScript

内存区域交换: 实现被加载程序内特定一块内存区域的交换,该方法实现原理就是两个变量之间的交换,只是在交换时需要逐个字节进行,调用read_memory_byte()函数实现起了很容易。

from LyScript32 import MyDebug

# 交换两个内存区域
def memory_xchage(dbg,memory_ptr_x,memory_ptr_y,bytes):
ref = False
for index in range(0,bytes):
# 读取两个内存区域
read_byte_x = dbg.read_memory_byte(memory_ptr_x + index)
read_byte_y = dbg.read_memory_byte(memory_ptr_y + index) # 交换内存
ref = dbg.write_memory_byte(memory_ptr_x + index,read_byte_y)
ref = dbg.write_memory_byte(memory_ptr_y + index, read_byte_x)
return ref if __name__ == "__main__":
dbg = MyDebug()
dbg.connect() eip = dbg.get_register("eip") # 内存交换
flag = memory_xchage(dbg, 6815744,6815776,4)
print("内存交换状态: {}".format(flag))
dbg.close()

PE文件头节点交换后如下:

内存区域对比: 可用于对比该进程内存中的特定一块区域的差异,返回是列表中的字典形式,分别传入对比内存x,y以及需要对比的内存长度,此处建议不要超过1024字节。

from LyScript32 import MyDebug

# 对比两个内存区域
def memory_cmp(dbg,memory_ptr_x,memory_ptr_y,bytes):
cmp_memory = []
for index in range(0,bytes): item = {"addr":0, "x": 0, "y": 0} # 读取两个内存区域
read_byte_x = dbg.read_memory_byte(memory_ptr_x + index)
read_byte_y = dbg.read_memory_byte(memory_ptr_y + index) if read_byte_x != read_byte_y:
item["addr"] = memory_ptr_x + index
item["x"] = read_byte_x
item["y"] = read_byte_y
cmp_memory.append(item)
return cmp_memory if __name__ == "__main__":
dbg = MyDebug()
dbg.connect() eip = dbg.get_register("eip") # 内存对比
cmp_ref = memory_cmp(dbg, 6815744,6815776,4)
for index in range(0,len(cmp_ref)):
print("地址: 0x{:08X} -> X: 0x{:02x} -> y: 0x{:02x}".format(cmp_ref[index].get("addr"),cmp_ref[index].get("x"),cmp_ref[index].get("y"))) dbg.close()

对比特定内存区域,返回差异字节地址:

内存与磁盘机器码比较: 通过调用read_memory_byte()函数,或者open()打开文件,等就可以得到程序磁盘与内存中特定位置的机器码参数,然后通过对每一个列表中的字节进行比较,就可得到特定位置下磁盘与内存中的数据是否一致的判断。

#coding: utf-8
import binascii,os,sys
from LyScript32 import MyDebug # 得到程序的内存镜像中的机器码
def get_memory_hex_ascii(address,offset,len):
count = 0
ref_memory_list = []
for index in range(offset,len):
# 读出数据
char = dbg.read_memory_byte(address + index)
count = count + 1 if count % 16 == 0:
if (char) < 16:
print("0" + hex((char))[2:])
ref_memory_list.append("0" + hex((char))[2:])
else:
print(hex((char))[2:])
ref_memory_list.append(hex((char))[2:])
else:
if (char) < 16:
print("0" + hex((char))[2:] + " ",end="")
ref_memory_list.append("0" + hex((char))[2:])
else:
print(hex((char))[2:] + " ",end="")
ref_memory_list.append(hex((char))[2:])
return ref_memory_list # 读取程序中的磁盘镜像中的机器码
def get_file_hex_ascii(path,offset,len):
count = 0
ref_file_list = [] with open(path, "rb") as fp:
# file_size = os.path.getsize(path)
fp.seek(offset) for item in range(offset,offset + len):
char = fp.read(1)
count = count + 1
if count % 16 == 0:
if ord(char) < 16:
print("0" + hex(ord(char))[2:])
ref_file_list.append("0" + hex(ord(char))[2:])
else:
print(hex(ord(char))[2:])
ref_file_list.append(hex(ord(char))[2:])
else:
if ord(char) < 16:
print("0" + hex(ord(char))[2:] + " ", end="")
ref_file_list.append("0" + hex(ord(char))[2:])
else:
print(hex(ord(char))[2:] + " ", end="")
ref_file_list.append(hex(ord(char))[2:])
return ref_file_list if __name__ == "__main__":
dbg = MyDebug() connect_flag = dbg.connect()
print("连接状态: {}".format(connect_flag)) module_base = dbg.get_base_from_address(dbg.get_local_base())
print("模块基地址: {}".format(hex(module_base))) # 得到内存机器码
memory_hex_byte = get_memory_hex_ascii(module_base,0,100) # 得到磁盘机器码
file_hex_byte = get_file_hex_ascii("d://Win32Project1.exe",0,100) # 输出机器码
print("\n内存机器码: ",memory_hex_byte)
print("\n磁盘机器码: ",file_hex_byte) dbg.close()

读取后输出时会默认十六个字符一次换行,输出效果如下。

我们继续增加磁盘与内存对比过程,然后就能实现对特定内存区域与磁盘区域字节码一致性的判断。

#coding: utf-8
import binascii,os,sys
from LyScript32 import MyDebug # 得到程序的内存镜像中的机器码
def get_memory_hex_ascii(address,offset,len):
count = 0
ref_memory_list = []
for index in range(offset,len):
# 读出数据
char = dbg.read_memory_byte(address + index)
count = count + 1 if count % 16 == 0:
if (char) < 16:
print("0" + hex((char))[2:])
ref_memory_list.append("0" + hex((char))[2:])
else:
print(hex((char))[2:])
ref_memory_list.append(hex((char))[2:])
else:
if (char) < 16:
print("0" + hex((char))[2:] + " ",end="")
ref_memory_list.append("0" + hex((char))[2:])
else:
print(hex((char))[2:] + " ",end="")
ref_memory_list.append(hex((char))[2:])
return ref_memory_list # 读取程序中的磁盘镜像中的机器码
def get_file_hex_ascii(path,offset,len):
count = 0
ref_file_list = [] with open(path, "rb") as fp:
# file_size = os.path.getsize(path)
fp.seek(offset) for item in range(offset,offset + len):
char = fp.read(1)
count = count + 1
if count % 16 == 0:
if ord(char) < 16:
print("0" + hex(ord(char))[2:])
ref_file_list.append("0" + hex(ord(char))[2:])
else:
print(hex(ord(char))[2:])
ref_file_list.append(hex(ord(char))[2:])
else:
if ord(char) < 16:
print("0" + hex(ord(char))[2:] + " ", end="")
ref_file_list.append("0" + hex(ord(char))[2:])
else:
print(hex(ord(char))[2:] + " ", end="")
ref_file_list.append(hex(ord(char))[2:])
return ref_file_list if __name__ == "__main__":
dbg = MyDebug() connect_flag = dbg.connect()
print("连接状态: {}".format(connect_flag)) module_base = dbg.get_base_from_address(dbg.get_local_base())
print("模块基地址: {}".format(hex(module_base))) # 得到内存机器码
memory_hex_byte = get_memory_hex_ascii(module_base,0,1024) # 得到磁盘机器码
file_hex_byte = get_file_hex_ascii("d://Win32Project1.exe",0,1024) # 输出机器码
for index in range(0,len(memory_hex_byte)):
# 比较磁盘与内存是否存在差异
if memory_hex_byte[index] != file_hex_byte[index]:
# 存在差异则输出
print("\n相对位置: [{}] --> 磁盘字节: 0x{} --> 内存字节: 0x{}".
format(index,memory_hex_byte[index],file_hex_byte[index]))
dbg.close()

代码运行后即可输出,存在差异的相对位置:

内存ASCII码解析: 通过封装的get_memory_hex_ascii得到内存机器码,然后再使用如下过程实现输出该内存中的机器码所对应的ASCII码。

from LyScript32 import MyDebug
import os,sys # 转为ascii
def to_ascii(h):
list_s = []
for i in range(0, len(h), 2):
list_s.append(chr(int(h[i:i+2], 16)))
return ''.join(list_s) # 转为16进制
def to_hex(s):
list_h = []
for c in s:
list_h.append(hex(ord(c))[2:])
return ''.join(list_h) # 得到程序的内存镜像中的机器码
def get_memory_hex_ascii(address,offset,len):
count = 0
ref_memory_list = []
for index in range(offset,len):
# 读出数据
char = dbg.read_memory_byte(address + index)
count = count + 1 if count % 16 == 0:
if (char) < 16:
ref_memory_list.append("0" + hex((char))[2:])
else:
ref_memory_list.append(hex((char))[2:])
else:
if (char) < 16:
ref_memory_list.append("0" + hex((char))[2:])
else:
ref_memory_list.append(hex((char))[2:])
return ref_memory_list if __name__ == "__main__":
dbg = MyDebug()
dbg.connect() eip = dbg.get_register("eip") # 得到模块基地址
module_base = dbg.get_base_from_address(dbg.get_local_base()) # 得到指定区域内存机器码
ref_memory_list = get_memory_hex_ascii(module_base,0,1024) # 解析ascii码
break_count = 1
for index in ref_memory_list:
if break_count %32 == 0:
print(to_ascii(hex(int(index, 16))[2:]))
else:
print(to_ascii(hex(int(index, 16))[2:]),end="")
break_count = break_count + 1 dbg.close()

输出效果如下,如果换成中文,那就是一个中文搜索引擎了。

内存特征码匹配: 通过二次封装get_memory_hex_ascii()实现扫描内存特征码功能,如果存在则返回True否则返回False。

from LyScript32 import MyDebug
import os,sys # 得到程序的内存镜像中的机器码
def get_memory_hex_ascii(address,offset,len):
count = 0
ref_memory_list = []
for index in range(offset,len):
# 读出数据
char = dbg.read_memory_byte(address + index)
count = count + 1 if count % 16 == 0:
if (char) < 16:
ref_memory_list.append("0" + hex((char))[2:])
else:
ref_memory_list.append(hex((char))[2:])
else:
if (char) < 16:
ref_memory_list.append("0" + hex((char))[2:])
else:
ref_memory_list.append(hex((char))[2:])
return ref_memory_list # 在指定区域内搜索特定的机器码,如果完全匹配则返回
def search_hex_ascii(address,offset,len,hex_array):
# 得到指定区域内存机器码
ref_memory_list = get_memory_hex_ascii(address,offset,len) array = [] # 循环输出字节
for index in range(0,len + len(hex_array)): # 如果有则继续装
if len(hex_array) != len(array):
array.append(ref_memory_list[offset + index]) else:
for y in range(0,len(array)):
if array[y] != ref_memory_list[offset + index + y]:
return False array.clear()
return False if __name__ == "__main__":
dbg = MyDebug()
dbg.connect() eip = dbg.get_register("eip") # 得到模块基地址
module_base = dbg.get_base_from_address(dbg.get_local_base()) re = search_hex_ascii(module_base,0,100,hex_array=["0x4d","0x5a"]) dbg.close()

特征码扫描一般不需要自己写,自己写的麻烦,而且不支持通配符,可以直接调用我们API中封装好的scan_memory_one()它可以支持??通配符模糊匹配,且效率要高许多。

LyScript 内存交换与差异对比的更多相关文章

  1. Atitit 硬件 软件 的开源工作 差异对比

    Atitit 硬件 软件 的开源工作 差异对比 1.1. 模块化,标准化,以及修改的便捷性1 1.2. 生产和发布成本 1 1.3.   3. 入行门槛搞2 1.4.  在软件业极度发达的今天,任何具 ...

  2. 如何在Linux上使用文件作为内存交换区(Swap Area)

    交换区域(Swap Area)有什么作用? 交换分区是操作系统在内存不足(或内存较低)时的一种补充.通俗的说,如果说内存是汽油,内存条就相当于油箱,交换区域则相当于备用油箱. Ubuntu Linux ...

  3. Linux swappiness参数设置与内存交换

    swappiness参数设置与内存交换 by:授客 QQ:1033553122 简介 swappiness,Linux内核参数,控制换出运行时内存的相对权重.swappiness参数值可设置范围在0到 ...

  4. Linux命令 swap:内存交换空间

    swap 内存交换空间的概念 swap使用上的限制

  5. SeaJS 与 RequireJS 的差异对比

    这篇文章主要介绍了SeaJS 与 RequireJS 的差异对比,本文主要对CMD规范和AMD规范的弊端做了对比,并做出了一个总结,需要的朋友可以参考下 “历史不是过去,历史正在上演.随着 W3C 等 ...

  6. Python 数据库之间差异对比

    参考资料: Python 集合(set)   此脚本用于两个数据库之间的表.列.栏位.索引的差异对比. cat oracle_diff.py #!/home/dba/.pyenv/versions/3 ...

  7. 016——VUE中v-show的使用与v-if的差异对比

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. Python自动化运维——文件内容差异对比

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 模块:difflib 安装:Python版本大于等于2.3系统自带 功能:对比文本之间的差异,而且支持输出可读性比 ...

  9. 16.VUE学习之-v-show的使用与v-if的差异对比

    v-show的使用与v-if的差异对比 相同点: 都可以达到隐藏和显示的效果. 不同点: v-show 会用display:none 来隐藏元素节点,推荐使用这种方式 v-if 会移除节点,可以配合v ...

随机推荐

  1. 论文解读(SCGC))《Simple Contrastive Graph Clustering》

    论文信息 论文标题:Simple Contrastive Graph Clustering论文作者:Yue Liu, Xihong Yang, Sihang Zhou, Xinwang Liu论文来源 ...

  2. CoaXPress 简介

    CoaXPress 背景 CoaXPress (简称CXP)是指一种采用同轴线缆进行互联的相机数据传输标准,主要用于替代之前的cameralink协议,常见于科学相机.工业相机.医学图像.航空防务等场 ...

  3. .Net分表分库动态化处理

    介绍 本期主角:ShardingCore 一款ef-core下高性能.轻量级针对分表分库读写分离的解决方案,具有零依赖.零学习成本.零业务代码入侵 背景 最近有个小伙伴来问我,分表下他有一批数据,这个 ...

  4. Java ES 实现or查询

    es mapping里有三个字段: A:Integer B:Integer C:TEXT 现在想实现一个查询,来检索  (  (A =1 and B=2)  or (c like "test ...

  5. 《C Primer Plus》第六版笔记--1~3章

    目录 第一章 初识C语言 1 使用C语言的7个步骤 1.1 定义程序目标 1.2 设计程序(功能实现) 1.3 编写代码 1.4 编译 1.5 运行程序 1.6 测试和调试程序 1.7 维护和修改代码 ...

  6. GDKOI 2021 Day2 TG 总结

    又是爆炸的一天,炸多了本蒟蒻已经习以为常 但今天比昨天整整高了 40 分!!!!却还是没有 100 今天本蒟蒻本想模仿奆佬的打字速度,结果思路混乱让我无法开始 T1 不是吧怎么是期望 dp ,期望值怎 ...

  7. 开源流程引擎camunda如何扩展

    ​  市场上基于Java语言的开源工作流引擎有:osworkflow.jbpm.activiti.flowable.camunda等,其中osworkflow.jbpm流程引擎已经过时,目前主流的开源 ...

  8. 李呈祥:bilibili在湖仓一体查询加速上的实践与探索

    导读: 本文主要介绍哔哩哔哩在数据湖与数据仓库一体架构下,探索查询加速以及索引增强的一些实践.主要内容包括: 什么是湖仓一体架构 哔哩哔哩目前的湖仓一体架构 湖仓一体架构下,数据的排序组织优化 湖仓一 ...

  9. Linux常用命令-创建用户修改密码-useradd

    命令简介 useradd/userdel 创建新用户/删除用户,需要管理员权限操作. 在创建用户时,如果不配置密码,用户的默认密码是不可用的,所以,useradd命令一般与passwd命令配合使用,下 ...

  10. 1.1 操作系统的第一个功能——虚拟化硬件资源 -《zobolの操作系统学习札记》

    1.1 操作系统的第一个功能--虚拟化硬件资源 目录 1.1 操作系统的第一个功能--虚拟化硬件资源 问1:操作系统一般处于计算机系统的哪一个位置? 问2:管理硬件资源为什么要单独交给操作系统? 问3 ...