《加密与解密》读书笔记1

news2024/9/20 16:47:43

1、常用断点包括INT3断点、硬件断点、内存断点和消息断点。

        1.1 INT断点:一个常用的断点,在OD和x64dbg中按F2快捷键来设置/取消断点。当执行一个INT3断点时,该地址处的内容就被调试器使用INT3指令替换掉了,此时OD和x64dbg将INT3隐藏,显示出来的仍然是中断前的指令。这个INT3指令,因其机器码是0xCC,也常被称为CC指令。当被调试进程执行INT3指令导致一个异常时,调试器就会捕获这个异常,从而停在断点处,然后将断点处的指令恢复成原来的指令。INT3断点的优点是可以设置无数个断点,缺点是改变了原程序机器码,容易被软件检测到。

        1.2硬件断点:硬件断点和DRx调试寄存器有关,如下图所示:

        DRx调试寄存器总共有8个(DR0~DR7),每个寄存器的特性如下:

                A) DR0~DR3:调试地址寄存器,用于保存需要捡尸的地址,例如设置硬件断点;

                B)  DR4~DR5:保留,未公开具体作用;

                C)DR6:调试寄存器组状态寄存器

                D)  DR7:调试寄存器组控制寄存器

       硬件断点的原理就是使用DR0、DR1、DR2、DR3设定地址,并使用DR7设定状态,因此最多设置4各个断点。硬件执行断点与CC断点的作用一样,但因为硬件执行断点不会讲指令首字节修改为CC,所以更难检测

        1.3内存断点:分为内存访问断点和内存写入断点,原理是对所设的地址赋予不可方访问/不可写属性,当访问/写入的时候就会产生异常。调试器补货异常后,比较异常地址是不是断点地址,如果是就中断,让用户继续操作。因为每次出现异常是都要通过比较来确定是否该中断,所哟内存断点会降低调试器的执行速度,因此OD考虑到执行速度才规定只能下一个内存断点。需要注意的是:硬件访问/写入断点是在触发硬件断点的下一条指令处下断,而内存断点是在触发断点处的指令处下断内存断点不修改原始代码,不会像INT3断点那样因为修改代码而被程序校验导致下断失败。因此,在遇到代码校验且硬件断点失灵的情况,可以使用内存断点。

        1.4消息断点:当某个特定窗口函数接收到某个特定断点时,消息断点使程序中断。消息断点与INT3断点的区别在于:INT3断点可以在程序启动之前设置,消息断点只有在窗口被创建之后才能设置并拦截消息。

        1.5条件断点:在调试过程中,我们希望断点在满足一定条件时才会中断,这类断点称为条件断点。OD的条件断点可以按寄存器、存储器和消息的等设断。条件断点是一个带有条件表达式的普通INT3断点。当调试器遇到这类断点时,断将点计算表达式的值,如果结果非零或者表达式有效,则断点生效,被调试程序将会暂停

2、PE文件中的模块:当PE文件通过Windows加载器载入内存之后,内存中的版本称为模块。映射文件的起始地址称为模块句柄,也称为基地址。如下图所示:

内存中模块代表进程将这个可执行文件所需要的代码、数据、资源、输入表和输出表以及其他有用的数据结构所使用的内存都放在一个连续的内存块中。程序员只需要知道装在程序映像到内存后的基址,PE文件的剩余部分可以被读入,但可能无法映射。基地址的值是由PE文件本身设定的。

        2.1、虚拟地址VA:每个程序都有自己的虚拟空间,这个虚拟地址空间中的内存地址称为虚拟地址VA。

        2.2、相对虚拟地址VA:。RVA只是内存中一个简单的、相对于PE文件载入地址的偏移位置,它是一个相对地址(或称偏移量)。将一个RVA转换成真实的虚拟地址VA可使用如下公式:虚拟地址VA= 基地址ImageBase + 相对虚拟地址VAPE头内部信息大多以RVA形式存在,原因在于PE文件(主要是DLL类文件)加载到进程虚拟内存的特定位置时,该位置可能已经加载了其他PE文件()DLL。此时必须通过重定位将其加载到其他空白位置,若PE头使用的是VA,则无法正常访问,因此使用RVA来定位信息,即使发生了重定位,只要相对于基准位置的相对地址没有发生变化,就能正常访问到指定信息不会出现任何问题

        2.3文件偏移地址:当PE文件存储在磁盘时,某个数据相对于文件头的偏移量称为文件偏移地址或者物理地址FOA。文件偏移地址从PE文件的第1个字节开始计数,起始值为0。用十六进制工具打开文件时所显示的地址就是文件偏移地址。

        PE文件的基本结构:从DOS头(DOS header)到节区头(Section header)是PE头部分,剩下的节区合成PE体。文件中是偏移,内存中使用VA来表示位置。文件加载到内存时,情况就会发生变化(节区的大小、位置等)。PE文件的内容(即PE文件体)一般分为代码节、数据节、资源节,分别保存。各个节区对应的节区头定义了各个节区在文件或者内存中的大小、位置、属性等

        2.4 PE头:PE Header是PE相关结构NT头(IMAGE_NT_HEADER)的简称。当执行体在支持PE文件结构的操作系统中执行时,PE装载器从IMAGE_DOS_HEADER结构的e_lfanew字段找到PE HEADER的起始偏移量,用其加上基址,得到PE文件头的指针:

                PNTHEADER = ImageBase + dosHeader->e_lfanew

     NT头由PE头标识、PE文件头、PE可选头(又称为扩展头)组成。NT头下的文件头中的一个字段指出了PE可选头的大小,如下图所示(图中偏移量是相对于PE文件头而言的):

        需要注意的是NT头下的PE文件头中,使用了NumberOfSections来指出文件中存在的节区数量

        PE可选头虽然名称带有可选二字,但是PE文件头结构不足以定义PE文件的属性,但实际上完全不必考虑文件头和可选头之间的区别,二者连起来才是一个完整的PE文件头结构。PE可选头的定义提如下图(图中偏移量也是相对于PE文件头而言的):

        需要特别说明的是NT头下可选头中的ImageBase:PE文件被加载到虚拟内存中时,ImageBase指出文件的优先载入地址。EXE、DLL文件被载入到用户内存的(0~2^31-1)中,SYS文件被载入到内核内存中的(2^31~2^32-1)中。一般而言,使用开发工具创建好EXE之后,ImageBase的值为0x00400000,DLL文件的ImageBase值为0x10000000(当然也可以指定为其他值)。执行PE文件时,PE装载器先创建进程再将PE文件载入内存,然后把EIP寄存器的值设置为ImageBase+AddressOfEntryPoint

        2.5、区块表(节区表,节区头):紧跟在IMAGE_NT_HEADERS之后,它是一个IMAGE_SECTION_HEADER结构体的数组。每个区块表包含了它所关联的区块的信息,如位置、长度、属性。该数组的长度由NT下的PE文件头中的NumberOfSection字段指出。节表后面就是节的内容。在PE文件中创建多个节区的好处是:可以保证程序的安全性。若把code与data放在一个节区中相互纠缠很容易引发安全问题,即使忽略过程的烦琐。PE文件格式的设计者将具有相同属性的数据统一保存在一个被称为节区的地方,然后把各个节区的属性记录在节区头中(节区属性中有文件/内存的起始位置、大小、访问权限等)。不同节区的特性和访问权限如下所示:

        PE文件中“映像”的概念:PE加载到内存时,文件不会原封不动地加载,二要根据节区头中定义的节区起始地址、节区大小等加载。因此磁盘文件中的PE与内存中的PE具有不同的形态。将装载到内存中的形态称为“映像”以示区别

       2.6区块(节区):PE文件中一般至少有两个区块,一个是代码块一个是数据块。每个区块都有特定的名字,用于表示这个区块的用途。区块在影像中是按照起始地址RVA排列的,而非按字母顺序排列。区块并非全部在链接时形成,更准确的说,它们一般是从Obj文件开始被编译器放置的。链接器的工作就是合并所有Obj和库中需要的块,使其成为一个更合适的区块。合并区块的优点是节省磁盘和内存空间。区块的大小是需要对齐的,有两种对齐值:文件对齐和内存对齐。在PE文件中,FileAlignment定义了磁盘区块的对齐值。每一个区块从对齐值的倍数的偏移位置开始,但区块实际上使用的长度不一定是这么多,在不足的地方一般用00h来填充,这就是区块的间隙。同样,SectionAlignment定义了PE文件在内存中的对齐值,当PE文件映射到内存中时,区块总是至少从一个页边界处开始。也就是说,当一个PE文件被映射到内存中时,每个区块的第一个字节对应于某个内存页面。在x86系列CPU中,内存是按照4KB(0x1000)排列的,在x64中,内存是按照8Kb(0x2000)排列的。

        2.7、文件偏移与虚拟地址的转换:一些PE文见为减少体积,磁盘对齐值不是一个内存页0x1000,而是0x200,当这类文件映射到内存之后,统一数据相对于文件头的偏移量在内存和磁盘文件中是不同的。这样就出现了文件偏移地址又虚拟内存地址的转换问题。而那些磁盘对齐值0x1000与内存页相同的区块,同一数据在磁盘文件中的偏移与内存中的偏移相同,因此不需要转换。下图中显示了实例文件在磁盘中华与内存中各个区块的地址、大小等信息。虚拟地址和虚拟大小是指该区块在虚拟地址空间中的地址和大小,物理地址和物理大小是指该区块在磁盘文件中的地址和大小。(图中磁盘对齐值为0x200, 与内存对齐值不同,故磁盘映像和内存影像不同)

        PE文件被映射到内存中时,MS-DOS头部、PE文件头和块表的偏移位置与大小均没有发生变化(即PE文件头在磁盘中和内存中是没有变化的),而当各区块被映射到内存中,其偏移位置就发生了变化。因此文头部数据结构中的所有RVA字段都可以通过比较方法将该RVA定位到某个具体的节,有了这个节的内存起始RVA0,就可以求出指定RVA距离节头的偏移offset,而这个偏移在磁盘文件中和内存中都是一样的(因为对齐时是在节的数据后面补0而不是前面)。根据RVA求FOA的步骤:1)判断RVA落在哪个节中;2)求出该节的起始RVA0=IMAGE_SECTION_HEADER.VirtualAddress;3)求出偏移量offset=RVA- RVA0;4)FOA = IMAGE_SECTION_HEADER.PointerToRawData + offset

        2.8、数据目录项IMAGE_DATA_DIRECTORY:该字段为NT头的最后一个字段,它定义了PE文件中出现的所有不同类型的数据的目录信息。应用程序中的数据按照用途被分成很多种类,如导入表、导出表、资源、重定位等。在内存中这些数据被操作系统以页为单位组织起来,并赋予不同的访问属性;在文件中,这些数据也同样被组织起来,按照不同类别分别存放在文件的指定位置。数据目录项就是用来描述这些不同类别的数据在文件(和内存中)的位置以及大小的。该结构体只有两个字段,如下图所示:

        2.9、为了避免内存浪费,Windows OS设计者引入了DLL,其设计思想如下:1)不要把库包含到程序中,单独组成DLL文件,需要时使用;2)内存映射技术使加载后的DLL代码、资源在多个进程中实现共享;3)更新库时只要替换相关DLL文件即可,简便易行。加载DLL的方式有两种:显示链接(程序使用DLL时加载,使用完之后释放内存)和隐式链接(程序开始时即一同加载DLL,程序结束时再释放占用的内存)。IAT提供的机制与隐式链接有关。实际操作过程无法保证DLL一定会被加载到PE头内指定的ImageBase处。但是EXE文件(生成进程的主体)却能准确加载到自身的ImageBase中,因为EXE文件拥有自己的虚拟空间。DLL重定位使得我们无法对实际地址进行硬编码,另一个无法硬编码的原因是PE头中表示地址时不使用VA而是RVA。

        2.10、导入表:可执行文件使用来自其他DLL的代码或者数据的动作称为输入。当PE文件被载入时,Windows加载器的工作之一就是定位所有被输入的函数和数据,并让正在载入的文件可以使用那些地址,这项工作是通过PE文件的导入表Import Table完成的。导入表中保存的是函数和其驻留的DLL等动态链接所需的信息。输入函数就是被程序调用但其执行代码不在程序中的函数,这些函数的代码位于相关的DLL文件中,在调用程序中只保留相关的函数信息,如函数名和DLL文件名等。对于磁盘上的PE文件来说,它无法得知这些输入函数在内存中的地址。只有当PE文件载入内存之后,Windows加载器才将相关DLL载入,并将调用输入函数的指令和函数所处的地址联系起来。如果一个动态库在一个进程被加载过,而且在其他进程中也引用了该链接库的函数,操作系统不会再次加载这个动态链接库,而是用过页面调度基址使两个进程同时访问一个动态链接库,为了节约内存资源,操作系统只保证一份代码存在于物理内存中,不同进程中加载地址不同的相同动态链接库,其实只是页面存取机制下的一个映射而已。执行一个普通程序时往往需要导入多个库,一个导入库对应于一个IDD,导入多少库就存在多少个IMAGE_IMPORT_DESCRIPTOR(IDD)结构体,这些结构体形成了数组,且结构体数组最后以NULL结构体结束。

        OriginalFirstChunk包含了指向导入名称表INT的RVA,INT是一个IMAGE_THUNK_DATA结构的数组,数组中的每个IMAGE_THUNK_DATA结构都指向IMAGE_IMPORT_BY_NAME结构,数组以一个内容为0的IMAGE_THUNK_DATA结构结束。FirstThunk包含指向导入地址表IAT的RVA,IAT也是一个IMAGE_THUNK_DATA结构的数组

         注意:PE文件中的表指的是数组,INT和IAT是长整型(4个字节数据类型)数组,以NULL指出。(未另外明确指出大小),INT中各元素的值为IMAGE_IMPORT_BY_NAME结构体指针(有时IAT也拥有相同的值),INT与IAT的大小应相同。OriginalFirstThunk与FirstThunk相似,它们分别指向两个本质上相同的IMAGE_THUNK_DATA结构的数组,如下图所示:

        IMAGE_THUNK_DATA结构体实际上是一个双字,但在不同的时候拥有不同的解释,包括如下两种:1)双字最高位0,表示导入符号是一个数值,该数值是一个RVA;2)双字最高为1,表示导入符号是一个名称

        每一个结构IMAGE_DATA_DESCRIPTOR都对应于一个唯一的DLL文件,以及引用了该动态链接库的多个函数,每个函数的最终“值-名称”描述都可以沿着如下图所示的桥1或者桥2找到,这种导入表结构称为双桥结构。

        双桥结构的导入表在文件中存在着两份完全相同的地址列表,一般情况下,桥2指向的地址列表对应于IAT,桥1指向的地址列表对应于INT。PE文件中所有导入函数jmp指令操作数的集合组成了导入函数地址表IAT,该表是数据目录的第13个数据目录项。导入表与导入函数地址表IAT的关系如上图所示。IAT是一个双字的数组,该数组中的每个元素代表的是一个导入函数的VA(导入函数地址IA)。用户指令可以jmp指令跳转到VA指定处,便可以运行导入函数的指令。由于IAT中定义了不止一个DLL库的函数,为了进行区分,规定所有导入函数按照链接库进行分类:相邻链接库的函数地址排列在一起,最后以一个双字的0表示IAT的结束。通过上图中的桥2即可定位IAT。在内存中,桥1可以让我们找到调用函数名称或者函数的索引编号,桥2可以帮助我们找到该函数指令代码在内存空间中的地址。但是当PE文件被加载到虚拟地址空间中后,IAT的内容会被操作系统更改为函数的VA,这个修改最终会导致桥2中IAT通向“值-名称”的连接发生断裂,如下图所示:

        当桥2发生断裂以后,如果没有桥1作为参照(桥1和桥2维护了两个一一对应的函数RVA),我们就无法找重新找到该地址对应的函数名(根据IAT和INT中的数组下标(或数组索引)进行对应),这就是为什么会在导入表数据结构中存在两个桥的原因,也是为什么单桥导入表结构无法实施绑定的原因。

参考链接:

        1、《加密与解密 第4版》

        2、《Windows PE文件权威指南》

        3、《逆向工程核心原理》

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flink1.18 编译遇到的问题

1. flink-runtime-web编译失败 源码编译时一直卡在 [INFO] Running ‘npm ci --cache-max0 --no-save’ in 处理方法&#xff1a; 修改flink-runtime-web/pom.xml文件 将<arguments>ci --cache-max0 --no-save ${npm.proxy}</arguments> 替换为&#xff1a;<a…

Delphi5实现鱼C记事本程序(TRichEdit版)

效果图 鱼C记事本程序 程序图标 Delphi5的程序图标需要ICO后缀名的文件&#xff0c;已经上传到CSDN&#xff0c;可以用一下。 有什么快捷生成ICO文件的方法&#xff0c;可以在评论区分享一下噢&#xff0c;谢谢&#xff01;&#xff01; MainMenu菜单组件 TRichEdit 组件 在…

多线程(2)——线程的六种状态

1. 线程的所有状态 进程状态&#xff1a; 就绪&#xff1a;正在 cpu 上执行&#xff0c;或者随时可以去 cpu 上执行 阻塞&#xff1a;暂时不能参与 cpu 执行 Java 的线程&#xff0c;对于状态做了更详细的区分&#xff0c;不仅仅是就绪和阻塞了&#xff0c;六种&#xff1a…

2024懒人精灵七天从入门到精通实战课程(付源码)

写在开始&#xff1a;对于想学习自动化技术的同学&#xff0c;给你们一些建议&#xff1b;如果你已经选择开始&#xff0c;还在坚持&#xff0c;我奉劝你坚持下去&#xff0c;水到渠成&#xff1b;如果你还没开始就选择放弃&#xff0c;我建议你就此放弃&#xff0c;老师也不鼓…

合宙Air780EP_LuatOS_MQTT应用指南

简介 Air780EP 是合宙的低功耗4G模组之一&#xff0c;支持LuatOS的脚本二次开发&#xff0c;即使是不太懂技术的老板&#xff0c;也能轻松使用 Air780EP开发产品。 本文应各位大佬邀请&#xff0c;详细讲解了Air780EP 的MQTT的应用教程&#xff01; MQTT协议具有长连接、低带宽…

开源AI智能名片商城系统:重塑大零售生态的创新实践与深度分析

摘要&#xff1a;在数字经济浪潮的推动下&#xff0c;零售行业正经历着前所未有的变革。传统零售模式面临消费者需求多样化、市场竞争加剧等多重挑战&#xff0c;而开源AI智能名片商城系统的出现&#xff0c;为零售行业的转型升级提供了新的思路和技术支持。本文深入探讨了开源…

C语言----字符串的匹配

字符串的匹配 实例说明&#xff1a; 本实例实现对两个字符串进行匹配操作&#xff0c;即在第一个字符串中查找是否存在第二个字符串。如果字符串完全匹配&#xff0c;则提示匹配的信息&#xff0c;并显示第二个字符串在第一个字符串中的开始位置&#xff0c;否则提示不匹配。 …

STM32 - 笔记

1 STM32的串口通信 【keysking的STM32教程】 第8集 STM32的串口通信_哔哩哔哩_bilibili 波特律动 串口助手

观成科技:海莲花活跃木马KSRAT加密通信分析

概述 自2023年8月至今&#xff0c;海莲花组织多次利用KSRAT远控木马对我国发起攻击。KSRAT通过HTTP协议与C&C服务器进行通信&#xff0c;每个样本都使用了不同的URL。其心跳包采用XOR算法进行加密&#xff0c;而控制指令包和数据回传包则使用了XOR以及“XORAES-128-CBC”组…

【C语言篇】递归详细介绍(基础概念习题及汉诺塔等进阶问题)

文章目录 递归是什么递归的思想递归的限制条件 递归举例求n的阶乘分析和代码实现画图推演 顺序打印一个整数的每一位分析和代码实现画图推演 递归与迭代递归求第n个斐波那契数迭代求第n个斐波那契数 拓展练习青蛙跳台阶问题递归求解迭代求解 汉诺塔问题 递归是什么 递归是学习…

FPGA使用sv生成虚拟单音数据

FPGA使用sv生成虚拟单音数据 之前一直使用matlab生成虚拟的数据&#xff0c;导出到txt或是coe文件中&#xff0c;再导入到fpga中进行仿真测试。 复杂的数据这样操作自然是必要的&#xff0c;但是平日使用正弦数据进行测试的话&#xff0c;这样的操作不免复杂&#xff0c;今日…

CentOS 安装Redis

在 CentOS 安装 Redis 操作系统&#xff1a;centos-7.9.2009-Core 1. 更新系统 首先&#xff0c;确保你的系统是最新的&#xff1a; sudo yum update -y2. 安装 EPEL 仓库 Redis 可能不在默认的 CentOS 仓库中&#xff0c;因此你需要安装 EPEL&#xff08;Extra Packages f…

【源码+文档+调试讲解】活力健身馆管理系统

摘 要 活力健身馆管理系统的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品&#xff0c;体验高科技时代带给人们的方便&#xff0c;同时也能让用户体会到与以往常规产品不同的体验风格。 与安卓&#xff0c;iOS相比较起来&am…

springboot狱内罪犯危险性评估系统的设计与实现论文源码调试讲解

第一章系统成功运行案例 第2章 程序开发技术 2.1 Mysql数据库 开发的程序面向用户的只是程序的功能界面&#xff0c;让用户操作程序界面的各个功能&#xff0c;那么很多人就会问&#xff0c;用户使用程序功能生成的数据信息放在哪里的&#xff1f;这个就需要涉及到数据库的知识…

CTFHUB-web-RCE-eval执行

开启题目 查看源码发现直接用蚁剑连接就可以&#xff0c;连接之后发现成功了

冒烟测试:快速初步检测软件稳定性的关键步骤

目录 前言1. 冒烟测试的定义1.1 冒烟测试的起源1.2 冒烟测试的特点 2. 冒烟测试的重要性2.1 确保构建稳定性2.2 早期发现重大问题2.3 提高测试效率 3. 冒烟测试的实施方法3.1 制定测试计划3.2 选择测试用例3.3 执行测试3.4 分析测试结果 4. 冒烟测试的最佳实践4.1 自动化冒烟测…

Opera浏览器与IPXProxy代理IP集成步骤详解

​对于经常需要使用公共WiFi网络进行网络操作的人来说&#xff0c;安全性是至关重要的。作为Opera浏览器的用户&#xff0c;我非常关注隐私安全&#xff0c;也尝试过各种提高安全性的方法&#xff0c;其中使用IPXProxy代理IP是不错的方法之一。下面为大家带来Opera浏览器与IPXP…

【java】升级jetty-client解决Too many open files问题

文章目录 升级jetty-client解决Too many open files问题问题背景排查原因解决lsof命令拓展 升级jetty-client解决Too many open files问题 问题背景 生产环境的采集经过一段时间就会报错 Too many open files&#xff0c;导致接下来的采集都会失败&#xff0c;已经严重影响到…

NSSCTF练习记录:[SWPUCTF 2021 新生赛]include

题目&#xff1a; 随便传入一个file 因为存在include_once函数&#xff0c;可以使用php伪协议获取flag.php源码&#xff0c;再通过base64解码得到flag。 php:// 访问各个输入/输出流&#xff0c;常用php://filter和php://input&#xff0c;php://filter用于读取源码&#xff…

gin框架 自定义404错误页面,自定义500等服务端异常,业务异常,根据不同异常类型显示不同的异常页面方法 整理

在gin框架中&#xff0c;要显示自定义的异常页面&#xff0c;首先需要通过gin路由对象中的LoadHTMLFiles或者LoadHTMLGlob方法加载自定义的错误页面模板文件&#xff0c; 然后定义符合 gin.HandlerFunc 类型的路由处理函数/方法 &#xff0c;即只有一个参数(c *ginx.XContext)的…