首页 > 其他分享 >【加密与解密】第四章①

【加密与解密】第四章①

时间:2023-01-11 18:33:35浏览次数:43  
标签:调用 加密 函数 解密 调用函数 编译器 参数 寄存器 第四章

通过分析汇编代码来理解其代码功能,然后用高级语言重新描述这段代码,逆向分析原始软件的思路,这就是逆向工程。

32位软件逆向技术

启动函数

首先被执行的是启动函数的相关代码,这段代码是由编译器生成的。启动函数就是对该运行库进行一个初始化。当所有的初始化操作结束后,启动函数会调用应用程序的进入点函数。进入点返回时,启动函数便调用C运行库的exit函数,将返回值传递给他,再推出。

函数

逆向工程中将重点放在函数的识别及参数的传递是明智的,这样可以将注意力集中在一段代码上。

1.函数的识别

程序通过调用程序调用函数,函数执行后又返回调用程序继续执行。实际上,调用函数的代码中保存了一个返回地址,该地址会与参数一起传递给被调用的函数。很多情况下,编译器都是用call与ret。
call给出的地址就是被调用函数的起始位置,ret命令则用于结束函数的执行。有一个例子。

也有例外,程序的调用函数通过间接调用,即通过寄存器传递函数地址或者动态计算函数地址调用,也有例子

2.函数的参数

参数传递有三种方式,栈放肆,寄存器方式及通过全局变量进行隐含函数参数传递。如果是栈方式,就需要定义参数在栈中的顺序并约定被调用后谁来平衡栈。如果是寄存器传递,就需要规定存放在哪个寄存器当中。

①栈传递

栈后进先出。在调用函数时,调用者依次把参数压入栈,然后调用函数。函数调用后,栈中取得数据并计算。当参数的个数多于一个时,以什么样的顺序压入栈有一个约定。这就是调用约定。不同的语言有不同的调用约定。

我们可以理解stdcall是缝合的约定协议。有cdecl的特点:参数传递由右到左(先压入最后面的),也有pascal的特点:由调用函数清除栈。

非优化编译器用一个专门的寄存器通常是ebp,对参数进行寻址。

对于函数传递,也通过对高级语言分析出了汇编语言。


此外enter和leave指令也可以进行栈的维护,诸如此类的可以看出编译器对程序进行优化,以此来减少代码提高运行速度。

②利用寄存器传递参数

利用寄存器传递参数没有标准。fastcall顾名思义也很快。
左边的2个不大于4个字节的参数放在ecx和edx寄存器中。左边的3个不大于4个字节的参数放在eax,edx和ecx寄存器中。
另外也有一款编译器总是通过寄存器来传递参数。第一个参数用eax,第二个edx第三个ebx第四个ecx。

③名称修饰约定

为了允许使用操作符和函数重载,C++编译器往往会按照某种规则改写每一个入口点的符号名,从而允许同一个名字有多个用法且不破坏现有的基于C的链接器。这项技术通常称为名称改变或者名称修饰。
C编译的函数名修饰约定规则如下

C++编译

3.函数的返回值

函数被调用执行后,将向调用者返回一个或者多个执行结果,称为函数返回值。

①return操作符

一般情况下,返回值存放在eax返回。如果超过规模那么高32位就会放在edx寄存器当中。

②通过参数按传引用方式返回值

函数参数传递方式有两种,分别是传值和传引用。传值调用时,会建立参数的一份副本,传给参数,在调用函数中修改副本不影响原来的值。传引用调用允许修改原始量。

数据结构

数据结构是计算机存储,组织数据的方式。本节将讨论厂家的呢数据结构以及他们在汇编中的实现方式。

1.局部变量

是函数内部定义的一个变量。作用域和生命周期局限于所在函数内。

①利用栈存放局部变量

程序用sub语句为局部变量分配空间,用【ebp-xxxx】寻址调用这些变量,而参数调用相对于ebp偏移量是正的,即【ebp+xxxx】。另外push reg用取代sub esp,4指令也可以节省几个字节

②利用寄存器存放局部变量

除了栈占用的两个寄存器,编译器还会利用6个通用寄存器尽可能有效的存放局部变量。如果寄存器不够了,编译就会将变量放在栈中。

2.全局变量

全局变量作用于整个程序,放在全局变量的内存区中。绝大部分情况中,汇编代码识别全局变量比在其他结构当中容易的多。全局变量位于.data的数据区块当中。调用全局变量的时候一般会用一个硬编码地址进行内存寻址

与全局变量类似的是静态变量都直接方式寻址,区别在静态变量仅在定义这些变量的函数中有效。

3.数组

数组是相同数据类型的元素的结合。在汇编状态下访问数组一般是基址加变址寻址实现的。例如下面这例子

虚函数

C++是一门支持面向对象的语言。它的核心概念不多,最重要的概念是虚函数。虚函数的地址不能在编译时确定,只能在调用时确定。所有对虚函数的引用通常放在一个专用数组,虚函数表。调用虚函数时先取出虚函数表指针,再得到虚函数表的地址,并通过这个地址取出虚函数。

有一个例子


虚函数表中有两组数据分别是add函数和sub函数

所以看出虚函数是函数表的指针间接加以调用的。

控制语句

识别关键跳转是软件解密的一项重要技能

1.if then else语句

cmp指令不会修改操作数。操作数相减会影响处理的几个标志,例如零标志,进位标志符号标志和溢出标志。jz等指令就是条件跳转指令。实际上,很多编译器用test或者or之类的短的逻辑指令替换cmp。一般是“test eax,eax”如果eax值为0,逻辑与运算结果为0,zf为1否则zf为0.

2.switch-case语句

实际上就是多个if then语句的嵌套组合。

不优化版本

优化后

优化时用dec eax代替了cmp,指令更短运行速度更快。

3.转移指令机器码的计算

分为短转移和长转移。短转移:无条件和条件转移都是2个字节。长转移:无条件为5字节,有条件为6字节。子程序调用指令:有两类,一类类似于长位移,一类是调用的参数设计寄存器,栈比较复杂。

①短转移指令机器码计算实例

有一段无条件转移指令

无条件转移的机器码格式为“EBxx”,EB00h~EB7Fh为后位移80h到FFh是向前位移。

②长位移指令机器码计算实例


标签:调用,加密,函数,解密,调用函数,编译器,参数,寄存器,第四章
From: https://www.cnblogs.com/Corax0o0/p/17044577.html

相关文章

  • RSA非对称加密和MD5不可逆加密代码示例
    加密算法可以分为三大类:对称加密算法:DES 非对称加密算法: RSAHash算法: MD5登陆密码加密流程:web端用公钥加密密码,server端用私钥解码,将解出的明文用MD5加密......
  • SQL Server 2016 Always Encrypted(始终加密)
    AlwaysEncrypted功能旨在保护AzureSQLDatabase或SQLServer数据库中存储的敏感数据,如信用卡号或身份证号(例如美国社会安全号码)。始终加密允许客户端对客户端应用程......
  • 【加密与解密】第三章⑦
    其他功能1.图形化功能这种模式比文本模式的可视性更好,用户更容易看清函数的代码流程。通过空格切换文本模式或者图形化模式。2.修改可执行文件使用IDA可以直接修改二进......
  • Golang实现16/32位MD5加密
    转自:Golang实现16/32位MD5加密packagemainimport( "crypto/md5" "encoding/hex" "fmt")//返回一个32位md5加密后的字符串funcGetMD5Encode(datastring)stri......
  • MySQL必知必会第四章-检索数据
    检索数据SELECT语句SELECT语句用途是从一个或多个表中检索信息。为了使用SELECT检索表数据,必须至少给出两条信息——想选择什么,以及从什么地方选择。检索单个列利用SEL......
  • 记录一下 php解密java的问题
    使用大佬的:https://github.com/lpilp/phpsm2sm3sm4php版本国密意见问题:在判断椭圆点的时候x,y报错。发现java部分的问题在于/***分解加密字串*(C1=C1标志位2位+C1......
  • SimpleAdmin手摸手教学之:国密加密
    一、什么是国密加密二、国密实现本系统实现了国密SM2和SM4加解密,可以在SimpleAdmin.Core下的Utils->Cryptogram文件夹下找到。2.1SM2Sm2加解密需要配置公钥和私钥,在......
  • java SSL加密传输
    网络传输是存在风险的,因此对服服务端和客户端进行安全校验和传输信息的加密就显得非常的重要。上面一句有点拗口,简单解释如下文: 当客户使用SSL向站点服务器发送请求时......
  • 简单聊聊数据脱敏与数据加密
    数据的脱敏与加密在数据安全领域极为重要,也是大数据平台、数据中台建设中不可缺少的一环,我将以数据脱敏与数据加密的特征以及区别、方法论来进行研究学习。一、数据脱敏与......
  • 【加密与解密】第三章⑥
    IDA调试器IDA支持调试器功能,弥补了静态分析能力的不足。1.加载目标文件在Debugger-selectdebugger中可以根据当前文件类型选择调试器类型,如图所示选择win32debugger......