ModSecurity SQL注入攻击 – 深度绕过技术挑战
ModSecurity是一个入侵探测与阻止的引擎,它主要是用于Web应用程序所以也可以叫做Web应用程序防火墙.它可以作为Apache Web服务器的一个模块或单独的应用程序来运行。ModSecurity的目的是为增强Web应用程序的安全性和保护Web应用程序避免遭受来自已知与未知的攻击。本文主要介绍了针对开源WAF的一次渗透测试比赛中的思路。
1. 文章背景
ModSecurity SQL Injection Challenge(ModSecurity发起的一个针对开源WAF的一次渗透测试比赛)
http://www.modsecurity.org/demo/challenge.html
owasp-modsecurity-crs(OWASP针对ModSecurity编写的权威rule)
https://github.com/SpiderLabs/owasp-modsecurity-crs
2. 绕过思路分析
0×1:
目标应用系统: Acunetix Acuart Site
注入点: http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=1';
分析:
注入点很明显,通过测试可以知道这个注入点为数字型的注入,各种拼接都可以进行,但是普通的注入方法无一例外都会触发Mod的拦截规则。
这里采用mysql注释+CRLF绕过思路来进行注入
1) "#"用于单行注释
2) "– "用于单行注释,但要注意使用这种风格的注释符必须保证在"双横线"后面跟上一个"空格或控制符Control Char(控制符可以是空格, Tab制表符, 换行符Newline…)"(在使用的时候要注意URL编码,例如换行符的URL编码为%0D%0A)。关于这种"Double Dash注释符"在Mysql的官方文档中还有一点细节要注意(重点就是新版的Mysql解析引擎的改进避免了"基于减号导致的注释型注入")
3) "/* */"C风格的注释符,这种注释允许跨行注释(即允许在注释符中添加换行符,例如: /*..%0D%0A..*/)
mysql> SELECT 1+1; # This comment continues to the end of line
mysql> SELECT 1+1; -- This comment continues to the end of line
mysql> SELECT 1/* this is an in-line comment */ + 1;
mysql> SELECT 1+
/*
this is a
multiple-line comment
*/
1;
回到我们的注入点上来看看,我们使用mysql注释+CRLF来进行payload的构造(注意URL编码):
对其URL转义如下(注意换行符的解析):
0 div 1 union#foo*/*bar
select#foo
1,2,current_user
这句sql语句到了Mysql的解析引擎后会再次被解析为:
0 div 1 union select 1,2,current_user
可以看到,注释符之间进行了就近原则的交错组合,Mysql的Sql Parser则选择进行了忽略。
而ModSecurity CRS的规则如下:
注意到这个":replaceComments",我们知道,ModSecurity使用正则表达式来对Input Sql进行匹配检测,对Select、Union在敏感位置的出现都进行了拦截,但是ModSecurity有一个特点(或者叫优点),它会对输入进行"规范化",规范化的本意本来是防御"基于编码格式、解析顺序"的绕过的。
例如:
Mod可以抵抗这种形式的绕过:
SEL/**/ECT
在"规范化"之后,攻击者的本来目的就暴力在了Mod的检测下,这个时候再上规则就可以检测出来了,可以说,规范化是一个很好的防御思路。
但是这里却导致了另一种的"绕过"
问题的关键就在于ModSecurity对注释的理解和Mysql的解析引擎理解不同
(这似乎又回到了那个老问题: 同一个业务规则在不同的系统中的理解语义不同往往可能导致绕过)
:replaceComments
Unterminated comments will also be replaced with a space (ASCII 0x20). However, a standalone termination of a comment (*/) will not be acted upon.
也就是说,Mod会忽略前向半开注释并把后向半开注释当成单行注释(如果它没有找到后向半开的闭合注释时)
Mod的拦截日志中可以看到如下记录:
这样,在Mod看来,我们输入的Payload就变成了:
"0 div 1 union#foo* "
但是在Mysql看来,我们的sql语句其实是:
0 div 1 union select 1,2,current_user
防御方法:
1) 将原来的去除注释方法改为对SQL注释的匹配
#
# -=[ Detect SQL Comment Sequences ]=-
#
SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \
"(\/\*\!?|\*\/|\-\-[\s\r\n\v\f]|(?:--[^-]*-)|([^\-&])#.*[\s\r\n\v\f]|;?\\x00)" \
"phase:2,rev:'2.2.2',id:'981231',t:none,t:urlDecodeUni,block,msg:'SQL Comment Sequence Detected.',capture,logdata:'%{tx.0}',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.sql_injection_score=+1,setvar:'tx.msg=%{rule.msg}',setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"
但是这种方法从本质上又回到了"黑名单模式"的范畴中,有可能再次导致别的形式的绕过
2) 使用多行匹配(MultiMatch Action)+规范化方法(ReplaceComments)
SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "(?i:\buser_tables\b)" \
"phase:2,rev:'2.2.2',capture,multiMatch,t:none,t:urlDecodeUni,t:replaceComments,ctl:auditLogParts=+E,block,msg:'Blind SQL Injection Attack',id:'959918',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{TX.0}',severity:'2',setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.
0×2:
目标应用系统: Cenzic Crack Me Bank
注入点: http://www.modsecurity.org/Kelev/php/accttransaction.php (POST)
注入Payload:
绕过分析:
这里采用了"碎片注入法(分段SQL注入)",或者是我们常说的"Split And Balance原则"。例如:
对于最简单的情况,可以使用字符串连接技术将较小的部分构造成一个字符串。不同的数据库使用不同的语法来构造字符串
oracle: 'selec'||'t'
sqlserver: 'selec'+'';
mysql: 'selec'+'t'
(这就是所谓的split and balance思想)
还要注意的是,加号和空格要先进行URL编码后再发送
这种技术的好处是可以将原本完整的Payload分成几段,利用ModSecurity对SQL语义的理解不全来进行规则绕过。常常用于进行"二值逻辑"的盲注推理。
回到我们的注入点上来看:
对于Mod来说,我们的攻击Payload为:
hUserId=22768&FromDate=a1%27+or&ToDate=%3C%3Eamount+and%27&sendbutton1=Get+Statement
而对于Mysql的解析引擎来说,它会自动去除、转换这些连接控制符,从而变成:
hUserId=22768&FromDate=a1%27+or&ToDate=<>amount and%27&sendbutton1=Get Statement
防御方法:
1) 这里有个概念叫"String Termination/Statement Ending Injection Testing"。攻击者在进行SQL注入检测的时候常常会使用一些"终止符",例如单引号、NULL等等,并通过观察页面是否报错来获知当前页面是否存在注入点。
为了防御这种注入,我们可以使用以下CRS规则:
#
# -=[ String Termination/Statement Ending Injection Testing ]=-
#
# Identifies common initial SQLi probing requests where attackers insert/append
# quote characters to the existing normal payload to see how the app/db responds.
#
SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \
"(?i:(\!\=|\&\&|\|\||>>|<<|>=|<=|<>|<=>|xor|rlike|regexp|isnull)|(?:not\s+between\s+0\s+and)|(?:is\s+null)|(like\s+null)|(?:(?:^|\W)in[+\s]*\([\s\d\"]+[^()]*\))|(?:xor|<>|rlike(?:\s+binary)?)|(?:regexp\s+binary))" \
"phase:2,rev:'2.2.2',capture,t:none,t:urlDecodeUni,block,msg:'SQL Injection Attack: SQL Operator Detected',id:'981212',logdata:'%{TX.0}',severity:'2',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.notice_anomaly_score},setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"
2) 注意到我们的攻击Payload中一个Mysql逻辑运算符: "<>"。攻击者可以利用逻辑运算符进行"盲注推理"。例如,我们常见的传统盲注手段:
and (ascii(substring((select username from admin),1,1)))>97
(这种就是将逐个字符转成ASCII值然后用二分查找法进行猜测) UPDATE table SET views = '1' WHERE id = -2441 OR (ORD(MID((SELECTIFNULL(CAST(FirstName AS CHAR),0x20) FROM nowamagic.`tb2` ORDER BY id LIMIT 1,1),2,1))>112)#
(同样的思路,换了一个函数)
为了防御这种注入,我们可以使用以下CRS规则
#
# -=[ SQL Operators ]=-
#
SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \
"(?i:(\!\=|\&\&|\|\||>>|<<|>=|<=|<>|<=>|xor|rlike|regexp|isnull)|(?:not\s+between\s+0\s+and)|(?:is\s+null)|(like\s+null)|(?:(?:^|\W)in[+\s]*\([\s\d\"]+[^()]*\))|(?:xor|<>|rlike(?:\s+binary)?)|(?:regexp\s+binary))" \
"phase:2,rev:'2.2.2',capture,t:none,t:urlDecodeUni,block,msg:'SQL Injection Attack: SQL Operator Detected',id:'981212',logdata:'%{TX.0}',severity:'2',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.notice_anomaly_score},setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"
0×3:
目标应用系统: IBM demo.testfire.net site
注入点: http://www.modsecurity.org/bank/login.aspx (POST)
注入Payload:
这里使用了HPP(HTTP Parameter Pollution)注入技术,关于HPP,有很多相关的资料:
http://www.freebuf.com/articles/web/5908.html
http://hi.baidu.com/aullik5/item/860da508a90709843c42e2ca
http://hi.baidu.com/4b5f5f4b/item/abc28dda72c100f154347f36
https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf
回到我们的注入Payload上来,我们注意到after这个字段出现了3次,其中后2次的出现其实是产生了逗号的作用,以此来进行绕过。要注意的一点是,HPP攻击和具体的应用系统环境有很大关系,在不同的系统上表现不太一致:
https://www.trustwave.com/spiderlabs/advisories/TWSL2011-006.txt
防御方法:
我们可以采用以下的CRS规则来防御HPP攻击:
# -=[ Rules Logic }=-
# The ruleset below is not looking for attacks directly, but rather is a crude normalization
# function that mimics ASP.NET with regards to joining the payloads of parameters with the
# same name. These rules will create a new TX:HPP_DATA variable that will hold this data.
# If you have enabled PARANOID_MODE, then this variable data will also be searched against
# attack filters.
#
# -=[ References ]=-
# http://tacticalwebappsec.blogspot.com/2009/05/http-parameter-pollution.html
#
SecRule ARGS "^" "chain,phase:2,t:none,nolog,pass,capture,id:'900032',rev:'2.2.9',setvar:tx.%{matched_var_name}=+1"
SecRule TX:/^ARGS:/ "@gt 1" "chain,t:none"
SecRule MATCHED_VARS_NAMES "TX:(ARGS:.*)" "chain,capture,t:none,setvar:tx.hpp_names=%{tx.1}"
SecRule ARGS ".*" "chain,t:none,capture,setvar:tx.arg_counter=+1,setvar:'tx.hppnamedata_%{tx.arg_counter}=%{matched_var_name}=%{tx.0}'"
SecRule TX:/HPPNAMEDATA_/ "@contains %{tx.hpp_names}" "chain,setvar:tx.hpp_counter=+1,setvar:tx.hpp_counter_%{tx.hpp_counter}=%{matched_var}"
SecRule TX:/HPP_COUNTER_/ "ARGS:(.*)?=(.*)" "capture,setvar:'tx.hpp_data=%{tx.hpp_data},%{tx.2}'"
0×4:
目标应用系统: Cenzic Crack Me Bank
注入点: http://www.modsecurity.org/Kelev/php/accttransaction.php (POST)
注入Payload:
思路分析:
这里采用了"半开注释符(Unterminated Comments)"+"Mysql注释符代码执行(MySQL Comment Extensions for conditional code execution)"技术来进行绕过
半开注释符我们之前说过了,是利用Mod的replaceComments来进行敏感关键字的绕过。而"Mysql注释符代码执行"则是Mysql的一个运行机制。
Mysql的官方文档如下:
MySQL Server supports some variants of C-style comments. These enable you to write code that includes MySQL extensions, but is still portable, by using comments of the following form:
(Mysql允许C风格的注释符,并允许在其中写入Mysql扩展,即插入可执行sql代码)
/*! MySQL-specific code */
Mysql的Paerser引擎会自动解析这种格式中的sql代码,同时其他的数据库(例如MSSQL、ORACLE会自动忽略这些注释),也就是说,这是Mysql特有的特性:
select 1 union/*! select */version();
select 1 union/*!32302 select */version();
防御方法:
和 0×1 一样,采用使用多行匹配(MultiMatch Action)+规范化方法(ReplaceComments)
0×5:
目标应用系统: IBM demo.testfire.net site
注入点: http://www.modsecurity.org/bank/login.aspx (COOKIE)
注入Payload:
注入分析:
注入点并没有什么特别的,关键在与这里采用了COOKIE注入
防御方法:
关于这个COOKIE注入,我想延伸几点想法:
在注入点的选择中,HTTP中的任何字段、任何位置都"有可能"产生SQL注入,这里只能说有可能,因为是否能否产生注入,和具体的应用系统的环境有关,即应用系统会使用哪些字段带入数据进行执行
"GPCS"的作用:
在php.ini中有一项配置: variables_order = "GPCS"(具体的顺序和字符和具体你的配置有关)
如果在php.ini中开启了"register_globals"这个选项,则PHP会按照"$GET"、"$POST"、"$COOKIE"、"SERVER"的顺序来把这些全局数据中国的子键抽取出来,注册到本地变量的的符号表中,即全局变量本地化。这个顺序很重要,这往往是很多本地变量覆盖漏洞利用的关键
3. HTTP中的任意位置都有可能产生SQL注入,看下面的例子:
http://sebug.net/vuldb/ssvid-8427
Create New Admin Exploit FOR php168 v4.0SP
这个例子中,注入点发生在"X-FORWARDED-FOR"这个字段中,这本来是应用系统用来做记录登录用户的IP、代理IP的业务功能,但是因为没有过滤严格,导致了注入的发生
0×6:
目标应用系统: Acunetix Acuart Site
注入点: http://www.modsecurity.org/testphp.vulnweb.com/listproducts.php?artist=1'
注入Payload:
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=%40%40new%20union%23sqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsql%0Aselect%201,2,database%23sqlmap%0A%28%29
Payload分析:
这里采用了"Mysql注释(MySQL Comment )"+"换行绕过(New Line trick )"的组合方法来进行Mod的绕过(本质上是对Mod所使用的正则表达式的绕过)
在Mod看来,我们的Payload如下:
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=@@new union#sqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsqlmapsql
select 1,2,database#sqlmap
()
然而,当这段SQL代码进入Mysql的解析引擎的时候,Mysql看到的是这样的形式:
artist=@@new union select 1,2,database()
防御方法:
我们知道,SQL(Structure Query Language)是一种及其灵活的命令式语言,各个元素之间的组合可以有很多种,采用正则REGEX的方法来进行匹配常常无法做到精确指导,为了解决这个问题,我们有两种思路
1) 采用高阶的SQL解析方法,例如AST:
http://www.cnblogs.com/LittleHann/p/3495602.html
2) 改进正则,采用敏感关键字匹配的方法
SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \
"([\~\!\@\#\$\%\^\&\*\(\)\-\+\=\{\}\[\]\|\:\;\"\'\´\’\‘\`\<\>].*){4,}" \
"phase:2,t:none,t:urlDecodeUni,block,id:'981173',rev:'2.2.1',msg:'Restricted SQL Character Anomaly Detection Alert - Total # of special characters exceeded',capture,logdata:'%{tx.1}',setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},setvar:tx.sql_injection_score=+1,setvar:'tx.msg=%{rule.msg}',setvar:tx.%{rule.id}-WEB_ATTACK/RESTRICTED_SQLI_CHARS-%{matched_var_name}=%{tx.0}"
0×7:
目标应用系统: Acunetix Acuart Site
注入点: http://www.modsecurity.org/testphp.vulnweb.com/listproducts.php?artist=1'
注入Payload:
Payload分析:
这里采用了"Mysql错误回显"+"Tab键分隔绕过"的组合方法来进行Mod的绕过,这里的关键点是没有使用传统的空格来进行"Split And Balance"。
这里要提的是黑名单思想,对"Split And Balance"的防御如果采用黑名单容易产生绕过:
如果一定要采用黑名单,则必须进行严格的代码审计和测试,保证黑名单的完整性
例如,在Mysql中允许的分隔符为:
09
0A
0B
0C
0D
A0
防御方法:
采用完整的"准空格分隔符"黑名单CRS
SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* \
"(?i:(?:,.*[)\da-f(\"|'|`|´|’|‘)](\"|'|`|´|’|‘)(?:(\"|'|`|´|’|‘).*(\"|'|`|´|’|‘)|\Z|[^(\"|'|`|´|’|‘)]+))|(?:\Wselect.+\W*from)|((?:select|create|rename|truncate|load|alter|delete|update|insert|desc)\s*\(\s*space\s*\())" \
"phase:2,capture,multiMatch,t:none,t:urlDecodeUni,t:replaceComments,block,msg:'Detects MySQL comment-/space-obfuscated injections and backtick termination',id:'981257',tag:'WEB_ATTACK/SQLI',tag:'WEB_ATTACK/ID',logdata:'%{TX.0}',severity:'2',setvar:'tx.msg=%{rule.id}-%{rule.msg}',setvar:tx.anomaly_score=+5,setvar:'tx.%{tx.msg}-WEB_ATTACK/SQLI-%{matched_var_name}=%{tx.0}',setvar:'tx.%{tx.msg}-WEB_ATTACK/ID-%{matched_var_name}=%{tx.0}'
3. 总结
Blacklist filtering is not enough — 不要依赖黑名单机制
应该使用多种方法进行纵深防御
https://www.trustwave.com/application-security/
对输入验证采用安全模型,包括规范化、数据类型,数据格式,数据长度
https://www.trustwave.com/web-application-firewall/
WAF作为一个防御手段,从某种程序上来说只是增加了攻击者的攻击成本,并不能从根本上解决注入的发生,要解决注入漏洞的产生,保护敏感数据,必须多管齐下,从应用系统、WAF、数据库防火墙的角度去思考
ModSecurity SQL注入攻击 – 深度绕过技术挑战的更多相关文章
- ModSecurity SQL注入攻击
ModSecurity是 一个入侵探测与阻止的引擎,它主要是用于Web应用程序所以也可以叫做Web应用程序防火墙.它可以作为Apache Web服务器的一个模块或单独的应用程序来运行.ModSecur ...
- PHP的SQL注入攻击的技术实现以及预防措施
最近在折腾 PHP + MYSQL 的编程.了解了一些 PHP SQL 注入攻击的知识,总结一下经验.在我看来,引发 SQL 注入攻击的主要原因,是因为以下两点原因: 1. php 配置文件 php. ...
- 2017-2018-2 20179205《网络攻防技术与实践》第十一周作业 SQL注入攻击与实践
<网络攻防技术与实践>第十一周作业 SQL注入攻击与实践 1.研究缓冲区溢出的原理,至少针对两种数据库进行差异化研究 缓冲区溢出原理 在计算机内部,输入数据通常被存放在一个临时空间内, ...
- 【web渗透技术】渗透攻防Web篇-SQL注入攻击初级
[web渗透技术]渗透攻防Web篇-SQL注入攻击初级 前言不管用什么语言编写的Web应用,它们都用一个共同点,具有交互性并且多数是数据库驱动.在网络中,数据库驱动的Web应用随处可见,由此而存在的S ...
- 实例讲解 SQL 注入攻击
这是一篇讲解SQL注入的实例文章,一步一步跟着作者脚步探索如何注入成功,展现了一次完整的渗透流程,值得一读.翻译水平有限,见谅! 一位客户让我们针对只有他们企业员工和顾客能使用的企业内网进行渗透测试. ...
- 防止SQL注入攻击的一些方法小结
SQL注入攻击的危害性很大.在讲解其防止办法之前,数据库管理员有必要先了解一下其攻击的原理.这有利于管理员采取有针对性的防治措施. 一. SQL注入攻击的简单示例. statement := &quo ...
- SQL注入攻击
SQL注入攻击是黑客对数据库进行攻击的常用手段之一.随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候, ...
- SQL注入攻击的种类和防范手段
观察近来的一些安全事件及其后果,安全专家们已经得到一个结论,这些威胁主要是通过SQL注入造成的.虽然前面有许多文章讨论了SQL注入,但今天所讨论的内容也许可帮助你检查自己的服务器,并采取相应防范措施. ...
- SQL注入攻击三部曲之高级篇
SQL注入攻击三部曲之高级篇 经过了入门篇和进阶篇的学习,相信诸位想要破解一般的网站是没有什么问题了,但是先别得意.正所谓学海无涯,技术的进步也是没有止境的.SQL注入是一个看起来简单,但是变数很多的 ...
随机推荐
- redis健康检查与故障转移
哨兵三个定时监控任务 每隔10s每隔sentinel节点会向主节点和从节点发送info命令获取最新的拓扑结构 每隔2S,每个sentinel节点会向redis数据节点的__sentiel__:hell ...
- @Async的简单用法总结
前言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时 候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3 ...
- [luoguU48834][count]
题目链接 思路 这个题可以考虑用全部情况减去不合法的情况,来求解.首先需要知道n个点所组成的图总共有\(C(_n^2)\)种,然后用f[n]表示n个点的图联通的方案数. 然后钦定1在联通图里面,考虑不 ...
- 【洛谷 P1616 疯狂的采药】
题目背景 此题为NOIP2005普及组第三题的疯狂版. 此题为纪念LiYuxiang而生. 题目描述 LiYuxiang是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的 ...
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊(分块算法)
传送门 题意: 中文题意,不再赘述. 题解: 下午在补分块算法的相关知识,看到某大神博客推荐的这道题目,就试着做了做: TLE了一下午可还行: 我的思路: 将这 n 个点分成 sqrt(n) 块: i ...
- 详解Vue 开发模式下跨域问题
vue项目中,前端与后台进行数据请求或者提交的时候,如果后台没有设置跨域,前端本地调试代码的时候就会报“No 'Access-Control-Allow-Origin' header is prese ...
- Unity 着色器
Unity中定义了很多种Shader类型,同样的Shader类型我们可以自定义,需要用到ShaderLab着色语言. 一个3D图形是怎样显示在我们的视觉? 3D数据文件-----3D显示程序----- ...
- 面向对象【day08】:类的起源与metaclass(二)
本节内容 1.概述 2.类的起源 3.__new__方法 4.__metaclass__方法 一.概述 前面我们学习了大篇幅的关于类,通过类创建对象,那我们想知道这个类到底是怎么产生的呢?它的一切来源 ...
- Linux 内核里的数据结构:位图(bitmap)
注: 本文由 LCTT 原创翻译,Linux中国 荣誉推出 Linux 内核中的位数组和位操作 除了不同的基于链式和树的数据结构以外,Linux 内核也为位数组(或称为位图(bitmap))提供了 A ...
- MY服务器架设
研究了一天,终于弄出来了,进游戏耍了会,感觉不错,下面分享架设步骤给大家 分享端的大大也出了个虚拟机运行需要注意的视频,大家看看吧,我就这样弄架设成功了 链接:链接: http://pan.baidu ...