-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
171 lines (145 loc) · 4.5 KB
/
main.go
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package main
import (
"bytes"
"encoding/binary"
"flag"
"fmt"
"math/rand"
"os"
"path/filepath"
"time"
"golang.org/x/sys/windows"
)
const peHeaderOffset = 0x3C
const fileHeaderOffset = 0x6
func main() {
// 定义命令行参数
filename := flag.String("f", "", "需要更新时间的文件或目录")
timeStr := flag.String("t", "", "要设置的目标时间(格式:'2006-01-02 15:04:05')")
compileTime := flag.Bool("pe", false, "是否更新编译时间")
randomMinutes := flag.Int("r", 0, "随机时间范围(分钟)")
flag.Parse()
if *filename == "" || *timeStr == "" {
fmt.Println("请使用 -f 和 -t 标志提供文件名或目录名以及目标时间")
os.Exit(1)
}
// 解析目标时间
targetTime, err := time.Parse("2006-01-02 15:04:05", *timeStr)
if err != nil {
fmt.Println("解析时间时出错:", err)
os.Exit(1)
}
info, err := os.Stat(*filename)
if err != nil {
fmt.Println("获取文件信息时出错:", err)
os.Exit(1)
}
// 先更新目录本身的时间
if info.IsDir() {
if err := updateFileTimes(*filename, targetTime, *compileTime, *randomMinutes); err != nil {
fmt.Printf("更新目录 %s 时间时出错:%v\n", *filename, err)
os.Exit(1)
} else {
fmt.Printf("成功更新目录 %s 的时间\n", *filename)
}
}
// 遍历目录中的文件和子目录
err = filepath.Walk(*filename, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if err := updateFileTimes(path, targetTime, *compileTime, *randomMinutes); err != nil {
fmt.Printf("更新 %s 时间时出错:%v\n", path, err)
} else {
fmt.Printf("成功更新 %s 的时间\n", path)
}
return nil
})
if err != nil {
fmt.Println("遍历路径时出错:", err)
os.Exit(1)
}
}
// 更新文件或目录的时间
func updateFileTimes(filename string, targetTime time.Time, modifyCompileTime bool, randomMinutes int) error {
if randomMinutes > 0 {
// 添加随机时间
offset := time.Duration(rand.Intn(randomMinutes*60)) * time.Second
targetTime = targetTime.Add(offset)
}
// 随机生成访问时间、修改时间、创建时间之间的差距
accessOffset := time.Duration(rand.Intn(60)) * time.Second
modifyOffset := accessOffset + time.Duration(rand.Intn(60))*time.Second
createOffset := modifyOffset + time.Duration(rand.Intn(60))*time.Second
// 确保访问时间 <= 修改时间 <= 创建时间
accessTime := targetTime.Add(-accessOffset)
modifyTime := targetTime.Add(-modifyOffset)
createTime := targetTime.Add(-createOffset)
if modifyCompileTime {
if err := modifyPEFileCompileTime(filename, createTime); err != nil {
return fmt.Errorf("修改 PE 文件编译时间时出错:%w", err)
}
}
// 更新最后访问时间、修改时间和创建时间
if err := setFileTimes(filename, createTime, accessTime, modifyTime); err != nil {
return err
}
return nil
}
// 修改 PE 文件的编译时间
func modifyPEFileCompileTime(filename string, targetTime time.Time) error {
file, err := os.OpenFile(filename, os.O_RDWR, 0)
if err != nil {
return err
}
defer file.Close()
// 读取 PE 头偏移量
var offset int32
if _, err := file.Seek(peHeaderOffset, 0); err != nil {
return err
}
if err := binary.Read(file, binary.LittleEndian, &offset); err != nil {
return err
}
// 读取时间戳
timeDateStampOffset := int64(offset) + fileHeaderOffset
if _, err := file.Seek(timeDateStampOffset, 0); err != nil {
return err
}
timestamp := uint32(targetTime.Unix())
buf := new(bytes.Buffer)
if err := binary.Write(buf, binary.LittleEndian, timestamp); err != nil {
return err
}
if _, err := file.Write(buf.Bytes()); err != nil {
return err
}
return nil
}
// 设置文件或目录的时间
func setFileTimes(filename string, creationTime, lastAccessTime, lastWriteTime time.Time) error {
path, err := windows.UTF16PtrFromString(filename)
if err != nil {
return err
}
hFile, err := windows.CreateFile(
path,
windows.FILE_WRITE_ATTRIBUTES,
windows.FILE_SHARE_WRITE|windows.FILE_SHARE_READ|windows.FILE_SHARE_DELETE,
nil,
windows.OPEN_EXISTING,
windows.FILE_FLAG_BACKUP_SEMANTICS,
0,
)
if err != nil {
return err
}
defer windows.CloseHandle(hFile)
creationTimeFt := windows.NsecToFiletime(creationTime.UnixNano())
lastAccessTimeFt := windows.NsecToFiletime(lastAccessTime.UnixNano())
lastWriteTimeFt := windows.NsecToFiletime(lastWriteTime.UnixNano())
if err := windows.SetFileTime(hFile, &creationTimeFt, &lastAccessTimeFt, &lastWriteTimeFt); err != nil {
return err
}
return nil
}