LyScript实现内存交换与差异对比的方法详解

目录
  • 内存区域交换
  • 内存区域对比
  • 内存与磁盘机器码比较
  • 内存ASCII码解析
  • 内存特征码匹配

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实现内存交换与差异对比的方法详解的文章就介绍到这了,更多相关LyScript内存交换 对比内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • LyScript寻找ROP漏洞指令片段的方法详解

    ROP绕过片段简单科普一下,你可以理解成一个可以关闭系统自身内存保护的一段机器指令,这段代码需要我们自己构造,这就涉及到在对端内存搜寻这样的指令,LyScript插件增强了指令片段的查找功能,但需要我们在LyScript插件基础上封装一些方法,实现起来也不难. LScript项目地址:https://github.com/lyshark/LyScript 封装机器码获取功能: 首先封装一个方法,当用户传入指定汇编指令的时候,自动的将其转换成对应的机器码,这是为搜索ROP片段做铺垫的,代码很简单,

  • Python利用LyScript插件实现批量打开关闭进程

    LyScript是一款x64dbg主动化操控插件,经过Python操控X64dbg,完成了远程动态调试,解决了逆向工作者剖析漏洞,寻觅指令片段,原生脚本不行强壮的问题,经过与Python相结合使用Python语法的灵活性以及丰富的第三方库,进步剖析功率,完成主动化剖析代码. python包请装置与插件一致的版别,在cmd命令行下履行pip命令即可装置. 装置Python包:pipinstallLyScript32或者pipinstallLyScript64 其次你需求手动下载对应x64dbg版别

  • LyScript获取上一条与下一条汇编指令的方法详解

    LyScript 插件默认并没有提供上一条与下一条汇编指令的获取功能,当然你可以使用LyScriptTools工具包直接调用内置命令得到,不过这种方式显然在效率上并不理想,我们需要在LyScript插件API基础上自己封装实现这个功能. LyScript项目地址:https://github.com/lyshark/LyScript 获取下一条汇编指令 下一条汇编指令的获取需要注意如果是被命中的指令则此处应该是CC断点占用一个字节,如果不是则正常获取到当前指令即可. 1.我们需要检查当前内存断点

  • LyScript实现对内存堆栈扫描的方法详解

    LyScript插件中提供了三种基本的堆栈操作方法,其中push_stack用于入栈,pop_stack用于出栈,而最有用的是peek_stack函数,该函数可用于检查指定堆栈位置处的内存参数,利用这个特性就可以实现,对堆栈地址的检测,或对堆栈的扫描等. LyScript项目地址:https://github.com/lyshark/LyScript peek_stack命令传入的是堆栈下标位置默认从0开始,并输出一个十进制有符号长整数,首先实现有符号与无符号数之间的转换操作,为后续堆栈扫描做准

  • 利用LyScript实现应用层钩子扫描器

    Capstone 是一个轻量级的多平台.多架构的反汇编框架,该模块支持目前所有通用操作系统,反汇编架构几乎全部支持,本篇文章将运用LyScript插件结合Capstone反汇编引擎实现一个钩子扫描器. 要实现应用层钩子扫描,我们需要得到程序内存文件的机器码以及磁盘中的机器码,并通过capstone这个第三方反汇编引擎,对两者进行反汇编,最后逐条对比汇编指令,实现进程钩子扫描的效果. LyScript项目地址:https://github.com/lyshark/LyScript 通过LyScri

  • Python+LyScript实现自定义反汇编

    LyScript 插件默认提供了一个get_disasm_code()方法可以直接获取到指定行数的反汇编代码,但如果需要自定义获取或者是需要自己封装一个反汇编方法,则你可以用如下两种方式来得到. LyScript项目地址: https://github.com/lyshark/LyScript 第一步直接获取到指定EIP位置的反汇编代码,这段代码可以这样来写. from LyScript32 import MyDebug if __name__ == "__main__": dbg =

  • LyScript实现内存交换与差异对比的方法详解

    目录 内存区域交换 内存区域对比 内存与磁盘机器码比较 内存ASCII码解析 内存特征码匹配 LyScript 针对内存读写函数的封装功能并不多,只提供了内存读取和内存写入函数的封装,本篇文章将继续对API进行封装,实现一些在软件逆向分析中非常实用的功能,例如内存交换,内存区域对比,磁盘与内存镜像比较,特征码检索等功能. LyScript项目地址:https://github.com/lyshark/LyScript 内存区域交换 实现被加载程序内特定一块内存区域的交换,该方法实现原理就是两个变

  • 解析Android获取系统cpu信息,内存,版本,电量等信息的方法详解

    Android获取系统cpu信息,内存,版本,电量等信息 1.CPU频率,CPU信息:/proc/cpuinfo和/proc/stat 通过读取文件/proc/cpuinfo系统CPU的类型等多种信息.读取/proc/stat 所有CPU活动的信息来计算CPU使用率 下面我们就来讲讲如何通过代码来获取CPU频率: 复制代码 代码如下: package com.orange.cpu; import java.io.BufferedReader;import java.io.FileNotFound

  • goFrame的队列gqueue对比channel使用详解

    目录 channel gqueue 概念 使用场景: 代码演示 打印结果 优势 底层实现 阻止进程销毁 运行结果 总结 channel 首先明确一下channel的作用:用于go协程间的通信. go语言最大的特点就是支持高并发:goroutine和channel是支持高并发的重要组成部分. 单纯地将函数并发执行是没有意义的.函数与函数间需要交换数据才能体现并发执行函数的意义. 如果说 goroutine 是Go程序并发的执行体,channel就是它们之间的连接.channel是可以让一个 gor

  • Java 不使用第三方变量交换两个变量值的四种方法详解

    目录 变量本身交换数值 算术运算 指针地址操作 位运算 简单总结 哈喽,大家好,我是阿Q.前几天有个小伙伴去面试,被面试官的一个问题劝退了:请说出几种不使用第三方变量交换两个变量值的方法. 问题有点绕,好不容易缕清了面试官的问题,却发现答不上来.一时间尴尬无比,只能硬着头皮说不会. 遇到交换变量值的问题,通常我们的做法是:定义一个新的变量,借助它完成交换. 代码如下: t = a; a = b; b = t; 但问题的重点是"不使用第三方变量",那就变得"可爱"起来

  • Python中高效的json对比库deepdiff详解

    目录 deepdiff是什么 deepdiff安装 案例1.对比txt文件 案例2.对比json 工作中我们经常要两段代码的区别,或者需要查看接口返回的字段与预期是否一致,如何快速定位出两者的差异?除了一些对比的工具比如Beyond Compare.WinMerge等,或者命令工具diff(在linux环境下使用),其实Python中也提供了很多实现对比的库,比如deepdiff和difflib,这两个的区别是deepdiff显示的对比效果比较简洁,但是可以设置忽略的字段,difflib显示的对

  • LyScript实现Hook隐藏调试器的方法详解

    目录 Patch_PEB Patch_IsDebuggerPresent Patch_CheckRemoteDebuggerPresent Patch_GetTickCount Patch_ZwQueryInformationProcess Patch_FindWindow Patch_EnumWindows LyScript 插件集成的内置API函数可灵活的实现绕过各类反调试保护机制,前段时间发布的那一篇文章并没有详细讲解各类反调试机制的绕过措施,本次将补充这方面的知识点,运用LyScript

  • LyScript实现Hook改写MessageBox的方法详解

    LyScript 可实现自定义汇编指令的替换功能,用户可以自行编写一段汇编指令,将程序中特定的通用函数进行功能改写与转向操作,此功能原理是简单的Hook操作. 首先我们先来实现一个Hook模板,在代码中实现中转机制,如下代码以MessageBoxA函数为案例实现修改汇编参数传递. from LyScript32 import MyDebug # 传入汇编列表,写出到内存 def assemble(dbg, address=0, asm_list=[]): asm_len_count = 0 fo

随机推荐