zoukankan      html  css  js  c++  java
  • 记一次应急响应描述

    1、什么是应急响应

    即事件发生了后怎么去做

    2、应急响应流程

    在这里插入图片描述
    简单概括:

    准备阶段:需要快照(日志、服务端口等)、应急响应工具包、

    启动(检测)阶段:讨论相关的阶段

    抑制阶段:不重要的业务断网、隔离、中断服务、断开接连等操作

    根除阶段:对控制的木马病毒进行删除

    恢复阶段:像木马病毒进行的操作对其还原原来的状态

    跟进阶段:对被入侵的机器进行监控,防止再次出现问题

    3、主机入侵排查思路

    Windows

    一、检查系统账号安全

    1、查看服务器是否有弱口令,远程管理端口是否对公网开放。

    检查方法:据实际情况咨询相关服务器管理员。

    2、查看服务器是否存在可疑账号、新增账号。

    检查方法:打开 cmd 窗口,输入lusrmgr.msc命令,查看是否有新增/可疑的账号,如有管理员群组的(Administrators)里的新增账户,如有,请立即禁用或删除掉。

    3、查看服务器是否存在隐藏账号、克隆账号。

    检查方法:

    a、打开注册表 ,查看管理员对应键值。

    b、使用D盾_web查杀工具,集成了对克隆账号检测的功能。

    在这里插入图片描述

    4、结合日志,查看管理员登录时间、用户名是否存在异常。

    检查方法:

    a、Win+R打开运行,输入“eventvwr.msc”,回车运行,打开“事件查看器”。

    b、导出Windows日志--安全,利用Log Parser进行分析。

    在这里插入图片描述

    二、检查异常端口、进程

    1、检查端口连接情况,是否有远程连接、可疑连接。

    检查方法:

    a、netstat -ano 查看目前的网络连接,定位可疑的ESTABLISHED

    b、根据netstat 定位出的pid,再通过tasklist命令进行进程定位 tasklist | findstr “PID”

    在这里插入图片描述

    2、进程

    检查方法:

    a、开始--运行--输入msinfo32,依次点击“软件环境→正在运行任务”就可以查看到进程的详细信息,比如进程路径、进程ID、文件创建日期、启动时间等。

    b、打开D盾_web查杀工具,进程查看,关注没有签名信息的进程。

    c、通过微软官方提供的 Process Explorer 等工具进行排查 。

    d、查看可疑的进程及其子进程。可以通过观察以下内容:

    没有签名验证信息的进程

    没有描述信息的进程

    进程的属主

    进程的路径是否合法

    CPU或内存资源占用长时间过高的进程

    3、小技巧:

    a、查看端口对应的PID: netstat -ano | findstr “port”

    b、查看进程对应的PID:任务管理器--查看--选择列--PID 或者 tasklist | findstr “PID”

    c、查看进程对应的程序位置:

    任务管理器--选择对应进程--右键打开文件位置

    运行输入 wmic,cmd界面 输入 process

    d、tasklist /svc 进程--PID--服务

    e、查看Windows服务所对应的端口: %system%/system32/drivers/etc/services(一般%system%就是C:Windows)

    三、检查启动项、计划任务、服务

    1、检查服务器是否有异常的启动项。

    检查方法:

    a、登录服务器,单击【开始】>【所有程序】>【启动】,默认情况下此目录在是一个空目录,确认是否有非业务程序在该目录下。 b、单击开始菜单 >【运行】,输入 msconfig,查看是否存在命名异常的启动项目,是则取消勾选命名异常的启动项目,并到命令中显示的路径删除文件。 c、单击【开始】>【运行】,输入 regedit,打开注册表,查看开机启动项是否正常,特别注意如下三个注册表项: HKEY_CURRENT_USERsoftwaremicorsoftwindowscurrentversion un HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionRun HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionRunonce 检查右侧是否有启动异常的项目,如有请删除,并建议安装杀毒软件进行病毒查杀,清除残留病毒或木马。

    d、利用安全软件查看启动项、开机时间管理等。

    e、组策略,运行gpedit.msc。

    在这里插入图片描述

    2、检查计划任务

    检查方法:

    a、单击【开始】>【设置】>【控制面板】>【任务计划】,查看计划任务属性,便可以发现木马文件的路径。

    b、单击【开始】>【运行】;输入 cmd,然后输入at,检查计算机与网络上的其它计算机之间的会话或计划任务,如有,则确认是否为正常连接。

    3、服务自启动

    检查方法:单击【开始】>【运行】,输入services.msc,注意服务状态和启动类型,检查是否有异常服务。

    四、检查系统相关信息

    1、查看系统版本以及补丁信息

    检查方法:单击【开始】>【运行】,输入systeminfo,查看系统信息

    2、查找可疑目录及文件

    检查方法:

    a、 查看用户目录,新建账号会在这个目录生成一个用户目录,查看是否有新建用户目录。

    Window 2003 C:Documents and Settings

    Window 2008R2 C:Users

    b、单击【开始】>【运行】,输入%UserProfile%Recent,分析最近打开分析可疑文件。

    c、在服务器各个目录,可根据文件夹内文件列表时间进行排序,查找可疑文件。

    五、自动化查杀

    病毒查杀

    检查方法:下载安全软件,更新最新病毒库,进行全盘扫描。

    webshell查杀

    检查方法:选择具体站点路径进行webshell查杀,建议使用两款webshell查杀工具同时查杀,可相互补充规则库的不足。

    六、日志分析

    系统日志

    分析方法:

    a、前提:开启审核策略,若日后系统出现故障、安全事故则可以查看系统的日志文件,排除故障,追查入侵者的信息等。

    b、Win+R打开运行,输入“eventvwr.msc”,回车运行,打开“事件查看器”。

    C、导出应用程序日志、安全日志、系统日志,利用Log Parser进行分析。

    WEB访问日志

    分析方法:

    a、找到中间件的web日志,打包到本地方便进行分析。

    b、推荐工具:Window下,推荐用 EmEditor 进行日志分析,支持大文本,搜索效率还不错。

    Linux下,使用Shell命令组合查询分析

    Linux

    一、账号安全

    基本使用:

    1、用户信息文件/etc/passwd
    root:x:0:0:root:/root:/bin/bash
    account:password:UID:GID:GECOS:directory:shell
    用户名:密码:用户ID:组ID:用户说明:家目录:登陆之后shell
    注意:无密码只允许本机登陆,远程不允许登陆
     
    2、影子文件/etc/shadow
    root:$6$oGs1PqhL2p3ZetrE$X7o7bzoouHQVSEmSgsYN5UD4.kMHx6qgbTqwNVC5oOAouXvcjQSt.Ft7ql1WpkopY0UV9ajBwUt1DpYxTCVvI/:16809:0:99999:7:::
    用户名:加密密码:密码最后一次修改日期:两次密码的修改时间间隔:密码有效期:密码修改到期到的警告天数:密码过期之后的宽限天数:账号失效时间:保留
     
    who     查看当前登录用户(tty本地登陆  pts远程登录)
    w       查看系统信息,想知道某一时刻用户的行为
    uptime  查看登陆多久、多少用户,负载
    

    入侵排查:

    1、查询特权用户特权用户(uid 为0)
    [root@localhost ~]# awk -F: '$3==0{print $1}' /etc/passwd
    2、查询可以远程登录的帐号信息
    [root@localhost ~]# awk '/$1|$6/{print $1}' /etc/shadow
    3、除root帐号外,其他帐号是否存在sudo权限。如非管理需要,普通帐号应删除sudo权限
    [root@localhost ~]# more /etc/sudoers | grep -v "^#|^$" | grep "ALL=(ALL)"
    4、禁用或删除多余及可疑的帐号
        usermod -L user    禁用帐号,帐号无法登录,/etc/shadow第二栏为!开头
        userdel user       删除user用户
        userdel -r user    将删除user用户,并且将/home目录下的user目录一并删除
    

    二、历史命令

    基本使用:

    通过.bash_history查看帐号执行过的系统命令
    1、root的历史命令
    histroy
    2、打开/home各帐号目录下的.bash_history,查看普通帐号的历史命令
     
    为历史的命令增加登录的IP地址、执行命令时间等信息:
    1)保存1万条命令
    sed -i 's/^HISTSIZE=1000/HISTSIZE=10000/g' /etc/profile
    2)在/etc/profile的文件尾部添加如下行数配置信息:
    ######jiagu history xianshi#########
    USER_IP=`who -u am i 2>/dev/null | awk '{print $NF}' | sed -e 's/[()]//g'`
    if [ "$USER_IP" = "" ]
    then
    USER_IP=`hostname`
    fi
    export HISTTIMEFORMAT="%F %T $USER_IP `whoami` "
    shopt -s histappend
    export PROMPT_COMMAND="history -a"
    ######### jiagu history xianshi ##########
    3)source /etc/profile让配置生效
     
    生成效果: 1  2018-07-10 19:45:39 192.168.204.1 root source /etc/profile
     
    3、历史操作命令的清除:history -c
    但此命令并不会清除保存在文件中的记录,因此需要手动删除.bash_profile文件中的记录。
    

    入侵排查:

    进入用户目录下
    cat .bash_history >> history.txt
    

    三、端口

    使用netstat 网络连接命令,分析可疑端口、IP、PID

    netstat -antlp|more
     
    查看下pid所对应的进程文件路径,
    运行ls -l /proc/$PID/exe或file /proc/$PID/exe($PID 为对应的pid 号)
    

    四、进程

    使用ps命令,分析进程

    ps aux | grep pid
    

    五、开机启动项

    基本使用:

    系统运行级别示意图:

    运行级别 含义
    0 关机
    1 单用户模式,可以想象为windows的安全模式,主要用于系统修复
    2 不完全的命令行模式,不含NFS服务
    3 完全的命令行模式,就是标准字符界面
    4 系统保留
    5 图形模式
    6 重启动

    查看运行级别命令 runlevel

    系统默认允许级别

    vi  /etc/inittab
    id=3:initdefault  系统开机后直接进入哪个运行级别
    

    开机启动配置文件

    /etc/rc.local
    /etc/rc.d/rc[0~6].d
    

    例子:当我们需要开机启动自己的脚本时,只需要将可执行脚本丢在/etc/init.d目录下,然后在/etc/rc.d/rc*.d中建立软链接即可

    root@localhost ~]# ln -s /etc/init.d/sshd /etc/rc.d/rc3.d/S100ssh
    

    此处sshd是具体服务的脚本文件,S100ssh是其软链接,S开头代表加载时自启动;如果是K开头的脚本文件,代表运行级别加载时需要关闭的。

    入侵排查:

    启动项文件: more /etc/rc.local /etc/rc.d/rc[0~6].d ls -l /etc/rc.d/rc3.d/

    六、定时任务

    基本使用

    1、利用crontab创建计划任务

    · 基本命令

    crontab -l 列出某个用户cron服务的详细内容

    Tips:默认编写的crontab文件会保存在 (/var/spool/cron/用户名 例如: /var/spool/cron/root

    crontab -r 删除每个用户cront任务(谨慎:删除所有的计划任务)

    crontab -e 使用编辑器编辑当前的crontab文件

    如:/1 * echo "hello world" >> /tmp/test.txt 每分钟写入文件

    2、利用anacron实现异步定时任务调度

    · 使用案例

    每天运行 /home/backup.sh脚本: vi /etc/anacrontab @daily 10 example.daily /bin/bash /home/backup.sh

    当机器在 backup.sh 期望被运行时是关机的,anacron会在机器开机十分钟之后运行它,而不用再等待 7天。

    入侵排查

    重点关注以下目录中是否存在恶意脚本

    /var/spool/cron/* 
    /etc/crontab
    /etc/cron.d/*
    /etc/cron.daily/* 
    /etc/cron.hourly/* 
    /etc/cron.monthly/*
    /etc/cron.weekly/
    /etc/anacrontab
    /var/spool/anacron/*
    

    小技巧:

     more /etc/cron.daily/*  查看目录下所有文件
    

    七、服务

    服务自启动

    第一种修改方法:

    chkconfig [--level 运行级别] [独立服务名] [on|off]
    chkconfig –level  2345 httpd on  开启自启动
    chkconfig httpd on (默认level是2345)
    

    第二种修改方法:

    修改/etc/rc.d/rc.local 文件  
    加入 /etc/init.d/httpd start
    

    第三种修改方法:

    使用ntsysv命令管理自启动,可以管理独立服务和xinetd服务。

    入侵排查

    1、查询已安装的服务:

    RPM包安装的服务

    chkconfig  --list  查看服务自启动状态,可以看到所有的RPM包安装的服务
    ps aux | grep crond 查看当前服务
     
    系统在3与5级别下的启动项 
    中文环境
    chkconfig --list | grep "3:启用|5:启用"
    英文环境
    chkconfig --list | grep "3:on|5:on"
    

    源码包安装的服务

    查看服务安装位置 ,一般是在/user/local/
    service httpd start
    搜索/etc/rc.d/init.d/  查看是否存在
    

    八、系统日志

    日志默认存放位置:/var/log/

    查看日志配置情况:more /etc/rsyslog.conf

    日志文件 说明
    /var/log/cron 记录了系统定时任务相关的日志
    /var/log/cups 记录打印信息的日志
    /var/log/dmesg 记录了系统在开机时内核自检的信息,也可以使用dmesg命令直接查看内核自检信息
    /var/log/mailog 记录邮件信息
    /var/log/message 记录系统重要信息的日志。这个日志文件中会记录Linux系统的绝大多数重要信息,如果系统出现问题时,首先要检查的就应该是这个日志文件
    /var/log/btmp 记录错误登录日志,这个文件是二进制文件,不能直接vi查看,而要使用lastb命令查看
    /var/log/lastlog 记录系统中所有用户最后一次登录时间的日志,这个文件是二进制文件,不能直接vi,而要使用lastlog命令查看
    /var/log/wtmp 永久记录所有用户的登录、注销信息,同时记录系统的启动、重启、关机事件。同样这个文件也是一个二进制文件,不能直接vi,而需要使用last命令来查看
    /var/log/utmp 记录当前已经登录的用户信息,这个文件会随着用户的登录和注销不断变化,只记录当前登录用户的信息。同样这个文件不能直接vi,而要使用w,who,users等命令来查询
    /var/log/secure 记录验证和授权方面的信息,只要涉及账号和密码的程序都会记录,比如SSH登录,su切换用户,sudo授权,甚至添加用户和修改用户密码都会记录在这个日志文件中

    日志分析技巧:

     
    1、定位有多少IP在爆破主机的root帐号:    
    grep "Failed password for root" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -nr | more
     
    定位有哪些IP在爆破:
    grep "Failed password" /var/log/secure|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"|uniq -c
     
    爆破用户名字典是什么?
     grep "Failed password" /var/log/secure|perl -e 'while($_=<>){ /for(.*?) from/; print "$1
    ";}'|uniq -c|sort -nr
     
    2、登录成功的IP有哪些:     
    grep "Accepted " /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -nr | more
     
    登录成功的日期、用户名、IP:
    grep "Accepted " /var/log/secure | awk '{print $1,$2,$3,$9,$11}' 
     
    3、增加一个用户kali日志:
    Jul 10 00:12:15 localhost useradd[2382]: new group: name=kali, GID=1001
    Jul 10 00:12:15 localhost useradd[2382]: new user: name=kali, UID=1001, GID=1001, home=/home/kali
    , shell=/bin/bash
    Jul 10 00:12:58 localhost passwd: pam_unix(passwd:chauthtok): password changed for kali
    #grep "useradd" /var/log/secure 
     
    4、删除用户kali日志:
    Jul 10 00:14:17 localhost userdel[2393]: delete user 'kali'
    Jul 10 00:14:17 localhost userdel[2393]: removed group 'kali' owned by 'kali'
    Jul 10 00:14:17 localhost userdel[2393]: removed shadow group 'kali' owned by 'kali'
    # grep "userdel" /var/log/secure
     
    5、su切换用户:
    Jul 10 00:38:13 localhost su: pam_unix(su-l:session): session opened for user good by root(uid=0)
     
    sudo授权执行:
    sudo -l
    Jul 10 00:43:09 localhost sudo:    good : TTY=pts/4 ; PWD=/home/good ; USER=root ; COMMAND=/sbin/shutdown -r now
    

    溯源简单介绍:

    溯源:有了攻击IP,即追踪到攻击者的攻击达成的手法即完成,也就是怎么攻击的怎么做的。

    1、首先操作系统层溯源:

    ​ 从两个层面:操作系统漏洞、弱口令

    ​ 没有的话问题的话,看系统日志

    2、web程序方面溯源:

    ​ web程序方面,根据日志溯源(如果日志被清除那就根据安全设备的流量备份,对其分析攻击特征)
    主要就是日志和流量,都没有的话那基本难以溯源。

    (流量备份是等保要求的)

    补充

    svchost服务的宿主程序,一般是6-7个

    Svchost.exe进程的研究分析————————

    你是否经常在你电脑看到很多svchost.exe进程呢?有的人电脑有6个svchost.exe进程、有的人电脑更多的svchost.exe进程。例如我的电脑就有5个svchost.exe程序。一般来说Windows 2000有两个这样的进程,XP中有4~6个,Win7中一般是6个,但这都不是绝对的,或许有的人会这样想,是不是我多了就不正常,其实并不是这样的,svchost.exe进程是个核心宿主进程,这个程序对系统的正常运行是非常重要,而且是不能随意被结束的,一旦结束可能会造成系统崩溃、关机。但很多木马也会通过模仿该进程名或者通过DLL注入到该进程之中。

    Svchost 全称是“Service host”,翻译成中文来说“服务的宿主程序”。所以我们经常说svchot.exe就是一个宿主服务进程。它所在的路径为:C:WindowsSystem32Svchost.exe。它是一个可执行文件。下面我们一起来学习几点关于Svchost.exe必要的知识。

    【1】:服务对应的二进制文件可分为可执行文件和DLL动态链接库文件两类。对于可执行文件来说,本身就是一个宿主程序,但是对于DLL动态链接库来说不可以直接去执行它,只有通过一个宿主程序来调用它来进行执行。对于服务,我们可以通过开始——运行——输入“services.msc”进入到服务。我们就拿个最简单的Telnet服务来说,右击可以看到它所调用的文件就是C:WindowsSystem32 lnsvr.exe的可执行文件,这种可执行文件本身就是一个服务宿主程序,不需要调用DLL动态链接来实现,如果该宿主文件不存在,或者文件名不对,那么就无法启动Telnet服务了。当我们启动Telnet的时候,进程中自然多出一个服务宿主程序的进程。而对于某些服务需要调用DLL动态链接库,如果我们直接去运行DLL动态链接库是无法直接执行的,必须通过一个宿主程序来进行调用执行,经常使用到的这个服务宿主程序就是Svchost.exe。

    【2】Svhost.exe,是大多数Windows服务的宿主程序。Svchost.exe程序就是一个用于加载服务对应的二进制文件为DLL的宿主程序。

    【3】Svchost.exe一般位于%systemroot%system32目录里,如果启用了DllCache功能,还可能备份在%systemroot%system32dllcache目录下,另外,如果WindowsService Pack不是使用集成安装的,也就是不是集成SP补丁包的而是通过微软更新的,那么还可能存在于%systemroot%ServicePack目录下。除此之外Svchost.exe不应该存在其它目录下,如果存在,那么这个Svchost.exe可能不是系统自带的而是一种病毒等一些而已软件生成的,请小心检查。特别是一些木马经常使用这个程序来进行伪装运行在内存中。

    【4】Svchost.exe作为服务的宿主程序,在启动的时候,通过以下方法来启动服务:系统启动的时候,系统读取注册表:

    HKEY_LOCAL_MACHINESoftwareMicrosoftWindows NTCurrentVersionSvchost下的键值,在这个分支下,有很多键值为REG_MULTI_SZ的键值,也就是多字符串值,在该主键下每一个键值代表着一组服务。Svchost.exe的每个实例将执行一个键值为REG_MULTI_SZ的键值,举例来说,当Svchost.exe开始读取netsvcs的时候,系统将创建一个svchost.exe的实例(在任务管理器里面呈现为进行)来处理netsvcs键值的数据。所有在netsvcs里面描述的服务将运行于一个svchost.exe进程里面,也就是说,一个svchost.exe将处理所有netsvcs里面记录的服务。这就是所谓宿主的概念。不过有一点需要注意,如果有任何一个服务发生问题,可能导致宿主程序svchost.exe的崩溃,甚至导致Windows崩溃。如果强制结束svchost.exe进程,那么这个宿主程序所启动的服务都将停止崩溃。

    【5】在不停的系统中,svchost.exe的实例数目是不相同的。这是因为微软将不同的服务归结到不同的svchost.exe实例中,在Windows Server 2003和XP下,RpcSc(提供终结点映射服务RPC服务)服务就单独的由一个svchost.exe实例负责,这是为了保证不会由于其它服务的错误而导致整个svchost.exe进程错误。而netsvcs中的几十个服务却也使用一个Svchost.exe实例来进行负责,我们可以通过“tasklist /svc” 和注册表中就可以轻易的看到。

    【6】我们可以这样理解:如果有一个svchost.exe作为2和服务的宿主,其中一个是系统重要的服务A,如果A停止,则整个系统就崩溃,而另外一个是服务B,B不是一个重要的服务,停止B不会引起整个系统的崩溃。如果某一天服务B发生异常,导致B的宿主程序svchost.exe崩溃,那么也会导致服务A崩溃。从而导致系统崩溃。

    【7】一个svchost.exe作为几个服务的宿主很重要的,也不要对自己的系统里面的svchost.exe实例数量为什么要比别人多,其实影响svchost.exe实例数量完全决定于你开启的服务的数量或者某些程序需要通过注入到该宿主服务中进行启动。如果某些不需要的服务可以停止掉以减少内存的使用,如果停止的一些服务都是包含于一个svchost.exe,那么这个进程就会不再启动,因为没有服务需要这个实例进行启动了。微软之所以将那么多服务使用一个宿主程序来启动就是为了节省我们的系统资源。

    【8】要想知道我们进程中的每一个Svchost.exe分别是启动了哪些服务,可以通过tasklist /svc查看每一个加载不同服务的svchost.exe的PID值,并且在任务管理器查看——选择列——勾选PID(进程标识符),这样就可以很好的知道哪个svchost.exe是加载哪些服务的。

    【9】如何使用辅助工具判断svchost.exe是否为伪造进程呢?第一个就是判断svchost.exe的所在的启动路径,正常的路径都是在C:WindwosSystem32下,第二个还是必须要大家的经验,也就是说,你必须要熟悉一个正常系统的svchost.exe是启动了的哪些服务是正常的。
    主程序svchost.exe崩溃,那么也会导致服务A崩溃。从而导致系统崩溃。

    【7】一个svchost.exe作为几个服务的宿主很重要的,也不要对自己的系统里面的svchost.exe实例数量为什么要比别人多,其实影响svchost.exe实例数量完全决定于你开启的服务的数量或者某些程序需要通过注入到该宿主服务中进行启动。如果某些不需要的服务可以停止掉以减少内存的使用,如果停止的一些服务都是包含于一个svchost.exe,那么这个进程就会不再启动,因为没有服务需要这个实例进行启动了。微软之所以将那么多服务使用一个宿主程序来启动就是为了节省我们的系统资源。

    【8】要想知道我们进程中的每一个Svchost.exe分别是启动了哪些服务,可以通过tasklist /svc查看每一个加载不同服务的svchost.exe的PID值,并且在任务管理器查看——选择列——勾选PID(进程标识符),这样就可以很好的知道哪个svchost.exe是加载哪些服务的。

    【9】如何使用辅助工具判断svchost.exe是否为伪造进程呢?第一个就是判断svchost.exe的所在的启动路径,正常的路径都是在C:WindwosSystem32下,第二个还是必须要大家的经验,也就是说,你必须要熟悉一个正常系统的svchost.exe是启动了的哪些服务是正常的。

  • 相关阅读:
    ArrayList removeRange方法分析
    LinkedHashMap源码分析(基于JDK1.6)
    LinkedList原码分析(基于JDK1.6)
    TreeMap源码分析——深入分析(基于JDK1.6)
    51NOD 2072 装箱问题 背包问题 01 背包 DP 动态规划
    51 NOD 1049 最大子段和 动态规划 模板 板子 DP
    51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子
    8月20日 训练日记
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/jeromeyoung/p/14435369.html
Copyright © 2011-2022 走看看