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