Hackergame 2020 Writeup

开篇废话

新的一年过去了,新的一届 hackergame 开始了
score

然而今年连前200都没了 去年立下的 flag 有反向效果
不管怎么样,还是记录下我当时做题的思路。

题目

签到

没什么好说的,F12走起 step 改成 1 然后拖动下,就可以拿到整数为 1 的 flag 了
// 老板给我拿1个flag
sign

猫咪问答++

  1. 以下编程语言、软件或组织对应标志是哺乳动物的有几个?
    Docker,Golang,Python,Plan 9,PHP,GNU,LLVM,Swift,Perl,GitHub,TortoiseSVN,FireFox,MySQL,PostgreSQL,MariaDB,Linux,OpenBSD,FreeDOS,Apache Tomcat,Squid,openSUSE,Kali,Xfce.
    提示:学术上一般认为龙不属于哺乳动物。
程式/系统名称 标志代表
docker 🐳
Plan 9 🐰
PHP 🐘
GNU 祖传🐐
LLVM 🐲(所以不属于)
Swift 燕子
Perl 🐫
Github 🐙 触手🐱
TortoiseSVN 🐢
Firefox 喜马拉雅小熊猫 🦊
Mysql 🐳
PostgreSQL 🐘
Mariadb 🦭
OpenBSD 🐡
FreeDOS 🐳
Tomcat 🐱
Squid 🐙
Kali 🐲
Xfce 🐭
12
  1. 第一个以信鸽为载体的 IP 网络标准的 RFC 文档中推荐使用的 MTU (Maximum Transmission Unit) 是多少毫克?
    提示:咕咕咕,咕咕咕。

直接搜索咯
关键词
Homing pigeon mtu
https://tools.ietf.org/html/rfc1149

256
  1. USTC Linux 用户协会在 2019 年 9 月 21 日自由软件日活动中介绍的开源游戏的名称共有几个字母? 直接搜索 + 1

https://lug.ustc.edu.cn/news/2019/09/2019-sfd-ustc/

最后一项是李文睿同学介绍了开源游戏 Teeworlds,由于底层代码开源,开发者可以做出自己的定制,可玩性非常高。

9
  1. 中国科学技术大学西校区图书馆正前方(西南方向) 50 米 L 型灌木处共有几个连通的划线停车位?
    提示:建议身临其境。

搜索 + 2
https://720yun.com/t/05fjurmOkn9?scene_id=21438061

根据全景图,有9个停车位
L_parking_number

// 一开始用百度全景的,路痴表示根本找不到什么 L 的东西(事后对比 其实我找到了)

9
  1. 中国科学技术大学第六届信息安全大赛所有人合计提交了多少次 flag?

https://web.archive.org/web/20200922083048/https://hack.lug.ustc.edu.cn/

17098

总结:就考察搜索能力啦,搜索一下就出来了

2048

解法0

手动完成

解法1

参考这个帖子

GameManager.prototype.addRandomTile = function () {
if (this.grid.cellsAvailable()) {
    var value = 8192;
    var tile = new Tile(this.grid.randomAvailableCell(), value);

    this.grid.insertTile(tile);
}
};

扔 F12 动两下,就刷分了

解法2

我们打开 F12 可以看到 游戏状态是用 localStorage 保存的,那我们暴力修改并刷新就能赢了(草)

let gameState = JSON.parse(localStorage.gameState)
gameState.score = '1145141919'
gameState.won = true
localStorage.gameState = JSON.stringify(gameState)
location.reload()

解法3

我们继续网页源码(瞎点),可以找到请求 flag 的 api 源码 || 备份

于是我们就可以简单修改 // 或者用 postman curl 之类的

// ba NAN a 草
let url = "/getflxg?my_favorite_fruit=" + ('b'+'a'+ +'a'+'a').toLowerCase();
let request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = 'text';
request.onload = function() {
    prompt('flag is',request.response);
};
request.send();

一闪而过的 Flag

没什么好说的,先开个 cmd / powershell 然后把文件拖进去就是了

flag{Are_you_eyes1ght_g00D?_can_you_dIst1nguish_1iI?}

自复读的复读机

反向复读

随便搜索 可以搜索到 python quine 相关内容

_=')""=dne,]0~::[_%%_(tnirp;%r=_';print(_%_[::~0],end="")

然后 flag 就有了

flag{Yes!_Y0U_h4v3_a_r3v3rs3d_Qu1ne_xxx}

哈希复读

没有做出来 看官方题解吧

从零开始的记账工具人

基本就处理把,我随手撸了个脚本

const fs = require('fs')
// .csv 就是 xlsx 从 Excel 复制出来的,用 tab 做分割
let a = fs.readFileSync('./ustc.csv').toString().split('\n')
// 0 - ⑨
const n1 = ['零','壹','贰','叁','肆','伍','陆','柒','捌','玖']
let total = 0
a.map(x=>{
    // 默认用 tab 分割,粘贴后可能变成 space 了,自己改改
    x = x.split('	')
    let num = []
    // 默认是 1 (不除)
    let flag = 1
    if(x[0].indexOf('分') > -1){
        flag = 100
    }else if(x[0].indexOf('角') > -1){
        flag = 10
    }
    let temp = x[0].split('').reverse()
    temp.map((t,n)=>{
        if(n1.indexOf(t) > -1)
            num.push(n1.indexOf(t))
        else if(t == '拾'){
            if(temp[n - 1] == '元' ){
                num.push(0)
                if(temp[n + 1] == undefined){
                    num.push(1)
                }
            }else if(temp[n + 1] == undefined){
                num.push(1)
            }
        }
    })
    let number = (parseInt(num.reverse().join('')) / flag)
    console.log(number)
    total += (number * parseInt(x[1]))
})
console.log(Math.round(total * 100) / 100)
// 浮点数喜 我拿 floor 的结果(17940.80)结果炸了

flag{17940.81}

233 同学的 Docker

我们可以看到 在 hub.docker.com layer 的第 28 行

/bin/sh -c rm /code/flag.txt

(掩耳盗铃艹)
之前并没有怎么用过 docker 的我自己没有什么好办法 ,就手艹镜像了 首先去 gayhub 随便找个 docker image downloader
我用的是这个 https://github.com/NotGlop/docker-drag 然后解压就完事了,慢慢找, 我在 e19efd5ae62b2f88938ee22e9a85def414664042924d1eaa275ff885f4871cbd 找到了 /code 文件夹没删除前的东西

> cat code/flag.txt flag{Docker_Layers!=PS_Layers_hhh}

从零开始的 HTTP 链接

这道题正解应该是要改 busybox (或者 netcat / curl )的源码 或者手撸 raw request 来做这个,我用了比较 dirty 的办法(端口转发/映射)
首先我们准备一台 routeros 版本随意
在 /ip/firewall/nat 创建端口转发
如图所示
routeros_firewall_nat

access_forwarded_port_0

狗狗银行

你能在狗狗银行成功薅到羊毛吗?

这题就很明显不是去年的 达拉崩吧大冒险 的那样的大 整 数溢出了。
在这题中,提供了两种卡类的选项。
银行卡 0.3% 利率,信用卡 0.5% 利率,从常理来讲,这基本是完成不的任务呢。
经过一段时间的动手手动注入,可以看出,利率金额都是四舍五入的,那我们就有薅羊毛的办法了。
167 是利率为 1 的最低金额(
2099 利息为 10 的最低欠款)
同时,开卡是都是免费的,无论是开借记卡(debit)还是信用卡(credit)
虽然后面限制了只能开1000张卡
具体思路是这样的: 开信用卡 借钱 > 下一天 > 储蓄卡的钱回流到信用卡里(利息更不容易爆炸)> 下一天 > (循环前两步) > 拿到 flag

这里我用 js 随便撸了个脚本,开了50张信用卡和700张左右储蓄卡

# npm i node-fetch
const fetch = require('node-fetch')
const token = 'Bearer 114514:MEYCIQCywQbgqD041xKjX+Vzbty+d8JXqKLnHAltRCsO7rFs/QIhAIRI9mfYXMkbU2KYCf7ogRb89tiOfoYU8/jbtuzQINOa'
async function create(start,end,type){
  console.log(start,end)
  let b = await fetch("http://202.38.93.111:10100/api/create", {
      "headers": {
        "authorization": token,
        "content-type": "application/json;charset=UTF-8"
      },
      "referrer": "http://202.38.93.111:10100/",
      "referrerPolicy": "strict-origin-when-cross-origin",
      "body": JSON.stringify({type: type}),
      "method": "POST",
      "mode": "cors"
    });
  if(start <= end){
    start++
    create(start,end,type)
  }
}
async function transfer(src,dst,amount){
    let b = await fetch("http://202.38.93.111:10100/api/transfer", {
        "headers": {
          "authorization": token,
          "content-type": "application/json;charset=UTF-8"
        },
        "body": JSON.stringify({
          src: src,
          dst: dst,
          amount: amount
        }),
        "method": "POST",
        "mode": "cors"
      });
    console.log(b)
}
// 吃
async function looooop(){
    let a = await fetch("http://202.38.93.111:10100/api/eat", {
        "headers": {
          "authorization": token,
          "content-type": "application/json;charset=UTF-8"
        },
        "body": "{\"account\":1}",
        "method": "POST",
        "mode": "cors"
      });
    
}
async function all_credit_to_debit(credit,i,count){
  if(i >= count){
    return
  }
  await transfer(credit,1,2099)
  await all_credit_to_debit(parseInt(credit) + 1,i++,count)
}

async function debit_to_debit(debit,count){
  if(debit >= count){
    return
  }
  await transfer(1,debit,170)
  debit++
  await debit_to_debit(debit,count)
}

async function pay_back(debit,credit,amount = 2,s = 1,i = 1, count = 10){
  if(credit > 53){
    return true
  }
  console.log(debit,credit,amount,s,i)
  await transfer(debit,credit,amount)
  debit++
  if(i >= count){
    s++
    credit++
    await pay_back(debit,credit,amount,s,1,count)
  }else{
    await pay_back(debit,credit,amount,s,i + 1,count)
  }
}


// 这边依次取消注释 重新运行
// create(1,50,'credit') // 开信用卡 编号 2-52
// create(53,700,'debit') // 开储蓄卡
// all_credit_to_debit(1,1,50) // 借钱 2099 达到4舍效果
// debit_to_debit(58,688) // 本金分散到各个卡 达到5入效果
// pay_back(53,2) // 还钱 每次喜加一后运行一次(也可以不用,因为基数足够大)

懂了 这就去开 114514 张卡

总结

有些题还是有思路的,比如说 超简易的网盘服务器 来自未来的信笺 这两题,后面没有时间也就懒得解了 其实就是咕咕咕
想 oepngl 那些的,入门教程也没时间啃,就放弃了,有兴趣的可以看看这个项目 LearnOpenGL
还有题 超安全的代理服务器 我用 curl 怼了下,不太行,也放弃了,我觉得也是能做出来的(((
最好 数理基础相关题目已经自动无视了(绝望)

去年许的愿望今年还是一个都没实现,接下来一年继续加油吧。