Merge branch 'master' of github.com:USTC-Hackergame/hackergame2020-writeups

This commit is contained in:
RubyOcelot
2020-11-07 14:15:11 +08:00
22 changed files with 8714 additions and 8 deletions
+8 -3
View File
@@ -2,7 +2,7 @@
本文档收集整理了中国科学技术大学第七届信息安全大赛的官方与非官方题解。
该仓库仍在活跃更新中,欢迎各位选手以 Pull Request 的形式提交自己的 write-up(players 目录下以自己的昵称创建新文件夹)。
该仓库仍在活跃更新中,欢迎各位选手以 Pull Request 的形式提交自己的 write-up(players 目录下以自己的昵称创建新文件夹,并在本文件的「来自选手」部分增加一行)。
若大家对本题解有任何疑问或改进建议,欢迎 [提 issue](https://github.com/USTC-Hackergame/hackergame2020-writeups/issues/new)
@@ -16,7 +16,7 @@
| ------------------------------------------------------------ | ------------------------------------------------------- |
| [签到](official/签到/README.md) | 无 |
| [猫咪问答++](official/猫咪问答++/README.md) | 无 |
| [2048](official/2048/README.md) | 暂无 |
| [2048](official/2048/README.md) | 暂无(之后会有) |
| [一闪而过的 Flag](official/一闪而过的%20Flag/README.md) | [文件、源代码](official/一闪而过的%20Flag/src) |
| [从零开始的记账工具人](official/从零开始的记账工具人/README.md) | [文件、源代码](official/从零开始的记账工具人/src) |
| [超简单的世界模拟器](official/超简单的世界模拟器/README.md) | [文件、源代码](official/超简单的世界模拟器/src) |
@@ -38,7 +38,7 @@
| [室友的加密硬盘](official/室友的加密硬盘/README.md) | 无 |
| [超简易的网盘服务器](official/超简易的网盘服务器/README.md) | [文件、源代码](official/超简易的网盘服务器/src) |
| [超安全的代理服务器](official/超安全的代理服务器/README.md) | [文件、源代码](official/超安全的代理服务器/src) |
| [证验码](official/证验码/README.md) | 暂无 |
| [证验码](official/证验码/README.md) | 暂无(之后会有) |
| [动态链接库检查器](official/动态链接库检查器/README.md) | [文件、源代码](official/动态链接库检查器/src) |
| [超精准的宇宙射线模拟器](official/超精准的宇宙射线模拟器/README.md) | [文件、源代码](official/超精准的宇宙射线模拟器/src) |
| [超迷你的挖矿模拟器](official/超迷你的挖矿模拟器/README.md) | [文件、源代码](official/超迷你的挖矿模拟器/src) |
@@ -52,6 +52,11 @@
| write-up | 备注 | 包含题目 |
| - | - | - |
| mcfx [Markdown](players/mcfx/writeup.md) [PDF](players/mcfx/writeup.pdf) | 总排名第一名 | 全部题目 |
| [ProfFan](players/ProfFan/writeup.md) | | 证验码 |
| [NaiveTomcat](players/NaiveTomcat/) | | 超简陋的 OpenGL 小程序, 狗狗银行, 233 同学的字符串工具, 233 同学的 Docker |
| [sparkcyf](players/sparkcyf/writeup.md) | | 从零开始的记账工具人 |
| [A-wing](players/a-wing/writeup.md) | | 一闪而过的 Flag, 233 同学的字符串工具, 233 同学的 Docker |
| [hsfzxjy](players/hsfzxjy) | | 超基础的数理模拟器, 从零开始的 HTTP 链接, 永不溢出的计算器 |
## 其他资源
@@ -6,7 +6,7 @@
## 简单的解法
在 Linux 下,安装 socat,然后运行 `socat TCP-LISTEN:20000,fork,reuseaddr TCP:202.38.93.111:0`,再从浏览器访问 localhost:20000 即可。
在 Linux 下,安装 socat,然后运行 `socat TCP-LISTEN:20000,fork,reuseaddr TCP:202.38.93.111:0`,再从浏览器访问 localhost:20000 即可。(注:这里的 20000 也可以换成其他端口号,与下文「花絮」中提到的 20000 没有关系)
要注意,如果你在用 Linux 虚拟机,很多虚拟机软件的 NAT 实现不能正确处理 0 号端口,你需要把虚拟机的网络设置从 NAT 模式改为桥接模式。
+1 -1
View File
@@ -28,6 +28,6 @@ Security
在网上搜索「ldd exploit」之类的关键词可以查到 CVE-2019-1010023,在[这个链接](https://sourceware.org/bugzilla/show_bug.cgi?id=22851)中,我们可以看到 ldd 任意命令执行的示例代码,然而这个问题并没有被修复。
所以我们把示例代码保存成文件,把 `shellcode.asm` 最后的 `cat /etc/passwd` 改成读取 flag 的命令 `cat /flag`,然后在 Linux 环境下使用 `make` 命令编译,得到的 `libevil.so` 就可以上传到题目的网页获得 flag 了。
所以我们把示例代码保存成文件,把 `shellcode.asm` 最后的 `cat /etc/passwd` 改成读取 flag 的命令 `cat /flag`,然后在 Linux 环境下使用 `make evil` 命令编译,得到的 `libevil.so` 就可以上传到题目的网页获得 flag 了。
[解题代码](src/solution)
@@ -0,0 +1 @@
测试 token: `233333:MEUCIQDTTJu25fXbAgKcF+MDCGp1OSTd+4OwvNmTn/DhZryCiAIgDQXsmAHvLrAe2BSwaoSZO+ml6as+Aj0N51PI3e6Befs=`
+2 -2
View File
@@ -47,8 +47,8 @@ $('#number')[0].value = 1;
## 一些统计
下面是比赛期间服务器统计的收到的 number 值的统计:
下面是比赛期间服务器收到的 number 值的统计:
![0_1.5](images/numbers_0_1.5.png)
![-5_50](images/numbers_-5_50.png)
![-5_50](images/numbers_-5_50.png)
@@ -0,0 +1,6 @@
# Docker WP
## 思路
`/var/lib/docker/overlay2`中有pull下来的docker镜像的文件,而这个docker的构建是先有flag.txt
后来删除的,于是就能在这个目录中搜索到flag.txt。
@@ -0,0 +1,35 @@
# 字符串工具WP
## 大小写转换
### 思路
本问利用Unicode连字U+FB02fl连写),该字符被传入python的upper()方法后会被转为FL
进而达到绕过过滤的方法
### 脚本
```python
#!/usr/bin/python
import pwn
token="token"
p=pwn.remote("202.38.93.111",10233)
p.sendline(token)
p.recvuntil("2. Convert my UTF-7 string to UTF-8!!")
p.sendline("1")
p.recvuntil("Welcome to the capitalizer tool, please input your string:")
payload="\ufb02\u0061\u0067"
p.sendline(payload)
p.interactive()
```
## UTF-7到UTF-8转换
### 思路
本问利用UTF-7编码规则,将flag中每个字母扩充为双字节(即在前面加/x00),整体base64编码
并在最前面加上“+”以及去除末尾“=”,发送到服务,被UTF-7解码成flag进而获取flag
### payload
`+AGYAbABhAGc`
@@ -0,0 +1,18 @@
# 狗狗银行WP
## 切入点
后端计算利息的近似方法为四舍五入,故构造合理余额可使得借记卡利息达到0.6%,高于信用卡的0.5%从而获取利润
## 解题方法
分析创建卡、转账的请求,使用burp的intruder批量发包,首先自行手动创建一张信用卡,再通过burp批量创建998张借记卡
(为了满足题目新增要求),再通过burp从信用卡向每一张新增的信用卡转账167元
吃饭后,此时,每张卡都会有理论0.501元的利息,经过后端计算舍入得1元利息,共获得998元利息,而信用卡欠款166666元,
利息833.33元,有164元差额。除去吃饭的10元仍有利润。重复几天就可以使净资产大于2000。
## 错误解题方法
看到题我的第一思路是整型溢出,于是借了很多钱,用burp请求/api/eat很多次,最后返回的欠款有2^1000不止。后端应该用
的BigDecimal,不会出现溢出。
@@ -0,0 +1,23 @@
# 超简陋的OpenGL小程序WP
## 思路
着色器脚本中更改视角和光源位置,更改完后运行即可
## patch
basic_lighting.fs
```diff
19c19
< vec3 lightDir = normalize(-0.9* lightPos + FragPos);
---
> vec3 lightDir = normalize(lightPos - FragPos);
```
basic_lighting.vs
```diff
14c14
< FragPos = vec3(-1 *model * vec4(aPos, 1.0));
---
> FragPos = vec3(model * vec4(aPos, 1.0));
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 253 KiB

+210
View File
@@ -0,0 +1,210 @@
今年肝 paper 实在太忙,只做了一题和自己研究相关的(
顺便膜各位师傅 orz
# 证验码
注意到题目给的是 BMP 格式,显然是为了保存图片的一些统计特征。继续审代码,发现随机数均为真随机,故这个方向没有价值。众所周知字体渲染是有 Anti-aliasing 的,所以每个字都有独特的灰度分布。
故我们可以计算每张图片的灰度分布,再加上预计算每个单独字符的灰度分布,得到直方图,在直方图上做优化即可得到验证码。
注意此处应当使用 L1 而不是 L2 (最小二乘)优化,因为16个字符远少于 26*2+10,结果应当是稀疏的。本题用 L2 也可以得到解,但是如果增加干扰线条的密度,L2 应该会失败。
# 代码
```python
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import random, string
```
```python
import shuffle
```
```python
# !wget https://github.com/adobe-fonts/source-code-pro/raw/release/TTF/SourceCodePro-Light.ttf
```
```python
alphabet = sorted(string.digits + string.ascii_letters)
#code = "".join([random.choice(alphabet) for _ in range(16)])
code = "01234567890ABcde"
print("Code:", code)
```
Code: 01234567890ABcde
```python
original = shuffle.generate_captcha(code, shuffle_mode=False)
shuffled = shuffle.generate_captcha(code, shuffle_mode=True)
```
```python
plt.subplot(211)
plt.imshow(original)
plt.subplot(212)
plt.imshow(shuffled)
```
<matplotlib.image.AxesImage at 0x7f8312f56970>
![svg](solver_files/solver_5_1.svg)
```python
fig, axs = plt.subplots(2, 10, figsize=(20,6))
for i in range(10):
test_onealpha = np.array(shuffle.img_generate("{}".format(i)))
axs[0][i].imshow(test_onealpha)
counts = np.bincount(test_onealpha[:, :, 0].flatten(),minlength=255)
axs[1][i].plot(counts)
axs[1][i].set_yscale('log')
```
![svg](solver_files/solver_6_0.svg)
```python
counts_full = []
for k in range(3):
counts = np.bincount(np.array(shuffled)[:, :, 0].flatten(),minlength=256)
counts[255] = 0
counts_full.append(counts)
counts_full = np.hstack(counts_full)
print(counts_full.shape)
```
(768,)
```python
# %pip install cvxpy
```
```python
import cvxpy as cvx
```
```python
bases = []
for i in range(len(alphabet)):
bases_rgb = []
for k in range(3):
test_onealpha = np.array(shuffle.img_generate("{}".format(alphabet[i])))
counts = np.bincount(test_onealpha[:, :, k].flatten(),minlength=256)
counts[255] = 0
bases_rgb.append(counts)
bases.append(np.hstack(bases_rgb))
A = np.vstack(bases).T
print(A.shape)
print(A.T)
```
(768, 62)
[[224 5 2 ... 3 5 0]
[134 1 1 ... 0 2 0]
[171 2 1 ... 3 4 0]
...
[ 94 1 2 ... 2 6 0]
[118 4 3 ... 2 6 0]
[195 2 2 ... 1 3 0]]
/usr/lib/python3.8/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.
and should_run_async(code)
```python
import PIL
shuffled = PIL.Image.open("./captcha_shuffled.bmp")
# Solve actual problem
counts_full = []
for k in range(3):
counts = np.bincount(np.array(shuffled)[:, :, 0].flatten(),minlength=256)
counts[255] = 0
counts_full.append(counts)
counts_full = np.hstack(counts_full)
print(counts_full.shape)
```
(768,)
/usr/lib/python3.8/site-packages/ipykernel/ipkernel.py:287: DeprecationWarning: `should_run_async` will not call `transform_cell` automatically in the future. Please pass the result to `transformed_cell` argument and any exception that happen during thetransform in `preprocessing_exc_tuple` in IPython 7.17 and above.
and should_run_async(code)
```python
vx = cvx.Variable(len(alphabet))
objective = cvx.Minimize(cvx.norm(A*vx - counts_full, 1))
constraints = [vx >= 0]
prob = cvx.Problem(objective, constraints)
result = prob.solve(verbose=True)
```
ECOS 2.0.7 - (C) embotech GmbH, Zurich Switzerland, 2012-15. Web: www.embotech.com/ECOS
It pcost dcost gap pres dres k/t mu step sigma IR | BT
0 -2.788e-13 +1.258e-12 +5e+05 8e-01 4e-01 1e+00 3e+02 --- --- 1 2 - | - -
1 +4.640e+03 +4.675e+03 +2e+05 3e-01 1e-01 3e+01 1e+02 0.7401 2e-01 1 1 1 | 0 0
2 +5.846e+03 +5.861e+03 +9e+04 1e-01 4e-02 1e+01 6e+01 0.6585 8e-02 1 1 1 | 0 0
3 +5.968e+03 +5.970e+03 +1e+04 1e-02 3e-03 2e+00 6e+00 0.9494 6e-02 1 1 1 | 0 0
4 +6.080e+03 +6.080e+03 +3e+03 4e-03 1e-03 5e-01 2e+00 0.7566 6e-02 1 1 1 | 0 0
5 +6.151e+03 +6.152e+03 +2e+03 2e-03 6e-04 3e-01 1e+00 0.6536 5e-01 1 1 1 | 0 0
6 +6.193e+03 +6.193e+03 +9e+02 1e-03 3e-04 1e-01 5e-01 0.6015 1e-01 1 1 1 | 0 0
7 +6.198e+03 +6.198e+03 +8e+02 1e-03 3e-04 1e-01 5e-01 0.2129 7e-01 1 1 1 | 0 0
8 +6.216e+03 +6.216e+03 +6e+02 9e-04 2e-04 1e-01 3e-01 0.5360 4e-01 1 1 1 | 0 0
9 +6.230e+03 +6.230e+03 +3e+02 6e-04 1e-04 6e-02 2e-01 0.6585 4e-01 1 1 1 | 0 0
10 +6.244e+03 +6.244e+03 +2e+02 3e-04 5e-05 3e-02 1e-01 0.6652 2e-01 1 1 1 | 0 0
11 +6.249e+03 +6.249e+03 +1e+02 2e-04 3e-05 2e-02 7e-02 0.5025 4e-01 1 1 1 | 0 0
12 +6.255e+03 +6.255e+03 +6e+01 1e-04 2e-05 1e-02 4e-02 0.7639 3e-01 1 1 1 | 0 0
13 +6.259e+03 +6.259e+03 +3e+01 5e-05 7e-06 6e-03 2e-02 0.6280 1e-01 1 1 1 | 0 0
14 +6.261e+03 +6.261e+03 +1e+01 2e-05 3e-06 2e-03 7e-03 0.7859 2e-01 1 1 1 | 0 0
15 +6.262e+03 +6.262e+03 +4e+00 8e-06 1e-06 9e-04 2e-03 0.7343 1e-01 1 1 1 | 0 0
16 +6.263e+03 +6.263e+03 +8e-01 2e-06 2e-07 2e-04 5e-04 0.8474 6e-02 1 1 1 | 0 0
17 +6.263e+03 +6.263e+03 +3e-01 7e-07 9e-08 8e-05 2e-04 0.6258 6e-02 1 1 1 | 0 0
18 +6.263e+03 +6.263e+03 +4e-02 7e-08 1e-08 8e-06 2e-05 0.9127 2e-02 1 1 1 | 0 0
19 +6.263e+03 +6.263e+03 +2e-03 3e-09 4e-10 4e-07 1e-06 0.9579 2e-04 2 1 1 | 0 0
20 +6.263e+03 +6.263e+03 +2e-05 3e-11 5e-12 4e-09 1e-08 0.9890 1e-04 2 1 1 | 0 0
OPTIMAL (within feastol=3.4e-11, reltol=2.7e-09, abstol=1.7e-05).
Runtime: 0.048064 seconds.
/home/fan/.local/lib/python3.8/site-packages/cvxpy/expressions/expression.py:550: UserWarning:
This use of ``*`` has resulted in matrix multiplication.
Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1.
Use ``*`` for matrix-scalar and vector-scalar multiplication.
Use ``@`` for matrix-matrix and matrix-vector multiplication.
Use ``multiply`` for elementwise multiplication.
warnings.warn(__STAR_MATMUL_WARNING__, UserWarning)
```python
print(*zip(alphabet, vx.value.round(0)))
```
('0', 1.0) ('1', 0.0) ('2', -0.0) ('3', 0.0) ('4', -0.0) ('5', 1.0) ('6', 0.0) ('7', -0.0) ('8', 0.0) ('9', -0.0) ('A', 0.0) ('B', -0.0) ('C', -0.0) ('D', -0.0) ('E', 1.0) ('F', 0.0) ('G', -0.0) ('H', 1.0) ('I', -0.0) ('J', -0.0) ('K', 0.0) ('L', 1.0) ('M', -0.0) ('N', -0.0) ('O', 0.0) ('P', 1.0) ('Q', -0.0) ('R', -0.0) ('S', 1.0) ('T', -0.0) ('U', 0.0) ('V', 0.0) ('W', 1.0) ('X', 1.0) ('Y', 0.0) ('Z', 1.0) ('a', -0.0) ('b', 0.0) ('c', 0.0) ('d', 0.0) ('e', -0.0) ('f', -0.0) ('g', -0.0) ('h', -0.0) ('i', -0.0) ('j', -0.0) ('k', -0.0) ('l', 2.0) ('m', -0.0) ('n', -0.0) ('o', -0.0) ('p', -0.0) ('q', 0.0) ('r', -0.0) ('s', 1.0) ('t', -0.0) ('u', 1.0) ('v', 0.0) ('w', 1.0) ('x', 1.0) ('y', -0.0) ('z', -0.0)
+1
View File
@@ -0,0 +1 @@
本文件夹收录来自选手的非官方题解。
+107
View File
@@ -0,0 +1,107 @@
## 一闪而过的 Flag
有 windows 的话很好办(我专门借了别人的 Window 机测试,这个很容易,就是白送的)
可是我没有。。。只能这样看二进制数据
```sh
hexdump -Cv Untitled01.exe
```
可以找到这样一段
```sh
00000a70 48 98 c6 44 05 90 66 8b 45 fc 8d 50 01 89 55 fc |H..D..f.E..P..U.|
00000a80 48 98 c6 44 05 90 6c 8b 45 fc 8d 50 01 89 55 fc |H..D..l.E..P..U.|
00000a90 48 98 c6 44 05 90 61 8b 45 fc 8d 50 01 89 55 fc |H..D..a.E..P..U.|
00000aa0 48 98 c6 44 05 90 67 8b 45 fc 8d 50 01 89 55 fc |H..D..g.E..P..U.|
00000ab0 48 98 c6 44 05 90 7b 8b 45 fc 8d 50 01 89 55 fc |H..D..{.E..P..U.|
00000ac0 48 98 c6 44 05 90 41 8b 45 fc 8d 50 01 89 55 fc |H..D..A.E..P..U.|
00000ad0 48 98 c6 44 05 90 72 8b 45 fc 8d 50 01 89 55 fc |H..D..r.E..P..U.|
00000ae0 48 98 c6 44 05 90 65 8b 45 fc 8d 50 01 89 55 fc |H..D..e.E..P..U.|
00000af0 48 98 c6 44 05 90 5f 8b 45 fc 8d 50 01 89 55 fc |H..D.._.E..P..U.|
00000b00 48 98 c6 44 05 90 79 8b 45 fc 8d 50 01 89 55 fc |H..D..y.E..P..U.|
00000b10 48 98 c6 44 05 90 6f 8b 45 fc 8d 50 01 89 55 fc |H..D..o.E..P..U.|
00000b20 48 98 c6 44 05 90 75 8b 45 fc 8d 50 01 89 55 fc |H..D..u.E..P..U.|
00000b30 48 98 c6 44 05 90 5f 8b 45 fc 8d 50 01 89 55 fc |H..D.._.E..P..U.|
00000b40 48 98 c6 44 05 90 65 8b 45 fc 8d 50 01 89 55 fc |H..D..e.E..P..U.|
00000b50 48 98 c6 44 05 90 79 8b 45 fc 8d 50 01 89 55 fc |H..D..y.E..P..U.|
00000b60 48 98 c6 44 05 90 65 8b 45 fc 8d 50 01 89 55 fc |H..D..e.E..P..U.|
00000b70 48 98 c6 44 05 90 73 8b 45 fc 8d 50 01 89 55 fc |H..D..s.E..P..U.|
00000b80 48 98 c6 44 05 90 31 8b 45 fc 8d 50 01 89 55 fc |H..D..1.E..P..U.|
00000b90 48 98 c6 44 05 90 67 8b 45 fc 8d 50 01 89 55 fc |H..D..g.E..P..U.|
00000ba0 48 98 c6 44 05 90 68 8b 45 fc 8d 50 01 89 55 fc |H..D..h.E..P..U.|
00000bb0 48 98 c6 44 05 90 74 8b 45 fc 8d 50 01 89 55 fc |H..D..t.E..P..U.|
00000bc0 48 98 c6 44 05 90 5f 8b 45 fc 8d 50 01 89 55 fc |H..D.._.E..P..U.|
00000bd0 48 98 c6 44 05 90 67 8b 45 fc 8d 50 01 89 55 fc |H..D..g.E..P..U.|
00000be0 48 98 c6 44 05 90 30 8b 45 fc 8d 50 01 89 55 fc |H..D..0.E..P..U.|
00000bf0 48 98 c6 44 05 90 30 8b 45 fc 8d 50 01 89 55 fc |H..D..0.E..P..U.|
00000c00 48 98 c6 44 05 90 44 8b 45 fc 8d 50 01 89 55 fc |H..D..D.E..P..U.|
00000c10 48 98 c6 44 05 90 3f 8b 45 fc 8d 50 01 89 55 fc |H..D..?.E..P..U.|
00000c20 48 98 c6 44 05 90 5f 8b 45 fc 8d 50 01 89 55 fc |H..D.._.E..P..U.|
00000c30 48 98 c6 44 05 90 63 8b 45 fc 8d 50 01 89 55 fc |H..D..c.E..P..U.|
00000c40 48 98 c6 44 05 90 61 8b 45 fc 8d 50 01 89 55 fc |H..D..a.E..P..U.|
00000c50 48 98 c6 44 05 90 6e 8b 45 fc 8d 50 01 89 55 fc |H..D..n.E..P..U.|
00000c60 48 98 c6 44 05 90 5f 8b 45 fc 8d 50 01 89 55 fc |H..D.._.E..P..U.|
00000c70 48 98 c6 44 05 90 79 8b 45 fc 8d 50 01 89 55 fc |H..D..y.E..P..U.|
00000c80 48 98 c6 44 05 90 6f 8b 45 fc 8d 50 01 89 55 fc |H..D..o.E..P..U.|
00000c90 48 98 c6 44 05 90 75 8b 45 fc 8d 50 01 89 55 fc |H..D..u.E..P..U.|
00000ca0 48 98 c6 44 05 90 5f 8b 45 fc 8d 50 01 89 55 fc |H..D.._.E..P..U.|
00000cb0 48 98 c6 44 05 90 64 8b 45 fc 8d 50 01 89 55 fc |H..D..d.E..P..U.|
00000cc0 48 98 c6 44 05 90 49 8b 45 fc 8d 50 01 89 55 fc |H..D..I.E..P..U.|
00000cd0 48 98 c6 44 05 90 73 8b 45 fc 8d 50 01 89 55 fc |H..D..s.E..P..U.|
00000ce0 48 98 c6 44 05 90 74 8b 45 fc 8d 50 01 89 55 fc |H..D..t.E..P..U.|
00000cf0 48 98 c6 44 05 90 31 8b 45 fc 8d 50 01 89 55 fc |H..D..1.E..P..U.|
00000d00 48 98 c6 44 05 90 6e 8b 45 fc 8d 50 01 89 55 fc |H..D..n.E..P..U.|
00000d10 48 98 c6 44 05 90 67 8b 45 fc 8d 50 01 89 55 fc |H..D..g.E..P..U.|
00000d20 48 98 c6 44 05 90 75 8b 45 fc 8d 50 01 89 55 fc |H..D..u.E..P..U.|
00000d30 48 98 c6 44 05 90 69 8b 45 fc 8d 50 01 89 55 fc |H..D..i.E..P..U.|
00000d40 48 98 c6 44 05 90 73 8b 45 fc 8d 50 01 89 55 fc |H..D..s.E..P..U.|
00000d50 48 98 c6 44 05 90 68 8b 45 fc 8d 50 01 89 55 fc |H..D..h.E..P..U.|
00000d60 48 98 c6 44 05 90 5f 8b 45 fc 8d 50 01 89 55 fc |H..D.._.E..P..U.|
00000d70 48 98 c6 44 05 90 31 8b 45 fc 8d 50 01 89 55 fc |H..D..1.E..P..U.|
00000d80 48 98 c6 44 05 90 69 8b 45 fc 8d 50 01 89 55 fc |H..D..i.E..P..U.|
00000d90 48 98 c6 44 05 90 49 8b 45 fc 8d 50 01 89 55 fc |H..D..I.E..P..U.|
00000da0 48 98 c6 44 05 90 3f 8b 45 fc 8d 50 01 89 55 fc |H..D..?.E..P..U.|
00000db0 48 98 c6 44 05 90 7d 8b 45 fc 8d 50 01 89 55 fc |H..D..}.E..P..U.|
```
## 233 同学的字符串工具 **(这里有坑)**
这道题其实是利用漏洞
1. python upper() 函数有漏洞
https://www.anquanke.com/post/id/196044
`fl` `U+FB02` `大写` `FL` `U+0046` `U+004C`
利用这个特殊字符可以生成 `FL` 。所以只要使用 `flag` 就可以在 `upper()` 转换成符合标准的字符
这个要特别注意 **(这里有坑)** ,如果用 nc 的话有些终端会自动转换。直接复制是不行的。要用那个浏览器提供的终端
## Docker
这个是考 Docker 的原理,docker image 就是 git 的一层一层叠加上去的
这里可以看一下这个容器历史记录
https://hub.docker.com/layers/8b8d3c8324c7/stringtool/latest/images/sha256-aef87a00ad7a4e240e4b475ea265d3818c694034c26ec227d8d4f445f3d93152?context=explore
根据这份官方文档,我们可以找到如何查看 rootfs 的 diff
https://docs.docker.com/storage/storagedriver/overlayfs-driver/
```sh
docker pull 8b8d3c8324c7/stringtool
docker image inspect 8b8d3c8324c7/stringtool:latest
```
`cat /var/lib/docker/overlay2/781c84bb2cc44b9b4a672de1475f0f50ed11c176a5a224b90b0e19b100d79917/diff/code/flag.txt`
`flag{Docker_Layers!=PS_Layers_hhh}`
@@ -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
```
+3 -1
View File
@@ -1,5 +1,7 @@
# Writeup
作者:mcfx
## 签到
审查元素,step 改成 0.5,然后拖到 1。
@@ -1781,4 +1783,4 @@ r.send(str(m1) + '\n')
while True:
open('out.txt', 'ab').write(r.read(1))
```
```
+96
View File
@@ -0,0 +1,96 @@
# 从零开始的记账工具人
既然题目是用Excel分发的,那就直接用Excel解(
解题使用的Excel表格已经放在了本文件夹内的从`零开始的记账工具人-convert.xlsx`中。
## Excel表格中每列的含义(Sheet1
### A-B
题目给出的金额(单位为大写)和数量。
### G-K
用于拆分佰,拾,元,角,分前的大写数字。
以G列为例:
```
=IFERROR(MID($A2,FIND(G$1,$A2)-1,1),0)
```
>函数 FIND 和 FINDB 用于在第二个文本串中定位第一个文本串,并返回第一个文本串的起始位置的值,该值从第二个文本串的第一个字符算起。
[`FIND`函数](https://support.microsoft.com/zh-cn/office/find%e3%80%81findb-%e5%87%bd%e6%95%b0-c7912941-af2a-4bdf-a553-d0d89b0a0628?ui=zh-cn&rs=zh-cn&ad=cn)用于寻找`A列`对应单元格(即`A2`)内“佰”字的位置,并输出其位置。
>MID 返回文本字符串中从指定位置开始的特定数目的字符,该数目由用户指定。
[`MID`函数](https://support.microsoft.com/zh-cn/office/mid%E3%80%81midb-%E5%87%BD%E6%95%B0-d5f9e25c-d7d6-472e-b568-4ecb12433028)用于读取“佰”字的位置的前一位的文字(即佰位的金额,此题中只有“零”和“壹”)
> 可以使用 IFERROR 函数捕获和处理公式中的错误。 如果公式的计算结果为错误值,则 IFERROR 返回您指定的值;否则,它将返回公式的结果。
[`IFERROR`函数](https://support.microsoft.com/zh-cn/office/iferror-%E5%87%BD%E6%95%B0-c526fd07-caeb-47b8-8bb6-63f3e417f611)用于处理单元格金额没有佰位的情况,没有佰位时输出0。
对拾,元,角,分位的处理同上。
### M-Q
用于将提取出的中文大写金额转换成数字。
以M列为例:
```
=VLOOKUP(G2,'LUT-UC'!$A$1:$B$12,2,0)
```
使用[`VLOOKUP`函数](https://support.microsoft.com/zh-cn/office/vlookup-%E5%87%BD%E6%95%B0-0bbc8083-26fe-4963-8ab8-93a18ad188a1),查找`LUT-UC`这个Sheet中对应的数字,并返回该数字。
`LUT-UC`中包含了中文大写金额和数字的对应关系:
| 0 | 0 |
| ---- | ---- |
| 零 | 0 |
| 壹 | 1 |
| 贰 | 2 |
| 叁 | 3 |
| 肆 | 4 |
| 伍 | 5 |
| 陆 | 6 |
| 柒 | 7 |
| 捌 | 8 |
| 玖 | 9 |
| 拾 | 0 |
**其中“拾”位由于有形如“拾X”(10-20之间的数额)在“拾”字之前没有“壹”,所以需要特殊处理:**
```
=VLOOKUP(H2,'LUT-UC'!$A$1:$B$12,2,0)+IFERROR(FIND("拾",A2,1)=1,0)
```
其中,处理10-20之间的数额时,“拾”位前没有字符,因此`H`列如果直接用给“佰”用的公式会返回0。因此N列公式的第二部分即是用于检查“拾”字是否是单元格的第一个字符。如果其为单元格的第一个字符,则返回**1**(给“拾”位的计数加1)。
### S
```
=M2*100+N2*10+O2*1+P2*0.1+Q2*0.01
```
将解析出的每位数字相加。
### T
```
=S2*B2
```
计算每行的金额之和。
### W2
```
=SUM(T:T)
```
计算总金额。