WriteUP-MISC(SP)-Seraph_JACK's red packet
Seraph_JACK的新年红包(MISC,SP)
我个人属于菜狗,研究该题(?)路程过于坎坷,坚持了15个小时(中间睡了个觉),主要是为了红包。
解红包过程
开门见山
中间大大一个hint死活看不见,虽然最后解出来才知道怎么用。
开门网页源代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2021 新年快乐!</title>
</head>
<body>
<div id="packet">
<span id="title">2021 新年快乐</span>
<span id="desc">输入口令领取红包<a href="/help.html">(?)</a></span>
<span id="pwd">输入口令:<input type="text" id="pwdIn"></span>
<div id="btn-box">
<span id="btn" onclick="submit()">提交</span>
</div>
</div>
</body>
<script>
function submit() {
// hint: check GET /main.go
var code = document.querySelector("#pwdIn").value;
var data = new URLSearchParams();
data.append("code", code);
fetch("/red_packet", {
method: "post",
body: data
}).then((res) => {
if (res.status === 200) {
res.text().then(b => {
window.location.href = b;
})
} else {
alert("口令错误!")
}
})
}
</script>
<style>
#btn {
cursor: pointer;
border-radius: 8px;
font-size: xx-large;
background-color: #ffe24b;
padding: 8px;
}
body {
display: flex;
justify-content: center;
}
#desc {
display: block;
font-size: large;
color: white;
text-align: center;
margin-top: 20px;
}
#desc a {
color: #ea0909;
font-size: xx-small;
}
#pwdIn {
width: 180px;
font-size: large;
}
#pwd {
display: inline-block;
margin-top: 150px;
margin-bottom: 80px;
text-align: center;
font-size: large;
color: white;
padding: 16px;
border-radius: 8px;
}
#btn-box {
display: flex;
justify-content: center;
margin-bottom: 20px;
}
#title {
color: white;
font-weight: bolder;
font-size: xxx-large;
display: inline-block;
margin: auto;
padding-top: 50px;
}
#packet {
background-color: red;
border-radius: 8px;
padding: 2px 8px;
}
</style>
</html>
首先知道了,我们POST的口令,就是code的值
var code = document.querySelector("#pwdIn").value;
var data = new URLSearchParams();
data.append("code", code);
fetch("/red_packet", {
method: "post",
body: data
然后看到了/main.go,老瞎子经别人提醒之后才发现上面还有个/help.html
/main.go
发现main函数源码,怎么是go写的,我爬了
package main
import (
"crypto/sha256"
"flag"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
fmt.Println("2021 Happy new year!")
listen := flag.String("listen", ":11451", "")
superSecretSalt := flag.String("salt", "this_is_not_the_salt", "")
redPacket := flag.String("packet", "no_packet_here", "")
flag.Parse()
r := gin.Default()
r.POST("/red_packet", func(ctx *gin.Context) {
key := ctx.PostForm("code")
val := []byte(key + *superSecretSalt)
hash := sha256.Sum256(val[:])
result := 0
for i := 0; i < 32; i++ {
result += int(hash[i])
}
if result == 2021 {
ctx.Header("Content-Type", "text/plain; charset=utf-8")
ctx.String(200, *redPacket)
} else {
ctx.Status(http.StatusForbidden)
}
})
r.NoRoute(gin.WrapH(http.FileServer(http.Dir("./static"))))
if err := r.Run(*listen); err != nil {
panic(err)
}
}
看了一下,主要就是,主函数通过post方法获取code的值(是一个字符串),加上*redPacket字符串后,经过sha256加密,所得的每一位ascii码之和为2021时,KEY则为答案
superSecretSalt := flag.String("salt", "this_is_not_the_salt", "")
redPacket := flag.String("packet", "no_packet_here", "")
flag.Parse()
r := gin.Default()
r.POST("/red_packet", func(ctx *gin.Context) {
key := ctx.PostForm("code")
val := []byte(key + *superSecretSalt)
hash := sha256.Sum256(val[:])
result := 0
for i := 0; i < 32; i++ {
result += int(hash[i])
}
if result == 2021 {
ctx.Header("Content-Type", "text/plain; charset=utf-8")
ctx.String(200, *redPacket)
} else {
ctx.Status(http.StatusForbidden)
}
})
中,的val := []byte(key + *superSecretSalt)
val就是key字符串和superSecretSalt指向的字符串相加
hash就是val经过sha256加密后的字符串hash := sha256.Sum256(val[:])
如果结果为2021则通过口令if result == 2021
/help.html
经过好心人指示,眼瞎的我终于发现了help.html
打开来是这个
源代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>再 放 送</title>
</head>
<body>
<span>The character is: '<span id="ch"></span>'</span>
<button onclick="left()">Go left</button>
<button onclick="right()">Go right</button>
<button onclick="back()">Go back</button>
</body>
<script>
var data = "320K2/5oM1L(...省略剩下字符,一共16384个字符)"
var cur = 1;
update();
function update() {
try {
let p = parseInt(window.location.hash.substr(1));
if (!isNaN(p)) cur = p;
} catch (e) {
// ignore
}
document.querySelector("#ch").innerHTML = data[cur];
}
function left() {
if (cur > 8192) {
alert("Can't go further!");
return;
}
window.location.hash = (cur * 2).toString();
update();
}
function right() {
if (cur > 8192) {
alert("Can't go further!");
return;
}
window.location.hash = (cur * 2 + 1).toString();
update();
}
function back() {
if (cur === 1) {
alert("Can't go back!");
return;
}
window.location.hash = Math.floor(cur / 2).toString();
update();
}
</script>
</html>
仔细看了看,是每次走左(cur✖2),是每次走右(cur✖2+1),或是返回(cur➗2)
回显一个值:data的cur索引(data[cur])对应字符
所以data是个索引表,考虑爆破它
爆破代码:
#include <cstdio>
#include <fstream>
using namespace std;
char s[] = "320K2/5oM1Lu8mmsTg8_(...省略)";
int ans[50] = {0};
ofstream outfile;
void recur(int sum, int layer) {
ans[layer] = sum;
if(sum>8192) {
for(int i=0;i<=layer;++i) {
// printf("%c",s[ans[i]]);
outfile << s[ans[i]];
}
outfile << endl;
}else {
recur(sum*2,layer+1);
recur(sum*2+1,layer+1);
}
}
int main(int argc, char const *argv[])
{
outfile.open("out.txt");
recur(1,0);
// printf("%d",'1');
outfile.close();
return 0;
}
// 2o2l_h4ppy_new_ye4r
结果:
找到了2021_salt.html
回到main.go
superSecretSalt
有了,就是2o2l_h4ppy_new_ye4r
想想和其他也没关系了,剩下就是sha256爆破,用go写了个爆破程序
package main
import (
"crypto/sha256"
"flag"
"fmt"
)
func main() {
fmt.Println("2021 Happy new year!")
superSecretSalt := flag.String("salt", "2o2l_h4ppy_new_ye4r", "")
// redPacket := flag.String("packet", "no_packet_here", "")
flag.Parse()
for i := 0; i < 999999999; i++ {
key := fmt.Sprint(i)
// key := "1"
val := []byte(key + *superSecretSalt)
hash := sha256.Sum256(val[:])
result := 0
for i := 0; i < 32; i++ {
result += int(hash[i])
}
// print(result)
// print("\n")
if result == 2021 {
print(key)
}
}
}
最后,414134692
,即为答案口令
搁着挖矿呢.jpg,还拿了挺多钱,快乐.jpg
Living with bustle, hearing of isolation.