johnpoint

johnpoint

(。・∀・)ノ゙嗨
github

Hackergame 2020 寫作

最終成績#

Sat Nov  7 09:59:22 AM CST 2020
當前分數:1500, 總排名:225 / 2415
binary:0 , general:850 , math:300 , web:350

啊,我真的是太菜了(

只做出了一點點題目

簽到#

謝邀,利益相關:老簽到出題人了。

今年出題組的要求是「來參加我們比賽的同學很多都是初學者,我們的簽到題要清晰明確一點,讓同學們輕鬆簽到。」

我完全明白了,簽到題就是送 flag,送就送,我最會送了.jpg

首先寫好題目介紹:「你需要點擊下面藍色的 “打開/下載題目” 按鈕,在打開的網頁上獲取到形如 flag{...} 的 flag,回到本頁面,將其完整填寫到下面的文本框中,並點擊灰色的 “提交” 按鈕即可完成本題。」

然後寫一個 flag 提取器,選手要多少個 flag,我就給多少個 flag,綠色背景,紅色加粗,顯眼的位置,標準的格式,這都不叫送,那還有什麼叫做送。

點擊 「打開/下載題目」 按鈕,打開 flag 提取器,獲取第一個 flag 吧!

提示:完成題目遇到困難?你可以參考 2018 年簽到題題解 與 2019 年簽到題題解。

image

F12 定位到拖動條,將最大值改為 1 然後將條拖到最大就可以得到 flag

<input type="range" id="number" name="number" class="form-control" value="0" min="0" max="1" step="0.00001">

貓咪問答 ++#

在科大西區的研究生食堂旁邊,有塊水泥石板盛產肥貓。 每一個晴朗的中午,其上都會有花花白白的貓咪慵懶地曬著太陽。 而許多吃完午飯的同學,也可以趁此良機大肆撸貓。

但是突然從某一天起,水泥石板上多了一隻貓首貓身的動物,攔住前來撸貓的同學,用它精心準備好的謎語考驗他們。 只有全部答對了才可以撸貓,如果不小心答錯了它就會炸毛給你看。

為了讓每日撸貓活動恢復正軌,熱心的 LUG 協會同學把這些謎題放到了這裡。 如果你能答對所有的謎題,就會有 flag 作為獎勵。

提示:正如撸貓不必親自到現場,解出謎題也不需要是科大在校學生。解題遇到困難?你可以參考 2018 年貓咪問答題解。

image

  1. 手動數,數量為 12
  2. 搜索到了 wikipedia -> RFC1149

A
typical MTU is 256 milligrams. Some datagram padding may be needed.

  1. https://ftp.lug.ustc.edu.cn/ 活動 / 2019.09.21_SFD/slides/ 閃電演講 / Teeworlds/ --> Teeworlds 答案 9

  2. 百度地圖街景手動數 答案 9

  3. https://news.ustclug.org/2019/12/hackergame-2019/ --> 答案 17098

2048#

路漫漫其修遠兮,FLXG 永不放棄!

要實現 FLXG,你需要過人的智慧,顽強的意志,和命運的眷屬。只有在 2048 的世界裡證明自己擁有這些寶貴的品質,實現「大成功」,你才有資格扛起 FLXG 的大旗。

image

真就是 2048,看下 js 文件,發現裡面有個 game_manager.js,粗略的瀏覽下邏輯,發現這麼一句

if (merged.value === 16384) self.won = true;

打斷點,手動修改變量值,就成功了

image

一閃而過的 Flag#

深秋清晨,也西湖畔。一位可憐的同學蜷在路邊的長椅上,用粗糙的手指敲擊著殘舊的神船筆記本,反復試圖打開桌面上的一個程序。程序每次運行時隱約可見黑色控制台上有 flag 一閃而過。

在他的腳邊搭著一塊用廢棄紙箱剪成的牌子,上面寫著「我很可愛,請給我 flag」。路上的人行色匆匆,而那地上用來盛 flag 的飯盒依舊空空如也。

一位詩人同學路過,見此情景,遂把牌子改成了:「flag 來了,可是我什麼也看不見!」

而你作為一名新生,不由動了恻隱之心。望著詩人瀟灑遠去的背影,你可以趕在下午詩人回來之前,幫助這位可憐的人,用 flag 裝滿他的飯盒嗎?

啊這、啊這,我覺得這個 flag 是白給的啊,程序運行以後我瞬間截圖就可以拿到 flag 了,之前還以為要錄像逐幀判斷...

從零開始的記帳工具人#

如同往常一樣,你的 npy 突然丟給你一個購物帳單:“我今天買了幾個小玩意,你能幫我算一下總共花了多少錢嗎?”

你心想:又雙叒叕要開始吃土了 這不是很簡單嗎?電子表格裡面一拖動就算出來了

只不過拿到帳單之後你才注意到,似乎是為了剁手時更加的安心,這次的帳單上面的金額全使用了中文大寫數字

注意:請將帳單總金額保留小數點後兩位,放在 flag{} 中提交,例如總金額為 123.45 元時,你需要提交 flag{123.45}

文件下載

首先另存為 csv,使用 python 將 csv 轉換為 json 下面比較好處理

統計源代碼:

import json


def cover(i):
    for j in range(0, len(text)):
        if text[j] == i:
            return j


yuan = 0
jiao = 0
fen = 0
text = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖", "拾"]

with open('bills.json', 'r') as f:
    a = json.load(f)
    for i in a:
        y = i["mon"].split("元")
        num = int(i["num"])
        for j in y:
            if "角" in j:
                jj = j.split("角")
                jiao += cover(jj[0])*num
                if len(jj) > 1 and "分" in jj[1]:
                    fen += cover(jj[1].split("分")[0])*num
                continue
            if "分" in j:
                fen += cover(j.split("分")[0].replace("零", ""))*num
                continue
            for i in range(0, len(j)):
                if j[i] == "整":
                    continue
                if j[i] == "佰":
                    continue
                if i+1 < len(j):
                    if j[i+1] == "拾":
                        yuan += cover(j[i])*10*num
                    elif j[i+1] == "佰":
                        yuan += cover(j[i])*100*num
                else:
                    if j[i] != "拾" and j[i] != "佰":
                        yuan += cover(j[i])*num
                if i-1 < 0 and j[i] == "拾":
                    yuan += 10*num

jiao += int(fen/10)
fen = fen % 10*0.01
yuan += int(jiao/10)
jiao = jiao % 10*0.1

print(yuan+jiao+fen)
print("y", yuan)
print("j", jiao)
print("f", fen)

答案 20262.53

來自一教的圖片#

小 P 在一教做傅里葉光學實驗時,在實驗室電腦的模擬程序裡發現了這麼一張的圖片:

image

數理基礎並不扎實的小 P 並不知道什麼東西成像會是這個樣子:又或許什麼東西都不是,畢竟這只是模擬 ... 但可以確定的是,這些看似奇怪的花紋裡確實隱藏著一些信息,或許是地下金礦的藏宝圖也未可知。

很簡單,題目給足了提示,做一下傅立葉逆變換就可以得到

image

超簡單的世界模擬器#

你知道生命遊戲(Conway's Game of Life)嗎?

你的任務是在生命遊戲的世界中,復現出蝴蝶扇動翅膀,引起大洋彼岸風暴的效應。

通過改變左上角 15x15 的區域,在遊戲演化 200 代之後,如果被特殊標註的正方形內的細胞被“清除”,你將會得到對應的 flag:

“清除”任意一個正方形,你將會得到第一個 flag。同時“清除”兩個正方形,你將會得到第二個 flag。

注: 你的輸入是 15 行文本,每行由 15 個 0 或者 1 組成,代表該區域的內容。

蝴蝶效應#

我的解:

000000000000000
000000000000000
000000000000000
000000000000000
000000110000000
000001111000000
000001101100000
000000011000000
000000000000000
000000000000000
000000110000000
000001111000000
000001101100000
000000011000000
000000000000000

參考了 知乎:生命遊戲(Game of Life)有哪些圖形?

233 同學的 Docker#

233 同學在軟工課上學到了 Docker 這種方便的東西,於是給自己的字符串工具項目寫了一個 Dockerfile。

但是 233 同學突然發現它不小心把一個私密文件(flag.txt)打包進去了,於是寫了一行命令刪掉這個文件。

「既然已經刪掉了,應該不會被人找出來吧?」233 想道。

Docker Hub 地址:8b8d3c8324c7/stringtool

從 Dockerfile 裡面的命令來看

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

flag 保存在了 /code 裡面

看起來只需要提取 docker layers 裡面的內容就好了,問題是我不會 搜索到了 Is there a way to tag a previous layer in a docker image or revert a commit?

docker save imagename $(sudo docker history -q imagename | tail -n +2 | grep -v \<missing\> | tr '\n' ' ') > image-caching.tar

使用這命令就把 layers 全部提取出來,接下來就每個 layers 都看看就好了

flag{Docker_Layers!=PS_Layers_hhh}

從零開始的火星文生活#

一年一度的 Hackergame 就要到了,L 同學打算叫上 Q 同學一起去參加,卻一連幾天都見不到 Q 同學的人影。然而在比賽開始的前一天晚上卻收到了來自 Q 同學的郵件:

Subject: 絕密!不要外傳!!!
Body: 詳情見附件
From: Q
L 同學打開附件一看,傻眼了,全都是意義不明的漢字。機智的 L 同學想到 Q 同學平時喜歡使用 GBK 編碼,也許是打開方式不對。結果用 GBK 打開卻看到了一堆夾雜著日語和數字的火星文……

L 同學徹底懵逼了,幾經周折,TA 找到了科大最負盛名的火星文專家 (你)。依靠多年的字符編碼解碼的經驗,你可以破譯 Q 同學發來的火星文是什麼意思嗎?

注:正確的 flag 全部由 ASCII 字符組成!

文件內容:

脦脪鹿樓脝脝脕脣 拢脠拢谩拢茫拢毛拢氓拢貌拢莽拢谩拢铆拢氓 碌脛路镁脦帽脝梅拢卢脥碌碌陆脕脣脣眉脙脟碌脛 拢忙拢矛拢谩拢莽拢卢脧脰脭脷脦脪掳脩 拢忙拢矛拢谩拢莽 路垄赂酶脛茫拢潞 拢忙拢矛拢谩拢莽拢没拢脠拢麓拢枚拢鲁拢脽拢脝拢玫拢脦拢脽拢梅拢卤拢脭拢猫拢脽拢鲁拢卯拢茫拢掳拢盲拢卤拢卯拢莽拢脽拢麓拢脦拢盲拢脽拢盲拢鲁拢茫拢掳拢脛拢卤拢卯拢脟拢脽拢鹿拢帽拢脛拢虏拢脪拢赂拢猫拢贸拢媒 驴矛脠楼卤脠脠眉脝陆脤篓脤谩陆禄掳脡拢隆 虏禄脪陋脭脵掳脩脮芒路脻脨脜脧垄脳陋路垄赂酶脝盲脣没脠脣脕脣拢卢脪陋脢脟卤禄路垄脧脰戮脥脭茫赂芒脕脣拢隆

額。。。這題目,我搜索 拢 utf8 的時候正好搜到了 代碼中包含的中文全為乱码,編碼問題求請教! 然後看了下回答

alcarl   2018-01-09 01:25:21 +08:00 via Android   ❤️ 3
先把這段字保存成 gb2312 編碼的文件,然後轉換成 utf8 編碼,保存,然後再轉換成 8859-1 保存,然後當成 gbk 打開就好了,=͟͟͞͞(꒪ᗜ꒪ ‧̣̥̇) 字是下面這樣的
類:包含對文件的操作(為了便於調試和觀察,我把網頁信息寫入了文件中,所以有了這個文件操作類)

參考 http://blog.zeerd.com/ffmpeg-c2c3-bug/

然後按照這操作就.... 就出來了...

我攻破了 Hackergame 的伺服器,偷到了它們的 flag,現在我把 flag 發給你:
flag{H4v3_FuN_w1Th_3nc0d1ng_4Nd_d3c0D1nG_9qD2R8hs}
快去比賽平台提交吧!
不要再把這份信息轉發給其他人了,要是被發現就糟糕了!

從零開始的 HTTP 連接#

眾所周知,數組下標應當從 0 開始。

同樣的,TCP 端口也應當從 0 開始。為了實踐這一點,我們把一個網站架設在伺服器的 0 號端口上。

你能成功連接到 0 號端口並拿到 flag 嗎?

點擊下面的打開題目按鈕是無法打開網頁的,因為普通的瀏覽器會認為這是無效地址。

地址: http://202.38.93.111:0/

從題目就可以看出來,應該自己構造 http 請求就可以得到 flag

我的解法:

網上找了個 C 實現的 http get (來源)

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#define IPSTR "202.38.93.111" //伺服器IP地址;
#define PORT 0
#define BUFSIZE 1024
 
int main(int argc, char **argv)
{
        int sockfd, ret, i, h;
        struct sockaddr_in servaddr;
        char str1[4096], str2[4096], buf[BUFSIZE], *str;
        socklen_t len;
        fd_set   t_set1;
        struct timeval  tv;
         
         //創建套接字
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
                printf("創建網絡連接失敗,本線程即將終止---socket error!\n");
                exit(0);
        };
 
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(PORT);
        if (inet_pton(AF_INET, IPSTR, &servaddr.sin_addr) <= 0 ){
                printf("創建網絡連接失敗,本線程即將終止--inet_pton error!\n");
                exit(0);
        };
 
        if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
                printf("連接到伺服器失敗,connect error!\n");
                exit(0);
        }
        printf("與遠端建立了連接\n");
        memset(str2, 0, 4096);
        str=(char *)malloc(128);
        len = strlen(str2);
        sprintf(str, "%d", len);
 
        memset(str1, 0, 4096);
        strcat(str1, "GET / HTTP/1.1\n");
        strcat(str1, "Host: 202.38.93.111\n");
        strcat(str1, "\n\n");
 
        // strcat(str1, str2);
        strcat(str1, "\r\n\r\n");
        printf("%s\n",str1);
 
        ret = write(sockfd,str1,strlen(str1));
        if (ret < 0) {
                printf("發送失敗!錯誤代碼是%d,錯誤信息是'%s'\n",errno, strerror(errno));
                exit(0);
        }else{
                printf("消息發送成功,共發送了%d個字節!\n\n", ret);
        }
 
        FD_ZERO(&t_set1);
        FD_SET(sockfd, &t_set1);
 
        while(1){
                sleep(2);
                tv.tv_sec= 0;
                tv.tv_usec= 0;
                h= 0;
                // printf("--------------->1\n");
                h= select(sockfd +1, &t_set1, NULL, NULL, &tv);
                // printf("--------------->2\n");
 
                //if (h == 0) continue;
                if (h < 0) {
                        close(sockfd);
                        printf("在讀取數據報文時SELECT檢測到異常,該異常導致線程終止!\n");
                        return -1;
                };
 
                if (h > 0){
                        memset(buf, 0, 4096);
                        i= read(sockfd, buf, 4095);
                        if (i==0){
                                close(sockfd);
                                printf("讀取數據報文時發現遠端關閉,該線程終止!\n");
                                return -1;
                        }
 
                        printf("%s\n", buf);
						break;
                }
        }
        close(sockfd);
 
 
        return 0;
}

得到 index.html 文件獲知關鍵信息

<script>
      const term = new Terminal();
      const fitAddon = new FitAddon.FitAddon();
      term.loadAddon(fitAddon);
      term.open(document.getElementById("terminal"));
      fitAddon.fit();
      window.addEventListener('resize', function(event) {
        fitAddon.fit();
      });
      var firstmsg = true;
      const socket = new WebSocket(
         "ws://202.38.93.111:0/shell"
      );
      const attachAddon = new AttachAddon.AttachAddon(socket);
      term.loadAddon(attachAddon);
      socket.onclose = event => {
        term.write("\nConnection closed");
      };
      socket.onmessage = event => {
        if (firstmsg) {
          firstmsg = false;
          let token = new URLSearchParams(window.location.search).get("token");
          window.history.replaceState({}, null, '/');
          if (token) {
            localStorage.setItem('token', token);
          } else {
            token = localStorage.getItem('token');
          }
          if (token) socket.send(token + "\n");
        }
      };
      term.focus();
    </script>

然後又整了個 C++ 的 websocket,連上他的伺服器,發送 token,flag 到手

easywsclient: connecting: host=202.38.93.111 port=0 path=/shell
Connected to: ws://202.38.93.111:0/shell
>>> 2533:MEUCIQCz8PiKvLdy1K7+TZJTwqM581W17UdJRfk3Q6hxPtr6sQIgb+Cy14NALA4ETpFQfXyfDhIxz10fyy0+t7GDEhEpS3c=

>>> Please input your token: 
>>> flag{TCP_P0RT_0_1s_re5erved_BUT_w0rks_e7e56860a1}

不經意傳輸#

解密消息#

某同學在某不知名百科網站上看到一個神奇的密碼學協議,叫做「不經意傳輸」(Oblivious transfer)。

於是他按照網站上描述的「1–2 oblivious transfer」自己實現了協議中一方的邏輯,你可以作為另一方與之進行交互。

完全按照百科網站上的算法來實現的協議應該不會有什麼問題吧?

點擊下載 源代碼

除了網頁終端,你也可以通過 nc 202.38.93.111 10031 來連接

源代碼

搜索一下題目裡的 1–2 oblivious transfer 查到了 這個

然後打開 python 照上面的步驟一步一步就可以拿到解密的消息

flag{U_R_0n_Th3_ha1f_way_0f_succe55_w0rk_h4rder!_163a930598}

超安全的代理伺服器#

找到 Secret#

在 2039 年,爆發了一場史無前例的疫情。為了便於在各地的同學訪問某知名大學「褲子大」的網站進行「每日健康打卡」,小 C 同學為大家提供了這樣一個代理服務。曾經信息安全專業出身的小 C 決定把這個代理設計成最安全的代理。

提示:瀏覽器可能會提示該 TLS 證書無效,與本題解法無關,信任即可。

公告:題目幫助頁面(https://146.56.228.227/help)右下角的「管理中心」鏈接有誤,應該與首頁相同,都是指向 http://127.0.0.1:8080/

地址 https://146.56.228.227/

首先進入頁面看看~

Notice: 我們已經向您 推送(PUSH) 了最新的 Secret ,但是你可能無法直接看到它。

去 google 一下,找到了 How to Test HTTP/2 Push using Google Chrome 按照裡面的指引,安裝了 HTTP/2 and SPDY indicator 擴展,打開以後看到了

The net-internals events viewer and related functionality has been removed. Please use chrome://net-export to save netlogs and the external netlog_viewer to view them.

導出了一下 log,然後在 netlog_viewer 裡尋找這一個 http/2 會話,然後很容易就可以看到

t=1410 [st=281729]  HTTP2_SESSION_SEND_RST_STREAM
                    --> description = "Duplicate pushed stream with url: https://146.56.228.227/e3b2a173-d763-409e-807c-584d13a10c92"
                    --> error_code = "7 (REFUSED_STREAM)"
                    --> stream_id = 6

訪問上面出現的 url,獲得 flag flag{d0_n0t_push_me}

參考鏈接#

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。