banner
Hi my new friend!

碎碎念

Scroll down

碎碎念

  1. 配置完环境变量使用命令source /bin/profile激活我才意识到原来一直使用的python环境激活source /venv/bin/activate中的这个activate居然也是一个文本文件,一直因为是一个看着还行文件

  2. webpack扒对应目标函数注入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    window.c = c;
    window.res = "";
    window.flag = false;
    c = function(r){
    if(flag){
    window.res = window.res + `"${r.toString()}"` + ":" + (e[r] + "" ) + ",";
    }
    return window.c(r);
    }
  3. python中的map()

    map的作用是:把一个函数,应用到一堆数据的每一个元素上

    1
    2
    b=map(func,list) # 对list中的每一个函数都作用到 返回的是一个可迭代对象的地址
    c=list(b) # list中每一个值都被func作用之后返回到的这个新的列表中
  4. python中的zip()

    1
    2
    3
    4
    5
    aaa=[1,2,3,4,5,6]
    bbb=[7,8,9,10,11,12]
    ccc=[13,14,15,16,17,18]
    ddd=zip(aaa,bbb,ccc) # 返回一个可迭代对象的地址
    c=list(ddd) # 这样就可以拿来用了

    AI解释

    zip是干嘛的?——“打包配对”

    想象一下你有三列队伍:

    • 第一队(客户端基):[+, x, +, ...]
    • 第二队(服务器基):[x, x, +, ...]
    • 第三队(客户端极化):[0, 1, 0, ...]

    zip的作用就是让这三队人并排站好,一次各出一人,组成一个三人小组

  5. 计算机中用来加密解密运算的时候通常使用字节
    计算机中的所有二进制数据确实都是以字节为基本单位存在和操作的**。比特更像是字节的”组成成分”,但计算机硬件层面直接处理的是字节。**

    • 也就是说在进行计算之前都得把值转换成byte然后才能进行运算

    • https://yb.tencent.com/s/W32lLsziElSE

    • 网络传输时,二进制数据通常编码为十六进制字符串(可读性好,避免特殊字符问题)

    • 但异或运算需要在原始的字节层面进行,不能直接用字符串

      格式 本质 主要用途 例子
      比特 信息最小单位 位级操作、标志位、协议字段、按位运算 0b10110100
      字节 计算机基本单位 文件读写、网络通信、内存管理、加密解密、数据库储存 b'\xb4'
      十六进制 人类可读表示 调试显示、配置、数据交换 "b4"
  6. 软硬连接

    1. 基本理解

      1
      2
      3
      ls -li file # 查看inode编号
      ln file newfile # 创建一个硬链接 有一样的inode编号
      ln -s file newfile # 创建一个软连接 inode编号不同
    2. 主要区别

      1
      2
      3
      4
      5
      6
      7
      对于硬链接:
      hardlinkfile --> inode编号 --> 文件地址
      sourcefile --> inode编号 --> 文件地址

      对于软连接
      sourcefile --> inode编号 --> 文件地址
      softlinkfile --> sourcefile --> inode编号 --> 文件地址

      删除软连接源文件之后这个软连接就失效了,因为inode储存的是源文件地址

      硬链接则不会失效

    3. 对于两种链接在无论哪边改动文件另一半的文件内容也会改变

  7. windows的\在github中无法解析成图片需要换成/

    1
    find . -name "*.md" -exec sed -i 's/\(!\[[^]]*\]([^)]*\)\\/\1\//g' {} +
  8. iptables设置端口禁用

    一定要指定网卡 一定要指定协议 生效顺序是从上往下的 如果没有指定网卡 则本地(nginx)也接受不到

    1
    2
    iptables -A FORWARD -p tcp -i lo --dport 8000 -j ACCEPT
    iptables -A FORWARD -p tcp -i eth3 --dport 8000 -j DROP
  9. python中的with作用,主要是用来自动管理使用文件的资源管理

    1. 常规使用

      1
      2
      3
      4
      f = open("test.txt", "w")
      f.write("Hello World")
      # 如果这里中间的代码报错了,下面的 f.close() 永远不会执行
      f.close()
    2. 如果使用了with

      1
      2
      3
      with open("test.txt", "w") as f:
      f.write("Hello World")
      # 代码执行完这一块,文件会自动关闭,即使中途报错了也会关掉
    3. with 后面跟着的对象,必须是一个**“上下文管理器”**。它在底层逻辑上包含两个神奇的方法:

      1. __enter__:当你进入 with 语句块时,它先执行(比如:打开文件)。
      2. __exit__:当你离开 with 语句块时(无论是正常结束,还是因为代码报错崩溃了),它强制执行(比如:关闭文件、释放内存、断开数据库连接)。
    4. 也就是说相当于自动搞了个try-finally

    5. with解决的痛点

      正如你之前提到的,操作系统有内存回收机制,但有些资源是操作系统没法帮你“乱猜”什么时候该回收的。比如:

      • 文件占用:如果你在 Windows 下运行程序打开了一个文件没关,你可能无法在文件夹里删除这个文件,系统会提示“文件正在被另一个程序使用”。
      • 网络/数据库连接:每个连接都占用服务器的槽位。如果不释放,服务器很快就会满员,拒绝新连接。
      • 多线程锁 (Lock):在多线程编程中,如果不及时释放锁,整个程序就会死锁(卡死)。
  10. linux如何查看占用某个端口的程序是什么

    1
    2
    ss -tanp | grep ':80'
    ps -up 80

powershell小命令

  1. 密码的原来自己解压缩包的python应用想要使用python -m http.server需要手动配置防火墙策略

  2. 构造图片码的方法(/b是指使用二进制解析)

    1
    copy /b normal.jpg + shell.php malicious.jpg
  3. powershell查询hash

    1
    Get-FileHash filepath
  4. powershell检查数字签名 有效值

    1
    Get-AuthenticodeSignature Filepath

Windows系统日志自定义分类

使用Windows原生命令行

  1. 设置一个新的单独的windwos系统日志分类和新的日志源(全程添加的时候要使用管理员身份)

    1
    [System.Diagnostics.EventLog]::Exists("Testcategory") # 判断一个日志分类是否存在

    image-20251204142208359

    1
    New-EventLog -LogName "TestCategory" -Source "Test1" -ErrorAction Stop # 创建一个新的日志分类和日志源

    需要注意的是: 事件源 (Source) 的名称是全局唯一的。一旦你在注册表中注册了 "Test1" 这个事件源,系统会将其视为一个特定的程序或组件的唯一标识符。

    原有的日志情况
    image-20251204141945285
    新的日志添加后的情况

    image-20251204142534236

    插入一个新的日志情况,需要注意的是,这个地方 必须是现有的日志源!

    1
    Write-EventLog -LogName "TestCategory" -Source "Test1" -EventId 1001 -EntryType Information -Message "测试事件:分类创建验证"

    image-20251204142750137

  2. 删除日志分类

    1
    Remove-EventLog -LogName TestCategory -ErrorAction SilentlyContinue

    需要注意的是: 删除一个事件日志分类(LogName)时,与该分类相关联的所有事件源(Event Source)配置也会一并被删除。

python实现

  1. 需要注意的是python对于日志的操作全部是通过powershell实现的

  2. 使用python来实现自动新建事件源(需要管理员身份),自动插入日志(无需管理员身份),主要还是使用subprocess来调用powershell

  3. 查看系统日志分类存在情况

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 方法1:使用简单的存在性检查
    success, stdout, stderr = self._run_powershell_safe(
    f'[System.Diagnostics.EventLog]::Exists("{self.category_name}")'
    )

    if success and "True" in stdout:
    print(f"✅ 分类存在: {self.category_name}")
    self._setup_complete = True
    self._setup_event_source()
    else:
    print(f"❌ 分类不存在或检查失败: {self.category_name}")
    self._setup_complete = False
  4. 创建新的日志源

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    success, stdout, stderr = self._run_powershell_safe(
    f'[System.Diagnostics.EventLog]::SourceExists("{self.script_name}")'
    )

    if success and "True" in stdout:
    print(f"✅ 事件源已存在: {self.script_name}")
    return
    else:
    # 创建事件源
    print(f"🔄 创建事件源: {self.script_name}")
    success, stdout, stderr = self._run_powershell_safe(
    f'New-EventLog -LogName "{self.category_name}" -Source "{self.script_name}"'
    )
    if success:
    print(f"✅ 事件源创建成功")
    else:
    print(f"❌ 事件源创建失败")
    print(stdout,stderr)
    self._setup_complete = False
  5. 写入日志

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    try:
    # 写入事件日志
    success, stdout, stderr = self._run_powershell_safe(
    f'Write-EventLog -LogName "{self.category_name}" -Source "{self.script_name}" -EventId {event_id} -EntryType {level_map[level]} -Message "{message}"'
    )

    if success:
    print("✅ 事件写入成功")
    return True
    else:
    print(f"❌ 事件写入失败")
    return False

    except Exception as e:
    print(f"❌ 写入异常: {e}")
    return False
  6. 完整代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116

    import subprocess
    import sys


    class FixedEncodingLogger:
    """修复编码问题的事件日志记录器"""

    def __init__(self, category_name="AAAAHardwareProject", script_name="PriceMonitor"):
    # 使用英文分类名称避免编码问题
    self.category_name = category_name
    self.script_name = script_name
    self._setup_logging()

    def _run_powershell_safe(self, command):
    """安全运行PowerShell命令,处理编码问题"""
    try:
    # 使用正确的编码和错误处理
    result = subprocess.run(
    ["powershell", "-Command", command],
    capture_output=True,
    text=True,
    encoding='gbk', # Windows系统默认编码
    errors='ignore' # 忽略无法解码的字符
    )
    return result.returncode == 0, result.stdout, result.stderr
    except Exception as e:
    return False, "", str(e)

    def _setup_logging(self):
    """设置日志系统"""
    print(f"🔍 检查分类: {self.category_name}")

    # 方法1:使用简单的存在性检查
    success, stdout, stderr = self._run_powershell_safe(
    f'[System.Diagnostics.EventLog]::Exists("{self.category_name}")'
    )

    if success and "True" in stdout:
    print(f"✅ 分类存在: {self.category_name}")
    self._setup_complete = True
    self._setup_event_source()
    else:
    print(f"❌ 分类不存在或检查失败: {self.category_name}")
    self._setup_complete = False

    def _setup_event_source(self):
    """设置事件源"""
    try:
    # 检查事件源是否存在
    success, stdout, stderr = self._run_powershell_safe(
    f'[System.Diagnostics.EventLog]::SourceExists("{self.script_name}")'
    )

    if success and "True" in stdout:
    print(f"✅ 事件源已存在: {self.script_name}")
    return
    else:
    # 创建事件源
    print(f"🔄 创建事件源: {self.script_name}")
    success, stdout, stderr = self._run_powershell_safe(
    f'New-EventLog -LogName "{self.category_name}" -Source "{self.script_name}"'
    )
    if success:
    print(f"✅ 事件源创建成功")
    else:
    print(f"❌ 事件源创建失败")
    print(stdout,stderr)
    self._setup_complete = False

    except Exception as e:
    print(f"❌ 事件源设置失败: {e}")
    self._setup_complete = False

    def log(self, message, event_id=1000, level="info"):
    """记录日志"""
    level_map = {"info": "Information", "warning": "Warning", "error": "Error"}
    icons = {"info": "ℹ️", "warning": "⚠️", "error": "❌"}

    print(f"{icons[level]} [{level.upper()}] {message}")

    if not getattr(self, '_setup_complete', False):
    return False

    try:
    # 写入事件日志
    success, stdout, stderr = self._run_powershell_safe(
    f'Write-EventLog -LogName "{self.category_name}" -Source "{self.script_name}" -EventId {event_id} -EntryType {level_map[level]} -Message "{message}"'
    )

    if success:
    print("✅ 事件写入成功")
    return True
    else:
    print(f"❌ 事件写入失败")
    return False

    except Exception as e:
    print(f"❌ 写入异常: {e}")
    return False

    def info(self, message, event_id=1000):
    return self.log(message, event_id, "info")

    def warning(self, message, event_id=2000):
    return self.log(message, event_id, "warning")

    def error(self, message, event_id=3000):
    return self.log(message, event_id, "error")


    # 测试
    if __name__ == "__main__":
    logger = FixedEncodingLogger("AAAAHardwareProject", "Alert")
    logger.info("🚀 测试修复编码问题")
    logger.info("📊 这是一条测试消息")

git命令

git clone代理

1
git -c http.proxy=socks5://127.0.0.1:20170 clone

ssh key

生成密钥对

1
ssh-keygen -t ed25519 -C "注释"

然后判断要不要输入密码,直接回车就是无密码

需要注意的是这个命令生成的公私钥都是在本地的

上传公钥的命令

1
ssh-copy-id -i ~/.ssh/123.pub root@ip

或者直接传入公钥

1
cat ./id_rsa.pub >> ~/.ssh/authorized_keys

成功以后就能添加密钥

公钥登陆

1
ssh -i ~/.ssh/123.pub root@ip

或者使用config文件来配置快速登录,找到目录

1
~/.ssh/config

添加

1
2
3
4
Host
HostName ip
IdentityFile ~/.ssh/123
User root

awk速查

  1. 模式匹配

    awk默认是条件+动作 ;隔开语句

    1
    2
    awk 'NR==2 || NR==11 {print $2}' # 只有一个语句
    awk 'NR==2 ; NR==11 {print $2}' # 有两个语句, 没有动作默认print $0所以NR==2会整行打印
  2. -F参数的含义

    -F'[= ]'是awk的字段分隔符参数:**# 需要注意的是 awk默认使用空格来进行分割 **

    • -F:指定字段分隔符(Field separator)
    • '[= ]':这是一个正则表达式,表示按等号=或空格``进行分割
    1
    awk -F '[= ]' '{print $1}'
  3. //使用正则表达式来进行定位 提到函数substr()

    1
    ip a | awk '/^[0-9]+:/{ip=substr($2,1,length($2)-1);print ip}'

    substr()命令解析

    substr(字符串, 开始位置, 长度)

  4. -f读取awk命令文件

  5. -v定义变量传入

    1
    awk -v ip='0.0.0.0' '{print ip}' file
  6. awk都是按照file的按行读入,每一行都会执行一次

  7. $n是分割开来的第几个,从1开始,$0就是表示第一行

    如果是本来就分割好的就能直接使用$n

    1
    df -h | awk '{print $1 $3}'

    可以自己分割然后在使用$n

    1
    awk -F '[= ]' '{print $1}'
  8. 除了读取特定文件 awk还可以读取当前文件夹下的所有文件,但是必须是文件不能有文件夹 否则会报错

    就是一个*

    1
    awk '/20202020/{print $0}' *
  9. 默认按照空格切分,例如以下例子。(需要注意的是awk关注单双引号闭合的情况,只会关注空格)

    1
    220.181.108.153 - - [20/Dec/2012:14:11:03 +0800] "GET /clim/climintro.jsp HTTP/1.1" 200 3270 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"

    $0是一整行,$1是第一个-,$8是200

  10. 如果只在某个元素中进行匹配的方法

    1
    2
    awk '$7 ~ /\.jsp/{print $7}' *(当前目录下所有文件)/filename
    awk 'match($7,/\.jsp/,a){print $7}' *
  11. if 的使用必须包裹在{}但是可以不使用if就无需包裹

    1
    2
    3
    4
    5
    # 可以工作但不简洁
    username_file=`awk '{if(NR==1) print $1}' user.txt`

    # 更简洁的标准写法(推荐)
    username_file=`awk 'NR==1{print $1}' user.txt`
  12. 如果是使用正则匹配完希望打印匹配到的前后一定距离的东西(例如是在一个url中的最后一个文件,匹配后缀和前面的最后一个/) 使用函数match()

    1
    2
    3
    4
    5
    awk 'match($7,/\/.*\.jsp/,a){print a[0]}' # 贪婪匹配 会匹配前面全部的/,不精确 -> /a/c/listClassification.jsp

    awk 'match($7,/\/[^/]*\.jsp/,a){print(a[1])}}' #精确匹配 --> listClassification.jsp

    awk '{n=split($7, a, "/"); if(a[n] ~ /\.jsp$/) print a[n]}' file #精确 --> listClassification.jsp

    命令解析

    1
    2
    3
    4
    5
    awk '{
    n=split($7, a, "/");
    if(a[n] ~ /\.jsp$/)
    print a[n]
    }' file

    同10,这个地方可以不使用if

    1
    2
    3
    4
    awk '{
    n = split($7,a,"/");
    a[n] ~ /\.jsp$/ {print a[n]}
    }' file

    n=split($7, a, "/"); 是对字符串$7进行按照/的分组,分完的组在a中,同时n是返回元素的个数

    if(a[n] ~ /\.jsp$/) 和上面一样的逻辑,对某一个元素进行正则

  13. match()函数解析

    对于这样一个例子:

    1
    aaa/aaaa/vvv//sss/dsadw/vasdac/123.jsp?aaa=ssxx&xxx=asadw

    如果仅仅想要匹配出123.jsp但是不要其他内容,就要使用正则表达式

    1
    match($7,/\/([^/]*\.jsp)/,a);print a[0]

    正则表达式的解析: /\/([^/*].jsp)/

    (1) /.*/两侧的/使用来表示这个是一个正则表达式

    (2) [^/]匹配不是/的内容,^是取反的意思

    (3) 也就是说这个匹配/开始然后filename.jsp的内容

    (4) 这里面a[0]是匹配到的所有东西/filename.jsp, a[1]是括号内的东西filename.jsp

  14. 如果匹配多个(使用|) 并且要删去某些匹配到脏东西的(多个条件用&&)

    1
    2
    # 必须在linux环境下!或者是git bash
    awk '/limit|/select|from|contract/{if($0 !~ /selectresult/ && $0 ~ /\.jsp/)}' *
  15. 按照某个值进行排序然后输出(提到函数)

    1
    2
    3
    4
    5
    6
    7
    8
    awk '/select|limit|from|concat/ && !/selectResult/ {
    count[$1]++
    }
    END {
    for(ip in count) {
    print count[ip], ip
    }
    }' ex180223.log | sort -nr

    命令解析: sort

    -n按照数字排序

    -r降序排序

    -u 去重

    -k 指定排序字段

  16. 如何按照时间进行排序?

    1
    2
    3
    4
    5
    6
    # 如果实在同一天可以直接把时间转化为一个肉眼可见的数字
    awk '/banner_home.jpg/
    {n=split($4,time1,":");
    time2=time1[n]+time1[n-1]*100+time1[n-2]*10000;
    print(time2,$0)}
    ' ex180223.log | sort -n | head

    image-20251125212408434

    手动解析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    awk '/banner_home.jpg/{
    # 时间格式: 23/Feb/2018:09:04:58
    split($4, datetime, "[/:]");
    day = datetime[1];
    month = datetime[2];
    year = datetime[3];
    hour = datetime[4];
    minute = datetime[5];
    second = datetime[6];

    # 月份名称转数字
    month_num = (month=="Jan") ? 1 : (month=="Feb") ? 2 :
    (month=="Mar") ? 3 : (month=="Apr") ? 4 :
    (month=="May") ? 5 : (month=="Jun") ? 6 :
    (month=="Jul") ? 7 : (month=="Aug") ? 8 :
    (month=="Sep") ? 9 : (month=="Oct") ? 10 :
    (month=="Nov") ? 11 : 12;

    # 创建可排序的时间戳
    timestamp = sprintf("%04d%02d%02d%02d%02d%02d", year, month_num, day, hour, minute, second);
    print timestamp, $0;
    }' ex180223.log | head
  17. 其实还有新的办法使用函数 使用函数gsub()

    这是一个全局替换函数,可以吧匹配处理啊的东西全部替换,和 **sub()**的区别就是sub()只匹配第一个

    1
    aaa = gsub(正则表达式,需要替换后的内容,需要替换的部分) # 会在原来的数据上直接修改,aaa是记录替换多少个值
    1
    awk '/banner_home.jpg/{aa=gsub(":","",$4);print $4}' filename | head

    image-20251125213958485

  18. BEGIN模块

    这个模块只在开始的时候执行一次,可用性十分广泛,在处理任何输入数据之前执行一次性设置或初始化操作。

    1. 各种使用参数

      变量 作用 示例
      FS 设置输入字段分隔符 BEGIN{FS=","}:告诉 awk 以逗号分隔输入行。
      OFS 设置输出字段分隔符 BEGIN{OFS="\t"}:设置输出字段之间使用制表符(Tab)。
      RS 设置输入记录分隔符 BEGIN{RS="."}:如您第二个例子所示,设置以点号分隔记录。
      ORS 设置输出记录分隔符 BEGIN{ORS="---"}:设置每行输出结束后追加 --- 而不是默认的换行符。

      对上述表格的解析: 字段是每一行的每一列, 记录默认是按照’\n’来进行分割,感官上就是一行一个记录

      1
      awk 'BEGIN{RS="."};{print $0}' ifconfig12.txt

      image-20251217164757038

      也可以按照模块来表达格式

      1
      2
      3
      4
      awk '
      BEGIN{RS='.';}
      {print $0;}
      ' ifconfig12.txt
    2. 初始化变量

      初始化自定义变量,用于在后续的数据处理块中进行计数、累加或状态跟踪。

      • 示例: BEGIN{count=0; sum=0}
        • 在开始处理文件之前,将 countsum 初始化为 0。
    3. 打印头部或报告标题

      在处理数据之前,打印报告的标题或列头。

      • 示例: BEGIN{print "--- 报告标题 ---"; print "编号\t姓名\t分数"}
        • 在读取文件数据前,先输出一个清晰的标题和列名。
  19. 格式化打印

    1. print

      1
      awk '{print "ip:"$2, "netmask:"$4, "broadcoast:"$6}' ifconfig13.txt

      image-20251217170830467

    2. printf

      1
      2
      awk '{printf "%-6s%-20s%-10s%-20s%-10s%-20s\n",$1,$2,$3,$4,$5,$6}' ifconfig13
      .txt
      格式说明符 含义 字段应用
      %-5s 左对齐 (-),占用 5 个字符的宽度 (5),以字符串 (s) 形式打印。 打印 $1 (例如: inetether)
      %-20s 左对齐,占用 20 个字符的宽度。 打印 $2 (例如: 172.20.0.102:42:d5:6d:8c:31)
      %-10s 左对齐,占用 10 个字符的宽度。 打印 $3 (例如: netmasktxqueuelen)
      %-20s 左对齐,占用 20 个字符的宽度。 打印 $4 (例如: 255.255.0.00)
      \n 换行符,在格式化输出后另起一行。

      image-20251217170942594

grep速查

  1. 在都是文本文件的文件夹中查找'aaa'

    1
    grep -r 'aaa' fold
    1
    2
    3
    4
    fold
    | - - 1.txt
    | - - 2.txt
    | - - 3.txt
  2. 如果希望加上正则表达式可以使用-E,如果要搜索文件夹使用-r
    如果实在文件夹中使用正则表达式使用-rE

CTF观察

  1. string居然可以查pcap

    1
    string 1.pcap | grep flag

GPG公钥过期解决方法

  1. 类似报错

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Err:9 https://apt.v2raya.org v2raya InRelease                                                                             
    The following signatures were invalid: EXPKEYSIG 354E516D494EF95F mzz2017 (apt) <mzz@tuta.io>
    Fetched 11.1 MB in 3s (4,158 kB/s)
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    280 packages can be upgraded. Run 'apt list --upgradable' to see them.
    W: https://download.docker.com/linux/ubuntu/dists/jammy/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.
    W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: https://apt.v2raya.org v2raya InRelease: The following signatures were invalid: EXPKEYSIG 354E516D494EF95F mzz2017 (apt) <mzz@tuta.io>
    W: Failed to fetch https://apt.v2raya.org/dists/v2raya/InRelease The following signatures were invalid: EXPKEYSIG 354E516D494EF95F mzz2017 (apt) <mzz@tuta.io>
    W: Some index files failed to download. They have been ignored, or old ones used instead.
    1. 区分是否是小众软件,如果是的话(像这个v2raya,就可以直接去官网上寻找公钥地址)

      1
      2
      rm /etc/apt/keyrings/v2raya.asc
      wget -qO - https://apt.v2raya.org/key/public-key.asc | sudo tee /etc/apt/keyrings/v2raya.asc
    2. 禁用更新该原件源

      1
      2
      # 删除 /etc/apt/sources.list.d 中的文件
      sudo rm -f /etc/apt/sources.list.d/v2raya.list

python处理网络数据包

  1. 使用scapy库进行处理

  2. from scapy.all import *
    
    packets = rdpcap('./bb84_attack.pcapng')
    packets[0] # 第一个数据包
    packets[1] # 第二个数据包
    
    每个数据包中层级
    packets[0][TCP]
    packets[0][Raw]  # 获取Raw层对象
    packets[0][Raw].load     # 获取原始字节数据:b'seed:123456789'
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    3. 提取数据

    ```python
    # 步骤1:提取种子
    raw_bytes = packets[0][Raw].load # b'seed:123456789'
    decoded_text = raw_bytes.decode() # 'seed:123456789'
    seed_text = decoded_text.split(":")[1] # '123456789'
    seed = int(seed_text) # 123456789
  3. 判断层级 需要注意的是这样只能获取原始载荷 无法获取多个数据包组成的数据流(例如http)

    1
    2
    3
    if i.haslayer(TCP): # 判断是否有TCP层
    if i.haslayer(Raw): # 判断是否有Raw层
    print(i.getlayer(Raw).load) #其实这个和print(i[Raw].load)是一个效果
  4. 追踪流

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    sessions = packets.sessions()
    for session, session_packets in sessions.items():
    print(f"\n会话: {session}")

    for pkt in session_packets:
    if pkt.haslayer(TCP) and pkt.haslayer(Raw):
    raw_data = pkt[Raw].load

    # 判断是否为HTTP数据
    if b'HTTP' in raw_data:
    print(f"HTTP响应: {raw_data[:200]}...")
    elif b'GET' in raw_data or b'POST' in raw_data:
    print(f"HTTP请求: {raw_data[:200]}...")
    else:
    print(f"TCP数据: {raw_data[:100]}...")

字符集规则

  1. ANSI是Ascii的扩充码

  2. ascii使用的是一个字节的低7位,本来是考虑最高一位用来拓展,但是不够,衍生出了ANSI,总共有65536个2^16

  3. 每个国家按照这个ANSI标准来创造自己的编码规则例如gbk---

  4. 但是还是发现这个ANSI不好用,每个国家都有自己的编码,于是出现了全球统一编码unicode,使用2^32但是发现他很浪费

  5. unicode在网络传输中很难用,非常的浪费,很多是空值,而且还很容易和其他的二进制流(图片视频)来出现混淆

  6. 但是在内存层面使用unicode是合适的,因为长度固定,容易寻址,并且操作系统具有内存回收操作(满了自动删或者重启全都删)不怕浪费

  7. 可变长度的unicode就是utf,存在多个版本utf-8,utf-16…..

  8. utf-8最小长度的字符是8bit-1Byte, utf-16最小长度的字符是16bit/2B

  9. 所有文字的传输和存储都必须使用utf-8/gbk转换成字节

    1
    2
    aaa = "我爱你"
    aaa.encode(编码集)

utf-8的编码逻辑

  1. 字符长度可变,最短就是8bit/1B

  2. ascii中的就使用1B

  3. 欧洲那些就是2B

  4. 中文(gbk)3B

  5. 天坑

    1
    2
    3
    4
    5
    ## 天坑
    print(b"c" == b"\x63") ==> True # 这就是因为11.1.1中直接显示的就是ascii

    bbb = b"\xaa\xca\xaa" # 正常情况下,\x后面跟着两个十六进制表示一个B 这里面的字节分别是\xaa \xca \xaa这3个
    ccc = b"\xaac\xcc\xbbb" #在这种情况下就是utf和ascii混用的情况,字节分别是\xaa c \xcc \xbb b
  6. 求二进制串长度

    1
    print(ccc.__len__())

控制字符区别LFCRLF

  1. 属于是不同阵营(linux/windows)的控制字符(如何进行换行表示?)

  2. windwos认为换行必须先把光标放到最前面, linux认为直接换行就好了

  3. 什么是 LF 和 CRLF?

    这两个词起源于老式电传打字机时代,代表了两个不同的机械动作:

    术语 全称 转义符 动作含义
    LF Line Feed \n 换行:纸张向上卷一行,但打字头还在原来的水平位置。
    CR Carriage Return \r 回车:打字头迅速回到当前行的起始(最左边)位置。
    CRLF CR + LF \r\n 回车换行:打字头回最左边,且纸张向上卷一行。
  4. 主要区别是占用空间不一样, LF一个B,CRLF2个B

  5. git提交的时候统一使用LF,会自动转换

  6. 高级语言读入内存时统一认为是\n

nginx 配置

  1. 颁发双向tls证书

    1
    2
    3
    4
    5
    6
    7
    8
    9
    openssl req -x509 -newkey rsa:4096 -nodes -keyout ./ca.key -out ./ca.crt -subj "/CN=domainname"  -days 3650


    openssl req -newkey rsa:2048 -nodes -keyout ./server.key -out ./server.csr -subj "/CN=domainname"
    openssl x509 -req -in server.csr -out ./server.crt -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -days 3650


    openssl req -newkey rsa:2048 -nodes -keyout ./client.key -out ./client.csr -subj "/CN=domainname"
    openssl x509 -req -in client.csr -out ./client.crt -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -days 3650

    但是python中需要使用的是pem

    1
    cat client.crt client.key > client_bundle.pem
    1
    2
    3
    4
    5
    client = requests.Session()
    client.verify = './ssl/ca.crt' # CA证书
    client.cert = './ssl/client_bundle.pem' # 客户端证书

    response = client.post()
  2. nginx配置双向tls认证

    实际上这个双向认证的证书和tls验证的证书是分开的,也就是说可以使用一个脚本去每90天更新一次免费的https_tls证书,但是一直使用同一份双向tls认证证书

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    ....
    http{
    ....
    ##
    # SSL Settings
    ##

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    server {
    listen 443 ssl;

    server_name _;

    # Nginx 服务器自身的证书和私钥
    ssl_certificate /etc/nginx/ssl/certs/server.crt;
    ssl_certificate_key /etc/nginx/ssl/private/server.key;

    # 客户端证书颁发机构 (CA) 的根证书
    ssl_client_certificate /etc/nginx/ssl/certs/ca.crt;

    # mTLS 核心配置
    ssl_verify_client on;
    ssl_verify_depth 1;

    # 修改location块以正确处理请求
    location /api/abc {
    # 使用proxy_pass直接转发,避免rewrite带来的问题
    proxy_pass http://127.0.0.1:8000/;

    # 保留所有HTTP方法和头部信息
    proxy_method $request_method;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    # WebSocket支持
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    }
    }
    }
其他文章
目录导航 置顶
  1. 1. 碎碎念
  2. 2. powershell小命令
  3. 3. Windows系统日志自定义分类
    1. 3.1. 使用Windows原生命令行
    2. 3.2. python实现
  4. 4. git命令
  5. 5. ssh key
  6. 6. awk速查
  7. 7. grep速查
  8. 8. CTF观察
  9. 9. GPG公钥过期解决方法
  10. 10. python处理网络数据包
  11. 11. 字符集规则
    1. 11.1. utf-8的编码逻辑
    2. 11.2. 控制字符区别LF和CRLF
  12. 12. nginx 配置
请输入关键词进行搜索