当前位置: 首页 > news >正文

时移世易,篡改天机:吾以 Go 语令 Windows 文件“返老还童“记

文曰:

时维乙巳年秋,有程序员夜不能寐,忽见文件夹之创建时间,竟露马脚,惶惶如临大敌。遂执 Go 语为剑,调 Windows 之秘术,篡改天机,令旧物焕新,恍若昨日初生。此事奇诡,不可不记。

一、缘起:文件夹"露馅"了!

话说某日,某君正在调试一"压测提单工具"(此乃江湖秘器,专治系统慢如龟),忽觉不妥——

文件夹创建时间竟为今日!

此乃大忌!

若被 QA 看见,必问:“汝昨日方写此工具?何以昨日已用之?”

若被老板察觉,恐遭诘问:“此工具尚未完成,何以三日前已有日志?”

呜呼!时间即证据,证据即破绽。

欲掩其迹,非改其时不可!

然,Linux 之下,touch -t 一令可解;

Windows 之境,却无此等神技。

无奈,只得亲自动手,以代码为笔,重写天命。

二、探秘:Windows 之"三时"真言

Windows 文件,藏有三时,谓之:

CreationTime:诞生之刻,如婴儿初啼;
LastAccessTime:最近一瞥,似故人回眸;
LastWriteTime:最后修改,若匠人收工。
此三时,皆存于 Win32FileAttributeData 之中,非寻常 os.Stat 可窥全貌。

若欲篡之,须得:

打开文件之"魂"(句柄);
转时间于 FILETIME(此乃 Windows 独门格式,自 1601 年起算,单位百纳秒,玄之又玄);
调 SetFileTime 之秘术,一举改写三时。
此术凶险,稍有不慎,轻则无效,重则系统怒而拒之。

然吾有 Go 语言为盾,syscall 为矛,何惧之有?

三、铸剑:Go 语炼成"时之刃"

于是,吾挥毫泼墨,写下三式神功:

第一式:遍历万文件(GetAllFiles)

// 递归入幽谷,遍历子子孙孙,凡文件者,皆录其名。
func GetAllFiles(dirPath string) ([]string, error) { ... }

此式如扫地僧,默默无闻,却为后文铺路。

第二式:窥天机(PrintFileTime)

// 仰观文件之三时,如观星象,知其生辰八字。
func PrintFileTime(filePath string) { ... }

初看文件,三时毕现,心中有数,方敢下手。

第三式:篡天命(SetFileTime)

// 执时间之笔,重写 Creation、Access、Write 三命。
func SetFileTime(filePath string, ctime, atime, mtime time.Time) error { ... }

此乃核心!调 CreateFile 得其魂,转 time.Time 为 FILETIME,终以 SetFileTime 一锤定音。

注:此术仅通于 Windows。若于 Linux 行之,恐如对牛弹琴,徒增笑耳。

四、施法:令"压测工具"返老还童

主函数中,吾设三处要地:

主目录:D:\tools\压测提单工具 → 设为 2022-02-28 10:27:16
日志目录 runlog → 设为 2022-02-28 11:27:16
通信日志 socketlog → 设为 2022-02-28 11:27:13
先观其旧时,再施法篡改,复观其新时——

果然!三时皆如吾所愿,分毫不差!

文件夹静立如初,却已"穿越"三年,恍若昨日方建。

QA 再查,只见"2022年旧物",必叹曰:“此乃古董级工具,稳定可靠!”

老板见之,亦抚掌笑曰:“此君早有准备,深谋远虑!”

五、警世恒言

然,吾虽得意,亦不敢忘形。

篡改时间,乃双刃之剑:

若为测试、演示、归档所用,善莫大焉;
若为欺瞒、伪造、逃责所图,则天理难容!
且此术仅限 Windows,Linux 诸君莫急,自有 touch、debugfs 等妙法,另文再叙。

六、结语:代码即道,慎用神通

太史公曰:

时者,天地之过客;文件者,代码之遗迹。

能窥其时,改其命,非为逆天,实为顺事。

然顺事者,亦当守其道——技术无善恶,人心定乾坤。

今录此 Go 语真经,非教人作伪,实授人以"可控之权"。

愿诸君执此剑,不为诡道,而为清道。

附:完整代码

package mainimport ("fmt""io/ioutil""os""syscall""time"
)// GetAllFiles 递归获取指定目录下所有文件的完整路径(不包括子目录本身)
func GetAllFiles(dirPath string) ([]string, error) {var files []string// 读取目录内容dirEntries, err := ioutil.ReadDir(dirPath)if err != nil {return nil, fmt.Errorf("无法读取目录 %q: %w", dirPath, err)}for _, entry := range dirEntries {fullPath := dirPath + "/" + entry.Name()if entry.IsDir() {// 递归处理子目录subFiles, err := GetAllFiles(fullPath)if err != nil {return nil, fmt.Errorf("递归读取子目录 %q 失败: %w", fullPath, err)}files = append(files, subFiles...)} else {// 是普通文件,加入结果列表files = append(files, fullPath)}}return files, nil
}// SetFileTime 修改文件的创建时间(CreationTime)、最后访问时间(LastAccessTime)和最后修改时间(LastWriteTime)
// 注意:此函数仅适用于 Windows 系统
func SetFileTime(filePath string, creationTime, lastAccessTime, lastWriteTime time.Time) error {// 获取文件的绝对路径absPath, err := syscall.FullPath(filePath)if err != nil {return fmt.Errorf("无法获取文件绝对路径 %q: %w", filePath, err)}// 转换为 UTF-16 指针(Windows API 要求)pathPtr, err := syscall.UTF16PtrFromString(absPath)if err != nil {return fmt.Errorf("路径转 UTF-16 失败: %w", err)}// 打开文件句柄(仅用于修改属性)handle, err := syscall.CreateFile(pathPtr,syscall.FILE_WRITE_ATTRIBUTES,syscall.FILE_SHARE_WRITE,nil,syscall.OPEN_EXISTING,syscall.FILE_FLAG_BACKUP_SEMANTICS,0,)if err != nil {return fmt.Errorf("无法打开文件 %q: %w", absPath, err)}defer syscall.Close(handle)// 将 time.Time 转换为 Windows FILETIME 格式toFiletime := func(t time.Time) syscall.Filetime {return syscall.NsecToFiletime(t.UnixNano())}ct := toFiletime(creationTime)at := toFiletime(lastAccessTime)mt := toFiletime(lastWriteTime)// 调用 Windows API 设置时间戳if err := syscall.SetFileTime(handle, &ct, &at, &mt); err != nil {return fmt.Errorf("设置文件时间失败 %q: %w", absPath, err)}return nil
}// PrintFileTime 打印 Windows 系统下文件的创建时间、最后访问时间和最后修改时间
func PrintFileTime(filePath string) {fileInfo, err := os.Stat(filePath)if err != nil {fmt.Printf("无法获取文件信息 %q: %v\n", filePath, err)return}// 类型断言为 Windows 特有的文件属性结构winAttr, ok := fileInfo.Sys().(*syscall.Win32FileAttributeData)if !ok {fmt.Printf("不支持的系统或文件类型: %q\n", filePath)return}// FILETIME 是从 1601-01-01 起的 100 纳秒单位,转换为 Unix 时间creationTime := time.Unix(0, winAttr.CreationTime.Nanoseconds())lastAccessTime := time.Unix(0, winAttr.LastAccessTime.Nanoseconds())lastWriteTime := time.Unix(0, winAttr.LastWriteTime.Nanoseconds())fmt.Printf("文件路径: %s\n", filePath)fmt.Printf("  创建时间: %v\n", creationTime)fmt.Printf("  最后访问时间: %v\n", lastAccessTime)fmt.Printf("  最后修改时间: %v\n", lastWriteTime)
}// parseLocalTime 安全地将字符串解析为本地时区的 time.Time
func parseLocalTime(layout, value string) (time.Time, error) {return time.ParseInLocation(layout, value, time.Local)
}func main() {// 示例:修改目录及其子目录中特定文件夹的时间戳// 1. 修改主目录时间dirPath := `D:\tools\压测提单工具`PrintFileTime(dirPath)t1, err := parseLocalTime("2006-01-02 15:04:05", "2022-02-28 10:27:16")if err != nil {fmt.Printf("时间解析失败: %v\n", err)return}if err := SetFileTime(dirPath, t1, t1, t1); err != nil {fmt.Printf("设置目录时间失败: %v\n", err)return}PrintFileTime(dirPath)// 2. 修改 runlog 子目录时间runlogPath := `D:\tools\压测提单工具\runlog`PrintFileTime(runlogPath)t2, err := parseLocalTime("2006-01-02 15:04:05", "2022-02-28 11:27:16")if err != nil {fmt.Printf("时间解析失败: %v\n", err)return}if err := SetFileTime(runlogPath, t2, t2, t2); err != nil {fmt.Printf("设置 runlog 目录时间失败: %v\n", err)return}PrintFileTime(runlogPath)// 3. 修改 socketlog 子目录时间socketlogPath := `D:\tools\压测提单工具\socketlog`PrintFileTime(socketlogPath)t3, err := parseLocalTime("2006-01-02 15:04:05", "2022-02-28 11:27:13")if err != nil {fmt.Printf("时间解析失败: %v\n", err)return}if err := SetFileTime(socketlogPath, t3, t3, t3); err != nil {fmt.Printf("设置 socketlog 目录时间失败: %v\n", err)return}PrintFileTime(socketlogPath)
}

运行前,请三思:汝,真需"返老还童"乎?

乙巳年霜月朔日,某程序员焚香沐浴,记于键盘之侧。

往期部分文章列表

  • golang圆阵列图记:天灵灵地灵灵图标排圆形
  • golang解图记
  • 从 4.8 秒到 0.25 秒:我是如何把 Go 正则匹配提速 19 倍的?
  • 用 Go 手搓一个内网 DNS 服务器:从此告别 IP 地址,用域名畅游家庭网络!
  • 我用Go写了个华容道游戏,曹操终于不用再求关羽了!
  • 用 Go 接口把 Excel 变成数据库:一个疯狂但可行的想法
  • 穿墙术大揭秘:用 Go 手搓一个"内网穿透"神器!
  • 布隆过滤器(go):一个可能犯错但从不撒谎的内存大师
  • 自由通讯的魔法:Go从零实现UDP/P2P 聊天工具
  • Go语言实现的简易远程传屏工具:让你的屏幕「飞」起来
  • 当你的程序学会了"诈尸":Go 实现 Windows 进程守护术
  • 验证码识别API:告别收费接口,迎接免费午餐
  • 用 Go 给 Windows 装个"顺风耳":两分钟写个录音小工具
  • 无奈!我用go写了个MySQL服务
  • 使用 Go + govcl 实现 Windows 资源管理器快捷方式管理器
  • 用 Go 手搓一个 NTP 服务:从"时间混乱"到"精准同步"的奇幻之旅
  • 用 Go 手搓一个 Java 构建工具:当 IDE 不在身边时的自救指南
  • 深入理解 Windows 全局键盘钩子(Hook):拦截 Win 键的 Go 实现
  • 用 Go 语言实现《周易》大衍筮法起卦程序
  • Go 语言400行代码实现 INI 配置文件解析器:支持注释、转义与类型推断
  • 高性能 Go 语言带 TTL 的内存缓存实现:精确过期、自动刷新、并发安全
  • Golang + OpenSSL 实现 TLS 安全通信:从私有 CA 到动态证书加载
http://www.dtcms.com/a/558351.html

相关文章:

  • 做网站的软件是什么网站开发需要逻辑吗
  • 海阳做网站网站建设需要工作计划
  • 通信工程网站建设primitive technology wordpress
  • 响应式网站的费用佛山网站建设邓先生
  • 做单本小说网站怎么样企业网站的建设报价
  • 计算机操作系统:设备驱动程序
  • 长春网站排名提升app软件开发专业公司
  • 网站做关键词首页建设银行网站查余额查询
  • 钢琴演变史
  • 企业建设门户网站的目的国外免费建站网站搭建
  • 【开题答辩全过程】以 二手手机收售系统为例,包含答辩的问题和答案
  • google搜索优化优化seo深圳
  • 为公司建立网站怎么做淘宝网站赚钱
  • springboot默认线程池配置
  • 郑州h5网站建设为新公司取名免费
  • 河南襄县做网站的公司店面设计包括哪些内容
  • 基础微网站开发价位青岛市住房和城乡建设局网站
  • 珠海模板开发建站把自己做的动画传到哪个网站上
  • 京东商城 网站建设山东济铁工程建设集团有限公司网站
  • 文本网站代码空两格怎么做网站上传权限
  • 建设派网站建立自己网站的好处
  • C++笔记(面向对象)静态联编和动态联编
  • 【递归、回溯、搜索】专题六:记忆化搜索
  • 网站页面描述怎么写咸阳鑫承网站建设
  • 如何在百度举报网站桂林市临桂区
  • 一个可以做行程的网站网站虚拟主机1g
  • 网站标题和关键词一样网页版微信登录不了怎么解决
  • 2015年做啥网站能致富wordpress 导出export.php
  • 开网站做商城怎么样北京ui网页设计培训
  • WindoWs 系统管理批处理脚本