REVERSE-COMPETITION-VNCTF-2024

REVERSE-COMPETITION-VNCTF-2024

    • 前言
    • TBXO
    • baby_c2
    • yun
    • obfuse
    • ko

前言

ko的随机数算法没看出来,可惜~
这里给自己打个广告:东南网安研二在读,求实习,求内推,求老板们多看看我QAQ
blog

TBXO

通过字符串定位到main函数汇编视图
存在混淆,最后retn的返回地址不太会算
调试发现就是几个块在栈上埋下返回地址,通过retn跳转,最后的retn还是会回到main函数
TBXO-main
继续向下调试发现是一个魔改的TEA,多异或了0x33
TBXO-tea
密文和密钥已知,直接解密即可

#include <stdio.h>
#include <stdint.h>//加密函数
void encrypt(unsigned int num_rounds, uint32_t *v, uint32_t *k)
{uint32_t v0 = v[0], v1 = v[1], sum = 0, i;uint32_t delta = 0x61C88647;uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];for (i = 0; i < num_rounds; i++){sum -= delta;v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) ^ 0x33;v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) ^ 0x33;}v[0] = v0;v[1] = v1;printf("sum==0x%x\n", sum);
}//解密函数
void decrypt(unsigned int num_rounds, uint32_t *v, uint32_t *k)
{uint32_t v0 = v[0], v1 = v[1], i;uint32_t delta = 0x61C88647, sum = 0xc6ef3720;uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];for (i = 0; i < num_rounds; i++){v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) ^ 0x33;v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) ^ 0x33;sum += delta;}v[0] = v0;v[1] = v1;printf("sum==0x%x\n", sum);
}//打印数据 hex_or_chr: 1-hex 0-chr
void dump_data(uint32_t *v, int n, bool hex_or_chr)
{if (hex_or_chr){for (int i = 0; i < n; i++){printf("0x%x,", v[i]);}}else{for (int i = 0; i < n; i++){for (int j = 0; j < sizeof(uint32_t) / sizeof(uint8_t); j++){printf("%c", (v[i] >> (j * 8)) & 0xFF);}}}printf("\n");return;
}int main()
{// v为要加解密的数据uint32_t v[] = {0x31363010, 0xad938623, 0x8492d4c5, 0x7567e366, 0xc786696b, 0xa0092e31, 0xdb695733, 0xdd13a893, 0x88d8a53e, 0x7e845437};// k为加解密密钥,4个32位无符号整数,密钥长度为128位uint32_t k[4] = {0x67626463, 0x696D616E, 0x79645F65, 0x6B696C69};// num_rounds,建议取值为32unsigned int r = 32;int n = sizeof(v) / sizeof(uint32_t);/*printf("加密前明文数据:");dump_data(v, n, 1);for (int i = 0; i < n / 2; i++){encrypt(r, &v[i * 2], k);}*/printf("加密后密文数据:");dump_data(v, n, 1);for (int i = 0; i < n / 2; i++){decrypt(r, &v[i * 2], k);}printf("解密后明文数据:");dump_data(v, n, 1);printf("解密后明文字符:");dump_data(v, n, 0);return 0;
}// VNCTF{Box_obfuscation_and_you_ar_socool}

baby_c2

附件为一段powershell和一个流量包
powershell先解码base64再通过iex运行
将iex替换为Write-Output并运行powershell
baby_c2-base64
发现又套了一层powershell,同样是先解码base64再通过iex运行
通过替换iex为Write-Output打印出解码结果
baby_c2-process
先解码base64,然后启动相应的进程
通过cyberchef解码并保存为exe文件
baby_c2-exe
ida打开该exe文件,调整跳转条件并去除花指令
baby_c2-decode
发现两段SMC,都是异或v3,v3是一个时间相关的值,不知道具体是什么
baby_c2-smc
继续分析发现这两个数组都被解释为了函数指针
一般情况下,函数开头的"push ebp"指令(机器码为0x55)是比较固定的,于是可知v3=0x55^0x8C=0xD9
手动还原代码,分析可知是标准的RC4加密算法
baby_c2-rc4
baby_c2-rc4
查找交叉引用来到,分析可知RC4密钥为文件名
baby_c2-main
在流量包中找到对应的TCP流
baby_c2-tcp
最后直接解密即可
baby_c2-flag

yun

安卓逆向,jadx-gui打开
java层就是简单的长度和格式校验
yun-java
ida打开libyun.so,搜索"java",只有一个静态注册的方法,但很明显方法名不对
yun-so
分析JNI_OnLoad,发现通过RegisterNatives动态注册了flag0_o方法
yun-so
yun-so
yun-so
method_name和method_signature是在init段动态修改的
yun-so
同样通过arr_xor动态修改的变量还有Vnvn,而校验函数会用到这个变量
yun-so
分析method_funcptr,inp传入enc,inp_enc与密文比较
yun-so
分析enc,记录inp和Vnvn的索引,然后对两组索引依次进行2*2的矩阵乘法
yun-so
最后又是一个查表和一个base64编码
yun-so
需要注意的是,密文在JNI_OnLoad也通过arr_xor被动态修改
yun-so
于是最终的解密脚本即为

import base64
import claripytab = "abcdefghijklmnopqrstuvwxyz1234567890-"cipher = [0x62, 0x6a, 0x4a, 0x79, 0x64, 0x58, 0x59, 0x34, 0x4c, 0x58, 0x42, 0x36, 0x63, 0x6e, 0x49, 0x79, 0x5a, 0x6a, 0x4a, 0x78, 0x61, 0x6d, 0x30,0x79, 0x64, 0x47, 0x4e, 0x76, 0x4d, 0x33, 0x52, 0x71, 0x4f, 0x47, 0x51, 0x30, 0x65, 0x54, 0x42, 0x70, 0x64, 0x48, 0x70, 0x6f, 0x4d, 0x58, 0x55, 0x74]
cipher = base64.b64decode(bytes(cipher)).decode()
cipher_idx = []
for c in cipher:cipher_idx.append(tab.find(c))key = "s0ry"
key_idx = []
for c in key:key_idx.append(tab.find(c))inp_idx = []
for idx in range(0, len(cipher_idx), 2):inp = [claripy.BVS(f"inp_{i}", 16) for i in range(2)]s = claripy.Solver()s.add((inp[0]*key_idx[0]+inp[1]*key_idx[2]) % len(tab) == cipher_idx[idx])s.add((inp[0]*key_idx[1]+inp[1]*key_idx[3]) %len(tab) == cipher_idx[idx+1])s.add(inp[0] >= 0)s.add(inp[0] < len(tab))s.add(inp[1] >= 0)s.add(inp[1] < len(tab))if s.check_satisfiability() == "SAT":for i in s.batch_eval(inp, 1):for ii in i:inp_idx.append(ii)flag = ""
for idx in inp_idx:flag += tab[idx]
print(flag)# 75531c14-8825-44ed-a9ec-74d47d5cb76b

obfuse

简单去一下jb/jnb这种模式的花指令
obfuse-main

from idaapi import *
from idautils import *
start = 0x0000000000401A10
finish = 0x0000000000407F41
while start <= finish:ins1 = get_bytes(start, 6)ins2 = get_bytes(start+6, 6)if ins1.hex().startswith("0f") and ins2.hex().startswith("0f"):addr1 = start+6+ins1[2]addr2 = start+6+6+ins2[2]if addr1 == addr2:patch_bytes(start, b"\x90"*(addr1-start))start += 12else:start += 1

边调试边猜,大致确定如下的校验逻辑
输入经过AES加密后与已知的密文比较,密钥已知,需要找到AES的魔改点
obfuse-main
构造输入为"abcdefghijklmnopqrstuvwxyz123456"
经过不断调试,发现在aes_encrypt函数中存在两步运算xor和aes
obfuse-aes
在进入aes前,输入的前16字节与一段固定的数据异或,也就是CBC模式的初始向量iv
通过异或前后的数据得到这段iv为

0x16, 0x16, 0x1a, 0x1a, 0x1e, 0x1e, 0x1a, 0x1a, 0x16, 0x16, 0x2a, 0x2a, 0x2e, 0x2e, 0x2a, 0x2a

随后进入aes,aes大概魔改了三个地方
obfuse-aes
第一个魔改点在aes_add_round_key,通过调试aes源码,比较数据可知魔改相当于如下效果
obfuse-aes
即在每轮标准的aes_add_round_key后又异或一段固定的数据,该段固定数据可计算得到为

uint8_t xor_arr[] = {0x0, 0x1, 0x2, 0x3, 0x1, 0x0, 0x3, 0x2, 0x2, 0x3, 0x0, 0x1, 0x3, 0x2, 0x1, 0x0};

第二个魔改点在aes_sub_bytes,最后多异或了0xC8
obfuse-aes
第三个魔改点在aes_mix_columns,最后多异或了0x64
obfuse-aes
对应的解密过程即应调整为
obfuse-aes
obfuse-aes
obfuse-aes
解密密文前16字节得到flag前16个字符为"VNCTF{th1s_t@ste"
obfuse-aes
然后调整输入为"VNCTF{th1s_t@steqrstuvwxyz123456"
计算得到输入的后16字节在进入aes前需要异或的初始向量iv为

0xa3,0x81,0x39,0x1a,0xac,0xce,0x11,0xfe,0x12,0xc8,0x7b,0xa9,0x5e,0xc8,0xd,0x5b

于是可解出flag后16个字符为"s_go0d_r1ght~~?}"
obfuse-aes
最后验证成功
obfuse-aes

ko

一堆数据需要异或
ko-xor
这里笔者是先找好数据范围,把数据全都dump出来,把异或运算复制出来,计算完再把结果写回去
ko-strings
通过字符串提示找到标准的rc4_init
ko-rc4
魔改的rc4_encode
ko-rc4
魔改点在于异或运算时对sbox的索引增加了一个随机数
ko-rc4
这个随机数由标准的MT19937算法生成,随机数种子为0xFA11010D
ko-rc4
同样地,通过字符串提示找到密文
ko-rc4
rc4密钥应该在运行过程中被直接打印出来
ko-rc4
于是可先计算得到42个随机数

def _int32(x):return int(0xFFFFFFFF & x)class MT19937:def __init__(self, seed):self.mt = [0] * 624self.mt[0] = seedself.mti = 0for i in range(1, 624):self.mt[i] = _int32(1812433253 * (self.mt[i - 1] ^ self.mt[i - 1] >> 30) + i)def extract_number(self):if self.mti == 0:self.twist()y = self.mt[self.mti]y = y ^ y >> 11y = y ^ y << 7 & 2636928640y = y ^ y << 15 & 4022730752y = y ^ y >> 18self.mti = (self.mti + 1) % 624return _int32(y)def twist(self):for i in range(0, 624):y = _int32((self.mt[i] & 0x80000000) +(self.mt[(i + 1) % 624] & 0x7fffffff))self.mt[i] = (y >> 1) ^ self.mt[(i + 397) % 624]if y % 2 != 0:self.mt[i] = self.mt[i] ^ 0x9908b0dfmt = MT19937(0xFA11010D)
rand_num = []
for i in range(42):rand_num.append(mt.extract_number())
print(rand_num)
# [4194389780, 1470670990, 3026560136, 833079161, 4131466323, 759157580, 4009079223, 2614551579, 513472238, 2993535632, 3748155928, 1410131130, 299129314, 1493771472, 794099837, 1833596110, 2003735283, 2301239837, 2210620102, 1212227044, 286209931, 3671727524, 2298672460, 4293907163, 1382287885, 2958570228, 2560383921, 2598710070, 1618082056, 461162807, 2533884627, 631807209, 1331614827, 3197521366, 586344870, 3568429591, 2977811948, 661755625, 1170402972, 1364250142, 3774156842, 380335765]

然后再进行rc4解密,即可得到flag

#include <stdio.h>/*
RC4初始化函数
*/
void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len_k)
{unsigned int i = 0, j = 0;char k[256] = {0};unsigned char tmp = 0;for (i = 0; i < 256; i++){s[i] = i;k[i] = key[i % Len_k];}for (i = 0; i < 256; i++){j = (j + s[i] + k[i]) % 256;tmp = s[i];s[i] = s[j];s[j] = tmp;}
}long long int rand_num[42] = {4194389780, 1470670990, 3026560136, 833079161, 4131466323, 759157580, 4009079223, 2614551579, 513472238, 2993535632, 3748155928, 1410131130, 299129314, 1493771472, 794099837, 1833596110, 2003735283, 2301239837, 2210620102, 1212227044, 286209931, 3671727524, 2298672460, 4293907163, 1382287885, 2958570228, 2560383921, 2598710070, 1618082056, 461162807, 2533884627, 631807209, 1331614827, 3197521366, 586344870, 3568429591, 2977811948, 661755625, 1170402972, 1364250142, 3774156842, 380335765};/*
RC4加解密函数
unsigned char* Data     加解密的数据
unsigned long Len_D     加解密数据的长度
unsigned char* key      密钥
unsigned long Len_k     密钥长度
*/
void rc4_crypt(unsigned char *Data, unsigned long Len_D, unsigned char *key, unsigned long Len_k) //加解密
{unsigned char s[256];rc4_init(s, key, Len_k);int i = 0, j = 0, t = 0;unsigned long k = 0;unsigned char tmp;for (k = 0; k < Len_D; k++){i = (i + 1) % 256;j = (j + s[i]) % 256;tmp = s[i];s[i] = s[j];s[j] = tmp;t = (s[i] + s[j] + rand_num[k]) % 256;Data[k] = Data[k] ^ s[t];}
}int main()
{//字符串密钥/*unsigned char key[] = "";unsigned long key_len = sizeof(key) - 1;*///数组密钥unsigned char key[] = {98, 51, 66, 108, 98, 110, 78, 122, 97, 67, 49, 114, 90, 88, 107, 116, 100, 106, 69, 65, 65, 65, 65, 65, 66, 71, 53, 118, 98, 109, 85, 65, 65, 65, 65, 69, 98, 109, 57, 117, 90, 81, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 65, 65, 65, 66, 108, 119, 65, 65, 65, 65, 100, 122, 99, 50, 103, 116, 99, 110, 78, 104, 65, 65, 65, 65, 65, 119, 69, 65, 65, 81, 65, 65, 65, 89, 69, 65, 119, 108, 49, 120, 68, 99, 65, 104, 98, 100, 109, 52, 57, 122, 57, 77, 69, 74, 117, 86, 107, 121, 119, 50, 106, 70, 106, 65, 65, 73, 86, 89, 116, 89, 73, 90, 50, 68, 51, 98, 75, 48, 89, 112, 75, 76, 117, 79, 89, 55, 117, 113, 116, 70, 79, 115, 106, 67, 79, 49, 73, 52, 55, 90, 76, 99, 50, 110, 71, 87, 102, 114, 118, 97, 120, 116, 67, 111, 50, 56, 78, 53, 54, 73, 101, 53, 66, 108, 118, 68, 104, 106, 107, 113, 108, 113, 78, 90, 106, 76, 119, 104, 65, 86, 67, 78, 76, 87, 110, 116, 67, 115, 88, 74, 110, 56, 120, 116, 51, 118, 104, 67, 69, 102, 57, 99, 99, 69, 105, 78, 75, 103, 74, 81, 122, 73, 118, 88, 115, 102, 57, 54, 85, 104, 50, 107, 55, 54, 99, 88, 76, 105, 54, 121, 113, 122, 118, 106, 122, 109, 78, 110, 107, 117, 113, 105, 80, 118};unsigned long key_len = sizeof(key);//加解密数据unsigned char data[] = {31, 209, 241, 145, 62, 90, 173, 108, 4, 37, 225, 196, 154, 90, 160, 119, 29, 107, 231, 23, 171, 16, 231, 172, 41, 73, 19, 251, 196, 135, 213, 190, 96, 215, 215, 150, 146, 236, 225, 97, 138, 176};//加解密rc4_crypt(data, sizeof(data), key, key_len);for (int i = 0; i < sizeof(data); i++){printf("%c", data[i]);}printf("\n");return 0;
}
// VNCTF{Welcome_To_Kernel_World@RETraveler}

感谢大家读到这里
最后再表达一下笔者的求职意愿,老板们可通过站内私信或添加微信P1umH0联系笔者
在此先谢过各位老板

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

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

相关文章

【Algorithms 4】算法(第4版)学习笔记 13 - 番外篇:二叉查找树的几何应用(下篇)

文章目录 前言参考目录学习笔记4&#xff1a;区间搜索树&#xff08;interval search trees&#xff09;4.1&#xff1a;一维区间搜索4.2&#xff1a;区间搜索树定义4.3&#xff1a;区间搜索树 demo 演示4.3.1&#xff1a;插入4.3.2&#xff1a;搜索命中4.3.3&#xff1a;搜索未…

[RCTF2015]EasySQL1 题目分析与详解

一、题目介绍&#xff1a; 1、题目来源&#xff1a; BUUCTF网址 2、题目介绍&#xff1a; 拿到flag。 二、解题思路&#xff1a; 我们发现题目首页有登录和注册账号两个选项&#xff0c;我们首先尝试注册账号&#xff0c;尝试注册username为admin的账号&#xff0c;输入密码…

如何更改虚拟机服务端口

如何更改虚拟机服务端口 背景internet information services开启/安装 IIS打开IIS管理器 修改端口 背景 今天我们来讲一下如何更改我们服务所占用的端口号&#xff0c;假设我们在虚拟机或者本地计算机上部署了一个服务&#xff0c;然后这个服务呢&#xff0c;我们默认安装了&a…

一番赏小程序开发,提升用户体量,增加收益

随着我国年轻人逐渐成为消费主力军&#xff0c;盲盒一番赏迅速迎来高速发展期&#xff0c;一番赏的市场规模也迅速扩大。 在互联网的支持下&#xff0c;当下国内形成了线上消费热潮&#xff0c; 一番赏开启了线上抽赏&#xff0c;衍生出了线上一番赏小程序&#xff0c;这让更多…

快速掌握MySql的常用基本操作

MySql 基本操作 一、MySql的数据类型二、MySql运算符三、MySql常用函数四、MySql完整性约束五、MySql核心操作&#xff08;库、表、CRUD、连接&#xff09;库操作表操作CRUD通过存储过程生成大量测试数据连接查询 一、MySql的数据类型 整数类型字节最小值最大值TINGINT1有符号…

白酒:生产过程的可追溯性与质量控制

在豪迈白酒的生产过程中&#xff0c;可追溯性与质量控制是确保产品安全与品质的重要手段。随着消费者对食品安全与质量的关注度不断提高&#xff0c;建立多方的可追溯体系和严格的质量控制措施成为了酒庄的必然选择。 首先&#xff0c;可追溯性是指从原材料到产品的整个生产过程…

electron安装最后一部卡住了?

控制台如下错误 不是的话基本可以划走了 这个很可能是镜像出现问题了&#xff0c;不一定是npm镜像 打开npm的配置文件添加下述 electron_mirrorhttps://cdn.npmmirror.com/binaries/electron/ electron_builder_binaries_mirrorhttps://npmmirror.com/mirrors/electron-build…

vscode 设置打开终端的默认工作目录/路径

vscode 设置打开终端的默认工作目录/路径** 文章目录 vscode 设置打开终端的默认工作目录/路径**打开vscode&#xff0c;打开设置UI 或是设置JSON文件&#xff0c;找到相关设置项方式1&#xff1a;通过打开settings.json的UI界面 设置:方式2&#xff1a;通过打开设置settings.j…

深入理解网络通信基本原理和tcp/ip协议

深入理解网络通信基本原理和tcp/ip协议 一、计算机网络体系1&#xff0c;计算机网络体系结构2&#xff0c;网络中数据传输2.1&#xff0c;浏览器中输入一个url的执行流程2.2&#xff0c;数据在网络中是的传输流程 3&#xff0c;三次握手和四次挥手3.1&#xff0c;三次握手3.1.1…

leetcode 2581. 统计可能的树根数目【换根dp】

原题链接&#xff1a;2581. 统计可能的树根数目 题目描述&#xff1a; Alice 有一棵 n 个节点的树&#xff0c;节点编号为 0 到 n - 1 。树用一个长度为 n - 1 的二维整数数组 edges 表示&#xff0c;其中 edges[i] [ai, bi] &#xff0c;表示树中节点 ai 和 bi 之间有一条边…

【appium】Hybrid应用自动化|微信小程序自动化

目录 一、Hybrid&#xff08;nativewebview&#xff09;应用自动化 1、webview 2、Hybrid应用自动化实现 2.1准备工作 Step1&#xff1a;准备android 4.4版本以上的手机/模拟器 Step2&#xff1a;在app源码中将webview调试模式打开 Step3&#xff1a;安装UC开发者工具 U…

4_相机透镜畸变

理论上讲&#xff0c;是可能定义一种透镜而不引入任何畸变的。然而现实世界没有完美的透镜。这主要是制造上的原因&#xff0c;因为制作一个“球形”透镜比制作一个数学上理想的透镜更容易。而且从机械方面也很难把透镜和成像仪保持平行。下面主要描述两种主要的透镜畸变并为他…

ICVQUANTUMCHINA报告:《2024全球量子计算产业发展展望》

2月20日&#xff0c;《2024量子计算产业发展展望》的中文版报告通过光子盒官方平台发布&#xff0c;英文版报告通过ICV官方平台发布。 英文版报告获取地址&#xff1a; https://www.icvtank.com/newsinfo/897610.html 在过去的一年里&#xff0c;光子盒与您一同见证了全球量子…

10 款最佳硬盘分区软件知识分享(2024更新)

硬盘分区软件是您当前需要的最重要的软件之一。我们知道&#xff01; 当今的硬盘分区软件具有令人难以置信的多功能性&#xff0c;并且由于激烈的竞争&#xff0c;对于大多数人来说仍然是相对低成本的投资。 目前&#xff0c;市场上有数十种硬盘分区软件可供选择 - 找到 2024…

力扣-移除元素

问题 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长…

进销存是什么意思?如何开发一款进销存管理系统?

这篇给大家详细介绍一下&#xff0c;进销存到底是什么&#xff0c;进销存管理系统有什么用&#xff1f;企业如何开发一款进销存管理系统&#xff1f; 以下内容示例工具均来自于JDY——https://www.jiandaoyun.com 一、进销存是什么&#xff1f; 1、基本概念 进销存&#xff0…

HarmonyOS开发云工程与开发云函数

创建函数 您可直接在DevEco Studio创建函数、编写函数业务代码、为函数配置调用触发器。 1.右击“cloudfunctions”目录&#xff0c;选择“New > Cloud Function”。 2.输入函数名称后&#xff0c;点击“OK”。 函数名称仅支持小写英文字母、数字、中划线&#xff08;-&a…

vue中组合式API和选项式API的区别

组合式api&#xff08;Composition API&#xff09;是vue3对我们开发者来说变化非常大的更新&#xff0c;我们先不关注具体语法&#xff0c;先对它有一个大的感知。 通过vue2, vue3两种形式实现同一个需求&#xff0c;理解vue3的compition api 带来的好处 两个独立的功能&…

leetcode 重复的子字符串

前要推理 以abababab为例&#xff0c;这里最主要的就是根据相等前后缀进行推导 s [ 0123 ] 如 t【 0123 】 f 【01 23 】 后两个分别是前后缀&#xff0c;第一个是总的字符串&#xff0c;然后可以推导 //首先还是算出…

从Spring Boot应用上下文获取Bean定义及理解其来源

前言 在Spring框架中&#xff0c;Bean是组成应用程序的核心单元。特别是在Spring Boot项目中&#xff0c;通过使用SpringApplication.run()方法启动应用后&#xff0c;我们可以获得一个ConfigurableApplicationContext实例&#xff0c;这个实例代表了整个应用程序的运行时环境…