LyScript 内存交换与差异对比
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 内存交换与差异对比的更多相关文章
- Atitit 硬件 软件 的开源工作 差异对比
Atitit 硬件 软件 的开源工作 差异对比 1.1. 模块化,标准化,以及修改的便捷性1 1.2. 生产和发布成本 1 1.3. 3. 入行门槛搞2 1.4. 在软件业极度发达的今天,任何具 ...
- 如何在Linux上使用文件作为内存交换区(Swap Area)
交换区域(Swap Area)有什么作用? 交换分区是操作系统在内存不足(或内存较低)时的一种补充.通俗的说,如果说内存是汽油,内存条就相当于油箱,交换区域则相当于备用油箱. Ubuntu Linux ...
- Linux swappiness参数设置与内存交换
swappiness参数设置与内存交换 by:授客 QQ:1033553122 简介 swappiness,Linux内核参数,控制换出运行时内存的相对权重.swappiness参数值可设置范围在0到 ...
- Linux命令 swap:内存交换空间
swap 内存交换空间的概念 swap使用上的限制
- SeaJS 与 RequireJS 的差异对比
这篇文章主要介绍了SeaJS 与 RequireJS 的差异对比,本文主要对CMD规范和AMD规范的弊端做了对比,并做出了一个总结,需要的朋友可以参考下 “历史不是过去,历史正在上演.随着 W3C 等 ...
- Python 数据库之间差异对比
参考资料: Python 集合(set) 此脚本用于两个数据库之间的表.列.栏位.索引的差异对比. cat oracle_diff.py #!/home/dba/.pyenv/versions/3 ...
- 016——VUE中v-show的使用与v-if的差异对比
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Python自动化运维——文件内容差异对比
Infi-chu: http://www.cnblogs.com/Infi-chu/ 模块:difflib 安装:Python版本大于等于2.3系统自带 功能:对比文本之间的差异,而且支持输出可读性比 ...
- 16.VUE学习之-v-show的使用与v-if的差异对比
v-show的使用与v-if的差异对比 相同点: 都可以达到隐藏和显示的效果. 不同点: v-show 会用display:none 来隐藏元素节点,推荐使用这种方式 v-if 会移除节点,可以配合v ...
随机推荐
- leetcode 643. Maximum Average Subarray I 子数组最大平均数 I
一.题目大意 https://leetcode.cn/problems/maximum-average-subarray-i/ 给你一个由 n 个元素组成的整数数组 nums 和一个整数 k . 请你 ...
- 课堂练习——neo4j简单使用
启动neo4j: neo4j.bat console 进入neo4j数据库的conf目录下,编辑neo4j.conf文件:将当前数据库设置为你要建立的数据库名称(数据库不能重名): dbms.acti ...
- cpulimit-限制CPU速率
CPULimit是一个简单的程序,它可以限制指定进程的CPU百分比. 1.安装依赖 root@localhost:~# apt-get -y install git 2.从GitHUB中克隆源码到本地 ...
- BZOJ4713 迷失的字符串 解题报告
BZOJ4713 题目大意:有 \(n\) 个点 \(n-1\) 条边,每条边有一个字符.给你 \(m\) 个字符串 \(s_i\),问每个字符串是否可以通过树上的一条简单路径表示. \(n,m\le ...
- C#语言中的类型转换方法(unfinished)
一.C#中的数据类型 1.数值类型 2.字符类型 3.字符串类型 4.布尔类型 5.枚举类型 6.Object类型 二.常见的类型转换 从转换方式的角度,类型转换分为隐式转换与显式转换两种. 其中,隐 ...
- Java_循环结构
目录 while循环 do...while循环 for循环 for循环嵌套 增强for循环 打印三角形 Debug 视频 while循环 while(布尔表达式){ //循环内容 } //死循环 wh ...
- 卸载windows安装ubuntu的完全指南
卸载windows安装ubuntu的完全指南 新配置了一台深度学习服务器,但是预装系统为windows10,与需求不符.于是,自己动手安装ubuntu(18.04).此文为过程记录. 主要步骤: 准备 ...
- 我用 AntV/S2 买了一套房
背景 经过一年多的摇号,我在前两天收到了某网红盘的摇中通知.还沉浸在摇中房屋喜悦中的我,很快被售房顾问告知选房的人很多,每位购房者的选房时间都很短,必须 一分钟内 快速选房.并且,排在 400 多号的 ...
- 写selenium常用到的js代码
selenium可以运行JavaScript代码,可以用一些JavaScript来辅助编写Selelnium代码. 1.scrollIntoView - 向下拉滚动条,使得某元素可见 IWebElem ...
- 在.NET中计算文件的MD5值
更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月2日. 直接上代码吧: using System; using System.IO; using System.Security. ...