ssrf漏洞

SSRF漏洞概述和演示

SSRF(Server-Side Request Forgery,服务器端请求伪造)是一种常见的Web应用程序安全漏洞。它允许攻击者诱使服务器端应用程序发起任意HTTP(S)请求到内部系统或者网络,而这些请求通常是正常情况下服务器自身为了某种功能而发起的,例如获取远程资源、API调用等。由于服务器信任自己的内部请求,因此这种漏洞可能会暴露内部网络中的敏感信息,进一步可能导致诸如读取内部服务器文件、攻击内部服务、端口扫描、DDoS攻击等严重后果。

SSRF漏洞概述:

  • 成因:SSRF漏洞主要源于Web应用对用户输入的URL没有充分过滤和校验,使得攻击者能够操控服务器向任意指定的URL发送请求。
  • 危害:攻击者可以利用SSRF漏洞绕过防火墙和其他网络防护措施,直接从内部网络发起攻击,这使得一些仅对外部访问设限的安全措施失效。
  • 利用方式:攻击者可能尝试注入恶意URL,如内网IP、本地文件协议(file:///)、特殊的网络协议(如RPC、FTP等),甚至是利用一些服务端软件存在的SSRF特性间接访问内部资源。

SSRF漏洞演示:

以下是一个简单的SSRF漏洞演示例子:

假设有一个Web应用,它提供一个功能,让用户输入一个公开可用的URL来获取网页标题。但是,它没有对用户输入的URL进行严格的检查和过滤:

def get_webpage_title(url):
    # 假设这是服务器端的伪代码,它直接使用用户提供的URL获取页面标题
    response = requests.get(url)
    return response.title

# 正常情况,用户可能输入像 http://example.com 这样的URL
# 攻击者则可能输入一个内部服务器的IP地址,例如 http://10.0.0.1/admin/private-info 或 file:///etc/passwd

攻击者通过提交内部网络地址,可能成功地让服务器返回了内部系统的敏感信息或执行了未授权的操作。

PHP SSRF相关函数和协议

在PHP中,与SSRF(Server-Side Request Forgery,服务器端请求伪造)漏洞相关的函数主要是那些可以发起网络请求或打开网络连接的函数。以下是一些可能导致SSRF漏洞的PHP函数:

  1. file_get_contents() - 可以从给定的URL读取内容,如果URL参数不受限制,攻击者就可能诱导服务器向任意地址发送请求。

$data = file_get_contents($_GET['url']);

 2.fopen()file_put_contents() 结合使用 - 类似于file_get_contents()fopen()可用于打开一个URL资源,并结合file_put_contents()将响应内容保存到文件中。

$handle = fopen($_GET['url'], 'r');
$contents = stream_get_contents($handle);
file_put_contents('output.txt', $contents);

3.cURL 函数族 - 包括 curl_init(), curl_setopt(), curl_exec() 等,它们用来初始化cURL会话、设置选项(包括URL)并执行请求。

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);

这段代码的作用是从用户通过GET请求传递的URL地址获取数据,并将获取的数据存储在 $response 变量中。在实际应用中,需要确保对用户提供的URL进行严格的验证和过滤,以防止潜在的安全风险。

4.fsockopen() - 用于打开一个网络或套接字连接,可以用来发起TCP/IP请求,包括HTTP请求。

$host = $_GET['host'];
$port = $_GET['port'];
$fp = fsockopen($host, $port, $errno, $errstr, 30);
if (!$fp) {
    // 处理错误
} else {
    // 发送请求...
}

5.SoapClient - 在特定条件下,当SOAP服务允许传入任意URL时,也可能成为SSRF的入口点。

<?php
class MyClass {
    public function callWebService($wsdlUrl, $operation, $params) {
        $client = new SoapClient($wsdlUrl);
        $result = $client->{$operation}($params); // 直接使用用户提供的$wsdlUrl创建SoapClient对象并调用方法
        return $result;
    }
}

// 假设在某个接口中直接使用了用户的输入
$myClass = new MyClass();
$wsdlUrl = $_GET['wsdl']; // 用户可以控制的WSDL URL
$operation = $_GET['operation'];
$params = json_decode($_GET['params'], true);

$response = $myClass->callWebService($wsdlUrl, $operation, $params);
echo $response;

在这个示例中,如果应用程序直接使用了来自用户输入的 $wsdlUrl 参数来创建 SoapClient 对象,攻击者就可以通过构造恶意的 WSDL 地址,导致服务器向任意地址发送 SOAP 请求。例如,如果攻击者提供了内部网络的 WSDL 地址或一个可触发其他内部操作的自定义WSDL,那么这就可能引发SSRF漏洞。

因为内容太多,此处的相关推文:

CTF SSRF 漏洞从0到1 - FreeBuf网络安全行业门户


协议

针对SSRF漏洞,攻击者可能利用的协议不仅限于HTTP(s),还包括但不限于以下几种:

  • file:// 协议 - 用于读取本地文件系统上的文件。
  • gopher:// 协议 - 旧式的信息检索协议,有时也可以被利用。
  • 内部网络IP地址和非标准端口 - 利用SSRF访问内部网络服务。
  • RPC(Remote Procedure Call)协议 - 如XML-RPC、JSON-RPC等,可能被用于调用内部服务接口。

ssrf常见场景

SSRF(Server-Side Request Forgery,服务器端请求伪造)漏洞的常见场景包括但不限于以下几个方面:

  1. 从指定URL加载资源

    • 网页内容抓取或镜像功能,如网页爬虫、动态加载第三方内容。
    • 图片上传后显示,服务器接收上传的图片URL,然后在前端展示时去请求这个URL。
    • 在线翻译、图片识别等服务,应用会根据用户提供的URL获取内容进行处理。
  2. API调用

    • 服务间通信时,服务器可能根据用户输入的URL调用其他内部服务的API。
    • 云服务商接口,如获取对象存储桶中的内容、管理云服务资源时,可能依赖用户提供的URI。
  3. Webhooks回调

    • 当应用支持webhook功能时,可能允许用户指定回调地址,服务器会在特定事件发生时向该地址发送请求。
  4. 共享/订阅功能

    • 社交媒体平台上的分享功能,可能允许用户分享外部链接并在服务器上预览或分析链接内容。
    • 订阅RSS/Atom feed时,服务器可能会定期去拉取用户提供的feed地址。
  5. 远程服务集成

    • 应用集成第三方服务时,可能通过URL形式调用远程API,如天气查询、地理位置服务等。
  6. 文件下载或上传

    • 文件托管服务可能允许上传或下载文件,攻击者可能会诱导服务器下载或上传内部服务器文件。
  7. 端口扫描和探测

    • 如果服务器对用户提供的IP地址和端口号不加限制,攻击者可能借此进行内网端口扫描或攻击内部服务。
  8. 内部服务利用

    • 利用内部网络服务如数据库、缓存服务(如Memcached、Redis)进行攻击,如提取敏感数据或发动DoS攻击。
  9. 无回显型SSRF

    • 即使服务器没有将请求结果直接显示给攻击者,攻击者仍可能通过观察服务的行为变化或通过其他间接反馈判断攻击效果。

ssrf ctf题目

[HNCTF 2022 WEEK2]ez_ssrf

爆破一下目录

访问flag.php

我们再来看一下index.php

上述代码的作用是,通过fsockopen函数发起一个TCP连接

$data=base64_decode($_GET['data']);:首先从GET参数中获取名为'data'的值,并使用base64_decode()函数对其进行解码,将其转换为原始二进制数据。

$host=$_GET['host'];:从GET参数中获取名为'host'的值,用于指定要连接的目标主机名或IP地址。

$port=intval($_GET['port']);:从GET参数中获取名为'port'的值,并使用intval()函数将其转换为整数,作为要连接的目标端口号。

fsockopen($host, intval($port), $error, $errstr, 30);: 创建一个到指定主机和端口的TCP连接。如果连接失败,$error变量将存储错误编号,$errstr变量将存储错误消息。最后的数字30是超时时间(单位秒)。

if(!$fp) { die(); }: 如果fsockopen()函数返回false(即连接失败),则终止脚本执行。

else { ... }: 如果连接成功,则执行else块中的代码。

fwrite($fp, $data);: 向socket连接写入解码后的数据(即$data)。

while(!feof($data)) { ... }: 创建一个循环,直到读取到数据流的末尾为止。这里需要注意的是,feof()函数在这儿可能并不是最佳选择,因为它用于检测文件是否到达EOF,而不是socket连接。在实际应用中,可能需要使用feof($fp)来判断socket连接是否结束。

echo fgets($fp, 128);: 从socket连接中读取最多128个字节的数据,并将其输出。每一圈循环都会读取并打印出一部分数据,直到socket关闭或者达到数据流的末尾。

与请求头中的Host值与flag.php的localhost形成照样

然后我们来看一下最基础的发起TCP连接的http

形式如上,此处有一个细节

一个http请求头的字符结束后有两个换行符

此图可以看出,http请求头确实是最后有两个换行符

此时构建php代码来实现

<?php
$out = "GET /flag.php HTTP/1.1\r\n";
$out .= "Host: 127.0.0.1\r\n";
$out .= "Connection: Close\r\n\r\n";
echo base64_encode($out);
?>

最终的payload:index.php/?host=127.0.0.1&port=80&data=R0VUIC9mbGFnLnBocCBIVFRQLzEuMQ0KSG9zdDogMTI3LjAuMC4xDQpDb25uZWN0aW9uOiBDbG9zZQ0KDQo=

疑问:

1.此处为什么端口不为443,而是80?

我猜此处可能是因为该题的URL是http,而非https的原因

2.上述的php代码中为什么不直接使用windows中的enter键,而是\r\n的方式

不知:

从上述的测试,证明了,win操作系统的enter键等同于\n

但是网上很多的博客,显示win中的enter键其实等同于\r\n

[NISACTF 2022]easyssrf

试过了127.0.0.1发现并没回显,试着利用file协议直接读取flag,file:///flag

此处不能包含file字段

方法一:相对路径读取:../../../flag

方法二:php伪协议:php://filter/read=convert.base64_encode/resource=/flag

ssrf靶场

pikachu靶场

1.curl函数库

发现传参:

直接试试file://协议,读取文件

成功读取了

试着探探端口

【注意】:curl函数库不能使用php://filter伪协议,也无法使用../上一级目录的凡是读取

扩展:

函数描述
curl_close()关闭一个cURL会话。
curl_copy_handle()复制一个cURL句柄和它的所有选项。
curl_errno()返回最后一次的错误号。
curl_error()返回一个保护当前会话最近一次错误的字符串。
curl_escape()返回转义字符串,对给定的字符串进行URL编码。
curl_exec()执行一个cURL会话。
curl_file_create()创建一个 CURLFile 对象。
curl_getinfo()获取一个cURL连接资源句柄的信息。
curl_init()初始化一个cURL会话。
curl_multi_add_handle()向curl批处理会话中添加单独的curl句柄。
curl_multi_close()关闭一组cURL句柄。
curl_multi_exec()运行当前 cURL 句柄的子连接。
curl_multi_getcontent()如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流。
curl_multi_info_read()获取当前解析的cURL的相关传输信息。
curl_multi_init()返回一个新cURL批处理句柄。
curl_multi_remove_handle()移除curl批处理句柄资源中的某个句柄资源。
curl_multi_select()等待所有cURL批处理中的活动连接。
curl_multi_setopt()设置一个批处理cURL传输选项。
curl_multi_strerror()返回描述错误码的字符串文本。
curl_pause()暂停及恢复连接。
curl_reset()重置libcurl的会话句柄的所有选项。
curl_setopt_array()为cURL传输会话批量设置选项。
curl_setopt()设置一个cURL传输选项。
curl_share_close()关闭cURL共享句柄。
curl_share_init()初始化cURL共享句柄。
curl_share_setopt()设置一个共享句柄的cURL传输选项。
curl_strerror()返回错误代码的字符串描述。
curl_unescape()解码URL编码后的字符串。
curl_version()获取cURL版本信息。

2.file_get_contents函数

看见参数file,直接file://协议读取文件成功

【注意】:还可以使用php://filter伪协议读取文件

探探端口

内网其他主机的请求

如何检测、挖掘SSRF漏洞

检测和挖掘SSRF(Server-Side Request Forgery,服务器端请求伪造)漏洞的过程主要包括以下几个步骤:

1. 了解应用架构与功能

  • 首先,熟悉目标应用的功能,找出所有可能发起网络请求的地方,如API接口、图像加载、数据抓取、重定向处理、文件上传、第三方服务集成等。

2. 检查源代码或二进制审计

  • 详细阅读源代码,寻找所有接受外部输入并用于构造HTTP请求的部分,查看是否对输入进行了恰当的过滤和验证。
  • 注意检查使用了哪些网络请求库(如cURL、fsockopen、file_get_contents等)以及如何处理用户提供的URL。

3. 动态测试

  • 利用黑盒测试方法,尝试构造带有不同参数的请求,如:
    • 测试内部IP地址(如 127.0.0.10.0.0.0)、内网IP段、localhost等。
    • 使用特殊协议(如 file://gopher://dict://)尝试读取本地文件或执行其他操作。
    • 测试云服务商的内网地址、AWS S3、阿里云OSS等云存储服务的私有URL。
    • 尝试探测内部网络服务和端口。

4. 工具辅助

  • 使用自动化工具进行模糊测试和SSRF漏洞扫描,例如:
    • SSRFmap
    • Burp Suite Pro的插件如Intruder或Scanner模块
    • ZAP(Zed Attack Proxy)的SSRF检测功能
    • 自定义开发的脚本或工具

5. 深度探测

  • 如果发现SSRF漏洞迹象,进一步尝试深入探测,如:
    • 通过SSRF漏洞访问内部网络服务、API、数据库等。
    • 尝试DNS Rebinding攻击来绕过防火墙防护。
    • 利用内网服务的特性执行远程命令(如果存在相关漏洞)。

6. 验证与报告

  • 验证漏洞是否确实存在,并评估其影响范围与严重程度。
  • 准备详细的漏洞报告,包括漏洞触发条件、危害描述、PoC(Proof-of-Concept)演示等内容。

如何防御SSRF漏洞

防御SSRF(Server-Side Request Forgery,服务器端请求伪造)漏洞的主要策略包括以下几个方面:

1. 输入验证与过滤

  • URL白名单:只允许请求预定义的、安全的、对外公开的域名或IP地址,拒绝所有不在白名单内的URL请求。
  • URL黑名单:阻止访问已知的内部IP地址、localhost、loopback地址、内网IP段以及特殊协议(如file、gopher、dict等)。
  • URL格式验证:确保URL格式正确,不包含额外的特殊字符或非法结构。

2. 网络请求限制

  • 限制端口:只允许访问常用服务端口,如HTTP(S)的80和443端口,禁止访问非标准端口。
  • 协议过滤:只允许HTTP和HTTPS协议,禁止其他可能导致安全问题的协议。

3. 代理服务器

  • 使用代理:所有对外部资源的请求通过一个安全的代理服务器进行,该服务器可以对请求的目标地址进行限制和过滤。

4. 服务端配置

  • 关闭不必要的服务:在服务器上禁用或限制对内部服务的访问,如关闭不必要的端口监听,限制对内部网络的访问。
  • 防火墙策略:在防火墙层面设置规则,阻止服务器对内部网络或特定外部资源的访问。

5. 代码层面安全实践

  • 最小权限原则:确保发起网络请求的组件具有最小权限,不提供对敏感资源的访问能力。
  • 异常处理:对网络请求失败或响应异常的情况做好捕获和处理,防止暴露内部错误信息。

6. 加密和认证

  • 对敏感资源的访问实施加密和身份验证,即使攻击者找到了SSRF漏洞,也无法获取未授权的内容。

7. 审计与监控

  • 持续监控和审计:定期进行安全审计,发现潜在的SSRF漏洞,并对异常网络活动进行实时监控和报警。

综合运用上述措施,可以帮助系统有效地防御SSRF漏洞,降低潜在的安全风险。同时,加强开发人员的安全意识培训,确保在开发过程中遵循安全编码规范,也是至关重要的。

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

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

相关文章

MYSQL | 数据库到底是怎么来的?

“以史为鉴&#xff0c;可以让我们更深刻地理解现在&#xff0c;预见未来。” 要想知道一件东西是怎么发生的, 我们不妨把时间拨回关系型数据库被提出前后来探索。在信息技术飞速发展的今天&#xff0c;回望数据库管理系统的演进之路&#xff0c;我们可以深刻理解到技术进步如…

产品推荐 - 基于6U VPX的双TMS320C6678+Xilinx FPGA K7 XC7K420T的图像信号处理板

综合图像处理硬件平台包括图像信号处理板2块&#xff0c;视频处理板1块&#xff0c;主控板1块&#xff0c;电源板1块&#xff0c;VPX背板1块。 一、板卡概述 图像信号处理板包括2片TI 多核DSP处理器-TMS320C6678&#xff0c;1片Xilinx FPGA XC7K420T-1FFG1156&#xff0c;1片…

20240309-1-校招前端面试常见问题-前端框架及常用工具

校招前端面试常见问题【5】——前端框架及常用工具 React Q&#xff1a;请简述一下虚拟 DOM 的概念&#xff1f; 基于 React 进行开发时所有的 DOM 构造都是通过虚拟 DOM 进行&#xff0c;每当数据变化时&#xff0c;React 都会重新构建整个 DOM 树&#xff0c;然后 React 将…

selenium之PO设计模式

初识PO模式 PO&#xff08;PageObject&#xff09;是一种设计模式。简单来说就是把一些繁琐的定位方法、元素操作方式等封装到类中&#xff0c;通过类与类之间的调用完成特定操作。 PO被认为是自动化测试项目开发实践的最佳设计模式之一。 在学习PO模式前&#xff0c;可以先…

力扣日记3.8-【回溯算法篇】37. 解数独

力扣日记&#xff1a;【回溯算法篇】37. 解数独 日期&#xff1a;2023.3.8 参考&#xff1a;代码随想录、力扣 37. 解数独 题目描述 难度&#xff1a;困难 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只…

存货计价方式 比较-移动平均和批次计价

SAP常用的存货计价方式有 标准价格移动平均价格批次计价 标准价格常用于制造企业&#xff0c;今天的方案比较主要集中在销售型企业常用的移动平均价和批次计价 批次计价&#xff1a; 移动平均&#xff1a; 两种计价方式的Pros&Cons 比较 批次计价 移动平均优点 1…

基于单片机的水平角度仪系统设计

目 录 摘 要 I Abstract II 引 言 1 1控制系统设计 3 1.1系统方案设计 3 1.2系统工作原理 4 2硬件设计 6 2.1单片机 6 2.1.1单片机最小系统 6 2.1.2 STC89C52单片机的性能 7 2.2角度采集电路 8 2.2.1 ADXL345传感器的工作原理 9 2.2.2 ADXL345传感器倾角测量的原理 9 2.2.3 AD…

YOLOv8优化策略:特征融合篇 | GELAN(广义高效层聚合网络)结构来自YOLOv9

🚀🚀🚀本文改进:使用GELAN改进架构引入到YOLOv8 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.YOLOv9介绍 论文: 2402.13616.pdf (arxiv.org) 摘要: 如今的深度学习方法重点关注如何设计最合适…

用 ChatGPT 搭配 STAR 原则,准备英文面试超轻松

用 ChatGPT 搭配 STAR 原则&#xff0c;准备英文面试超轻松 ChatGPT 除了可以帮忙改简历&#xff0c;在你的求职历程中&#xff0c;ChatGPT 也可以帮忙练英文面试。在我们实测之后&#xff0c;发现 ChatGPT 在练习英文面试上&#xff0c;不仅能针对你的回答给予回馈&#xff0…

Docker下Jenkins打包java项目并部署

docker 构建Jenkins sudo docker run --namezen_haslett --userjenkins --privilegedtrue --volume/home/cyf/server/jenkins/jenkins_home:/var/jenkins_home -v /usr/lib/jvm/java-17-openjdk-amd64:/usr/lib/jvm/java-17-openjdk-amd64 -v /usr/lib/maven/apache-mav…

FFmpeg--AAC音频解码流程

文章目录 AAC 组成函数分析读aac帧写aac帧aac的head参数设置 运行结果 AAC 组成 AAC音频格式&#xff1a;是⼀种由MPEG-4标准定义的有损⾳频压缩格式 ADTS:是AAC音频的传输流格式 AAC音频文件的每一帧由ADTS Header和AAC Audio Data组成 每⼀帧的ADTS的头⽂件都包含了⾳频的采…

ArmSoM Rockchip系列产品 通用教程 之 GPIO 使用

1. GPIO简介​ GPIO&#xff0c;全称 General-Purpose Input/Output&#xff08;通用输入输出&#xff09;&#xff0c;是一种在计算机和嵌入式系统中常见的数字输入输出接口。它允许软件控制硬件的数字输入和输出&#xff0c;例如开关、传感器、LED灯等。GPIO通常由一个芯片或…

C++矢量运算与java矢量运算

矢量运算 概述&#xff1a; 矢量运算是一种基于向量的数学运算&#xff0c;它遵循特定的法则。以下是矢量运算的一些基本原理&#xff1a; 矢量加法&#xff1a;可以使用平行四边形法则或三角形法则来执行。当两个矢量相加时&#xff0c;可以将它们的起点放在同一个点上&…

【硬件设计】(更新中)以 UCC27710 为例设计栅极驱动器元件选型(资料摘抄)

还没更新完。。。。。。。 【仅作自学记录&#xff0c;不出于任何商业目的。如有侵权&#xff0c;请联系删除&#xff0c;谢谢&#xff01;】 本文摘抄翻译自&#xff1a; Bootstrap Network Analysis: Focusing on the Integrated Bootstrap Functionality (infineon.com)Boo…

[nlp入门论文精读] | Transformer

写在前面 最近工作从CV转向了NLP&#xff0c;于是空余时间便跟着哔哩哔哩李沐老师的视频学习。其实研一NLP课程讲论文的时候&#xff0c;我们小组就选择了经典的Attention和Bert&#xff0c;但还有很多细节并不完全理解&#xff0c;实际使用时也很困惑。 因此这个系列就来记…

【Android 内存优化】KOOM 快手开源框架线上内存监控方案-源码剖析

文章目录 前言OOMMonitorInitTask.INSTANCE.initOOMMonitor.INSTANCE.startLoopsuper.startLoopcall() LoopState.Terminate dumpAndAnalysisdumpstartAnalysisService回到startLoop方法总结 前言 这篇文章主要剖析KOOM的Java层源码设计逻辑。 使用篇请看上一篇: 【Android …

Kubesphere前端项目分析

1 KubeSphere console功能导图 模块&#xff1a; 命令行工具 (kubectl) 日志&#xff08;Logging&#xff09; 平台设置&#xff08;Platform Settings&#xff09; 服务组件&#xff08;Service Components&#xff09; 监控和警报&#xff08;Monitoring & Alerting&…

手写分布式配置中心(六)整合springboot(自动刷新)

对于springboot配置自动刷新&#xff0c;原理也很简单&#xff0c;就是在启动过程中用一个BeanPostProcessor去收集需要自动刷新的字段&#xff0c;然后在springboot启动后开启轮询任务即可。 不过需要对之前的代码再次做修改&#xff0c;因为springboot的配置注入value("…

pytest教程-15-多个fixture以及重命名

领取资料&#xff0c;咨询答疑&#xff0c;请➕wei: June__Go 上一小节我们学习了fixture的yield关键字&#xff0c;本小节我们讲解一下使用多个fixture的方法。 使用多个fixture 如果用例需要用到多个fixture的返回数据&#xff0c;fixture也可以return一个元组、list或字…

[嵌入式系统-37]:龙芯1B 开发学习套件 -7-MIPS指令集

目录 一、MIPS指令分类 二、常用指令详解 三、常用MIPS指令集及格式&#xff1a; 四、CPU内部的32个寄存器&#xff1a; 一、MIPS指令分类 MIPS&#xff08;Microprocessor without Interlocked Pipeline Stages&#xff09;指令集是一种广泛用于教学和嵌入式系统的指令集…