首页 > 其他分享 >加密与解密x64逆向——虚函数

加密与解密x64逆向——虚函数

时间:2023-04-21 23:22:08浏览次数:34  
标签:调用 虚表 函数 继承 x64 解密 基类 加密 构造函数

4.整数的取模

取模运算可以通过除法指令实现。一般的优化做法是将其转换成等价的位运算或者除法运算,再由除法运算进行优化。

虚函数

C++的三大核心机制是封装,继承,多态,而虚函数就是多态的一种体现。软件逆向中,难免遇到使用面向对象思想设计的软件,而虚函数就是在实际软件逆向过程中的一种还原面向对象的重要手段。本章探讨编译器实现虚函数的原理。

1.虚表





首先在main的入口先申请了对象实例的内存空间。先调用构造函数,调用fun1,fun2.这些成员函数调用的第一个参数就是this指针,也就是rcx=this。C++语法规定在实例化对象时会自动调用构造函数,对象作用域会自动调用析构函数。
在逆向过程中,当一个对象是在某个作用域内调用的第一个函数,就可以怀疑是构造函数,如果是最后一个,就怀疑是析构函数的调用。
构造函数中首先初始化虚表指针,然后初始化数据成员,构造函数完成,返回this指针。

然而为什么析构函数还要赋值虚表,构造函数不是赋值了吗?这是因为C++语法规定,析构函数需要调用虚函数的多态性。在分辨哪一个是构造函数哪一个是析构的时候可以看调用的顺序。
虚标中的函数成员函数声明顺序依次放入的。需要注意的是函数分布顺序在某些情况,和声明顺序不一定相同。不过顺序对逆向还原也没有影响。本例中只写了一个虚析构函数吗,却生成了两个析构函数。其中一个是普通析构函数,一个是放在虚表里的。

2.单重继承虚表






为什么main函数使用new申请对象空间。因为虚表需要8字节虚表空间和8字节的内存对齐。这里可以看出派生类和基类共享一个虚表指针。

 

3.多重继承虚表

多重继承是指一个类同时继承多个父类。多重继承与单重继承相比,可以有多个父类。




可以看出main函数与单重继承无区别。在cderived构造函数中,首先按继承顺序调用两个基类的构造函数,然后执行自己的构造函数代码。
因为两个基类都有虚函数,在这种情况下编译器会为派生类生成两个虚表,在构造函数时初始化。虚表项的构造顺序和上一个例子基本一致,唯一的区别在于派生类新增的虚函数挂在了第一个虚表后面。

4.菱形继承虚表

两个子类继承自同一个父类,又有子类同时继承这两个子类(在子类的子类中出现)。在内存布局会出现两个相同的父类内存结构。







main函数中的构造函数调用有点特殊,多传递了一个标识是否调用基类构造函数的标志参数。按语法B的构造函数要先构造A,这样编译器就要在B类的构造函数里调用A类的构造函数。顺序没有问题,然而在BC的构造也要先构造B构造C,在BC的构造函数里调用了B类的构造函数和C的构造函数。这里就有问题,因为这样子A的构造函数就被调用了两次。而这是多传递了一个参数就是用来表示是否调用虚基类的构造这样就可以防止虚基类被调用两次。
在调用虚基类构造函数之前,出现了一个初始化虚基类偏离表的操作。这是因为存在徐继承,虚基类对象的内存在派生类的内存中只保留一份,所以在编译器方便定位虚基类在对象内存中的位置,做一个虚基类偏移表。
所以我们在逆向分析时,如果发现构造函数有初始化虚基类偏移表的操作就可以怀疑这个类继承层次带有虚继承。

5.抽象类虚表

在C++中,含有纯虚函数的类称为抽象类,它不能实例化对象。面向对象设计中常用抽象类给子类规范接口,接口的功能通常都是重要功能。它最大的特点就是没有实现代码。如果在逆向分析时找到一个类的抽象类那么就可以通过他的构造函数就可以定位它的所有子类,得到重要功能。



可以看出父类为抽象类的实现代码和单重继承没有太大区别,唯一的别就是虚表。由于纯虚函数没有实现代码,编译器默认填充_purecall函数地址。
如果发现一个类的虚表里面有_purecall虚表项。

小结

 

标签:调用,虚表,函数,继承,x64,解密,基类,加密,构造函数
From: https://www.cnblogs.com/bonelee/p/17342191.html

相关文章

  • 【逆向】x64程序逆向基础——调用约定和栈使用
    【逆向】x64程序逆向基础 主要区别1.所有地址指针都是64位。2.增加和扩展新的寄存器,并兼容原32位版本的通用寄存器。3.原指令指针寄存器EIP扩展为RIP。寄存器1.64位寄存器兼容原32位寄存器。2.新增加8个XMM寄存器(XMM8-XMM15)。3.扩展原32位寄存器的64位版本,并......
  • AES加解密
    AES加解密 https://www.cnblogs.com/SjhCode/p/AES.htmlAES加解密工具类  importjavax.crypto.Cipher;importjavax.crypto.spec.IvParameterSpec;importjavax.crypto.spec.SecretKeySpec;importjava.util.Objects;/***@author*@date2022/8/3115:......
  • Linux系统文件加密的详细教程
    Linux系统一切皆为文件而且Linux系统又是一个多用户系统,所以数据的安全性非常重要,有些情况需要对文件进行加密,那么Linux系统中如何对文件进行加密呢?下面良许教程网为大家分享一下Linux系统文件加密的方法。方法一:gzexe加密 这种加密方式不是非常保险的方法,但是能够满足一般的加......
  • 用C#写一个上传下载文件至OSS后返回文件路径用DES加密解密
    废话不多说,直接上代码:usingAliyun.OSS;//引入阿里云OSSSDKusingSystem;usingSystem.IO;usingSystem.Security.Cryptography;//引入.NETFramework中的加密库usingSystem.Text;publicclassOSSHelper{///<summary>///将文件上传至OSS,并使用D......
  • 期货基差显示美国投资者更看涨市场,Q1 加密公司股票表现优于BTC
    作者:NYDIG全球研究主管GregCipolaro编译:WEEXBlog本文要点:·一个关键指标表明,美国投资者更看好比*特币,从事对冲交易策略的人可能有机会。·加密行业股票的回报凸显了一些重要的商业模式动态。·比*特币生态的企业家精神。期货基差向美国投资者展示积极信号在岸受监管的期货......
  • AES算法 前端JavaScript加密 后端Java解密
    CryptoJShttps://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js中文文档https://cryptojs.gitbook.io/docs/varAES=function(){ constuuid32="00010203-04050607-08090A0B-0C0D0E0F".toString();constparam=Array.from(uuid32......
  • 哈希加密伪代码
    //定义SHA256压缩函数functionsha256_compress(data_block){for(leti=16;i<64;i++){w[i]=(ROTR(17,w[i-2])^ROTR(19,w[i-2])^(w[i-2]>>>10))+w[i-7]+(ROTR(7,w[i-15])^ROTR(18,w[i-15])^(w[i-15]>>>3))+w[i-16];}let[a,b,......
  • 升级Java17后Maven中使用bouncycastle加解密遇到JCE cannot authenticate the provide
    网上找了很多办法,逐一试过之后,发现有效的方式为修改打包方式:<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version&......
  • [Java并发包学习七]解密ThreadLocal
    相信读者在网上也看了很多关于ThreadLocal的资料,很多博客都这样说:ThreadLocal为解决多线程程序的并发问题提供了一种新的思路;ThreadLocal的目的是为了解决多线程访问资源时的共享问题。如果你也这样认为的,那现在给你10秒钟,清空之前对ThreadLocal的错误的认知!看看JDK中的源码是怎么......
  • Nlog-动态修改DatabaseTarget,对数据库字符串进行加密
    privatestaticLoggerprocessLogger;//①LnProcessDBLog标签LogManager.GetLogger("LnProcessDBLog");②使用前先保证不为null,否则InitNlog();//修改Nlog.config配置的文件privatestaticvoidInitNlog(){LoggingConfigurationloggingConf......