惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
K
Kaspersky official blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Proofpoint News Feed
G
GRAHAM CLULEY
V
Vulnerabilities – Threatpost
Security Latest
Security Latest
Scott Helme
Scott Helme
S
Securelist
美团技术团队
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
SegmentFault 最新的问题
W
WeLiveSecurity
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
AI
AI
L
Lohrmann on Cybersecurity
S
Security Affairs
Cloudbric
Cloudbric
SecWiki News
SecWiki News
爱范儿
爱范儿
雷峰网
雷峰网
Engineering at Meta
Engineering at Meta
C
Cyber Attacks, Cyber Crime and Cyber Security
大猫的无限游戏
大猫的无限游戏
N
News and Events Feed by Topic
I
InfoQ
S
Secure Thoughts
AWS News Blog
AWS News Blog
A
About on SuperTechFans
Schneier on Security
Schneier on Security
酷 壳 – CoolShell
酷 壳 – CoolShell
The Last Watchdog
The Last Watchdog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Check Point Blog
P
Palo Alto Networks Blog
博客园 - 【当耐特】
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Google DeepMind News
Google DeepMind News
Latest news
Latest news
I
Intezer
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
D
Docker

ABB00717

medusa 找不到 ssh module 中文文案排版指北 BugBounty Playbook 小知識 透過 Ubuntu 26 設定 Windows 11 雙系統並使用 Image Recovery 之踩坑全紀錄 清除 git history 中的機敏資料 編譯器筆記 部落格聚集地 HTB - Busqueda 788. Rotated Digits 396. Rotate Function 幫耳機補血! 紀錄/週刊/ 做過的夢(旅行) 做過的夢 週刊 Vol.18 週刊 Vol.17 週刊 Vol.16 做過的夢(火箭推進器和追蹤導彈) 在 Ubuntu 24.04 中安裝 python2 和 pip2 動態牆 紀錄/音樂/ 用 miniflux 和 Cloudflare Tunnel 自架 RSS Reader 週記 Vol.15 關於用了 GCC 擴充功能,而被批評不夠 Clean Code 這檔事 GDB Makefile HTB - TwoMillion 週記 Vol.14 紀錄/Hack-The-Box/ 週記 Vol.13 ABB00717's Blog 1980. Find Unique Binary String 週記 Vol.12 紀錄/Leetcode/ 在互聯網上,什麼該說,什麼又不該說? 週記 Vol.8 週記 Vol.7 天才之於一種義務 就算 LLM 能解答所有問題,你也不該放棄學習 Stack-Based Buffer Overflow 筆記/書籍/ 《絕佳時間》 週記 Vol.5 偽深刻的自我解構 筆記/Linux-雜項筆記/ 解決 Ubuntu 待機後喚醒異常的問題 將應用程式新增到 GNOME 的 Activities Overview 週記 Vol.4 Assembly Language 週記 Vol.3 筆記/ 文章/ 紀錄/ 資源/ 挑戰 週記 Vol.2 部落格該有的東西 週記 Vol.1 數學符號表 Advent of Code Day 8 Advent of Code Day 7 Obsidian 無痛轉成 Blog Advent of Code Day 6
週記 Vol.6
2026-01-25 · via ABB00717

不知道為什麼,這周感覺過得特別漫長 …。

音樂

這禮拜大部分聽的都是舊專輯,也沒有挖掘到想讓我大書特書的新專輯,就不寫心得了。

Hack The Box

Source

這禮拜完成了 Footprinting 模組。基本上就是針對企業內部常見服務的枚舉與嗅探大全。涵蓋了 NFS, FTP, SMB, DNS, IMAP, SNMP 等等。學會了如何掃描這些服務、尋找設定錯誤的權限,或是預設憑證來當作突破口。這部分比較偏向體力活和記憶,就是把工具指令記熟。

Quine

我還記得大二下 OOP 教授說過他以前做過 Quine(也鼓勵我們自己做一個),當時讀 Ken Thompson 的經典論文 Reflections on Trusting Trust 時,也大概理解 Quine 的邏輯,但一直沒親手實作過,直到這禮拜 Tsoding 出這隻影片 Self-Reproducing Programs

其實他的思路非常簡單,就是把程式分成「框架」和「數據」兩部分,重點在於如何用一個字串來表示程式自身,並將其格式化輸出。

char *self = "...";
 
int main() {
    print("%s", self);
}

最後就可以變成這樣:

#include <stdio.h>
#include <string.h>
 
int main() {
    // 利用 `~` 當作佔位符表示自己(`self`)
    // 推薦用魔法來複製和編輯程式骨架
    // Emacs & Vim: Could your VSCode do this?
    char *self = "#include <stdio.h>\n#include <string.h>\n\nint main() {\n    char *self = \"~\";\n    int n = strlen(self);\n\n    for (int i = 0; i < n; i++) {\n        if (self[i] == 126) {\n            for (int j = 0; j < n; j++) {\n                switch (self[j]) {\n                    case '\\n':\n                        printf(\"\\\\n\");\n                        break;\n                    case '\"':\n                        printf(\"\\\\\\\"\");\n                        break;\n                    case '\\\\':\n                        printf(\"\\\\\\\\\");\n                        break;\n                    default:\n                        printf(\"%c\", self[j]);\n                }\n            }\n        } else {\n            printf(\"%c\", self[i]);\n        }\n    }\n}\n";
    int n = strlen(self);
 
    // 透過遍歷 `self` 輸出 `main.c` 的程式框架
    for (int i = 0; i < n; i++) {
        // 當遇到 `~` 時,代表我們要一五一十的把整個字串輸出出來
        if (self[i] == 126) {
            for (int j = 0; j < n; j++) {
                switch (self[j]) {
                    // 這是最簡單的情況,遇到 \n 不能換行,而是要輸出 \n,為了輸出 \n 就必須用到逃脫字元 \
                    case '\n':
                        printf("\\n");
                        break;
                    // 這很酷。在上面 `self` 時,我們如果要表示 ",就必須用逃脫字元 \。而在這裡我們為了輸出 \ 和 ",我們必須個別為他們添上逃脫字元,也就變成了 \\\"
                    case '"':
                        printf("\\\"");
                        break;
                    // 同理!
                    case '\\':
                        printf("\\\\");
                        break;
                    default:
                        printf("%c", self[j]);
                }
            }
        } else {
            printf("%c", self[i]);
        }
    }
}

超酷的!還有其他的一些東東:

  • Wiki - Bloo:一個收藏各種語言的各種版本 Quine 實做的網站。

  • Github - Quine-Relay 一個 Ruby 程式,生成 Rust,再生成 Scala… 經歷 128 種語言後再變回原本的 Ruby 程式碼。藝術品 …

When I say that the programming language doesn’t matter, I hope you know where I’m coming from.

編譯器

這禮拜也看了些編譯器的東西。

總之我現在大概知道了編譯器的架構,分成前端、中端、後端。我原本對編譯器的理解只有停在詞法分析、語法分析、語義檢查的前端部份,中端和後端是最近才知道的。不過就我觀察,大部分自幹的編譯器,好像也都只專住在前端而已。

不需要分號的 C 編譯器

我好像變成 Tsoding 的 “Fanboy” 了 …。其實原理意外簡單,tinycc 的 Parser 在分析完一段 Statement 後會預期並檢查是否有分號,我們只要把那個「強制檢查」改成「可選」甚至是「略過」就好。

#include <stdio.h>
 
int main(){
    printf("Hello World\n")
    printf("Hello World\n")
    printf("Hello World\n")
    printf("Hello World\n")
    printf("Hello World\n")
 
    return 0
}
$ ./tcc no-semi.c
no-semi.c:5: error: ';' expected (got 'printf')

尋找 expected (got 是在哪裡報錯的。

ST_FUNC void skip(int c)
{
    if (tok != c) {
        char tmp[40];
        pstrcpy(tmp, sizeof tmp, get_tok_str(c, &tokc));
        tcc_error("'%s' expected (got '%s')", tmp, get_tok_str(tok, &tokc));
	}
    next();
}

所以我們需要找到哪裡呼叫了 skip(';')。透過 grep 可以發現它藏在 block 函數處理 Expression 的地方。

static void block(int flags)
{
...
                /* expression case */
            if (t != ';') {
                unget_tok(t);
    expr:
                if (flags & STMT_EXPR) {
                    vpop();
                    gexpr();
                } else {
                    gexpr();
                    vpop();
                }
                skip(';');
            }
...
}

這就是處理 Expression 的地方,把它邏輯改成「如果遇到 ; 再跳過」就可以了。

if (tok == ';') skip(';');

對於 return 也是如此。

...
    } else if (t == TOK_RETURN) {
        ...
        if (b)
            gfunc_return(&func_vt);
        if (tok == ';') skip(';');
        /* jump unless last stmt in top-level block */
        ...
    } else if (t == TOK_BREAK) {
...
$ ./tcc no-semi.c
$ ./a.out
Hello World
Hello World
Hello World
Hello World
Hello World

看!多奇妙啊!

寒假

寒假已經過了 5/9 個禮拜了天啊天啊天啊啊啊啊啊啊啊啊啊。

  • 預習編譯器、資料庫的課程,主要是把書粗略看一遍就差不多了
  • 剪輯演算法的影片,主要是動態規劃、貪婪演算法的部份(現在決定睡前剪)
  • 狂幹 HackTheBox Academy,當然希望可以直接把 CPTS Path 的所有 Modules 都看完
  • 制定專題《基於多維度漏洞挖掘之 IoT 設備安全審計與更新機制研究》的總體大綱