正则表达式
正则表达式:
- ^ 匹配行首(以什么开头;
- $ 匹配行尾(以什么结尾;
- [ ] 集合,匹配集合中的任意单个字符;
- 1 对集合取反;
- . 匹配任意单个字符;
- * 匹配前一个字符任意次数(需配合使用);
- .* 可以是空也可以是任意字符无数次;
- {n,m} 匹配前一个字符n到m次(匹配前一个字符排列在一起几次到几次)
- {n} 匹配前一个字符n次
- {n,} 匹配前一个字符n次以上
- () 保留 (复制)
使用 Linux系统中 grep命令举例:
- grep "^ro" /etc/passwd
- grep "sh$" /etc/passwd
- grep "[abc]" /etc/passwd
- grep "[^abc]" /etc/passwd #匹配不含a或b或c的行
- grep "r." /etc/passwd #匹配r与任意字符组合的行
- grep "a*" /etc/passwd #搜索a出现任意次数的行,0次也包括
- grep "..." /etc/passwd #搜索任意三个字符出现的行
- grep ".* " #可匹配任意行 包括空行
扩展正则表达式:
- + 最少匹配一次;
- ? 最多匹配一次;
- () 组合为整体,保留(相当于 复制)
- | 或者
- b 单次边界 \< >\
问题代码:
<?php
$key='flag{********************************}';
$Regular= preg_match("/zkaq.*key.{2,9}:\/.*\/(key*key)/i", trim($_GET["id"]), $match);
if( $Regular ){
die('key: '.$key);
}
?>
分析:
<1>、函数解析;
preg_match( )
preg_match()
函数可以根据正则表达式对字符串进行搜索匹配,函数的语法格式如下:
preg_match ( $pattern , $subject , $matches )
搜索subject与pattern给定的正则表达式的一个匹配.
参数 :
pattern
: 要搜索的模式,字符串类型(正则表达式)。subject
: 输入的字符串。matches
:(可有可无)如果提供了参数matches,它将被填充为搜索结果。 $matches[0]
将包含完整模式匹配到的文本, $matches[1]
将包含第一个捕获子组匹配到的文本,以此类推。
返回值 :
preg_match()
返回 pattern 的匹配次数。 它的值将是0次(不匹配)或1次,因为preg_match()
在第一次匹配后 将会停止搜索。preg_match_all()
不同于此,它会一直搜索subject 直到到达结尾。 如果发生错误preg_match()
返回 FALSE。
trip( )
trim()
函数移除字符串两侧的空白字符或其他预定义字符.
相关函数:
ltrim()
- 移除字符串左侧的空白字符或其他预定义字符。rtrim()
- 移除字符串右侧的空白字符或其他预定义字符。
trim(string,charlist)
参数 | 描述 |
---|---|
string | 必需。规定要检查的字符串。 |
charlist | 可选。规定从字符串中删除哪些字符。如果省略该参数,则移除下列所有字符:1."0" - NULL; 2."t" - 制表符; 3."n" - 换行; 4."x0B" - 垂直制表符; 5."r" - 回车; 6." " - 空格 |
<2>、配合代码解析;
最主要的一行就在于此:
$Regular= preg_match("/zkaq.*key.{2,9}:\/.*\/(key*key)/i", trim($_GET["id"]), $match);
- 其中
trim()
参数并未设置charlist,所以只是去除GET传参中两榜的特殊符号,并未设计具体字符移除,不用考虑; 主要考虑
preg_match()
,其中/zkaq.*key.{2,9}:\/.*\/(key*key)/i
:- //双斜杠中的才为具体匹配的内容;
- 后一个斜杠后的 i 表示不区分大小写;
- 得到更具体的进行匹配的字段
zkaq.*key.{2,9}:\/.*\/(key*key)
由上述给到的正则匹配规则,一一进行解析:
- zkaq == zkaq # 确定的字符串无法变动
- .* == # 通配符,任意字符串
- key == key # 确定的字符串无法变动
- .{2,9} == aa # 匹配前一个字符n到m次
- : == : # 确定的字符串无法变动
- / == / # 为转义符,使得/无特殊意义
- .* == a # 通配符,任意字符串
- / == / # 为转义符,使得/无特殊意义
- (key*key) == keykeykeykey #()为了组合为一个整体,但是第一个key后面又一个*表示任意次,所以这里我去了3次,后一个key为确定的字符无法变动
最终我给到的结果为: zkaqkeyaa:/a/keykeykeykey
提示:
当然提示的一点是前面我们给到的i
不区分大小写并未使用,所以字符串中字母的大小写可以任意,而且.*所匹配的任意字符串可以随意填写,以及后续的字符出现次数也可以随意。
<3>、验证;
将GET传参的 id 改为所得出的结果:
最终flag:
key: flag{regular_god_code}