Add write-ups from hsfzxjy

This commit is contained in:
hsfzxjy
2020-11-07 13:40:59 +08:00
parent 94b11d2637
commit a5dc4de4e0
3 changed files with 198 additions and 0 deletions
@@ -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
```