IDA PRO 0A - 交叉引用

本文将讨论IDA中的交叉引用的相关知识。

更多c++逆向知识可以看B站的课程《C++ 反汇编基础教程(IDA Pro Visual Studio)》

交叉引用

IDA 中的交叉引用通常简称为xref 。从名字可以看出,使用快捷键就可以找出某个函数或者数据被引用的地方。

在IDA 中有两类基本的交叉引用:代码交叉引用和数据交叉引用。这两种引用又分别包含几种不同的交叉引用。

文本CODE XREF 表示这是一个代码交叉引用,而非数据交叉引用(DATA XREF )。后面的地址(这里为_main+2A )是交叉引用的源头地址。

交叉引用中使用的地址提供了额外的信息,指出交叉引用是在一个名为_main 的函数中提出的,具体而言是 _main 函数中的第 0x2A(42 )字节。地址后面总是有一个上行或下行箭头,表示引用位置的相对方向。

下行箭头表示 _main+2A 的地址比sub_401000 要高,因此,你需要向下滚动才能到达该地址。同样,上行箭头表示引用地址是一个较低的内存地址,你需要向上滚动才能到达。最后,每个交叉引用注释都包含一个单字符后缀,用以说明交叉引用的类型。

代码交叉引用

代码交叉引用用于表示一条指令将控制权转交给另一条指令。

在 IDA中,指令转交控制权的方式叫做流 (flow )。IDA 中有3 种基本流:普通流 、跳转流 和调用流 。

在接下来的讨论中,我们使用以下例子讲解:

int read_it; //integer variable read in main
int write_it; //integer variable written 3 times in main
int ref_it; //integer variable whose address is taken in main

void callflow() {} //function called twice from main

int main() {
 int *p = &ref_it; //results in an "offset" style data reference
 *p = read_it; //results in a "read" style data reference
 write_it = *p; //results in a "write" style data reference

 callflow(); //results in a "call" style code reference

 if (read_it == 3) { //results in "jump" style code reference
  write_it = 2; //results in a "write" style data reference
 }
 else { //results in an "jump" style code reference
  write_it = 1; //results in a "write" style data reference
 }

 callflow(); //results in an "call" style code reference
}

其汇编代码如下:

.text:00401010 _main proc near
.text:00401010
.text:00401010 p = dword ptr -4
.text:00401010
.text:00401010 push ebp
.text:00401011 mov ebp, esp
.text:00401013 push ecx
.text:00401014 ➒ mov [ebp+p], offset ref_it
.text:0040101B mov eax, [ebp+p]
.text:0040101E ➐ mov ecx, read_it
.text:00401024 mov [eax], ecx
.text:00401026 mov edx, [ebp+p]
.text:00401029 mov eax, [edx]
.text:0040102B ➑ mov write_it, eax
.text:00401030 ➌ call callflow
.text:00401035 ➐ cmp read_it, 3
.text:0040103C jnz short loc_40104A
.text:0040103E ➑ mov write_it, 2
.text:00401048 ➊ jmp short loc_401054
➎.text:0040104A ; -------------------------------------------------------------
.text:0040104A
.text:0040104A loc_40104A: ➏ ; CODE XREF: _main+2C↑j
.text:0040104A ➑ mov write_it, 1
.text:00401054
.text:00401054 loc_401054: ➏ ; CODE XREF: _main+38↑j
 .text:00401054 ➌ call callflow
.text:00401059 xor eax, eax
.text:0040105B mov esp, ebp
.text:0040105D pop ebp
.text:0040105E ➋ retn
.text:0040105E _main endp

普通流 (ordinary flow )是一种最简单的流,它表示由一条指令到另一条指令的顺序流。这是所有非分支指令(如 ADD )的默认执行流。除了指令在反汇编代码清单中的显示顺序外,正常流没有其他特殊的显示标志。如果指令 A 有一个指向指令 B 的普通流,那么,在反汇编代码清单中,指令 B 会紧跟在指令 A 后面显示。在上面的汇编代码中,除➊、➋两处的指令外,其他每一条指令都有一个普通流指向紧跟在它们后面的指令。

处的 x86 call 指令,它分配到一个调用流(call flow ),表示控制权被转交给目标函数。多数情况下,call 指令同时也是一个普通流,因为大多数函数会返回到 call 之后的位置。如果IDA 认为某个函数并不返回(在分析阶段确定),那么,在调用该函数时,它就不会为该函数分配普通流。调用流通过在目标函数(流的目的地址)处显示交叉引用来表示。callflow 函数的反汇编代码清单如下所 示:

.text:00401000 callflow proc near ; CODE XREF: _main+20↓p
.text:00401000                    ; _main:loc_401054 ↓ p
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 pop ebp
.text:00401004 retn
.text:00401004 callflow endp

在这个例子中,callflow 所在的位置显示了两个交叉引用,表示这个函数被调用了两次。除非调用地址有相应的名称,否则,交叉引用中的地址会以调用函数中的偏移量表示。这里的交叉引用分别用到了上述两种地址。由函数调用导致的交叉引用使用后缀 p (看做是Procedure)。每个无条件分支指令和条件分支指令将分配到一个跳转流 (jump flow)。条件分支还分配到普通流,以在不进入分支时对流进行控制。无条件分支并没有相关的普通流,因为它总会进入分支。➎处的虚线表示相邻的两条指令之间并不存在普通流。跳转流与跳转目标位置显示的跳转式交叉引用有关,如➏处所示。与调用式交叉引用一样,跳转交叉引用显示引用位置(跳转的源头)的地址。跳转交叉引用使用后缀 j(看做是Jump)。

数据交叉引用

IDA 中最常用的3 种数据交叉引用分别用于表示某个位置何时被读取、何时被写入以及何时被引用

下面是与前一个示例程序有关的全局变量,其中包含几个数据交叉引用:

.data:0040B720 read_it dd ? ; DATA XREF: _main+E ↑ r
.data:0040B720              ; _main+25 ↑ r
.data:0040B724 write_it dd ? ; DATA XREF: _main+1B ↑w
.data:0040B724            ➓ ; _main+2E↑ w ...
.data:0040B728 ref_it db ? ; ; DATA XREF: _main+4 ↑ o
.data:0040B729 db ? ;
.data:0040B72A db ? ;
.data:0040B72B db ? ;

读取交叉引用 (read cross-reference)表示访问的是某个内存位置的内容。读取交叉引用可能仅仅源自于某个指令地址,但也可能引用任何程序位置。

全局变量 read_it 在➐处被读取。根据上面代码中显示的相关交叉引用注释,我们可以知道 main 中有哪些位置引用了read_it 。根据后缀r ,可以确定这是一个读取交叉引用。对read_it 的第一次读取是存到ECX寄存器中,所以 IDA 将read_it 格式化成一个双字。全局变量 write_it 在➑处被引用。写入交叉引用使用后缀 w 。值得注意的是,write_it 位置显示的交 叉引用以省略号➓处结束,表明对write_it 的交叉引用数量超出了当前的交叉引用显示限制。你可以通过Options→General对话框中Cross-references 选项卡中的 Number of displayed xrefs(显示的交叉引用数量)设置修改这个限制。第三类数据交叉引用为偏移量交叉引用 (offset cross-reference ),它表示引用的是某个位置的地址(而非内容)。全局变量ref_it 的地址在➒处被引用,因此,在上面的代码中,ref_it 所在的位置显示了偏移量交叉引用(后缀为 o )的注释。

通常,代码或数据中的指针操作会导致偏移量交叉用。例如,数组访问操作一般通过在数组的起始地址上加上一个偏移量来实现。因此,许多全局数组的第一个地址通常可以由偏移量交叉引用来确定。偏移量交叉引用可能源于指令位置或数据位置。

例如,如果一个指针表(如虚表)从表中的每个位置向的地方生成一个偏移量交叉引用,则这种偏移量交叉引用就属于源于程序数据部分的交叉引用。

分析上一篇中类SubClass 的虚表,就可以发现这一点,它的反汇编代码清单如下所示:

.rdata:00408148 off_408148 dd offset SubClass::vfunc1(void) ; DATA XREF: SubClass::SubClass(void)+12 ↑o
.rdata:0040814C dd offset BaseClass::vfunc2(void)
.rdata:00408150 dd offset SubClass::vfunc3(void)
.rdata:00408154 dd offset BaseClass::vfunc4(void)
.rdata:00408158 dd offset SubClass::vfunc5(void)

可以看到,类构造函数SubClass:: SubClass(void) 使用了虚表的地址。函数SubClass:: vfunc3(void) 的标题行如下所示,显示了连接该函数与虚表的偏移量交叉引用。

.text:00401080 public: virtual void __thiscall SubClass::vfunc3(void) proc near
.text:00401080                                            ; DATA XREF: .rdata:00408150↓o

这个例子证实了 C++ 虚函数的一个特点,结合偏移量交叉引用来考查,这个特点显得尤为明显,即 C++ 虚函数绝不会被直接引用,也绝不应成为调用交叉引用的目标。所有C++ 虚函数应由至少一个虚表条目引用,并且始终是至少一个偏移量交叉引用的目标。最后,回溯偏移量交叉引用是一种有用的技术,可迅速在程序的数据部分定位 C++ 虚表。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/254350.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NSSCTF第16页(3)

[SWPUCTF 2023 秋季新生赛]ez_talk 上传一句话木马得到 抓包改文件类型 上传成功,只是倒序而已 得到flag [第五空间 2021]PNG图片转换器 这道题采用的是ruby语言,第一次听说 2021-第五空间智能安全大赛-PNG图片转换器 | 管道符与反引号的配合、open…

使用python实现链表

手写代码 class Node(object):def __init__(self, item):self.item itemself.next Noneclass LinkListFunction(object):"""此对象为Node对象的方法类"""def __init__(self):self.linklistlength 0 # 当前链表的长度def create_linklist_he…

C语言学习第二十六天(算法的时间复杂度和空间复杂度)

1、算法效率 衡量一个算法的好坏,是从时间和空间两个方面来衡量的,换句话说就是从时间复杂度和空间复杂度来衡量的 这里需要补充一点:时间复杂度是衡量一个算法的运行快慢,空间复杂度是主要衡量一个算法运行所需要的额外空间。 …

「Verilog学习笔记」交通灯

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 timescale 1ns/1nsmodule triffic_light(input rst_n, //异位复位信号,低电平有效input clk, //时钟信号input pass_request,output wire[7:0]clock,output reg…

Shared Worker的快速理解与简单应用

SharedWorker 是 HTML5 中引入的一种 WebWorkers 类型,用于在浏览器中创建可在多个浏览器窗口或标签页之间共享的后台线程。Web Workers 是在主线程之外运行的脚本,允许执行一些耗时的任务而不会阻塞用户界面。 对 SharedWorker 的概念、理解和应用的简要…

2023第十七届中国品牌节,酷开科技荣获金谱奖!

11月18日,以“复苏与腾飞”为主题的2023第十七届中国品牌节,在杭州市云栖小镇国际会展中心盛大开幕。来自政界、商界、文化界等领域的6000余名嘉宾出席本次盛会,共同见证了民族品牌的崛起,全力奉献一场史无前例的“品牌人的亚运会…

Pikachu漏洞练习平台之暴力破解(基于burpsuite)

从来没有哪个时代的黑客像今天一样热衷于猜解密码 ---奥斯特洛夫斯基 Burte Force(暴力破解)概述 “暴力破解”是一攻击具手段,在web攻击中,一般会使用这种手段对应用系统的认证信息进行获取。 其过程就是使用大量的认证信息在认…

【操作系统】实验名称: 实验五 文件系统

实验目的: 1. 掌握文件系统的基本概念和工作机制 2. 掌握文件系统的主要数据结构的实现 3、掌握软件系统实现算法 实验内容: 设计并实现一个虚拟的一级(单用户)文件系统程序 提供以下操作 1、文件创建/删除接口命令 2、目录创建/删…

合并 K 个排序链表——Java解答

题目:合并 K 个排序链表 题目描述: 给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。 示例: 假设有以下三个链表: 1->4->5, 1->3->4,…

QUIC在零信任解决方案的落地实践

一 前言 ZTNA为以“网络为中心”的传统企业体系架构向以“身份为中心”的新型企业安全体系架构转变,提供解决方案。随着传统网络边界不断弱化,企业SaaS规模化日益增多,给终端安全访问接入创造了多元化的空间。其中BYOD办公方式尤为突出&#…

SpringBoot使用@DS配置 多数据源 【mybatisplus druid datasource mysql】

项目最近需要使用多数据源,不同的mapper分别读取不同的链接,本项目使用了mybatisplus druid 来配置多数据源,基于mysql数据库。 目录 1.引入依赖 ​2.配置文件 application.yaml 3.Mapper中使用DS切换数据源 4.使用DS的注意事项 1.引入依…

苹果忽略iPhone?2024可穿戴产品或成重心!

一代版本一代神,即便是强如iPhone也有着被忽视的一天,当然,这么说有些夸张。虽然iPhone永远都是苹果最重要的产品,但在明年,苹果的重心将偏向其他产品。 彭博社记者马克古曼(Mark Gurman)在新一…

如何确保对称密钥管理的存储安全?

确保对称密钥管理的存储安全是保障信息安全的重要一环。以下是一些建议,以确保对称密钥管理的存储安全: 使用安全存储设备:选择使用经过验证的安全存储设备来存储对称密钥。这些设备通常具有高度的物理安全性,可以防止未经授权的访…

使用Umi搭建React项目

环境准备 一、首先确保有 node环境,并确保 node 版本是 14 或以上。(推荐用 nvm 来管理 node 版本,windows 下推荐用 nvm-windows) nvm使用教程 二、然后需要包管理工具。node 默认包含 npm,但也可以选择其他方案&a…

eclipse-安装WindowBuilder,怎么安装

WindowBuilder是Eclipse的一个插件,可以帮助开发者使用Java Swing、JavaFX和SWT快速构建图形用户界面(GUI)。下面是WindowBuilder的安装步骤: 1. 打开Eclipse IDE(请确保已安装JDK)。 2. 点击“Help”菜单…

【MySQL】:表的删除和修改

表的删除和修改 一.update(修改)二.delete(删除)1.删除数据2.截断表 三.插入查询的数据四.聚合函数五.group by 句子的使用1.导入表2.进行操作 一.update(修改) 对查询到的结果进行列值更新 下面有一个表,接下来的操作都是对该表进行操作。 1.将孙悟空同学的数学成绩…

目标跟踪 MOT数据集和可视化

目录 MOT15数据集格式简介 gt可视化 本人修改的GT可视化代码: MOT15数据集格式简介 以下内容转自:【目标跟踪】MOT数据集GroundTruth可视化-腾讯云开发者社区-腾讯云 MOT15数据集下载:https://pan.baidu.com/s/1foGrBXvsanW8BI4eybqfWg?…

100GPTS计划-AI写诗PoetofAges

地址 https://chat.openai.com/g/g-Cd5daC0s5-poet-of-ages https://poe.com/PoetofAges 测试 创作一首春天诗歌 创作一首夏天诗歌 创作一首秋天诗歌 创作一首冬天诗歌 微调 诗歌风格 语气:古典 知识库

嵌入式Linux开发板硬件学习-基于cadence

嵌入式Linux开发板硬件学习-基于cadence 目录原理图网表输出功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创…

本章主要介绍Spring Framework中用来处理URI的多种方式

1.使用 UriComponentsBuilder 构建URi 话不多说 直接上代码 UriComponents uriComponents UriComponentsBuilder.fromUriString("https://example.com/hotels/{hotel}").queryParam("q", "{q}").encode().build();URI uri uriComponents.exp…
最新文章