20251909-2025-2026-2 《网络攻防实践》实践八

1.实践内容

加壳与反汇编

反汇编(Disassembly)
是将机器码(二进制指令)转换为人类可读的汇编代码的过程,也是把目标代码转化为汇编代码、将低级代码转化为高级代码的过程。它是逆向工程、软件调试和安全分析中的核心技术。其核心步骤包括:提取机器码、指令解码、地址与符号重建、生成汇编代码。

反汇编常用工具

工具名称 核心特点 适用场景
IDA Pro 商业级逆向工具,反汇编精度高、函数识别完善,支持交叉引用、结构体分析、调试联动,插件生态丰富 恶意代码深度分析、大型程序逆向、复杂二进制漏洞分析
x64dbg 轻量动态调试器,支持 32/64 位程序,界面简洁,断点、内存查看、指令追踪功能强大 动态调试、程序运行时反汇编、恶意行为实时分析
OllyDbg 经典 32 位调试逆向工具,体积小巧、操作简单,插件多,入门友好 入门反汇编、32 位程序调试、简单样本静态 + 动态分析

汇编:
一个程序从.c文件到可执行文件一共要经历4个步骤:

预处理 ------》编译------》汇编------》链接;
image

  • 加壳全称为可执行程序资源压缩,是一种通过特殊算法对可执行文件资源进行压缩保护的技术。压缩后的程序可直接运行,其解压过程在内存中完成,通过优先控制权转移隐藏原始程序入口点(OEP),阻止静态反编译和动态分析。加壳工具分为压缩壳和加密壳两类,压缩壳以减小软件体积为主,加密壳侧重于代码保护并可附加注册机制等功能限制。在Android平台称为加固技术,包含整体Dex加固、拆分Dex加固及虚拟机加固等方式,通过替换application/classes.dex或拆分Dex文件防止反编译,虚拟机加固会对字节码进行变化处理

几种常见的恶意代码

  • 计算机病毒
    依附正常程序或文件寄生,需要人为触发执行,具备自我复制能力,多通过文件感染扩散,主要破坏系统文件、篡改数据,消耗系统资源。
  • 木马程序
    伪装成正常软件诱导用户运行,无自主传播性,核心目的是远程控制、窃取账号密码、隐私数据、摄像头劫持,常作为内网渗透的入口工具。
  • 网络蠕虫
    利用系统漏洞、网络协议缺陷自动扫描横向传播,无需宿主文件,传播速度极快,易造成网络拥堵、服务器瘫痪,典型场景为内网批量感染。
  • 勒索软件
    主流高危恶意代码,通过加密本地、服务器、数据库关键文件,索要虚拟货币赎金,常结合漏洞爆破、钓鱼邮件投放,企业与政企为主要攻击目标。
  • 僵尸网络木马
    主机被植入后门后受控于 C2 服务器,受控主机沦为肉鸡,可批量发起 DDoS 攻击、恶意挖矿、垃圾邮件投递,是僵尸网络流量分析的重点研究对象。

恶意代码检测

恶意代码分析,一般分为静态分析和动态分析两种。
静态分析 会首先对可执行程序进行反汇编,在此基础上,分析并提取代码的特征信息。可以看出,静态分析本身并不需要实际执行代码,因此,不会对系统产生实质上的危害。但是,由于静态所分析的代码不一定是最终执行的代码,可能消耗大量时间于无用代码。于此同时,静态分析对反汇编技术的依赖也导致了其局限性。首先,恶意代码可使用各种混淆技术阻碍反汇编分析,主要有重排、加壳、垃圾代码插入等方法,有很多工作都试图将混淆代码恢复为混淆前的代码,来提高检测能力。但很多时候不能解决寄存器重分配、等价替换等其他混淆手段。

动态分析,则是在代码执行过程中进行分析,直接执行所分析的代码,但动态分析一次执行过程只能获取单一路径行为,而一些恶意代码存在多条执行路径,有一部分工作建立系统快照递归探索多执行路径的方法,使得动态分析方法有所进步。此外还开发了一系列动态分析工具来辅助人工分析如CWSandbox等。

2.实践过程

2.1 对提供的rada恶意代码样本,进行文件类型识别,脱壳与字符串提取,以获得rada恶意代码的编写作者。

实验环境:WinXPattacker
实验材料:由老师提供在学习通的rada
键入命令file Rada.exe查看文件类型,查看该文件类型,是一个有图形化界面(GUI)的 Win32 PE(可移植可执行)程序。其中 PE32 表示这是一个32位的运行在windows操作系统上的程序, GUI 表示这个程序是一个有图形界面的程序, intel 80386 表示处理器架构。
image
可以看到其内容为乱码,原因可能是加壳了。使用PEiD对该文件查壳。可以看到Rada.exe加了:
UPX 0.89.6 - 1.02 / 1.05 - 2.90 -> Markus & Laszlo壳。
image

使用超级巡警脱壳机等脱壳软件,对rada恶意代码样本进行脱壳处理。选择RaDa.exe文件,开始脱壳,完成后其脱壳的输出路径与Rada.exe在同一目录(桌面)。文件名为RaDa_unpacked.exe。
image
如下图我们再次使用strings命令查看其字符串,可以看到出现大量函数调用名以及其他有用字符串,但是并未查找到作者信息。

我们换用idapro进行静态分析:
image
将脱壳后的文件直接拖入即可分析,可以成功找到作者信息和发布时间
image
image

2.2 分析crackme1.exe

实验环境:WinXPattacker
实验材料:由老师提供在学习通的crackme1.exe、crackme2.exe
实验工具:IDA Pro
实验目的:寻找特定的输入,使其能够输出成功信息。
先使用file命令判断类型为32位pe文件
image
对其输入参数进行试探,分别输入1个、2个、3个参数…,直到出现重复的回复。可以看到只有在输入一个参数的时候它的回复和其他的不一致,所以猜测输入应该为一个参数。
image
将目标程序拖入后 我们在ida的string栏先来查看输出的字符串相关位置。
image
发现在Strings窗口一共发现四个字符串,分别是

I think you are missing someting
I know the secret
Pardon?What did you say?
You know how to speak to programs,Mr.Reverse—Engineer
根据前面的猜猜发现只出现过两句,这两句应该是一个最初始判断跳转,分别对应不同的逻辑。
think you are missing someting是输入的参数数量不正确
Pardon?What did you say?是从参数数量正确,但可能参数的内容或范围不正确。所以目标应该放在没有出现的两句上。我们需要阅读函数调用图和汇编代码,详细刨析程序逻辑。

  • 首先,找到代码中输出 ”I know the secret“的地方右键点击Edit function,可以发现是sub_401280中的输出
    image

再查看exe程序的调用函数图,查看哪里会调用该函数依次点击ida veiw——veiw——Gragh——Function calls。
image
此处我们要记住sub_401280函数调用的strcmp比较函数,fprintf、printf输出函数,以及sub_401510和sub_401840函数,对调用关系有一个清晰了解。

  • 再来看具体的函数汇编语句:
    我们注意到最上方语句“cmp [ebp+arg_01], 2”
    这是整个函数的入口分支点:
    cmp [ebp+arg_01], 2:将函数的第 1 个参数(记为arg_1)与立即数2做比较。
    后续的jz short loc_401202:是 “结果为零则跳转” 的条件分支指令。
    true分支:当arg_1 == 2时,跳转到右侧的代码块。
    false分支:当arg_1 != 2时,走左侧的代码块,输出 "I think you are missing something.\n"。
    I know the secret是函数sub_401280中的输出。
    从函数调用图中可以看到sub_401280函数调用的strcmp比较函数,fprintf、printf输出函数,以及sub_401510和sub_401840函数,
    image
    从上图可以看到如果命令行输入2个参数,则跳转至loc_4012D2。
    这里会读取第 2 个参数[ebp+arg_4],并执行:
    mov eax, [ebp+arg_4]:将第 2 个参数加载到eax寄存器;
    add eax, 4:指针后移 4 字节(跳过字符串的前 4 个字节);
    push eax:把处理后的字符串地址入栈;
    push offset i know The Secret:把常量字符串 "I know the secret" 的地址入栈;
    call strcmp:调用字符串比较函数,判断用户输入的字符串是否等于 "I know the secret"。
    是的话,输出You know how to speak to programs, Mr.Reserve-Engineer;否则,输出Pardon? What did you say?;
    如果命令行输入参数个数不为2,直接进入错误分支,执行fprintf,输出提示信息 "I think you are missing something.\n",随后跳转到函数末尾,。输出"I think you are missing something"后直接返回。

我们将整个程序转化成c语言代码示意如下;

    if (arg1 != 2) {
        fprintf(stderr, "I think you are missing something.\n");
        return 0;
    }

    if (strcmp(arg2 + 4, "I know the secret") == 0) {
        printf("You know how to speak to programs, Mr. ...");
        return 0;
    } else {
        fprintf(stderr, "Pardon? What did you say?\n");
        return 2;
    }
}
  • 程序验证
    image
    最后,键入”I know the secret”,发现输出”You know how to speak to programs, Mr.Reserve-Engineer”,表示成功运行程序。
    分析无误!

2.3 分析crackme2.exe

如下图,我们依然先运行该程序进行参数测试,我们先对crackme2.exe输入的参数个数进行测试,可以看到输入额外1个参数的时候,和输入其他数量的参数时不一致。
image

我们将程序拖入ida进行分析,首先观察输出字符串:
image

与上一步类似依旧使用IDA Pro工具分析可以发现Strings窗口发现五个字符串,其中 I think you are missing something.和I have an identity problem.在进行参数猜测时出现过,猜测这俩还是一个首先分支:
I think you are missing something.是输入的参数数量不正确的情况;
I have an identity problem.是参数数量正确,但可能参数的内容或者范围不正确;

另外3句没有出现过,我们照旧来找i know the secret。
查看i know the secret的来源可以发现,还是在函数sub_401280中。
image
和之前一样,查看sub_401280的地址值,可以发现仍为401280。
image
查看程序整体的函数调用图例
image
查看sub_401280函数的流程图,如下(这里由于整张截图不清晰,截取三次,下图1底部false和true分别正好对应图2的左右两个函数逻辑,图3同样):

image
image
image

从上图可知,该程序的前三层逻辑跳转如下

层级 关键指令 判断条件 失败分支(跳转去向 + 输出信息) 成功分支(跳转去向 + 后续动作) 作用
第一层:参数个数校验 cmp [ebp+arg_0], 2 jz short loc_4012D5 函数第一个参数 arg_0(对应命令行参数个数 argc)是否等于 2 跳转 004012B0 输出:"I think you are missing something.\n" 直接返回错误码 跳转 loc_4012D5,进入下一层校验 确保用户运行程序时传入了 1 个额外参数(argc=2 代表 程序名 + 1个参数),是后续所有校验的前提
第二层:程序名校验 strcmp(argv[0] 与 "crackmeplease.exe" 比较) jz short loc_401313 第二个参数 argv[0](程序自身名称)是否等于 "crackmeplease.exe" 跳转 004012EE 输出:"I have an identity problem.\n" 返回错误码 2 跳转 loc_401313 防止用户修改程序文件名后运行,强制程序必须以原始名称执行
第三层:核心密钥校验 mov eax, [ebp+arg_4] add eax, 4 strcmp(处理后字符串与 "I know the secret" 比较) jz short loc_401351 第三个参数 argv[1](用户输入的字符串)跳过前 4 个字节后,是否等于 "I know the secret" 跳转 0040132F 输出:"Pardon? What did you say?\n" 返回错误码 3 跳转 loc_401351,进入最终合法流程,返回成功码 0 要求用户输入的密钥必须满足:前4字节任意 + "I know the secret",是破解的关键条件

等价c语言代码如下:

int sub_401280(int argc, char** argv) {
    // 校验1:参数个数必须为2
    if (argc != 2) {
        printf("I think you are missing something.\n");
        return 1;
    }

    // 校验2:程序名必须是 "crackmeplease.exe"
    if (strcmp(argv[0], "crackmeplease.exe") != 0) {
        printf("I have an identity problem.\n");
        return 2;
    }

    // 校验3:用户输入的字符串,跳过前4字节后必须是 "I know the secret"
    if (strcmp(argv[1] + 4, "I know the secret") != 0) {
        printf("Pardon? What did you say?\n");
        return 3;
    }

    // 全部校验通过,进入成功流程
    return 0;
}

验证如下:
image

判断无误!

但是对于输出的语句:“we.......CHOCOLATE”感到莫名其妙,于是我们分析上图3中如下false分支语句:

0040135E:
.......
xor     eax, 42h          ; 解密:与 0x42(字符'B')异或
movsx   eax, al           ; 将8位字符符号扩展为32位(适配putchar参数)
.......
.......
lea     eax, [ebp+var_4]  ; 取索引变量的地址
inc     dword ptr [eax]   ; 索引自增1,准备处理下一个字符
jmp     short loc_401358  ; 跳回循环头部(图中未显示的循环判断位置)

可知:解密算法是单字节异或 0x42,只要拿到 unk_403080 处的原始数据,就能还原出完整字符串。
var_4 是循环索引,每次输出后 + 1,说明这是一个遍历数组的循环。
于是我们查看反汇编代码:

image

单字节异或上0x42,结果如下:

地址偏移(相对于unk_403080) 原始数据(Hex) 异或0x42后(Hex) 对应 ASCII 字符
0x00 15h 57h W
0x01 27h 65h e
0x02 62h 20h (空格)
0x03 2Ah 68h h
0x04 23h 61h a
0x05 34h 76h v
0x06 27h 65h e
0x07 62h 20h (空格)
0x08 23h 61h a
0x09 62h 20h (空格)
0x0A 2Eh 6Ch l
0x0B 28h 6Ah j
0x0C 36h 74h t
0x0D 2Eh 6Ch l
0x0E 27h 65h e
0x0F 62h 20h (空格)
0x10 31h 73h s
0x11 27h 65h e
0x12 21h 63h c
0x13 30h 72h r
0x14 27h 65h e
0x15 36h 74h t
0x16 78h 3Ah :
0x17 62h 20h (空格)
0x18 01h 43h C
0x19 2Ah 68h h
0x1A 2Dh 6Fh o
0x1B 21h 63h c
0x1C 2Dh 6Fh o
0x1D 2Eh 6Ch l
0x1E 23h 61h a
0x1F 36h 74h t
0x20 27h 65h e

至此We have a ljtle secret: Chocolate输出语句也是知其所以然!,实验正式结束!!

2.4 动态分析一个自制恶意代码样本rada

通过学习md5sum命令用于生成和校验文件的md5值,是一种逐位校验文件内容的算法。故这里使用md5sum命令查看Rada.exe文件摘要
image

可以看出摘要为caaa6985a43225a0b3add54f44a0d4c7

接着在和exploer.exe同文件夹下运行RaDa.exe。在Strings 对话框,在菜单栏中的Edit中点击Setup,设置类型为 Unicode。
image
查看Strings信息参数:可以看到作者和日期信息
image

分析程序运行信息:
image

HTTP请求 10.10.10.10\RaDa\RaDa_commands.html ,连接到目标为10.10.10.10的主机下的一个名为RaDa_commands的网页。
之后又下载和上传文件到 C:/RaDa/tmp 。
将文件 RaDa.exe 复制到了 C:\RaDa\ 目录下。
image

往下看Starting DDoS Smurf remote attack可以发现该恶意程序似乎对主机实行了DDos拒绝服务攻击

image

再往下看可以发现该恶意程序对主机的注册表进行了读写和删除操作
image
exe 在宿主主机中执行指定的命令, get 下载, put 上传, screenshot 截屏, sleep 休眠。
image
宿主主机C:\RaDa\bin目录下确实存在RaDa.exe
image
使用wireshark进行分析,可以看到受害主机向目标主机 10.10.10.10 发送了大量的数据包:
image
image

# 问题回答总结
1.提供该二进制文件的摘要及标识信息:文件哈希值为caaa6985a43225a0b3add54f44a0d4c7;程序经过UPX加壳处理,壳程序版本范围为UPX 0.89.6 - 1.02 / 1.05 - 2.90,由Markus与Laszlo开发维护。
2.分析二进制文件运行目的:该恶意文件具备联网控控能力,主机联网后,会发起HTTP网络请求对接指定服务端,持续接收攻击者下发的操作指令,实现对受害主机的完全管控,本质为一款后门程序。
3.识别二进制文件运行特征:程序运行后会自动拷贝自身程序文件至C盘目录,同时会周期性发起网络请求,尝试和地址10.10.10.10建立TCP通信链路。
4.阐述程序用到的反分析、反逆向手段:利用UPX加壳压缩混淆程序;通过读取设备MAC地址、检索VMware Tools注册表键值,判定当前运行环境是否为虚拟机,若检测到VMware环境,调用–authors指令将隐藏作者信息;内置虚假攻击字符串,伪造DDoS攻击相关提示内容,混淆分析人员判断,掩盖真实恶意行为。
5.恶意代码类别判定与依据:该样本无自主传播、文件感染能力,排除病毒、蠕虫类别;不存在伪装诱导用户执行的行为,不符合木马特征;综合行为特征判定为后门程序,若采用集群受控架构,可归类为HTTP僵尸程序。
6.列举同类历史恶意程序:2004年爆发的Bobax恶意程序和该样本原理高度相似,均依托HTTP通信方式,从远端服务器拉取命令配置,解析指令后在本地执行恶意操作。
7.开发者溯源可行性与限制条件:该样本开发者为Raul siles、David Perze。可借助IDA反汇编工具、strings字符串提取工具直接读取相关信息,或将程序放置在物理机等非虚拟机环境运行,执行–authors参数即可查看作者资料。

2.5 分析用Snort工具收集的蜜罐主机5天的网络数据源

该数据已通过编辑去除了一些不相关的流量并将其组合到了单独的一个二进制网络日志文件中,同时IP地址和其他特定敏感信息都已经被混淆以隐藏蜜罐主机的实际身份和位置。

  • 1.RC是什么?当IRC客户端申请加入一个IRC网络时将发送哪个消息?IRC一般使用哪些TCP端口? IRC是Internet Relay Chat
    的英文缩写,中文一般称为互联网中继聊天。只要在自己的PC上运行客户端软件,然后通过因特网以IRC协议连接到一台IRC服务器上即可。它的特点是速度非常之快,聊天时几乎没有延迟的现象,并且只占用很小的带宽资源。
    所有用户可以在一个被称为"Channel"(频道)的地方就某一话题进行交谈或密谈。每个IRC的使用者都有一个Nickname(昵称),所有的沟通就在他们所在的Channel内以不同的Nickname进行交谈。
    申请加入的时候要发送口令、昵称和用户信息:USER 、PASS 、NICK 6667端口(明文传输)、6697端口(SSL加密)

  • 2.僵尸网络是什么?僵尸网络通常用于干什么? 僵尸网络 Botnet 是指采用一种或多种传播手段,将大量主机感染bot程序(僵尸程序)病毒,从而在控制者和被感染主机之间所形成的一个可一对多控制的网络
    攻击者可以向自己控制的所有bots发送指令,让它们在特定的时间同时开始连续访问特定的网络目标,从而达到DDos的目的。
    利用Botnet发送大量的垃圾邮件,而且发送者可以很好地隐藏自身的IP信息
    Botnet的控制者可以从僵尸主机中窃取用户的各种敏感信息和其他秘密,例如个人帐号、机密数据等
    攻击者利用Botnet从事各种需要耗费网络资源的活动,从而使用户的网络性能受到影响,甚至带来经济损失

  • 3.蜜罐主机(IP:172.16.134.191)与哪些IRC服务器进行了通信?
    使用Wireshark打开数据文件,并设置过滤条件ip.src == 172.16.134.191 && tcp.dstport ==6667,因为我们上面的分析知道IRC通过6667端口,我们可以找到五个IRC服务器209.126.161.29、66.33.65.58、63.241.174.144、217.199.175.10、209.196.44.172
    image
    image

  • 4.在这段观察期间,多少了解不同的主机访问了以209.196.44.172为服务器的僵尸网络。
    按装工具tcpflow
    image
    通过命令tcpflow -r botnet_pcap_file.dat “host 209.196.44.172 and port 6667“去tcpflow分流筛选指定host与端口6667
    tcpflow -r botnet_pcap_file.dat "host 209.196.44.172 and port 6667"
    产生了三个文件,分别是:209.196.044.172.06667-172.016.134.191.01152、172.016.134.191.01152-209.196.044.172.06667、report.xml

查看配置文件report.xml
image
可获知两个主机互相通信的时间、IP、mac地址、使用端口!

使用管道命令进行筛选,键入cat 209.196.044.172.06667-172.016.134.191.01152 | grep -a "^:irc5.aol.com 353" | sed "s/^:irc5.aol.com 353 rgdiuggac @ #x[^x]*x 😕/g" | tr ' ' '\n' | tr -d "\15" | grep -v "^$" | sort -u | wc -l
image

  • 5、那些IP地址被用于攻击蜜罐主机?
    键入tcpdump -n -nn -r botnet_pcap_file.dat 'dst host 172.16.134.191' | awk -F " " '{print $3}' | cut -d '.' -f 1-4 | sort | uniq | more > swl123.txt;wc -l swl123.txt,找出所有连接主机的IP地址放入swl123.txt文件中,显示有165个。
    image
    image

打开swl123.txt,其中记录了所有被蜜罐捕获的ip。

  • 6、攻击者尝试攻击了那些安全漏洞?
    先键入tcpdump -r botnet_pcap_file.dat -nn 'src host 172.16.134.191 and tcp[tcpflags]== 0x12' | cut -d ' ' -f 3 | cut -d '.' -f 5 | sort | uniq,这条命令的作用是筛选TCP包。
    image
    再键入tcpdump -r botnet_pcap_file.dat -nn 'src host 172.16.134.191 and udp ' | cut -d ' ' -f 3 | cut -d '.' -f 5 | sort | uniq,这条命令的作用是筛选UDP包。
    image
    可以看到,TCP一共有5个端口响应,分别是135(RPC:RemoteProcedureCall,远程过程调用)、139(NetBIOS会话服务)、445(SMB:Server Message Block,服务器消息块)、4899(远程控制软件(remote administrator)服务端监听的端口)、80号端口(HTTP协议)。UDP端口一共有1个端口响应,即137号端口(NetBIOS名字服务)。
    这些端口都是流行网络病毒喜爱的后门端口,是黑客们最喜欢扫描的一些端口。
    因此,我们接下来有目的性地使用wireshark分析如上面提到的ip和端口来筛选流量。

  • 7、那些攻击成功了?是如何成功的?
    用wireshark打开该文件,在过滤器中键入tcp.dstport==80,查看所有有关80端口的攻击。
    image

image
image

由上三图,我们可以看到攻击机向蜜罐发送了大量的无意义填充符号,靶机经常性发送错误报告报文,例如TCP Dup ACK(重复确认)和TCP ZeroWindow(接受缓冲区满)。这表明靶机遭受了缓冲区溢出攻击。

对于端口135,在过滤器中键入tcp.port==135,发现只是对端口的一个简单扫描,并没有攻击。
image

对于端口139,在过滤器中键入tcp.port==139,发现企图与许多主机建立连接,但是都失败了,该攻击没有成功。
image

对于端口445,这个端口连接非常多,可以看到许多 \samr,\srvsvc 字符串。61.111.101.78向蜜罐放了PSEXESVC.EXE,这是一种Dv1dr32蠕虫病毒的特征码,这种蠕虫正是通过IRC进行通信,攻击者对系统注入了蠕虫病毒并成功获取了远程调用。对445端口实施的攻击是成功的。

image
image
分析137号udp服务端口:
image
未发现异常流量。

我们再来分析80号端口数据包
tcp.dstport == 80 and ip.dst == 172.16.134.191
image
如下图,大量源ip24.197.194.106的数据包目标访问80端口,的行为就是不停的用脚本攻击 IIS 服务器的漏洞,从而获取系统权限。
image

过滤结果中还有218.25.147.83访问80端口,追踪tcp流发现:
c:\notworm,说明这是一个蠕虫攻击。上网搜索发现是红色代码(red code)病毒。

image
此外,其余的 ip 地址均为正常访问蜜罐
至此所有实验完毕!

3.学习中遇到的问题及解决

  • 问题1:系统识别不了crakme2.exe
  • 问题1解决方案:询问豆包后,复制一份,修改命名运行即可

image

4.实践总结

本次实践是对恶意程序进行检测和分析。新知识内容非常丰富,结合以前汇编知识以及ida工具的使用技能,读懂返汇编代码,并验证自己对程序理解的正确性,
我复习了程序内部结构如何去查看,分析函数调用关系。
通过使用一些小工具,如巡警工具完成脱壳处理,通过数据流分析端口是否异常、提取字符串、分析exe程序
还在kali中分析流量日志,见识各种攻击手段。对网安功底的提升颇有裨益!

参考资料

参考资料

https://blog.csdn.net/2301_77472496/article/details/141388856
https://www.cainiaoya.com/assemblylanguage/assembly-language-jiaocheng.html
https://www.idaprocn.cn/

posted @ 2026-04-27 19:50  施为乐  阅读(46)  评论(0)    收藏  举报