发现漏洞的第一步则是需要寻找到可利用的反汇编指令片段,在某些时候远程缓冲区溢出需要通过类似于jmp esp等特定的反汇编指令实现跳转功能,并以此来执行布置好的ShellCode恶意代码片段,LyScript插件则可以很好的完成对当前进程内存中特定函数的检索工作。

一般而言远程缓冲区溢出攻击通常利用的是一些具有缓冲区溢出漏洞的函数或是特定的汇编指令片段,如:

  • strcpy:该函数将一个字符串复制到另一个字符串缓冲区中,但不会检查缓冲区的大小,因此很容易导致缓冲区溢出。
  • gets:该函数将用户输入的数据读入字符串缓冲区中,但不会检查缓冲区的大小,因此很容易导致缓冲区溢出。
  • sprintf:该函数将一个字符串格式化到字符串缓冲区中,但不会检查缓冲区的大小,因此很容易导致缓冲区溢出。

在远程缓冲区溢出攻击中,攻击者也可以利用汇编指令jmp esp来实现对攻击代码的执行。该指令允许攻击者跳转到堆栈中的任意位置,并从那里执行恶意代码。

4.3.1 搜索可利用汇编指令集

在默认情况下,LyScript插件并不具备搜索连续指令的能力,虽然提供了get_disasm_code()系列的反汇编函数,但此类函数通常仅仅只能实现简单的反汇编功能,读者如果需要实现其他附加功能,含需要自行动手去实现,首先我们自行实现一个简单的汇编指令检索功能,用于寻找可利用的指令片段"pop esp","jmp esp","jmp eax","pop ecx"等指令集。

这段代码实现的机制可总结为如下步骤;

  • 1.调用connect函数来连接到要调试的程序,并使用get_local_baseget_local_size函数获取程序的内存范围。
  • 2.定义一个名为search_asm的列表,该列表包含要搜索的汇编指令。
  • 3.使用一个while循环来遍历内存范围中的每一个地址,并调用get_disasm_one_code函数获取该地址处的反汇编代码。
  • 4.使用另一个for循环来遍历search_asm列表中的每一个指令,并检查当前反汇编代码是否与列表中的指令匹配。如果匹配,则输出该地址和反汇编代码。

代码很容易被理解和实现,本质上仅仅只是提取所内存中所有的汇编指令集,并依次枚举对比是否符合列表中的条件,其最终实现代码如下所示;

from LyScript32 import MyDebug

if __name__ == "__main__":
dbg = MyDebug()
dbg.connect() local_base_start = dbg.get_local_base()
local_base_end = local_base_start + dbg.get_local_size()
print("开始地址: {} --> 结束地址: {}".format(hex(local_base_start),hex(local_base_end))) search_asm = ["pop esp","jmp esp","jmp eax","pop ecx"] while local_base_start <= local_base_end:
disasm = dbg.get_disasm_one_code(local_base_start)
# print("地址: 0x{:08x} --> 反汇编: {}".format(local_base_start,disasm)) # 寻找指令
for index in range(0, len(search_asm)):
if disasm == search_asm[index]:
print("地址: {} --> 反汇编: {}".format(hex(local_base_start), disasm)) # 递增计数器
local_base_start = local_base_start + dbg.get_disasm_operand_size(local_base_start) dbg.close()

如上代码被运行后,则会输出当前进程内所有可被利用的指令片段,其输出效果图如下图所示;

4.3.2 搜索可利用机器码

机器码的搜索与汇编指令集的搜索方式基本保持一致,但庆幸的是搜索指令集可使用scan_memory_all()这个官方函数,该函数可用于扫描当前EIP所处位置,也就是当前EIP所在模块的所有符合条件的机器码,需要注意的是,在搜索具有漏洞函数时,通常我们会搜索进程内的完整模块,则此时应该先得到该模块的入口地址,并通过set_register()设置到该模块所在内存,然后再次对该内存区域进行搜索,代码中opcode用于指定一段机器码序列,此处读者可指定搜索多种机器码,并将搜索结果放入到该列表内进行存储。

这段代码的实现原理可总结为如下所示的步骤;

  • 定义一个名为opcode的列表,该列表包含要搜索的机器码。
  • 然后使用一个for循环来遍历每个模块,并调用get_all_module函数获取程序中的模块列表。对于每个模块,它将eip寄存器设置为该模块的入口点,然后调用scan_memory_all函数搜索该模块中是否存在要搜索的机器码。
  • 如果找到了指定的机器码,则输出模块名称、匹配个数以及机器码,并输出该机器码所在的地址。

根据上述流程可总结为如下所示的代码片段;

from LyScript32 import MyDebug
import time if __name__ == "__main__":
dbg = MyDebug()
dbg.connect() # 需要搜索的指令集片段
opcode = ['ff 25','ff 55 fc','8b fe'] # 循环搜索指令集内存地址
for index,entry in zip(range(0,len(opcode)), dbg.get_all_module()):
eip = entry.get("entry")
base_name = entry.get("name")
if eip != 0:
dbg.set_register("eip",eip)
search_address = dbg.scan_memory_all(opcode[index]) if search_address != False:
print("搜索模块: {} --> 匹配个数: {} --> 机器码: {}"
.format(base_name,len(search_address),opcode[index]))
# 输出地址
for search_index in search_address:
print("[*] {}".format(hex(search_index))) time.sleep(0.3)
dbg.close()

strcpy函数为例,读者只需要搜索特征['57 8b 7c 24 08 eb 6e','ff 55 fc','8b fe']即可定位到当前模块内所有调用该函数机器其他函数的内存地址。

运行后即可输出当前模块内所有被调用机器码的详细地址,输出效果如下图所示;

原文地址

https://www.lyshark.com/post/af00a46a.html

4.3 x64dbg 搜索内存可利用指令的更多相关文章

  1. JVM内存模型、指令重排、内存屏障概念解析

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  2. JVM内存模型、指令重排、内存屏障概念解析(转载)

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  3. JVM并发机制的探讨——内存模型、内存可见性和指令重排序

    并发本来就是个有意思的问题,尤其是现在又流行这么一句话:“高帅富加机器,穷矮搓搞优化”. 从这句话可以看到,无论是高帅富还是穷矮搓都需要深入理解并发编程,高帅富加多了机器,需要协调多台机器或者多个CP ...

  4. Vue 利用指令实现禁止反复发送请求

    前端做后台管控系统,在某些接口请求时间过长的场景下,需要防止用户反复发起请求. 假设某场景下用户点击查询按钮后,后端响应需要长时间才能返回数据.那么要规避用户返回点击查询按钮无外乎是让用户无法在合理时 ...

  5. Java内存模型与指令重排

    Java内存模型与指令重排 本文暂不讲JMM(Java Memory Model)中的主存, 工作内存以及数据如何在其中流转等等, 这些本身还牵扯到硬件内存架构, 直接上手容易绕晕, 先从以下几个点探 ...

  6. 进程间通信 - 动态链接库中共享内存(利用DLL的2~3G的地址段空间)

    前言 进程是装入内存并准备执行的程序,每个进程都有私有的虚拟地址空间,由代码.数据,以及其他的一些资源组成.32位系统的进程分配4G的虚拟地址空间.内存地址范围是0x00000000-0xFFFFFF ...

  7. CE搜索内存数据的原理

      最近发现有朋友在玩游戏时, 使用一款工具来修改游戏的部分数据,作弊的效果, 也就是CE(Cheat Engine),这款工具是 delphi 编写的, 于是好奇, 然后瞬间想到API OpenPr ...

  8. 【java多线程系列】java内存模型与指令重排序

    在多线程编程中,需要处理两个最核心的问题,线程之间如何通信及线程之间如何同步,线程之间通信指的是线程之间通过何种机制交换信息,同步指的是如何控制不同线程之间操作发生的相对顺序.很多读者可能会说这还不简 ...

  9. CTF内存高级利用技术

    起了一个比较屌的标题,233.想写这篇文章主要是看了kelwya分析的议题,于是准备自己动手实践一下.蓝莲花的选手真的是国际大赛经验丰富,有很多很多的思路和知识我完全都没有听说过.这篇文章会写一些不常 ...

  10. Java并发:volatile内存可见性和指令重排

    volatile两大作用 1.保证内存可见性 2.防止指令重排 此外需注意volatile并不保证操作的原子性. (一)内存可见性 1 概念 JVM内存模型:主内存和线程独立的工作内存 Java内存模 ...

随机推荐

  1. 四月八号java基础

    1.复合语句:JAVA语言不允许在两个嵌套的复合语句内声明同样的变量 2.注释:1)单行注释// 2)多行注释/*......*/3)/**......*/文件注释 3.else总是与之最近的if结构 ...

  2. C语言中,取反运算符~a=-(a+1)的原因

    1.因为计算机直接拿读取到的数据去运算付出的代价是最小的,所以计算机存储的数据的形式应该满足读取后不必经过任何加工就能直接用来运算由于原码不经加工无法实现(+a)+(-a)=0,所以不满足该要求,为了 ...

  3. 本地socket通讯

    本地socket通讯        虽然学过网络socket,但是对于本地socket通讯却不是很熟悉,刚在项目中看到,所以在网上找了一篇介绍的比较详细的,mark下!!!        socket ...

  4. shell执行一个程序过程

    1:shell调用执行程序或脚本 2:unix内核启动一个新的进程,在该进程中执行所指定的程序. 3:如果是编译型程序,内核成执行,如果无法执行指定的程序,返回"not executable ...

  5. [人脸活体检测] 论文:Searching Central Difference Convolutional Networks for Face Anti-Spoofing

    文章目录 Searching Central Difference Convolutional Networks for Face Anti-Spoofing 1 导读 2 简介 3 方法 中心差分卷 ...

  6. [C++核心编程] 1、内存分区模型

    文章目录 1 内存分区模型 1.1 程序运行前 1.2 程序运行后 1.3 new操作符 1 内存分区模型 C++程序在执行时,将内存大方向划分为4个区域 代码区:存放函数体的二进制代码,由操作系统进 ...

  7. Python3.10动态修改Windows系统(win10/win11)本地IP地址(静态IP)

    一般情况下,局域网里的终端比如本地服务器设置静态IP的好处是可以有效减少网络连接时间,原因是过程中省略了每次联网后从DHCP服务器获取IP地址的流程,缺点是容易引发IP地址的冲突,当然,还有操作层面的 ...

  8. 【Ubuntu】1. 创建虚拟机

    这一篇主要写了虚拟机的创建,不包含操作系统的安装,中间有些步骤没有提到的根据默认操作即可,也可以根据个人情况设置. 点击创建新的虚拟机 这一步可以选择典型安装,过程更简单些,这里我选择自定义. 在安装 ...

  9. 【自用】无限级分类获取SQL语句

    自定义函数: 1 USE [ExpenseCenter_Fibrogen] 2 GO 3 /****** Object: UserDefinedFunction [dbo].[GetSubordina ...

  10. stl-----map去重,排序,计数

    一.map erase()删除函数:可以迭代器删除,关键字删除,成片删除. 例:1.iter=mapStu.find(1); mapStu.erase(iter); 2.int n = mapStu. ...