Add write-ups from hsfzxjy
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
# 从零开始的 HTTP 链接
|
||||||
|
|
||||||
|
此处提供一个使用 socket 编程完成 TCP 桥接的解法。
|
||||||
|
|
||||||
|
运行 `python3 bridge.py :8080 202.38.93.111:0`,浏览器访问 `localhost:8080` 即可。
|
||||||
|
|
||||||
|
```python
|
||||||
|
"""
|
||||||
|
python3 bridge.py :8080 202.38.93.111:0
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import select
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
def address(addr):
|
||||||
|
host, port = addr.split(":", 1)
|
||||||
|
return host, int(port)
|
||||||
|
|
||||||
|
|
||||||
|
def main(bind, connect, log_level):
|
||||||
|
logging.basicConfig(level=log_level, format="%(asctime)s:%(levelname)s:%(message)s")
|
||||||
|
serv = socket.create_server(bind)
|
||||||
|
rtol = {}
|
||||||
|
ltor = {}
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
readers, _, _ = select.select(
|
||||||
|
tuple(rtol.values()) + tuple(ltor.values()) + (serv,), (), ()
|
||||||
|
)
|
||||||
|
for reader in readers:
|
||||||
|
if reader is serv:
|
||||||
|
local_client, addr = reader.accept()
|
||||||
|
remote_client = socket.create_connection(connect)
|
||||||
|
ltor[local_client.fileno()] = remote_client
|
||||||
|
rtol[remote_client.fileno()] = local_client
|
||||||
|
elif reader.fileno() in ltor:
|
||||||
|
data = reader.recv(2 ** 12)
|
||||||
|
if data:
|
||||||
|
logging.info("L -> R: %r", data)
|
||||||
|
ltor[reader.fileno()].sendall(data)
|
||||||
|
else:
|
||||||
|
remote = ltor[reader.fileno()]
|
||||||
|
del ltor[reader.fileno()], rtol[remote.fileno()]
|
||||||
|
remote.close()
|
||||||
|
reader.close()
|
||||||
|
else:
|
||||||
|
data = reader.recv(2 ** 12)
|
||||||
|
if data:
|
||||||
|
logging.info("R -> L: %r", data)
|
||||||
|
rtol[reader.fileno()].sendall(data)
|
||||||
|
else:
|
||||||
|
local = rtol[reader.fileno()]
|
||||||
|
del rtol[reader.fileno()], ltor[local.fileno()]
|
||||||
|
reader.close()
|
||||||
|
local.close()
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
finally:
|
||||||
|
for sock in tuple(rtol.values()) + tuple(ltor.values()) + (serv,):
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
bind = address(sys.argv[1])
|
||||||
|
connect = address(sys.argv[2])
|
||||||
|
main(bind, connect, "INFO")
|
||||||
|
```
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# 永不溢出的计算器
|
||||||
|
|
||||||
|
思路基本同官方。鉴于本题没有提供 TCP 接口,这里给出一个在浏览器里搜索不同二次剩余的脚本。
|
||||||
|
|
||||||
|
将以下代码贴在浏览器控制台运行即可。如果脚本停了,最后输出的两个数即是所要的 x 和 y。
|
||||||
|
|
||||||
|
此处的原理是利用页面暴露在全局的 WebSocket 对象 `socket` 直接收发数据。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
(() => {
|
||||||
|
function rand(a, b) {
|
||||||
|
return Math.round(Math.random() * (b - a) + a)
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectLargeNum() {
|
||||||
|
const len = Math.round(rand(154, 307))
|
||||||
|
let ret = ''
|
||||||
|
for (let i = 0; i < len; i++) ret += rand(0, 9)
|
||||||
|
return ret.replace(/^0+/, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
class Result {
|
||||||
|
constructor() {
|
||||||
|
this.reset()
|
||||||
|
}
|
||||||
|
reset() {
|
||||||
|
this.promise = new Promise(resolve => this.resolve = resolve)
|
||||||
|
this.text = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = new Result
|
||||||
|
socket.addEventListener('message', (msg) => {
|
||||||
|
result.text += msg.data
|
||||||
|
if (! /\r\n>\s+$/.test(result.text)) return
|
||||||
|
result.resolve(/(\d+)\r\n>\s+$/.exec(result.text)[1])
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
async function loop() {
|
||||||
|
let num = selectLargeNum()
|
||||||
|
result.reset()
|
||||||
|
socket.send(num + ' ^ 2\n')
|
||||||
|
let res = await result.promise
|
||||||
|
result.reset()
|
||||||
|
socket.send('sqrt(' + res + ')\n')
|
||||||
|
res = await result.promise
|
||||||
|
console.log(res)
|
||||||
|
console.log(num)
|
||||||
|
if (num !== res) return
|
||||||
|
setTimeout(loop, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
loop()
|
||||||
|
})()
|
||||||
|
```
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# 超基础的数理模拟器
|
||||||
|
|
||||||
|
由于学过符号计算软件,本人首先想到用 Mathematica 去算积分,绕了点弯路,但还是可做的。以下给出代码。其中有几个要点:
|
||||||
|
|
||||||
|
1. Mathematica 的 `ToExpression` 转换后的表达式是 `Integrate[...]` 也即符号积分,此时有可能算出奇怪的答案(比如复数解)。此时应该将 `Integrate` 替换为 `NIntegrate`。
|
||||||
|
2. 其他一些替换,如把自然对数底 `e` 换成 `E`;最后的 `{d x}` 换成 `dx`;`\` 换成 `\\`;被积函数要用 `{}` 括起来。
|
||||||
|
|
||||||
|
偶尔会有几个积分算不出来,但概率不大。半小时左右能拿到 flag。
|
||||||
|
|
||||||
|
```python
|
||||||
|
import re
|
||||||
|
import pexpect
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
|
||||||
|
"Referer": "http://202.38.93.111:10190/",
|
||||||
|
}
|
||||||
|
|
||||||
|
s = requests.session()
|
||||||
|
s.cookies.clear()
|
||||||
|
|
||||||
|
address = "http://202.38.93.111:10190/"
|
||||||
|
|
||||||
|
tex_pattern = re.compile(
|
||||||
|
r"(?P<progress>\d+)\s*题[.\s\S]+<p>\s*\$(?P<expr>.+)\$\s*</p>", re.M | re.X | re.U,
|
||||||
|
)
|
||||||
|
body_pattern = re.compile(r"(^[^\s]+\s)(?P<body>.*)\\")
|
||||||
|
|
||||||
|
|
||||||
|
def process_expr(expr: str):
|
||||||
|
expr = expr.replace("{d x}", "dx")
|
||||||
|
expr = re.sub(r"\be\b", "E", expr)
|
||||||
|
expr = body_pattern.sub(r"\g<1>(\g<body>)\\", expr)
|
||||||
|
expr = expr.replace("\\", "\\\\")
|
||||||
|
return expr
|
||||||
|
|
||||||
|
|
||||||
|
def get_code(expr: str):
|
||||||
|
return f'ToExpression["{expr}",TeXForm,Hold]/.Integrate->NIntegrate//ReleaseHold'
|
||||||
|
|
||||||
|
|
||||||
|
def next_probem(ans=""):
|
||||||
|
if ans:
|
||||||
|
response = s.post(address + "/submit", data=dict(ans=ans))
|
||||||
|
else:
|
||||||
|
response = s.get(address)
|
||||||
|
print(response.text)
|
||||||
|
matched = tex_pattern.search(response.text)
|
||||||
|
expr = matched.group("expr")
|
||||||
|
progress = matched.group("progress")
|
||||||
|
expr = process_expr(expr)
|
||||||
|
code = get_code(expr)
|
||||||
|
p = pexpect.spawn("wolframscript", ["-code", code])
|
||||||
|
p.wait()
|
||||||
|
if p.exitstatus != 0:
|
||||||
|
return "", progress
|
||||||
|
try:
|
||||||
|
answer = "{:.6f}".format(float(p.read().decode().strip()))
|
||||||
|
except ValueError:
|
||||||
|
return "", progress
|
||||||
|
return answer, progress
|
||||||
|
|
||||||
|
|
||||||
|
ans = ""
|
||||||
|
while True:
|
||||||
|
ans, round = next_probem(ans)
|
||||||
|
print(ans, round)
|
||||||
|
if round == 0:
|
||||||
|
break
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user