summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
l---------COPYING1
-rw-r--r--archetypes/default.md5
-rw-r--r--assets/main.scss248
-rw-r--r--content/_index.html3
-rw-r--r--haunt.scm25
-rw-r--r--images/bctf23_electronical-mountain_aes.pngbin0 -> 374007 bytes
-rw-r--r--images/bctf23_electronical-tux_aes.pngbin0 -> 305925 bytes
-rw-r--r--images/crewctf24_sniff/breadboard.jpgbin0 -> 528702 bytes
-rw-r--r--images/crewctf24_sniff/converted_eink_image.pngbin0 -> 1221 bytes
-rw-r--r--images/crewctf24_sniff/device.jpgbin0 -> 445374 bytes
-rw-r--r--images/crewctf24_sniff/digikey_datasheet.pngbin0 -> 173220 bytes
-rw-r--r--images/crewctf24_sniff/discord1.pngbin0 -> 88621 bytes
-rw-r--r--images/crewctf24_sniff/discord2.pngbin0 -> 118490 bytes
-rw-r--r--images/crewctf24_sniff/display1.jpgbin0 -> 351672 bytes
-rw-r--r--images/crewctf24_sniff/display2.jpgbin0 -> 514576 bytes
-rw-r--r--images/crewctf24_sniff/everything.jpgbin0 -> 390392 bytes
-rw-r--r--images/crewctf24_sniff/failed_flag.pngbin0 -> 1234 bytes
-rw-r--r--images/crewctf24_sniff/flag1.pngbin0 -> 500 bytes
-rw-r--r--images/crewctf24_sniff/flag2.pngbin0 -> 425 bytes
-rw-r--r--images/crewctf24_sniff/logic1.jpgbin0 -> 488848 bytes
-rw-r--r--images/crewctf24_sniff/logic2.jpgbin0 -> 583364 bytes
-rw-r--r--images/crewctf24_sniff/logic2_i2c_1.pngbin0 -> 12031 bytes
-rw-r--r--images/crewctf24_sniff/logic2_i2c_2.pngbin0 -> 110033 bytes
-rw-r--r--images/crewctf24_sniff/logic2_main.pngbin0 -> 43959 bytes
-rw-r--r--images/crewctf24_sniff/logic2_spi.pngbin0 -> 80047 bytes
-rw-r--r--images/crewctf24_sniff/logic2_spi_update_times.pngbin0 -> 16836 bytes
-rw-r--r--images/crewctf24_sniff/pi1.jpgbin0 -> 273607 bytes
-rw-r--r--images/crewctf24_sniff/pi2.jpgbin0 -> 401916 bytes
-rw-r--r--images/crewctf24_sniff/rpi_pinout.pngbin0 -> 108254 bytes
-rw-r--r--images/deadface23-shattered_dreams-forum.pngbin0 -> 97043 bytes
-rw-r--r--layouts/blog/rss.xml39
-rw-r--r--layouts/blog/section.html10
-rw-r--r--layouts/partials/foot.html4
-rw-r--r--layouts/partials/head.html14
-rw-r--r--posts/bctf23_electronical.md301
-rw-r--r--posts/crewctf24_sniff.md369
-rw-r--r--posts/csaw23_rebug1.md97
-rw-r--r--posts/deadface23_hostbusters3.md37
-rw-r--r--posts/deadface23_shattered-dreams.md166
-rw-r--r--posts/kobo_clara-custom-distro.md (renamed from content/blog/kobo_clara-custom-distro.md)88
-rw-r--r--posts/kobo_clara-nickel.md (renamed from content/blog/kobo_clara-nickel.md)9
-rw-r--r--posts/kobo_clara-plato.md (renamed from content/blog/kobo_clara-plato.md)7
-rw-r--r--posts/st-bitmap-font-fix.md (renamed from content/blog/st-bitmap-font-fix.md)8
-rw-r--r--posts/tmpfilehost.md (renamed from content/blog/tmpfilehost.md)8
-rw-r--r--posts/vfio-win10.md (renamed from content/blog/vfio-win10.md)8
-rw-r--r--posts/workflow_9years.md231
-rw-r--r--static/agpl-3.0.txt661
-rw-r--r--static/bsd_license.txt24
-rw-r--r--static/cc-by-nc-sa-4.0.txt (renamed from static/cc-by-4.0.txt)99
-rw-r--r--static/main.css203
-rw-r--r--theme.scm73
-rwxr-xr-xupdate.sh4
52 files changed, 2302 insertions, 440 deletions
diff --git a/COPYING b/COPYING
new file mode 120000
index 0000000..3fc648a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1 @@
static/agpl-3.0.txt \ No newline at end of file
diff --git a/archetypes/default.md b/archetypes/default.md
deleted file mode 100644
index c6f3fce..0000000
--- a/archetypes/default.md
+++ /dev/null
@@ -1,5 +0,0 @@
1+++
2title = '{{ replace .File.ContentBaseName "-" " " | title }}'
3date = {{ .Date }}
4draft = true
5+++
diff --git a/assets/main.scss b/assets/main.scss
deleted file mode 100644
index cea2e5e..0000000
--- a/assets/main.scss
+++ /dev/null
@@ -1,248 +0,0 @@
1$background: #0e0c06;
2$foreground: #d4b782;
3$black: #1b1918;
4$brblack: #544b44;
5$red: #d42215;
6$green: #358c15;
7$yellow: #9a6200;
8$blue: #00458d;
9$magenta: #773dbf;
10$cyan: #008a7b;
11$white: #cfb688;
12
13html {
14 font-family: sans-serif;
15 color: $foreground;
16 background-color: $background;
17}
18
19body {
20 max-width: 920px;
21 margin: 0 auto;
22 padding: 1rem;
23 font-family: monospace;
24}
25
26h1 {
27 margin-top: 0;
28 font-size: 1.5rem;
29
30 small {
31 display: block;
32 font-size: 1rem;
33 }
34}
35
36a {
37 color: $yellow;
38 text-decoration: none;
39}
40
41a:hover {
42 color: $yellow;
43 text-decoration: underline;
44}
45
46a:visited {
47 color: $green;
48}
49
50.index {
51 display: flex;
52 flex-direction: row;
53
54 .article-list {
55 flex-grow: 1;
56 margin: auto;
57 max-width: 600px;
58
59 .article {
60 margin-bottom: 1rem;
61 }
62
63 .date {
64 display: block;
65 color: $brblack;
66 }
67 }
68
69 aside {
70 width: 40%;
71
72 img {
73 display: block;
74 margin: 0 auto 1rem;
75 border-radius: 5px;
76 }
77
78 dt {
79 font-size: 0.9rem;
80 }
81
82 dd {
83 margin-left: 0;
84
85 &:not(:last-child) {
86 margin-bottom: 0.5rem;
87 }
88 }
89 }
90
91 @media(max-width: 640px) {
92 aside {
93 display: none;
94 }
95 }
96}
97
98article {
99 margin: 0 auto;
100 max-width: 720px;
101 line-height: 1.3;
102
103 img, video, iframe {
104 // !important for asciinema frames
105 display: block !important;
106 margin: 0 auto !important;
107 max-width: 90%;
108
109 @media(max-width: 640px) {
110 max-width: calc(100% - 2rem);
111 }
112 }
113
114 .comment {
115 margin: 2rem auto 0;
116 max-width: 80%;
117 color: #333;
118 }
119}
120
121.footnotes {
122 font-size: 0.85rem;
123}
124
125footer {
126 margin-top: 2rem;
127 text-align: center;
128 font-size: 0.8rem;
129 color: #333;
130}
131
132.float-img {
133 float: right;
134 display: inline;
135 padding-left: 1rem;
136
137 @media(max-width: 640px) {
138 display: block;
139 float: none;
140 padding-left: inherit;
141 }
142}
143
144pre {
145 background-color: $black;
146 padding: 0.25rem 1rem;
147 margin: 0 -1rem;
148 max-width: 100%;
149 overflow-x: auto;
150
151 .cp {
152 color: #800;
153 }
154
155 .k {
156 color: #008;
157 }
158
159 .kt, .kd, .kc {
160 color: #44F;
161 }
162
163 .s {
164 color: #484;
165 font-style: italic;
166 }
167
168 .cm, .c1 {
169 color: #333;
170 font-style: italic;
171 }
172
173 .gi {
174 color: $green;
175 }
176
177 .gd {
178 color: $red;
179 }
180
181 .gu {
182 color: $blue;
183 }
184}
185
186summary {
187 cursor: pointer;
188 background-color: $black;
189 padding: 0.25rem 1rem;
190 margin: 0 -1rem;
191}
192
193details[open] {
194 border-bottom: 1rem solid $black;
195 margin: 0 -1rem 1rem;
196 padding: 0 1rem;
197}
198
199.text-center {
200 text-align: center;
201}
202
203blockquote {
204 border-left: 5px solid #bbb;
205 background-color: $black;
206 padding: 0 1rem;
207 margin-left: calc(-1rem - 5px);
208 margin-right: -1rem;
209
210 blockquote {
211 margin-right: 0;
212 margin-left: 0;
213 }
214}
215
216dl {
217 display: grid;
218 grid-template-columns: auto 1fr;
219 grid-gap: 0.2rem 1rem;
220
221 dt {
222 font-weight: bold;
223 grid-column-start: 1;
224 }
225
226 dd {
227 grid-column-start: 2;
228 margin: 0;
229 }
230}
231
232.alert {
233 padding: 0.5rem;
234 border: 1px solid transparent;
235 margin-bottom: 1rem;
236
237 &.alert-danger {
238 background: #f8d7da;
239 color: #721c24;
240 border-color: #f5c6cb;
241 }
242
243 &.alert-info {
244 background: #d1ecf1;
245 color: #0c5460;
246 border-color: #bee5eb;
247 }
248}
diff --git a/content/_index.html b/content/_index.html
deleted file mode 100644
index 2f84b49..0000000
--- a/content/_index.html
+++ /dev/null
@@ -1,3 +0,0 @@
1---
2title: Vineet's site
3---
diff --git a/haunt.scm b/haunt.scm
new file mode 100644
index 0000000..b6d799a
--- /dev/null
+++ b/haunt.scm
@@ -0,0 +1,25 @@
1(use-modules (haunt asset)
2 (haunt builder blog)
3 (haunt builder atom)
4 (haunt builder assets)
5 (haunt reader commonmark)
6 (haunt publisher rsync)
7 (haunt post)
8 (haunt site)
9 (theme))
10
11(site #:title "Vineet's site"
12 #:domain "vineetk.net"
13 #:default-metadata
14 '((author . "Vineet K")
15 (email . "me@vineetk.net"))
16 #:readers (list commonmark-reader)
17 #:builders (list (blog #:theme vin-theme
18 #:collections
19 `(("Posts" "index.html" ,posts/reverse-chronological)))
20 (atom-feed)
21 (static-directory "images")
22 (static-directory "static"))
23 #:publishers (list (rsync-publisher #:destination "/var/www/vineetk_html/"
24 #:user "vin"
25 #:host "saklas")))
diff --git a/images/bctf23_electronical-mountain_aes.png b/images/bctf23_electronical-mountain_aes.png
new file mode 100644
index 0000000..2349e95
--- /dev/null
+++ b/images/bctf23_electronical-mountain_aes.png
Binary files differ
diff --git a/images/bctf23_electronical-tux_aes.png b/images/bctf23_electronical-tux_aes.png
new file mode 100644
index 0000000..0c0e0f8
--- /dev/null
+++ b/images/bctf23_electronical-tux_aes.png
Binary files differ
diff --git a/images/crewctf24_sniff/breadboard.jpg b/images/crewctf24_sniff/breadboard.jpg
new file mode 100644
index 0000000..63ce2b7
--- /dev/null
+++ b/images/crewctf24_sniff/breadboard.jpg
Binary files differ
diff --git a/images/crewctf24_sniff/converted_eink_image.png b/images/crewctf24_sniff/converted_eink_image.png
new file mode 100644
index 0000000..d017563
--- /dev/null
+++ b/images/crewctf24_sniff/converted_eink_image.png
Binary files differ
diff --git a/images/crewctf24_sniff/device.jpg b/images/crewctf24_sniff/device.jpg
new file mode 100644
index 0000000..b4341c9
--- /dev/null
+++ b/images/crewctf24_sniff/device.jpg
Binary files differ
diff --git a/images/crewctf24_sniff/digikey_datasheet.png b/images/crewctf24_sniff/digikey_datasheet.png
new file mode 100644
index 0000000..8451edd
--- /dev/null
+++ b/images/crewctf24_sniff/digikey_datasheet.png
Binary files differ
diff --git a/images/crewctf24_sniff/discord1.png b/images/crewctf24_sniff/discord1.png
new file mode 100644
index 0000000..5210b70
--- /dev/null
+++ b/images/crewctf24_sniff/discord1.png
Binary files differ
diff --git a/images/crewctf24_sniff/discord2.png b/images/crewctf24_sniff/discord2.png
new file mode 100644
index 0000000..3c9563f
--- /dev/null
+++ b/images/crewctf24_sniff/discord2.png
Binary files differ
diff --git a/images/crewctf24_sniff/display1.jpg b/images/crewctf24_sniff/display1.jpg
new file mode 100644
index 0000000..9e2b123
--- /dev/null
+++ b/images/crewctf24_sniff/display1.jpg
Binary files differ
diff --git a/images/crewctf24_sniff/display2.jpg b/images/crewctf24_sniff/display2.jpg
new file mode 100644
index 0000000..9940a6c
--- /dev/null
+++ b/images/crewctf24_sniff/display2.jpg
Binary files differ
diff --git a/images/crewctf24_sniff/everything.jpg b/images/crewctf24_sniff/everything.jpg
new file mode 100644
index 0000000..b59aced
--- /dev/null
+++ b/images/crewctf24_sniff/everything.jpg
Binary files differ
diff --git a/images/crewctf24_sniff/failed_flag.png b/images/crewctf24_sniff/failed_flag.png
new file mode 100644
index 0000000..6748138
--- /dev/null
+++ b/images/crewctf24_sniff/failed_flag.png
Binary files differ
diff --git a/images/crewctf24_sniff/flag1.png b/images/crewctf24_sniff/flag1.png
new file mode 100644
index 0000000..77eaa1f
--- /dev/null
+++ b/images/crewctf24_sniff/flag1.png
Binary files differ
diff --git a/images/crewctf24_sniff/flag2.png b/images/crewctf24_sniff/flag2.png
new file mode 100644
index 0000000..1f57257
--- /dev/null
+++ b/images/crewctf24_sniff/flag2.png
Binary files differ
diff --git a/images/crewctf24_sniff/logic1.jpg b/images/crewctf24_sniff/logic1.jpg
new file mode 100644
index 0000000..1e35cab
--- /dev/null
+++ b/images/crewctf24_sniff/logic1.jpg
Binary files differ
diff --git a/images/crewctf24_sniff/logic2.jpg b/images/crewctf24_sniff/logic2.jpg
new file mode 100644
index 0000000..f6a5c75
--- /dev/null
+++ b/images/crewctf24_sniff/logic2.jpg
Binary files differ
diff --git a/images/crewctf24_sniff/logic2_i2c_1.png b/images/crewctf24_sniff/logic2_i2c_1.png
new file mode 100644
index 0000000..fa4d16b
--- /dev/null
+++ b/images/crewctf24_sniff/logic2_i2c_1.png
Binary files differ
diff --git a/images/crewctf24_sniff/logic2_i2c_2.png b/images/crewctf24_sniff/logic2_i2c_2.png
new file mode 100644
index 0000000..96098de
--- /dev/null
+++ b/images/crewctf24_sniff/logic2_i2c_2.png
Binary files differ
diff --git a/images/crewctf24_sniff/logic2_main.png b/images/crewctf24_sniff/logic2_main.png
new file mode 100644
index 0000000..0d406ee
--- /dev/null
+++ b/images/crewctf24_sniff/logic2_main.png
Binary files differ
diff --git a/images/crewctf24_sniff/logic2_spi.png b/images/crewctf24_sniff/logic2_spi.png
new file mode 100644
index 0000000..f02c75f
--- /dev/null
+++ b/images/crewctf24_sniff/logic2_spi.png
Binary files differ
diff --git a/images/crewctf24_sniff/logic2_spi_update_times.png b/images/crewctf24_sniff/logic2_spi_update_times.png
new file mode 100644
index 0000000..11d9faf
--- /dev/null
+++ b/images/crewctf24_sniff/logic2_spi_update_times.png
Binary files differ
diff --git a/images/crewctf24_sniff/pi1.jpg b/images/crewctf24_sniff/pi1.jpg
new file mode 100644
index 0000000..794882b
--- /dev/null
+++ b/images/crewctf24_sniff/pi1.jpg
Binary files differ
diff --git a/images/crewctf24_sniff/pi2.jpg b/images/crewctf24_sniff/pi2.jpg
new file mode 100644
index 0000000..26e40f1
--- /dev/null
+++ b/images/crewctf24_sniff/pi2.jpg
Binary files differ
diff --git a/images/crewctf24_sniff/rpi_pinout.png b/images/crewctf24_sniff/rpi_pinout.png
new file mode 100644
index 0000000..b8f4aaf
--- /dev/null
+++ b/images/crewctf24_sniff/rpi_pinout.png
Binary files differ
diff --git a/images/deadface23-shattered_dreams-forum.png b/images/deadface23-shattered_dreams-forum.png
new file mode 100644
index 0000000..ea9557a
--- /dev/null
+++ b/images/deadface23-shattered_dreams-forum.png
Binary files differ
diff --git a/layouts/blog/rss.xml b/layouts/blog/rss.xml
deleted file mode 100644
index 3d3ae80..0000000
--- a/layouts/blog/rss.xml
+++ /dev/null
@@ -1,39 +0,0 @@
1{{- $pctx := . -}}
2{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
3{{- $pages := slice -}}
4{{- if or $.IsHome $.IsSection -}}
5{{- $pages = $pctx.RegularPages -}}
6{{- else -}}
7{{- $pages = $pctx.Pages -}}
8{{- end -}}
9{{- $limit := .Site.Config.Services.RSS.Limit -}}
10{{- if ge $limit 1 -}}
11{{- $pages = $pages | first $limit -}}
12{{- end -}}
13{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
14<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
15 <channel>
16 <title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title>
17 <link>https://open.crates.im</link>
18 <description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description>
19 <generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
20 <language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
21 <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
22 <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
23 <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
24 <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
25 {{ with .OutputFormats.Get "RSS" }}
26 {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
27 {{ end }}
28 {{ range $pages }}
29 <item>
30 <title>{{ .Title }}</title>
31 <link>{{ .Permalink }}</link>
32 <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
33 {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
34 <guid>{{ .Permalink }}</guid>
35 <description>{{- .Content | html -}}</description>
36 </item>
37 {{ end }}
38 </channel>
39</rss>
diff --git a/layouts/blog/section.html b/layouts/blog/section.html
deleted file mode 100644
index 9466f77..0000000
--- a/layouts/blog/section.html
+++ /dev/null
@@ -1,10 +0,0 @@
1<!doctype html>
2<html lang="en">
3<meta charset="utf-8" />
4<title>{{.Title}}</title>
5{{ $style := resources.Get "main.scss" | css.Sass | resources.Minify | resources.Fingerprint }}
6<link rel="stylesheet" href="{{ $style.RelPermalink }}">
7
8<main>
9 {{.Content}}
10</main>
diff --git a/layouts/partials/foot.html b/layouts/partials/foot.html
deleted file mode 100644
index 203510a..0000000
--- a/layouts/partials/foot.html
+++ /dev/null
@@ -1,4 +0,0 @@
1<footer>
2 The content for the site is under <a href="/cc-by-4.0.txt">CC-BY-4.0</a>.
3 The code is under the <a href="/bsd_license.txt">2-Clause BSD License</a> unless specified otherwise.
4</footer>
diff --git a/layouts/partials/head.html b/layouts/partials/head.html
deleted file mode 100644
index 3e6ccaa..0000000
--- a/layouts/partials/head.html
+++ /dev/null
@@ -1,14 +0,0 @@
1<!doctype html>
2<html lang="en">
3<head>
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1" />
6 {{ if $.Params.noindex }}
7 <meta name="robots" content="noindex">
8 {{ end }}
9 <title>{{$.Title}}</title>
10 <link rel="alternate" type="application/rss+xml" title="RSS" href="https://vineetk.net/blog/index.xml">
11 <link rel="icon" type="image/png" href="/AT_terminus.png">
12 {{ $style := resources.Get "main.scss" | css.Sass | resources.Fingerprint }}
13 <link rel="stylesheet" href="{{ $style.RelPermalink }}">
14</head>
diff --git a/posts/bctf23_electronical.md b/posts/bctf23_electronical.md
new file mode 100644
index 0000000..3f82ecb
--- /dev/null
+++ b/posts/bctf23_electronical.md
@@ -0,0 +1,301 @@
1title: BCTF23 crypto/Electronical (medium) Writeup
2date: 2023-10-26 12:00
3---
4
5> I do all my ciphering electronically. https://electronical.chall.pwnoh.io/
6
7When going to the linked site, you get told to encrypt any message or view the
8site's source code. After submitting a message to encrypt, it returns some hex
9string.
10
11The source is:
12```python
13from Crypto.Cipher import AES
14from flask import Flask, request, abort, send_file
15import math
16import os
17
18app = Flask(__name__)
19
20key = os.urandom(32)
21flag = os.environ.get('FLAG', 'bctf{fake_flag_fake_flag_fake_flag_fake_flag}')
22
23cipher = AES.new(key, AES.MODE_ECB)
24
25def encrypt(message: str) -> bytes:
26 length = math.ceil(len(message) / 16) * 16
27 padded = message.encode().ljust(length, b'\0')
28 return cipher.encrypt(padded)
29
30def decrypt(msg: str) -> bytes:
31 return cipher.decrypt(msg)
32
33@app.get('/encrypt')
34def handle_encrypt():
35 param = request.args.get('message')
36
37 if not param:
38 return abort(400, "Bad")
39 if not isinstance(param, str):
40 return abort(400, "Bad")
41
42 print(encrypt(param + flag))
43
44 return encrypt(param + flag).hex()
45
46@app.get('/source')
47def handle_source():
48 return send_file(__file__, "text/plain")
49
50@app.get('/')
51def handle_home():
52 return """
53 <style>
54 form {
55 display: flex;
56 flex-direction: column;
57 max-width: 20em;
58 gap: .5em;
59 }
60
61 input {
62 padding: .4em;
63 }
64 </style>
65 <form action="/encrypt">
66 <h2><i>ELECTRONICAL</i></h2>
67 <label for="message">Message to encrypt:</label>
68 <input id="message" name="message"></label>
69 <input type="submit" value="Submit">
70 <a href="/source">Source code</a>
71 </form>
72 """
73
74if __name__ == "__main__":
75 app.run()
76```
77It seems that the flag is appended to the user's message and then encrypted with
78AES-ECB. The total message is also padded to be a multiple of 16 bytes.
79
80According to Wikipedia, ECB (electronic codebook) works by dividing a message
81into blocks of a certain size (like 16 bytes). The problem however is that ECB
82doesn't attempt to make any encrypted block unique like by adding a salt or
83nonce, so any blocks of data that are identical would also be identical when
84encrypted. Wikipedia also has an interesting example of encrypting an image of
85Tux and a mountain (on French Wikipedia) with AES.
86
87![Tux AES](images/bctf23_electronical-tux_aes.png)
88
89![Mountain AES](images/bctf23_electronical-mountain_aes.png)
90
91Through some more searching online, it seems a way to exploit this is with
92something called a Chosen Plaintext Attack. Since the message before the flag is
93controlled by us the user (attacker?) and the flag is appended to the end, the
94provided message can be made in a way that only one byte of the flag needs to be
95bruteforced at a time.
96
97Let's say that this is our message: `thischallengesucksFLAG{5om3_!mp0r74nt_$3cr37}`
98
99This string is 45 characters, so the server would pad this with 3 \0 characters
100to make it evenly divisible by 16 characters.
101
102```
103b'thischallengesucksFLAG{5om3_!mp0r74nt_$3cr37}\x00\x00\x00'
104```
105
106We know what "thischallengesucks" is, but FLAG and anything else after is
107appended by the server and is what we're trying to find.
108
109"thischallengesucks" is 18 characters, but if we send a 15 character string,
110then the first block to be encrypted would be "thischallengesu?", where ? is the
111mystery character.
112
113For readability purposes, I'm going to use repeated "0" characters needed
114instead of "thischallengesucks".
115
116When passing "000000000000000?" to the server, a certain hex string would be
117returned (newlines every 32 characters not included in original):
118
119```
120b57189530dacbb9c5707c1cb0b044a34
1215377049685bb9553a73e4408565505dd
1220c614f69c4749b10f8cbc9c735fd7314
1235a9ae527825603a8eb0dba6a0347a4e5
124```
125Replacing the ? with any other character would result in only the first row being
126changed, like with "000000000000000A":
127
128```
129b2457a857e82a1d5ad919a4bdaf9133a
1307835c84bc75d836fad8ca5fbcec086ff
131937cf83a682fa26162a65f2295b2b119
1326b398dd6f75e212b1633c5189bdb5689
133```
134Since the other three blocks remained the same, the last character in the
135message being sent simply needs to bruteforced with every printable character
136until it results in the same block from ?. In this case, that character would be
137F:
138
139```
140b57189530dacbb9c5707c1cb0b044a34
1415377049685bb9553a73e4408565505dd
1420c614f69c4749b10f8cbc9c735fd7314
1435a9ae527825603a8eb0dba6a0347a4e5
144```
145```
146(0000000000000, 14 characters long)
1475ec61f1209adfeff202edbba28339f83
1484f7cc7a4c0c553380874383e93408678
149ca91d95b091956edb162da583b51051b
15033b91ab14b8807348fc98bf223b4b3a5
151
152(0000000000000FL, 16 characters long)
1535ec61f1209adfeff202edbba28339f83
1544f7cc7a4c0c553380874383e93408678
155ca91d95b091956edb162da583b51051b
15633b91ab14b8807348fc98bf223b4b3a5
157```
158Then the 0 left pad would be decreased by one character and the process repeats
159until the whole block is done. However, a flag usually won't be just 16
160characters long. I had some difficulty trying to bruteforce the 17th character
161and above because I was prepending and appending the zeros within a single block
162(between 0 and 15 padded 0s), but that was among a few other issues I had that
163were the result of the message I was sending being in the format of "pad +
164known_flag + brute_single_char + pad" where this only worked for the first
165block. This did not work later because those messages would have the pad bytes
166in the middle of the message, which did not go well.
167
168In the end, I realized that I can check the target block hexstring by sending
169only the padded 0 bytes (or anything else of that length) without other
170characters and then append my known bytes of the flag and a single other character
171to fill that block to brute force that last character.
172
173A visual representation is this:
174
175```
176Block size: 8 characters
177
1787 pad, 0 known
179XXXXXXX?
180XXXXXXXF
181
1826 pad, 1 known
183XXXXXX??
184XXXXXXFL
185
1865 pad, 2 known
187XXXXX???
188XXXXXFLA
189
190...
191
1920 pad, 7 known
193FLAG{5o?
194
1958 known
196FLAG{5om
197```
198This only decrypts the first block, so how I decrypted each additional block was
199by prepending another block of pad characters (blocksize - 1) and repeating the
200process.
201
202```
2037 pad, 7 known
204XXXXXXXFLAG{5om?
205XXXXXXXFLAG{5om3
206
2076 pad, 8 known
208XXXXXXFLAG{5om3?
209XXXXXXFLAG{5om3_
210
211...
212
2135 pad, 26 known
214XXXXXFLAG{5om3_!mp0r74nt_$3cr37?
215XXXXXFLAG{5om3_!mp0r74nt_$3cr37}
216
217...
2180 pad, 31 known
219FLAG{5om3_!mp0r74nt_$3cr37}\0\0?
220FLAG{5om3_!mp0r74nt_$3cr37}\0\0\0
221```
222After some automating help with python, I was able to finally get the flag.
223
224```
225Flag: bctf{1_c4n7_b3l13v3_u_f0und_my_c0d3b00k}
226```
227
228My python file to solve this was:
229```python
230from requests import get
231from requests.utils import quote
232
233# list of characters that will be bruteforced, these are the printable chars
234chars = [chr(i) for i in range(ord(' '), ord('~') + 1)]
235# nul character is also checked because that's the pad character
236chars += '\0'
237
238def encrypt(msg):
239 #url = "https://electronical.chall.pwnoh.io/encrypt?message="
240 url = "http://localhost:5000/encrypt?message="
241 return get(url + quote(msg)).content;
242
243def calc_padding_for_known():
244 # divided by 2 because each hex byte is 2 characters long
245 cur = len(encrypt("0")) // 2
246
247 # 16 chosen because that's the padding chosen in app.py on the server
248 for i in range(2, 16):
249 tmp = len(encrypt("0" * i)) // 2
250 if tmp > cur:
251 return tmp, tmp - cur, i - 1
252 # shouldn't come here
253 return 0,0,0
254
255totalblocks, bs, pad = calc_padding_for_known()
256
257print(f"Block size of padding: {bs}, {pad}")
258
259# first block are known to not be the flag (is all 0 being encrypted)
260# second block is what's being bruteforced
261# third block's last character is unknown and being compared with second block
262#msg = "0" * (bs + bs - 1) + "a" * 1 + "0" * (bs - 1)
263#cur = encrypt(msg)
264#print(cur)
265flag = ""
266curflag = ""
267
268tbs = bs * 2
269
270for j in range(totalblocks // bs):
271 for i in range(1, bs + 1):
272 known = "0" * (bs * (1 + j) - len(flag) - 1)
273 msg = known
274 target = encrypt(msg).decode("utf-8")
275
276 print(f"\nNew target message: {msg}")
277 print("New target message return:")
278 print('\n'.join([target[A:A + tbs] for A in range(0, len(target), tbs)]))
279
280 target = target[tbs * (0 + j):tbs * (1 + j)]
281 print(f"New target block: {target}")
282
283 for c in chars:
284 msg = known + flag + c
285 print(f"Current character: {c}")
286 print(f"Current message: {msg}")
287 print(f"Target block: {target}")
288 cur = encrypt(msg).decode("utf-8")
289 print('\n'.join([cur[A:A + tbs] for A in range(0, len(cur), tbs)]))
290
291 print(f"Current block: {cur[:tbs]}")
292
293 if (cur[tbs * (0 + j):tbs * (1 + j)] == target):
294 flag += c
295 print(flag)
296 break
297
298 print("\n")
299 curflag += flag
300print(flag)
301```
diff --git a/posts/crewctf24_sniff.md b/posts/crewctf24_sniff.md
new file mode 100644
index 0000000..32d1adb
--- /dev/null
+++ b/posts/crewctf24_sniff.md
@@ -0,0 +1,369 @@
1title: CrewCTF2024 misc/Sniff Writeup
2date: 2024-08-04 12:00
3---
4## Challenge
5### Description
6> I came across this mysterious device. So I hooked up my logic analyzer
7and recorded somebody using it. (`capture.sol`)
8This challenge has two flags in the `flag{}` format
9> * The first (easier) is the password that was typed on the keyboard.
10> * The second (significantly harder) is what was display on the screen after the password was entered.
11
12### Images
13![Device](https://vineetk.net/images/crewctf24_sniff/device.jpg)
14
15![Everything](https://vineetk.net/images/crewctf24_sniff/everything.jpg)
16
17![Raspberry Pi first](https://vineetk.net/images/crewctf24_sniff/pi1.jpg)
18
19![Raspberry Pi second](https://vineetk.net/images/crewctf24_sniff/pi2.jpg)
20
21![Logic Analyzer first](https://vineetk.net/images/crewctf24_sniff/logic1.jpg)
22
23![Logic Analyzer second](https://vineetk.net/images/crewctf24_sniff/logic2.jpg)
24
25![Display first](https://vineetk.net/images/crewctf24_sniff/display1.jpg)
26
27![Display second](https://vineetk.net/images/crewctf24_sniff/display2.jpg)
28
29## Intro
30Instead of sleeping, I made the mistake^Wwise decision of looking at my
31Discord notification that said there was a hardware challenge in this CTF. It
32just so happened that there it was using an ATmega-powered keyboard and an
33e-paper screen, and it almost seemed like a coincidence since I was designing
34my own keyboard and wanted to interface with an e-paper screen in the near
35future. This seemed like a great learning opportunity so I started working on
36the two-part challenge.
37
38There were a few files inside the `dist.zip`, with the most
39interesting one being capture.sal which was technically a zip but actually
40the analyzer file for Salae. Sadly it seemed to need their proprietary
41program to open.
42
43![Screenshot of Saleae Logic 2, the program used for viewing the dump.](https://vineetk.net/images/crewctf24_sniff/logic2_main.png)
44
45The first thing I did was figuring out what each channel was connected to
46and what it meant. It seemed that the keyboard and display were controlled by
47the Raspberry Pi which then seemed to go to the logic analyzer. So I looked
48at what each channel was connected to and based on its connected pin on the
49Pi, I found its function via pinout.xyz. I ended up with this:
50
51```
52Channel 0: P03 I2C SDA
53Channel 1: P05 I2C SCL
54Channel 2: P11 GPIO 17 (busy)
55Channel 3: P13 GPIO 27 (reset)
56Channel 4: P15 GPIO 22 (data/command)
57Channel 5: P21 MOSI
58Channel 6: P23 SPI0 SCLK
59Channel 7: P24 SPI0 CE0
60```
61
62![Raspberry Pi Pinout](https://vineetk.net/images/crewctf24_sniff/rpi_pinout.png)
63
64## Part 1
65In Logic 2, I opened the I2C analyzer and outputted the dump in the
66terminal tab into a file
67
68![I2C analyzer screenshot in Logic 2 in the Terminal view.](https://vineetk.net/images/crewctf24_sniff/logic2_i2c_1.png)
69![I2C analyzer screenshot in Logic 2 in the Data Table view.](https://vineetk.net/images/crewctf24_sniff/logic2_i2c_2.png)
70It seemed there was a lot of NUL bytes being sent, probably indicating
71that there wasn’t anything during that cycle, and a few seconds later there
72were also some other different bytes with NUL and some `0x01`
73bytes in between, and these seemed to be printable ASCII.
74
75```
76read to 0x5F ack data: 0x01
77read to 0x5F ack data: 0x01
78read to 0x5F ack data: 0x66
79read to 0x5F ack data: 0x6c
80read to 0x5F ack data: 0x61
81read to 0x5F ack data: 0x67
82read to 0x5F ack data: 0x7b
83read to 0x5F ack data: 0x37
84read to 0x5F ack data: 0x01
85read to 0x5F ack data: 0x31
86read to 0x5F ack data: 0x37
87read to 0x5F ack data: 0x66
88read to 0x5F ack data: 0x37
89read to 0x5F ack data: 0x35
90read to 0x5F ack data: 0x01
91read to 0x5F ack data: 0x33
92read to 0x5F ack data: 0x32
93read to 0x5F ack data: 0x7d
94read to 0x5F ack data: 0x01
95read to 0x5F ack data: 0x0d
96```
97
98Filtering out the `0x00` and `0x01` data bytes and
99converting to ASCII results in `flag{717f7532}`.
100
101## Part 2
102![Logic 2 SPI analyzer output.](https://vineetk.net/images/crewctf24_sniff/logic2_spi.png)
103
104I first outputted the SPI dump from the analyzer into a file and kept only
105the `MOSI` and `MISO` columns.
106
107```
108Time [s],Packet ID,MOSI,MISO
1094.108880200000000,0,0x12,0x00
1105.109988000000000,0,0x01,0x00
1115.110044320000000,0,0xF9,0xFF
1125.110062800000000,0,0x00,0xFF
1135.110081280000000,0,0x00,0xFF
1145.110125600000000,0,0x3A,0x00
1155.110167440000000,0,0x1B,0xFF
1165.110210120000000,0,0x3B,0x00
1175.110251760000000,0,0x0B,0xFF
118```
119
120To actually understand what’s going on, I couldn’t find any proper
121documentation initially. There wasn’t even a proper datasheet on DigiKey; the
122“datasheet” was just a summary of the product.
123
124![DigiKey “datasheet”](https://vineetk.net/images/crewctf24_sniff/digikey_datasheet.png)
125
126Then I found the [Python library
127source from Pimoroni](https://github.com/pimoroni/inky) of their epaper screens, which is probably what was
128used to make this challenge.
129
130```python
131def setup(self):
132 """Set up Inky GPIO and reset display."""
133 if not self._gpio_setup:
134 if self._gpio is None:
135 try:
136 import RPi.GPIO as GPIO
137 self._gpio = GPIO
138 except ImportError:
139 raise ImportError('This library requires the RPi.GPIO module\nInstall with: sudo apt install python-rpi.gpio')
140 self._gpio.setmode(self._gpio.BCM)
141 self._gpio.setwarnings(False)
142 self._gpio.setup(self.dc_pin, self._gpio.OUT, initial=self._gpio.LOW, pull_up_down=self._gpio.PUD_OFF)
143 self._gpio.setup(self.reset_pin, self._gpio.OUT, initial=self._gpio.HIGH, pull_up_down=self._gpio.PUD_OFF)
144 self._gpio.setup(self.busy_pin, self._gpio.IN, pull_up_down=self._gpio.PUD_OFF)
145
146 if self._spi_bus is None:
147 import spidev
148 self._spi_bus = spidev.SpiDev()
149
150 self._spi_bus.open(0, self.cs_pin)
151 self._spi_bus.max_speed_hz = 488000
152
153 self._gpio_setup = True
154
155 self._gpio.output(self.reset_pin, self._gpio.LOW)
156 time.sleep(0.5)
157 self._gpio.output(self.reset_pin, self._gpio.HIGH)
158 time.sleep(0.5)
159
160 self._send_command(0x12) # Soft Reset
161 time.sleep(1.0)
162 self._busy_wait()
163
164def _update(self, buf_a, buf_b, busy_wait=True):
165 """Update display.
166
167 Dispatches display update to correct driver.
168
169 :param buf_a: Black/White pixels
170 :param buf_b: Yellow/Red pixels
171
172 """
173 self.setup()
174
175 self._send_command(ssd1608.DRIVER_CONTROL, [self.rows - 1, (self.rows - 1) >> 8, 0x00])
176 # Set dummy line period
177 self._send_command(ssd1608.WRITE_DUMMY, [0x1B])
178 # Set Line Width
179 self._send_command(ssd1608.WRITE_GATELINE, [0x0B])
180 # Data entry squence (scan direction leftward and downward)
181 self._send_command(ssd1608.DATA_MODE, [0x03])
182 # Set ram X start and end position
183 xposBuf = [0x00, self.cols // 8 - 1]
184 self._send_command(ssd1608.SET_RAMXPOS, xposBuf)
185 # Set ram Y start and end position
186 yposBuf = [0x00, 0x00, (self.rows - 1) & 0xFF, (self.rows - 1) >> 8]
187 self._send_command(ssd1608.SET_RAMYPOS, yposBuf)
188 # VCOM Voltage
189 self._send_command(ssd1608.WRITE_VCOM, [0x70])
190 # Write LUT DATA
191 self._send_command(ssd1608.WRITE_LUT, self._luts[self.lut])
192
193 if self.border_colour == self.BLACK:
194 self._send_command(ssd1608.WRITE_BORDER, 0b00000000)
195 # GS Transition + Waveform 00 + GSA 0 + GSB 0
196 elif self.border_colour == self.RED and self.colour == 'red':
197 self._send_command(ssd1608.WRITE_BORDER, 0b00000110)
198 # GS Transition + Waveform 01 + GSA 1 + GSB 0
199 elif self.border_colour == self.YELLOW and self.colour == 'yellow':
200 self._send_command(ssd1608.WRITE_BORDER, 0b00001111)
201 # GS Transition + Waveform 11 + GSA 1 + GSB 1
202 elif self.border_colour == self.WHITE:
203 self._send_command(ssd1608.WRITE_BORDER, 0b00000001)
204 # GS Transition + Waveform 00 + GSA 0 + GSB 1
205
206 # Set RAM address to 0, 0
207 self._send_command(ssd1608.SET_RAMXCOUNT, [0x00])
208 self._send_command(ssd1608.SET_RAMYCOUNT, [0x00, 0x00])
209
210 for data in ((ssd1608.WRITE_RAM, buf_a), (ssd1608.WRITE_ALTRAM, buf_b)):
211 cmd, buf = data
212 self._send_command(cmd, buf)
213
214 self._busy_wait()
215 self._send_command(ssd1608.MASTER_ACTIVATE)
216```
217
218It was also communicating over SPI which seemed to indicate that this was
219the proper library. Then I looked at the `setup()` and
220`_update()` functions in
221`library/inky/inky_ssd1608.py`, and the SPI commands that were
222sent in the analyzed dump log matched exactly, including each byte of the LUT
223table.
224
225All the SPI commands used in the library are used with named constants
226that are defined `library/inky/ssd1608.py`:
227
228```python
229"""Constants for SSD1608 driver IC."""
230DRIVER_CONTROL = 0x01
231GATE_VOLTAGE = 0x03
232SOURCE_VOLTAGE = 0x04
233DISPLAY_CONTROL = 0x07
234NON_OVERLAP = 0x0B
235BOOSTER_SOFT_START = 0x0C
236GATE_SCAN_START = 0x0F
237DEEP_SLEEP = 0x10
238DATA_MODE = 0x11
239SW_RESET = 0x12
240TEMP_WRITE = 0x1A
241TEMP_READ = 0x1B
242TEMP_CONTROL = 0x1C
243TEMP_LOAD = 0x1D
244MASTER_ACTIVATE = 0x20
245DISP_CTRL1 = 0x21
246DISP_CTRL2 = 0x22
247WRITE_RAM = 0x24
248WRITE_ALTRAM = 0x26
249READ_RAM = 0x25
250VCOM_SENSE = 0x28
251VCOM_DURATION = 0x29
252WRITE_VCOM = 0x2C
253READ_OTP = 0x2D
254WRITE_LUT = 0x32
255WRITE_DUMMY = 0x3A
256WRITE_GATELINE = 0x3B
257WRITE_BORDER = 0x3C
258SET_RAMXPOS = 0x44
259SET_RAMYPOS = 0x45
260SET_RAMXCOUNT = 0x4E
261SET_RAMYCOUNT = 0x4F
262NOP = 0xFF
263```
264
265I then noticed that there was a long string of bytes being sent after a
266`0x24` which in the library indicated that it was the memory
267buffer for the black/white channel ending with a `0x00`
268`MISO`, with the yellow/red channel afterward with a
269`0x26` `MOSI` and also ended with `0x00`
270`MISO`
271
272```
273...
2740x19,0xFF
2750x01,0xFF
2760x00,0xFF
2770x3C,0x00
2780x01,0xFF
2790x4E,0x00
2800x00,0xFF
2810x4F,0x00
2820x00,0xFF
2830x00,0xFF
2840x24,0x00
2850xFF,0xFF
2860xFF,0xFF
2870xFF,0xFF
2880xFF,0xFF
2890xFF,0xFF
2900xFF,0xFF
2910xFF,0xFF
2920xFF,0xFF
2930xFF,0xFF
2940xFF,0xFF
295...
296```
297
298There also seemed to be two different updates at around 5 seconds and 70
299seconds.
300
301![Logic 2 SPI analyzer with 0x24 searched to show when each screen update started.](https://vineetk.net/images/crewctf24_sniff/logic2_spi_update_times.png)
302
303However, the number of bytes written was 4250, which wasn’t the 3812.5 or
3042756 bytes I was expecting. This wasn’t divisible by 250 nor 122 and so I was
305stuck for a long time. Looking through the library source for more than an
306hour with my tired self didn’t help much either. As a last ditch attempt, I
307tried converting the raw bytes into an image via Pillow, I used the
308`L` mode (`8bpp`) and just got an uninteresting garbled
309image.
310
311![Garbled image reflecting my sadness at being unable to get the flag.](https://vineetk.net/images/crewctf24_sniff/failed_flag.png)
312
313## Part 2 Part 2: Electric Boogaloo
314![Joey asking in the CTF’s Discord about the challenge.](https://vineetk.net/images/crewctf24_sniff/discord1.png)
315![Me being surprised in the Discord for my stupidity that I blame on being tired.](https://vineetk.net/images/crewctf24_sniff/discord2.png)
316
317After waking up and working on the CTF after it ended, my partner asked on
318the Discord and found some interesting very helpful information. It turned
319out the image was a packed 1bpp image. This meant that each byte in the
320memory framebuffer contained 8 pixels (8 bits / 1 bits per pixel = 8
321pixels).
322
323```python
324# under show()
325buf_a = numpy.packbits(numpy.where(region == BLACK, 0, 1)).tolist()
326buf_b = numpy.packbits(numpy.where(region == RED, 1, 0)).tolist()
327```
328
329In the Python source, this was shown by `buf_a` and
330`buf_b` being packed bits of 1bpp via NumPy. I don’t know much
331about NumPy, so this was a skill issue as I initially assumed it was a
332complicated way of saving all the black and red pixels into lists. This is a
333good reminder that the documentation should be checked for all unfamiliar
334functions instead of naively assuming what they seem to do.
335
336Also in addition to the screen being rotated by 90 degrees, the vertical
337resolution is actually 136 pixels and not 120 according to the driver.
338
339Knowing all this solved all my problems as 4250 * 8 was indeed divisible
340by 250 and the actual vertical resolution 136.
341
342All I had to do was change the Pillow mode when converting the bytes to an
343image from `L` (8bpp) to `1` (1bpp) and the (rotated)
344resolution from `(250, 16)` to `(136, 250)` and got an
345actual image.
346
347![Extracted image of the display showing the initial message shown in the challenge description.](https://vineetk.net/images/crewctf24_sniff/converted_eink_image.png)
348
349I used the first updated bytes which was the screen shown in the
350challenge’s screenshots. Using the second update’s bytes gave half of the
351flag in the black/white channel and the other half in the yellow/red
352channel.
353
354![The flag in the black/white channel.](https://vineetk.net/images/crewctf24_sniff/flag1.png)
355![The flag in the yellow/red channel.](https://vineetk.net/images/crewctf24_sniff/flag2.png)
356
357Each character index in both channels seemed to alternate, so the actual
358flag was `flag{ec9cf2b7}`. After I finished writing this writeup
359and seeing the two images side-by-side, they probably could’ve been overlayed
360after one’s colours are inverted, and is probably what was meant by
361“stitching” the channels together.
362
363## Conclusion
364This was my most favourite CTF challenge by far and I learned a lot,
365especially about stuff I wanted to learn like how SPI e-paper screens work
366and not be lost with I2C. I am personally now curious whether the SPI screens
367can be interfaced directly with the MCU instead of going through an
368intermediate daughterboard/HAT and how different the protocol for parallel
369screens are since they’re much faster and use more pins.
diff --git a/posts/csaw23_rebug1.md b/posts/csaw23_rebug1.md
new file mode 100644
index 0000000..7e21285
--- /dev/null
+++ b/posts/csaw23_rebug1.md
@@ -0,0 +1,97 @@
1title: CSAW23 rev/Rebug1 Writeup
2date: 2023-09-28 12:00
3---
4> Can't seem to print out the flag :( Can you figure how to get the flag
5with this binary?
6
7An innocent looking binary is given that asks for a string:
8
9```
10./test.out
11Enter the String: rptuainadui
12that isn't correct, im sorry!
13```
14
15This is part of the rev category (which I think is for reverse
16engineering). You could bruteforce this yes, but I found it easier
17to put this into a decompiler like the ones on [DogBolt (Decompiler
18Explorer)](https://dogbolt.org/) to see what it's doing.
19
20Decompiled main function (via angr):
21
22```
23int main()
24{
25 char v0; // [bp-0x448]
26 unsigned int v1; // [bp-0x41c]
27 char v2; // [bp-0x418]
28 char v3; // [bp-0x408]
29 unsigned long long v4; // [bp-0x18]
30 unsigned int v5; // [bp-0x10]
31 unsigned int v6; // [bp-0xc]
32 unsigned long long v8; // rax
33
34 printf("Enter the String: ");
35 __isoc99_scanf("%s", (unsigned int)&v3);
36 for (v6 = 0; (&v3)[v6]; v6 += 1);
37 if (v6 == 12)
38 {
39 puts("that's correct!");
40 v4 = EVP_MD_CTX_new();
41 (unsigned int)v8 = EVP_md5();
42 EVP_DigestInit_ex(v4, v8, 0x0, v8);
43 EVP_DigestUpdate(v4, "12", 0x2, "12");
44 v1 = 16;
45 EVP_DigestFinal_ex(v4, &v2, &v1, &v2);
46 EVP_MD_CTX_free(v4);
47 for (v5 = 0; v5 <= 15; v5 += 1)
48 {
49 sprintf(&(&v0)[2 * v5], "%02x", (&v2)[v5]);
50 }
51 printf("csawctf{%s}\n", (unsigned int)&v0);
52 return 0;
53 }
54 printf("that isn't correct, im sorry!");
55 return 0;
56}
57```
58
59This along with the rest of the decompiled binary can't be simply compiled again
60as-is because there are a few issues, like the OpenSSL functions being called
61having an extra argument added to the end.
62
63When looking at the functions being called, it seems that the flag is just an
64md5 of the number 12. The program also seems to give the flag itself if you give
65it the character with the ASCII value of 12 (form feed).
66
67The line that that has the data being checksummed is this:
68
69```
70EVP_DigestUpdate(v4, "12", 0x2, "12");
71```
72
73I did try piping the form feed character via printf to the binary, but it did
74not like that, so it seems that the only way to get the flag is through another
75way.
76
77While you could just create a very simplified version of the decompiled source
78with OpenSSL's crypto library (which is what I did originally), it's much easier
79to just pass the number 12 to a pre-installed md5 command (md5 on OpenBSD,
80md5sum on Linux).
81
82```
83$ echo -n 12 | md5
84c20ad4d76fe97759aa27a0c99bff6710
85```
86
87This CTF's flags were in the format of csawctf{somethinghere}, as also seen in
88the decompiled source, so the actual flag was this:
89
90```
91csawctf{c20ad4d76fe97759aa27a0c99bff6710}
92```
93
94This was my first time doing any decompilation of a program, and I think this
95was a good start to learn reverse engineering.
96
97``` \ No newline at end of file
diff --git a/posts/deadface23_hostbusters3.md b/posts/deadface23_hostbusters3.md
new file mode 100644
index 0000000..238ea65
--- /dev/null
+++ b/posts/deadface23_hostbusters3.md
@@ -0,0 +1,37 @@
1title: "DEADFACE CTF 2023 Host Busters 3 Writeup"
2date: 2023-10-26 12:00
3---
4> Continue characterizing the machine. Is there any way you can
5escalate to a user that has permissions the vim user does not have? Find
6the flag associated with this user.
7Submit the flag as `flag{flag_here}`.
8
9```
10vim@ghost404.deadface.io letmevim
11```
12
13You first login to vim, which has vim open. Then you escape from it like you
14did in the OverTheWire Bandit challenges with `:set shell=bash` and `:shell`. Now you have a proper shell over SSH.
15
16The first thing I looked at after mistaking Host Busters 1's key in the home
17directory as 3 was look at what other user home directories there were by
18running `ls /home`. I saw there were a few users, notably `gh0st404` and
19`spookyboi`.
20
21`gh0st404`'s user home directory had his OpenSSH private key as
22world-readable and in plain sight not in his `.ssh` hidden
23directory. It being world-readable would have had OpenSSH scream at you, but
24them being stupid was good for us.
25
26So, once you use that SSH private key to login as `gh0st404`,
27you can check the contents of hostbusters3.txt and you got the flag.
28
29```
30cat hostbusters3.txt
31```
32
33> "This is why you should have come to the Monday meetings for OverTheWire."
34~Joey, FPUSEC President
35
36[Here's](https://asciinema.org/a/ZhQQwEVwgaqtGCuaqRf6NWu8N) an
37asciinema of the entire thing in action.
diff --git a/posts/deadface23_shattered-dreams.md b/posts/deadface23_shattered-dreams.md
new file mode 100644
index 0000000..899433c
--- /dev/null
+++ b/posts/deadface23_shattered-dreams.md
@@ -0,0 +1,166 @@
1title: DEADFACE CTF 2023 Shattered Dreams Writeup
2date: 2023-10-26 12:00
3---
4> DEADFACE is on the brink of selling a patient's credit card details from the
5Aurora database to a dark web buyer. Investigate Ghost Town for potential leads
6on the victim's identity.
7
8A huge hint was dropped immediately, so I went to Ghost Town to find a thread
9titled "We got a potential buyer".
10
11The flag's format is `flag{Firstname Lastname}`.
12
13lilith, the original poster of the thread, said the victim's SHA1 hash we need
14to look for is "911d1fc5930fa5025dbc2d3953c94de9e4773584" and showed how she
15calculated that, including the (lack of) delimeter.
16
17![https://ghosttown.deadface.io/t/dark-web-dumps-anyone/101](https://vineetk.net/images/deadface23-shattered_dreams-forum.png)
18
19So, we can easily bruteforce getting this SHA1 hash by repeating what lilith
20did.
21
22The first three fields (card number, expiration, CCV) are values from the
23billing table and the rest of the fields is all the fields in the patient
24table.
25
26```sql
27CREATE TABLE `billing` (
28 `billing_id` int(11) NOT NULL AUTO_INCREMENT,
29 `patient_id` int(11) NOT NULL,
30 `credit_type_id` int(11) NOT NULL,
31 `card_num` varchar(24) NOT NULL,
32 `exp` varchar(8) NOT NULL,
33 `ccv` varchar(4) NOT NULL,
34 PRIMARY KEY (`billing_id`),
35 UNIQUE KEY `card_num` (`card_num`),
36 KEY `fk_billing_patient_id` (`patient_id`),
37 KEY `fk_billing_credit_type_id` (`credit_type_id`),
38 CONSTRAINT `fk_billing_credit_type_id` FOREIGN KEY (`credit_type_id`) REFERENCES `credit_types` (`credit_type_id`) ON DELETE CASCADE,
39 CONSTRAINT `fk_billing_patient_id` FOREIGN KEY (`patient_id`) REFERENCES `patients` (`patient_id`) ON DELETE CASCADE
40) ENGINE=InnoDB AUTO_INCREMENT=14443 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
41...
42CREATE TABLE `patients` (
43 `patient_id` int(11) NOT NULL AUTO_INCREMENT,
44 `first_name` varchar(32) NOT NULL,
45 `last_name` varchar(64) NOT NULL,
46 `middle` varchar(8) DEFAULT NULL,
47 `sex` varchar(8) NOT NULL,
48 `email` varchar(128) NOT NULL,
49 `street` varchar(64) NOT NULL,
50 `city` varchar(64) NOT NULL,
51 `state` varchar(8) NOT NULL,
52 `zip` varchar(12) NOT NULL,
53 `dob` date NOT NULL,
54 PRIMARY KEY (`patient_id`),
55 UNIQUE KEY `email` (`email`)
56) ENGINE=InnoDB AUTO_INCREMENT=18542 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
57```
58
59Since there are no delimeters, they can just be concatenated with each other
60and then piped to sha1. The difficult part I had was properly concatenating
61those values because I was not able to read the MySQL dump with sqlite3 nor
62mariadb.
63
64I noticed that each of the rows that were inserted into the tables were
65delimited by a comma, similar to CSV.
66
67```sql
68INSERT INTO `patients` VALUES (8151,'Lorrayne','Covey','E','Female','lcovey0@wunderground.com','40411 Old Shore Street','Houston','TX','77201','1985-02-08'),(8152,'Eddy','Omand','S','Female','eomand1@mysql.com','454 Pine View Alley','Columbus','OH','43226','1959-09-29'),(8153,'Renard','Berre','O','Male','rberre2@friendfeed.com','3496 Merrick Center','Pittsburgh','PA','15235','1978-12-05'),(8154,'Galven','Nardrup','M','Male','gnardrup3@mac.com','0 American Road','Denver','CO','80241','1984-04-09'), ...
69```
70
71So I was able to easily convert it into a CSV with the following command:
72
73```bash
74grep 'INSERT INTO `patients`' aurora.sql \
75 | sed 's/^INSERT[^(]*//' \
76 | awk '{gsub(/,\(/, "\n"); gsub(/\)*/, ""); print}'
77```
78
79Part of the output is now:
80
81```
82...18532,'Becka','Hurlin','T','Female','bhurlin80d@yolasite.com','58 Amoth Way','Ventura','CA','93005','1953-11-14'
8318533,'Aluin','Horwell','O','Male','ahorwell80e@cbc.ca','3 Oriole Terrace','Miami','FL','33190','1984-06-24'
8418534,'Glennis','Walder','R','Female','gwalder80f@cnet.com','966 Packers Hill','Topeka','KS','66617','1950-01-21'
85...
86```
87
88One problem I had when I used tr to replace ( with \n was that one of the names
89had () in their name for some reason, which messed up the concatenating of the
90two files to get the hash. I originally just manually edited it, but the above
91with awk is cleaner. The same goes with the 'INSERT INTO ...' part messing things up for the same reason. I didn't save my ~/.ksh_history file with the
92commands I ran, so this is a non-ugly version I remade with more awk.
93
94To properly concatenate the data fields, the comma and single quotes should
95also be removed, which tr can be used for unlike before.
96
97```bash
98grep 'INSERT INTO `patients`' aurora.sql \
99 | sed 's/^INSERT[^(]*//' \
100 | awk '{gsub(/,\(/, "\n"); gsub(/\)*/, ""); print}' \
101 | tr -d "'," >patients_.txt
102```
103
104Part of the output prior to being written to a file is now:
105
106```
10718527TannerMasselinAMaletmasselin808@google.es10080 Reindahl CourtBoca RatonFL334871957-08-15
10818528MerrelYeudeDMalemyeude809@ca.gov7934 Katie PassSaint PaulMN551881951-04-07
10918529JeffVan BaarenMMalejvanbaaren80a@sphinn.com58097 Autumn Leaf DriveNew OrleansLA701421984-01-13
110```
111
112It is written to a file so that it can be easy to concatenate both the billing
113and patient data by using the paste command.
114
115The next part is doing the same with the billing data. Unlike with the patient
116data, only three fields from the billing table is used instead of all, so cut
117or awk can be used with the delimeter set to a comma.
118
119Before that, we need to know what index (base 1) the three fields are at. The
120credit card number, expiry date, and ccv are fields 4, 5, and 6.
121
122```bash
123grep 'INSERT INTO `billing`' aurora.sql \
124 | sed 's/^INSERT[^(]*//' \
125 | awk '{gsub(/,\(/, "\n"); gsub(/\)*/, ""); print}' \
126 | cut -d, -f4,5,6 \
127 | tr -d "'," >billing_.txt
128```
129
130Some of the output looks like
131
132```
13351087507745678202025-01403
13450483770976260922023-07242
13550483739134688352023-12501
136```
137
138Both tables with the fields have been parsed and saved to two different files, but simply using cat on both the files would simply print the contents of the second file after the first file has finished printing, but we need each line of both the files to be joined together! That's where the paste command comes in. It combines each line of its input files, which is exactly what is required.
139
140These merged lines are then fed into sha1, and finally grep can be used to look for the hash we need and print the victim's name if it shows up.
141
142```bash
143target_hash="911d1fc5930fa5025dbc2d3953c94de9e4773584"
144
145paste billing_.txt patients_.txt | tr -d '\t' \
146 | while read line; do
147 echo -n "$line" | sha1 \
148 | grep "$target_hash" && echo "$line" && break
149 done
150```
151
152The outputted line of the victim who had the same hash is:
153
154```
15550483743238485412026-0498316314BertonLuchettiXMalebluchetti6ar@taobao.com39 Meadow Ridge TerraceClevelandOH441251964-10-29
156```
157
158So, the victim is Berton X. Luchetti, and the flag is `flag{Berton Luchetti}`.
159
160This challenge would probably have been easier if I was able to use proper SQL
161commands, but I couldn't do that and standard UNIX tools saved the day. I did
162the exact same process of parsing the tables for all the other SQL challenges
163and I found it funny that I solved all of them without needing to run a single
164SQL command (partly because they didn't load the file).
165
166``` \ No newline at end of file
diff --git a/content/blog/kobo_clara-custom-distro.md b/posts/kobo_clara-custom-distro.md
index f7d40e1..f32f836 100644
--- a/content/blog/kobo_clara-custom-distro.md
+++ b/posts/kobo_clara-custom-distro.md
@@ -1,8 +1,6 @@
1+++ 1title: Kobo Clara HD Custom Linux Distro/RootFS
2title = "Kobo Clara HD Custom Linux Distro/RootFS" 2date: 2021-07-22 12:00
3date = 2021-07-22 3---
4draft = false
5+++
6 4
7These are just some notes I made when creating my own mini-distro after 5These are just some notes I made when creating my own mini-distro after
8wanting something more custom than just using buildroot or making the 6wanting something more custom than just using buildroot or making the
@@ -106,11 +104,13 @@ EDIT 2022-10-21: also gone
106First I suggest exporting some environment variables to set the 104First I suggest exporting some environment variables to set the
107toolchain used as well as enabling static linking and LTO. 105toolchain used as well as enabling static linking and LTO.
108 106
109 export CROSS_COMPILE="arm-linux-musleabihf-" # change to your cross-tc 107```
110 export CC="${CROSS_COMPILE}gcc" 108export CROSS_COMPILE="arm-linux-musleabihf-" # change to your cross-tc
111 export LDFLAGS="--static" 109export CC="${CROSS_COMPILE}gcc"
112 export CFLAGS="-flto -static" 110export LDFLAGS="--static"
113 export ARCH=arm # for compiling the linux kernel 111export CFLAGS="-flto -static"
112export ARCH=arm # for compiling the linux kernel
113```
114 114
115To compile toybox, get the source from 115To compile toybox, get the source from
116https://landley.net/toybox/downloads/ (or clone the upstream repo). 116https://landley.net/toybox/downloads/ (or clone the upstream repo).
@@ -119,23 +119,27 @@ change it as you see fit. Personally, I disabled most of the programs I
119wouldn't use and kept only the ones that'll help with fixing a problem. 119wouldn't use and kept only the ones that'll help with fixing a problem.
120Finally, make sure to run make. 120Finally, make sure to run make.
121 121
122 make defconfig 122```
123 make menuconfig 123make defconfig
124 make 124make menuconfig
125make
126```
125 127
126To move it to your rootfs and set it's symlinks, you could probably run 128To move it to your rootfs and set it's symlinks, you could probably run
127make install after setting PREFIX to your rootfs's /bin directory, but 129make install after setting PREFIX to your rootfs's /bin directory, but
128I did it manually. 130I did it manually.
129 131
130 # automatic (didn't test, check README) 132```
131 make PREFIX=/path/to/rootfs/bin/ install 133# automatic (didn't test, check README)
134make PREFIX=/path/to/rootfs/bin/ install
132 135
133 # (semi?) manual 136# (semi?) manual
134 cp toybox /path/to/rootfs/bin 137cp toybox /path/to/rootfs/bin
135 138
136 # add symlinks if doing manual and you want them 139# add symlinks if doing manual and you want them
137 cd /path/to/rootfs/bin 140cd /path/to/rootfs/bin
138 for prog in $(qemu-arm ./toybox); do ln -s toybox "$prog"; done 141for prog in $(qemu-arm ./toybox); do ln -s toybox "$prog"; done
142```
139 143
140## dash 144## dash
141Also as of toybox 0.8.5, a shell still isn't included (probably would 145Also as of toybox 0.8.5, a shell still isn't included (probably would
@@ -148,20 +152,24 @@ First obtain the source[3] and cd into its
148untarred directory. Assuming your CC and CFLAGS are set, you can run 152untarred directory. Assuming your CC and CFLAGS are set, you can run
149these steps: 153these steps:
150 154
151 autoreconf -fiv 155```
152 ./configure --host=$CROSS_COMPILE --with-libedit 156autoreconf -fiv
153 make 157./configure --host=$CROSS_COMPILE --with-libedit
154 ${CROSS_COMPILE}strip src/dash 158make
159${CROSS_COMPILE}strip src/dash
160```
155 161
156As this is going to be used as the main shell, I've decided to just 162As this is going to be used as the main shell, I've decided to just
157copy it to /bin/sh in the rootfs directory, though copying it there but 163copy it to /bin/sh in the rootfs directory, though copying it there but
158as /bin/dash and /bin/sh being symlinked to dash is also an option. 164as /bin/dash and /bin/sh being symlinked to dash is also an option.
159 165
160 cp src/dash /path/to/rootfs/bin/sh 166```
161 # or 167cp src/dash /path/to/rootfs/bin/sh
162 cp src/dash /path/to/rootfs/bin 168# or
163 cd /path/to/rootfs/bin 169cp src/dash /path/to/rootfs/bin
164 ln -s dash sh 170cd /path/to/rootfs/bin
171ln -s dash sh
172```
165 173
166## felker's init 174## felker's init
167The init is just a single file that you can get from felker's site[2] 175The init is just a single file that you can get from felker's site[2]
@@ -171,8 +179,10 @@ on it so I'd change it to execvp() and remove the third (specifies
171environment). To compile and install the init, all you need to do is 179environment). To compile and install the init, all you need to do is
172run: 180run:
173 181
174 $CC $CFLAGS -o init init.c 182```
175 cp init /path/to/rootfs/sbin 183$CC $CFLAGS -o init init.c
184cp init /path/to/rootfs/sbin
185```
176 186
177Instead of /etc/rc being a shell script, you can also make a C program 187Instead of /etc/rc being a shell script, you can also make a C program
178that does whatever you think is needed for a proper startup. I'll still 188that does whatever you think is needed for a proper startup. I'll still
@@ -187,8 +197,10 @@ able to login to any user. So you'll have to create a file at
187/path/to/rootfs/etc/passwd. For an empty password to root, you can use 197/path/to/rootfs/etc/passwd. For an empty password to root, you can use
188this, though I suggest setting a password as soon as you login: 198this, though I suggest setting a password as soon as you login:
189 199
190 # in rootfs's /etc/passwd 200```
191 root::0:0:root:/root:/bin/sh 201# in rootfs's /etc/passwd
202root::0:0:root:/root:/bin/sh
203```
192 204
193With the passwd file created/updated, you should now be able to login 205With the passwd file created/updated, you should now be able to login
194to root after the rootfs is copied to your uSD card. Your rootfs so far 206to root after the rootfs is copied to your uSD card. Your rootfs so far
@@ -234,8 +246,10 @@ I had a hard time compiling the vendor kernel with many things
234disabled, so I've kept my config somewhat similar to the default 246disabled, so I've kept my config somewhat similar to the default
235config. The config I used is available here (EDIT: dead). 247config. The config I used is available here (EDIT: dead).
236 248
237 make menuconfig 249```
238 make zImage 250make menuconfig
251make zImage
252```
239 253
240Assuming it compiles properly and arch/arm/boot/zImage exists, all 254Assuming it compiles properly and arch/arm/boot/zImage exists, all
241that's needed to is to write it to your uSD card at the 1M offset. 255that's needed to is to write it to your uSD card at the 1M offset.
@@ -246,7 +260,9 @@ I have not done this yet, nor really plan to, but if you do manage to
246compile the Kobo's vendored u-boot source, then all you'd have to do to 260compile the Kobo's vendored u-boot source, then all you'd have to do to
247install it is: 261install it is:
248 262
249 dd if=u-boot-file of=/dev/mmcblk0 bs=128k count=1 seek=6 263```
264dd if=u-boot-file of=/dev/mmcblk0 bs=128k count=1 seek=6
265```
250 266
251If I remember correctly, this command was included in an older 267If I remember correctly, this command was included in an older
252firmware's startup script/rcS for updating udev, and it should still 268firmware's startup script/rcS for updating udev, and it should still
diff --git a/content/blog/kobo_clara-nickel.md b/posts/kobo_clara-nickel.md
index 7447283..3dbb068 100644
--- a/content/blog/kobo_clara-nickel.md
+++ b/posts/kobo_clara-nickel.md
@@ -1,9 +1,6 @@
1+++ 1title: Kobo Clara HD Notes for Nickel
2title = 'Kobo Clara HD Notes for Nickel' 2date: 2021-01-13 12:00
3date = 2021-01-13 3---
4draft = false
5layout = "post"
6+++
7 4
8My ereader of choice is the Kobo Clara HD and I particularly like it 5My ereader of choice is the Kobo Clara HD and I particularly like it
9because my eyes hurt less when reading for long periods of time 6because my eyes hurt less when reading for long periods of time
diff --git a/content/blog/kobo_clara-plato.md b/posts/kobo_clara-plato.md
index b7de110..6e6c72a 100644
--- a/content/blog/kobo_clara-plato.md
+++ b/posts/kobo_clara-plato.md
@@ -1,7 +1,6 @@
1+++ 1title: Kobo Clara HD Notes for Plato (and KSM)
2title = "Kobo Clara HD Notes for Plato (and KSM)" 2date: 2021-03-27 12:00
3date = 2021-03-27 3---
4+++
5 4
6These are my notes for getting Plato on the Kobo Clara HD from scratch 5These are my notes for getting Plato on the Kobo Clara HD from scratch
7as well as some notes for getting KSM to work, but I now boot directly 6as well as some notes for getting KSM to work, but I now boot directly
diff --git a/content/blog/st-bitmap-font-fix.md b/posts/st-bitmap-font-fix.md
index 53e6740..dc08b34 100644
--- a/content/blog/st-bitmap-font-fix.md
+++ b/posts/st-bitmap-font-fix.md
@@ -1,8 +1,6 @@
1+++ 1title: Fixing bitmap font fallbacks in the st terminal
2title = "Fixing bitmap font fallbacks in the st terminal" 2date: 2023-11-24 12:00
3date = 2023-11-24 3---
4draft = false
5+++
6tldr, change FC_SCALABLE in x.c from 1 to 0. (comes from the font2 patch) 4tldr, change FC_SCALABLE in x.c from 1 to 0. (comes from the font2 patch)
7 5
8For some context, I have been using xterm for a long while when I'm on OpenBSD 6For some context, I have been using xterm for a long while when I'm on OpenBSD
diff --git a/content/blog/tmpfilehost.md b/posts/tmpfilehost.md
index c8356d8..5249d8e 100644
--- a/content/blog/tmpfilehost.md
+++ b/posts/tmpfilehost.md
@@ -1,8 +1,6 @@
1+++ 1title: Creating a Temporary File Hoster
2title = "Creating a Temporary File Hoster" 2date: 2022-04-27 12:00
3date = 2022-04-27 3---
4draft = false
5+++
6For the past couple years, whenever I wanted to upload a file, I would 4For the past couple years, whenever I wanted to upload a file, I would
7curl the file to [lainsafe](https://git.qorg11.net/lainsafe.git/), [i/u.kalli.st](https://gt.kalli.st/kallist/uploader), and recently [ttm.sh](https://tildegit.org/tildeverse/ttm.sh). 5curl the file to [lainsafe](https://git.qorg11.net/lainsafe.git/), [i/u.kalli.st](https://gt.kalli.st/kallist/uploader), and recently [ttm.sh](https://tildegit.org/tildeverse/ttm.sh).
8 6
diff --git a/content/blog/vfio-win10.md b/posts/vfio-win10.md
index a24b78e..1cd339c 100644
--- a/content/blog/vfio-win10.md
+++ b/posts/vfio-win10.md
@@ -1,8 +1,6 @@
1+++ 1title: VFIO Install Notes
2title = "VFIO Install Notes" 2date: 2020-10-17 12:00
3date = 2020-10-17 3---
4draft = false
5+++
6You should first go look at [the Arch Wiki on it](https://wiki.archlinux.org/index.php/PCI%20passthrough%20via%20OVMF) or [Yuri Alek's guide on Single GPU passthrough](https://gitlab.com/YuriAlek/vfio) or [4chan's /g/ wiki on it](https://wiki.installgentoo.com/index.php/PCI_passthrough) as these assume prior knowledge. 4You should first go look at [the Arch Wiki on it](https://wiki.archlinux.org/index.php/PCI%20passthrough%20via%20OVMF) or [Yuri Alek's guide on Single GPU passthrough](https://gitlab.com/YuriAlek/vfio) or [4chan's /g/ wiki on it](https://wiki.installgentoo.com/index.php/PCI_passthrough) as these assume prior knowledge.
7 5
8# Prerequisites 6# Prerequisites
diff --git a/posts/workflow_9years.md b/posts/workflow_9years.md
new file mode 100644
index 0000000..9a4c24d
--- /dev/null
+++ b/posts/workflow_9years.md
@@ -0,0 +1,231 @@
1title: *nix workflow after nearly a decade (raw braindump)
2date: 2026-04-13 12:00
3---
4
5I was asked a few times from members of my university's cybersecurity
6club (I was a former e-board member and it's my main club) over the
7past months of how I use a computer since apparently how I use it is
8different from how others do it. They also found it fascinating that I
9used Linux/*BSD for as long as I did, and I'm probably among very few
10others if any at my university that used it for like 9.5 years. It's
11organized in what got me into this in the first place, my OS-hopping,
12my editor-hopping, what my current workflow is, and my (maybe lack of
13meaningful) thought process behind each switch. The TL;DR of that is
14I'm like a purist (primarily with the UNIX philosophy) and minimalist
15(reducing "bloat" as much as possible) and that guided a lot of my
16decisions up till now at the end of college. Any mistakes I made or
17any "cringe" I did like being a 4chan `/g/` kid can be blamed on me
18being 12/13 at the time. The following is the raw braindump before I
19condensed it into point form.
20
21---
22
23I was introduced to Linux via Luke Smith's early video on why use
24terminal programs. Then by watching his other videos, I got introduced
25to stuff like different kinds of distros (he used Parabola at the time
26and Parabola's wiki in 2017 hadn't removed the beginners guide page
27unlike Arch wiki, though in hindsight they're basically the same),
28tiling window managers (i3, dwm), suckless movement and minimalism
29(was the start of me obsessing over purism even to my detriment
30sometimes as in spending too much time that I miss deadlines), using
31LaTeX for documents and presentations, etc. This was during his early
32days back in 2017 and 2018, before he quit being a linguist professor
33in Georgia and moved to a cabin in Florida and now complains about les
34youths. I didn't watch other Linux-related channels until more
35recently with David Wilson's System Crafters for Emacs and Guix (more
36on this at the very end, it's a recent change that fundamentally
37changed how I do stuff, this will come up a lot).
38
39This put me on the path of both distro-hopping and
40WM-hopping. Reminder that I started this journey when I was 12
41(now 21) so I had lots of time on my hands. I started with Parabola
42and then switched to Arch shortly after for wifi drivers, then setup
43Gentoo through reading its handbook to learn about Linux more, and
44then later did a full LFS+BLFS twice, then CRUX, Sabotage, KISS,
45Alpine, and then switched between them depending on what little thing
46annoyed me at the time. Of these, CRUX really made me feel at "home"
47with giving me just enough packages for a minimal base and I liked
48being a package maintainer for a short while. I found CRUX through
49z3bra on the nixers.net forum talking about the differences between it
50and Gentoo. Sabotage (the way it did stuff was unique and interesting
51to me at the time but only used for one hop) and KISS (what I wished
52CRUX was but because it didn't have the drunk tux mascot I didn't use
53it much beyond a couple hops) from people on IRC and XMPP. I learned a
54lot about system administration and writing my own packages through
55distro-hopping. Eventually, the choices converged to Arch (if I wanted
56something easy), CRUX (because it made me feel fuzzy inside), Gentoo
57(USE flags put me further on the path of purism, not as much need to
58maintain so many packages in my overlay unlike CRUX). I later also
59found out about the BSDs in my goal of more minimalism and purism. It
60being direct descendants of the venerable Bell Labs's Research
61UNIX. FreeBSD was what I wished Linux was and I liked its better
62documentation and integrated first-class ZFS support. OpenBSD I loved
63for its documentation, focus on security above all else, tight-knit
64and knowledgeable mature community (unlike with most of Linux),
65package management feeling more similar to CRUX, mascot, and being
66Canadian (patriotism I guess). Among the OSes I used the longest
67without hopping, CRUX, Gentoo, and OpenBSD are the ones I really
68used. I usually switched away from CRUX due to power user burnout from
69maintaining packages for adding and making them more minimal, same
70from Gentoo but to lesser extent due to many other overlays, and from
71OpenBSD for Windows virtualization at the time and gaming (though I
72did find out more about FOSS engines and did more retro emulation
73under OpenBSD). I also had a phase in high school grade 12 with
74plan9/9front. Really loved the simplicity and elegance of it. Its
75windowing manager rio/8.5 and acme editor also showed me that mice
76aren't an inherently bad thing for computer use when designed
77properly. I couldn't go further with dailying it because my i219-v and
78r8168 driver wasn't working properly even after I tried patching it
79with my then meager C skills. Later in college around junior year, I
80was peer pressured into NixOS from my functional programming
81friends. I liked the idea behind it and it made systemd somewhat
82usable, but I disliked the special snowflake DSL (they should have
83used something else as a base like Haskell or anything else they took
84inspiration from) and it liked pulling in all sorts of transient
85dependencies, the exact opposite of what I wanted in Linux since I
86started using it years ago. What really put me off more than transient
87deps was poor and inconsistent documentation (like pretty much nothing
88about flakes: there was a disconnect in documentation of what the
89broader community used and what upstream deemed stable). But, it had
90advantages like helping organize my system+home configs and dotfiles
91all in one place which was very nice. So I briefly tried Guix, but
92once again without knowing its language was hard to use and also
93trying to mould my existing suckless+vi non-emacs worklow into it was
94hard at the time. So I once again switched back and forth between
95Arch, CRUX, Gentoo, and NixOS despite their shortcomings I detailed
96earlier: my power user burnout or getting bored. Continuing later for
97recent switch to Guix+Emacs.
98
99So now about window manager choice. I started with i3 since that's
100what Luke Smith used and I was curious about how a keyboard-only
101workflow would look like. It's also what the most popular WM on
102r/unixporn was. Back in the day when pretty much every post there was
103either a close-to-default i3-gaps setup or bspwm instead of sway and
104hyprland now. I then switched to bspwm because it was more minimal and
105UNIX philosophy like where it split keybind handling into separate
106program sxhkd. I also used herbstluftwm, the manual tiling was
107nice. Then comes dwm, my main WM of choice for a long time since it
108blended minimalism with functionality and also by suckless so was
109elegant. However, I still did end up switching to spectrwm since it
110looked similar visually but I found it easier to config. According to
111my screenshots though, that didn't last for long. I think I only
112stayed on it for a few months before switching back to dwm. I did
113briefly try out sway to see if Wayland was really all that great, but
114ultimately switched back to dwm again, and only really used it when I
115felt too lazy to setup Xorg on a new system and not using my
116pre-existing configs. Again, continuing later for my recent switch to
117Guix+Emacs.
118
119Missing what editor I used is criminal for this kind of topic. Going
120back to before Linux, I used Eclipse for Java and Notepad++ for
121regular stuff, and then I think I used Atom for a brief period of time
122(VS Code wasn't out yet or something in 2016/17). I didn't do much
123programming back then, partly because getting dependencies and
124compiling anything is a pain if my experience with compiling aseprite
125(sprite editor with cmake buildsystem) was anything to go off of. When
126I started using Linux, I also started with Vim. Programs like it were
127what got me to switch in the first place. Turns out learning your
128tools is important (and that comes up a lot). Even back then I didn't
129like using much of the pre-made configs, they were bloated and harder
130to reason about as a new user since defaults were changed. Also had a
131brief stint with Emacs, but not knowing basic Lisp made it hard to
132"know" it and it was bloated (common joke is it's an operating system
133that lacks a good editor) and also not optimized on Windows (same
134config from Linux) where it was just noticeably more sluggish on muh
135gamin' laptop when running Win10 instead of like Arch or Gentoo. After
136learning Vim enough like how to move easily and basic ex commands, I
137of course wanted more minimalism. Had a nice time with vis and nvi,
138used them for a while. In my plan9 phase, I used acme briefly and
139learned a lot about sam through its manual, which also taught me how
140to use ed the standard text editor, which also taught me (basic) regex
141which I can't overstate how much better it made editing files in
142addition to vi motions.
143
144Finally, my current workflow and choices. It's now all based around
145Lisp and Scheme because they make me feel all fuzzy inside when
146learning it, just like I did when learning to use Linux in middle
147school and how to program in C. The propaganda that got me into using
148this now was when I heard about the Lispy Gopher Show when I was
149briefly on the Fediverse through Prahou (the author/artist of
150unix_surrealism from analog_nowhere). While I did briefly use Emacs in
151the past, I did not learn it properly. As in, not knowing Lisp meant I
152needed to look a lot of things up instead of just writing them
153myself. Technically with the vi-like editors, I also didn't write
154scripts in them nor needed to touch their config due to how minimal
155they already were by default and that regex+vi-motions going a long
156way and there being packages to bridge the remaining gap for
157integrations. But with Emacs, the parentheses I guess made it more
158daunting or something. This sort of mirrors what I did when I first
159got into Linux (well Arch) as I read a lot through its wiki. But
160compared to just regular system administration where you run a bunch
161of commands or even making your own distro via LFS, I guess properly
162learning an editor and its programming language was too much for me at
163the time. For new Emacs users, it was also recommended a lot that they
164use a pre-made opinionated config like Doom-Emacs or Spacemacs (neovim
165has a similar situation) and that really put me off since that felt
166like I would be learning instead how those work instead of the editor
167itself. Now that I know some functional programming through OCaml and
168to some extent Nix from a couple summers ago, learning Lisp and Scheme
169was actually much easier. Compared to using a vi-like editor, using
170Emacs seemed nicer for working with these kinds of languages since I
171can selectively execute parts of a program, simliar to something like
172Jupyter notebook without it being so web- and Python-focused and being
173an inefficient use of system resources. The main reason why I did not
174want to use Emacs previously was that it seemed like a monolithic
175kitchen sink of everything. I think it being described as an operating
176system within an operating system isn't too much of an inaccurate
177description. However, compared to Linux and Xorg proper where I tried
178following minimalism and the UNIX philosophy as much as I could
179(i.e. small, minimal, self-contained programs for a specific task),
180there was not much cohesion between them. At most, they'll have
181vi-keybinds and happen to use ncurses but the layout of everything
182looks different and configured with different syntaxes (e.g. mutt the
183mail client looks different from newsboat the RSS reader and different
184from lynx and links2). Meanwhile with Emacs, yes there are multiple
185packages and yes I'm not necessarily using POSIX shell scripts for
186connecting things together, but Lisp is a more powerful language than
187something like shell that depends on other programs (written in other
188languages) to do even simple stuff. With Emacs, I now have everything
189integrated into a single program, everything properly goes through
190text-based buffers, and as a result is even easier to integrate around
191because everything is primarily text. Also previously, some popular
192packages that people use also seemed like it may have contributed to
193Emacs's bloat in my point of view at that time like /needing/
194something like ivy or helm. There's better packages available that do
195the same thing now, like orderless (for fuzzy searching) combined with
196vertico (for the vertical complete menu that ivy gave), and consult
197for better autocomplete for various existing Emacs functions, among
198other stuff. Now it's my main editor since like last summerish, and I
199configured it to be my editor, Scheme programming via Geiser, Lisp via
200just Emacs (since for now I'm mainly using Emacs Lisp and not Common
201Lisp+SLIME) and using the eval-* functions a lot (for both Lisp and
202Scheme), document editing and task planning and habit tracking through
203org-mode (some people use Emacs just for org-mode since it's much more
204than just a markup language), email through notmuch+mbsync+msmtp
205(stayed pretty much the same except I'm using notmuch.el directly
206instead of through like mutt or aerc), RSS through elfeed, browsing
207primarily through eww (though I have to use qutebrowser for js-heavy
208sites like Canvas), document viewing through pdftools and docview
209instead of through mupdf (though for some larger PDFs like textbooks,
210mupdf is just faster but not needed for most of my PDFs), backgrounded
211programs through dtach and its associated emacs management package
212instead of tmux, gptel for interacting with my local LLMs running on
213my desktop through vllm, and finally as my X window manager via EXWM
214instead of dwm or any other WM I used to use in the past. Works well
215when playing games too like Elite Dangerous, Emacs doesn't get in the
216way.
217
218I know this was very ramble-y. I just braindumped since there's so
219much to cover and a lot of stuff to remember over the past 9 years
220that I couldn't think in a more organized way without having all of it
221written down. I probably missed some stuff, so any questions?
222
223---
224
225In the actual presentation, I missed mentioning my peripherals (a
226Ferris Sweep with Kailh Choc Ambient Nocturnal switches for laptop,
227Corne with Zealios Zilent v2 switches for my desktop, and a Ploopy
228Adept as my mouse for both) as well since that's also different from
229how most people use it, as well as my current project "X380", a modded
230stripped-down X280 (I'll make a post when it's more finalized after
231fixing my 3D printer).
diff --git a/static/agpl-3.0.txt b/static/agpl-3.0.txt
new file mode 100644
index 0000000..be3f7b2
--- /dev/null
+++ b/static/agpl-3.0.txt
@@ -0,0 +1,661 @@
1 GNU AFFERO GENERAL PUBLIC LICENSE
2 Version 3, 19 November 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 Preamble
9
10 The GNU Affero General Public License is a free, copyleft license for
11software and other kinds of works, specifically designed to ensure
12cooperation with the community in the case of network server software.
13
14 The licenses for most software and other practical works are designed
15to take away your freedom to share and change the works. By contrast,
16our General Public Licenses are intended to guarantee your freedom to
17share and change all versions of a program--to make sure it remains free
18software for all its users.
19
20 When we speak of free software, we are referring to freedom, not
21price. Our General Public Licenses are designed to make sure that you
22have the freedom to distribute copies of free software (and charge for
23them if you wish), that you receive source code or can get it if you
24want it, that you can change the software or use pieces of it in new
25free programs, and that you know you can do these things.
26
27 Developers that use our General Public Licenses protect your rights
28with two steps: (1) assert copyright on the software, and (2) offer
29you this License which gives you legal permission to copy, distribute
30and/or modify the software.
31
32 A secondary benefit of defending all users' freedom is that
33improvements made in alternate versions of the program, if they
34receive widespread use, become available for other developers to
35incorporate. Many developers of free software are heartened and
36encouraged by the resulting cooperation. However, in the case of
37software used on network servers, this result may fail to come about.
38The GNU General Public License permits making a modified version and
39letting the public access it on a server without ever releasing its
40source code to the public.
41
42 The GNU Affero General Public License is designed specifically to
43ensure that, in such cases, the modified source code becomes available
44to the community. It requires the operator of a network server to
45provide the source code of the modified version running there to the
46users of that server. Therefore, public use of a modified version, on
47a publicly accessible server, gives the public access to the source
48code of the modified version.
49
50 An older license, called the Affero General Public License and
51published by Affero, was designed to accomplish similar goals. This is
52a different license, not a version of the Affero GPL, but Affero has
53released a new version of the Affero GPL which permits relicensing under
54this license.
55
56 The precise terms and conditions for copying, distribution and
57modification follow.
58
59 TERMS AND CONDITIONS
60
61 0. Definitions.
62
63 "This License" refers to version 3 of the GNU Affero General Public License.
64
65 "Copyright" also means copyright-like laws that apply to other kinds of
66works, such as semiconductor masks.
67
68 "The Program" refers to any copyrightable work licensed under this
69License. Each licensee is addressed as "you". "Licensees" and
70"recipients" may be individuals or organizations.
71
72 To "modify" a work means to copy from or adapt all or part of the work
73in a fashion requiring copyright permission, other than the making of an
74exact copy. The resulting work is called a "modified version" of the
75earlier work or a work "based on" the earlier work.
76
77 A "covered work" means either the unmodified Program or a work based
78on the Program.
79
80 To "propagate" a work means to do anything with it that, without
81permission, would make you directly or secondarily liable for
82infringement under applicable copyright law, except executing it on a
83computer or modifying a private copy. Propagation includes copying,
84distribution (with or without modification), making available to the
85public, and in some countries other activities as well.
86
87 To "convey" a work means any kind of propagation that enables other
88parties to make or receive copies. Mere interaction with a user through
89a computer network, with no transfer of a copy, is not conveying.
90
91 An interactive user interface displays "Appropriate Legal Notices"
92to the extent that it includes a convenient and prominently visible
93feature that (1) displays an appropriate copyright notice, and (2)
94tells the user that there is no warranty for the work (except to the
95extent that warranties are provided), that licensees may convey the
96work under this License, and how to view a copy of this License. If
97the interface presents a list of user commands or options, such as a
98menu, a prominent item in the list meets this criterion.
99
100 1. Source Code.
101
102 The "source code" for a work means the preferred form of the work
103for making modifications to it. "Object code" means any non-source
104form of a work.
105
106 A "Standard Interface" means an interface that either is an official
107standard defined by a recognized standards body, or, in the case of
108interfaces specified for a particular programming language, one that
109is widely used among developers working in that language.
110
111 The "System Libraries" of an executable work include anything, other
112than the work as a whole, that (a) is included in the normal form of
113packaging a Major Component, but which is not part of that Major
114Component, and (b) serves only to enable use of the work with that
115Major Component, or to implement a Standard Interface for which an
116implementation is available to the public in source code form. A
117"Major Component", in this context, means a major essential component
118(kernel, window system, and so on) of the specific operating system
119(if any) on which the executable work runs, or a compiler used to
120produce the work, or an object code interpreter used to run it.
121
122 The "Corresponding Source" for a work in object code form means all
123the source code needed to generate, install, and (for an executable
124work) run the object code and to modify the work, including scripts to
125control those activities. However, it does not include the work's
126System Libraries, or general-purpose tools or generally available free
127programs which are used unmodified in performing those activities but
128which are not part of the work. For example, Corresponding Source
129includes interface definition files associated with source files for
130the work, and the source code for shared libraries and dynamically
131linked subprograms that the work is specifically designed to require,
132such as by intimate data communication or control flow between those
133subprograms and other parts of the work.
134
135 The Corresponding Source need not include anything that users
136can regenerate automatically from other parts of the Corresponding
137Source.
138
139 The Corresponding Source for a work in source code form is that
140same work.
141
142 2. Basic Permissions.
143
144 All rights granted under this License are granted for the term of
145copyright on the Program, and are irrevocable provided the stated
146conditions are met. This License explicitly affirms your unlimited
147permission to run the unmodified Program. The output from running a
148covered work is covered by this License only if the output, given its
149content, constitutes a covered work. This License acknowledges your
150rights of fair use or other equivalent, as provided by copyright law.
151
152 You may make, run and propagate covered works that you do not
153convey, without conditions so long as your license otherwise remains
154in force. You may convey covered works to others for the sole purpose
155of having them make modifications exclusively for you, or provide you
156with facilities for running those works, provided that you comply with
157the terms of this License in conveying all material for which you do
158not control copyright. Those thus making or running the covered works
159for you must do so exclusively on your behalf, under your direction
160and control, on terms that prohibit them from making any copies of
161your copyrighted material outside their relationship with you.
162
163 Conveying under any other circumstances is permitted solely under
164the conditions stated below. Sublicensing is not allowed; section 10
165makes it unnecessary.
166
167 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168
169 No covered work shall be deemed part of an effective technological
170measure under any applicable law fulfilling obligations under article
17111 of the WIPO copyright treaty adopted on 20 December 1996, or
172similar laws prohibiting or restricting circumvention of such
173measures.
174
175 When you convey a covered work, you waive any legal power to forbid
176circumvention of technological measures to the extent such circumvention
177is effected by exercising rights under this License with respect to
178the covered work, and you disclaim any intention to limit operation or
179modification of the work as a means of enforcing, against the work's
180users, your or third parties' legal rights to forbid circumvention of
181technological measures.
182
183 4. Conveying Verbatim Copies.
184
185 You may convey verbatim copies of the Program's source code as you
186receive it, in any medium, provided that you conspicuously and
187appropriately publish on each copy an appropriate copyright notice;
188keep intact all notices stating that this License and any
189non-permissive terms added in accord with section 7 apply to the code;
190keep intact all notices of the absence of any warranty; and give all
191recipients a copy of this License along with the Program.
192
193 You may charge any price or no price for each copy that you convey,
194and you may offer support or warranty protection for a fee.
195
196 5. Conveying Modified Source Versions.
197
198 You may convey a work based on the Program, or the modifications to
199produce it from the Program, in the form of source code under the
200terms of section 4, provided that you also meet all of these conditions:
201
202 a) The work must carry prominent notices stating that you modified
203 it, and giving a relevant date.
204
205 b) The work must carry prominent notices stating that it is
206 released under this License and any conditions added under section
207 7. This requirement modifies the requirement in section 4 to
208 "keep intact all notices".
209
210 c) You must license the entire work, as a whole, under this
211 License to anyone who comes into possession of a copy. This
212 License will therefore apply, along with any applicable section 7
213 additional terms, to the whole of the work, and all its parts,
214 regardless of how they are packaged. This License gives no
215 permission to license the work in any other way, but it does not
216 invalidate such permission if you have separately received it.
217
218 d) If the work has interactive user interfaces, each must display
219 Appropriate Legal Notices; however, if the Program has interactive
220 interfaces that do not display Appropriate Legal Notices, your
221 work need not make them do so.
222
223 A compilation of a covered work with other separate and independent
224works, which are not by their nature extensions of the covered work,
225and which are not combined with it such as to form a larger program,
226in or on a volume of a storage or distribution medium, is called an
227"aggregate" if the compilation and its resulting copyright are not
228used to limit the access or legal rights of the compilation's users
229beyond what the individual works permit. Inclusion of a covered work
230in an aggregate does not cause this License to apply to the other
231parts of the aggregate.
232
233 6. Conveying Non-Source Forms.
234
235 You may convey a covered work in object code form under the terms
236of sections 4 and 5, provided that you also convey the
237machine-readable Corresponding Source under the terms of this License,
238in one of these ways:
239
240 a) Convey the object code in, or embodied in, a physical product
241 (including a physical distribution medium), accompanied by the
242 Corresponding Source fixed on a durable physical medium
243 customarily used for software interchange.
244
245 b) Convey the object code in, or embodied in, a physical product
246 (including a physical distribution medium), accompanied by a
247 written offer, valid for at least three years and valid for as
248 long as you offer spare parts or customer support for that product
249 model, to give anyone who possesses the object code either (1) a
250 copy of the Corresponding Source for all the software in the
251 product that is covered by this License, on a durable physical
252 medium customarily used for software interchange, for a price no
253 more than your reasonable cost of physically performing this
254 conveying of source, or (2) access to copy the
255 Corresponding Source from a network server at no charge.
256
257 c) Convey individual copies of the object code with a copy of the
258 written offer to provide the Corresponding Source. This
259 alternative is allowed only occasionally and noncommercially, and
260 only if you received the object code with such an offer, in accord
261 with subsection 6b.
262
263 d) Convey the object code by offering access from a designated
264 place (gratis or for a charge), and offer equivalent access to the
265 Corresponding Source in the same way through the same place at no
266 further charge. You need not require recipients to copy the
267 Corresponding Source along with the object code. If the place to
268 copy the object code is a network server, the Corresponding Source
269 may be on a different server (operated by you or a third party)
270 that supports equivalent copying facilities, provided you maintain
271 clear directions next to the object code saying where to find the
272 Corresponding Source. Regardless of what server hosts the
273 Corresponding Source, you remain obligated to ensure that it is
274 available for as long as needed to satisfy these requirements.
275
276 e) Convey the object code using peer-to-peer transmission, provided
277 you inform other peers where the object code and Corresponding
278 Source of the work are being offered to the general public at no
279 charge under subsection 6d.
280
281 A separable portion of the object code, whose source code is excluded
282from the Corresponding Source as a System Library, need not be
283included in conveying the object code work.
284
285 A "User Product" is either (1) a "consumer product", which means any
286tangible personal property which is normally used for personal, family,
287or household purposes, or (2) anything designed or sold for incorporation
288into a dwelling. In determining whether a product is a consumer product,
289doubtful cases shall be resolved in favor of coverage. For a particular
290product received by a particular user, "normally used" refers to a
291typical or common use of that class of product, regardless of the status
292of the particular user or of the way in which the particular user
293actually uses, or expects or is expected to use, the product. A product
294is a consumer product regardless of whether the product has substantial
295commercial, industrial or non-consumer uses, unless such uses represent
296the only significant mode of use of the product.
297
298 "Installation Information" for a User Product means any methods,
299procedures, authorization keys, or other information required to install
300and execute modified versions of a covered work in that User Product from
301a modified version of its Corresponding Source. The information must
302suffice to ensure that the continued functioning of the modified object
303code is in no case prevented or interfered with solely because
304modification has been made.
305
306 If you convey an object code work under this section in, or with, or
307specifically for use in, a User Product, and the conveying occurs as
308part of a transaction in which the right of possession and use of the
309User Product is transferred to the recipient in perpetuity or for a
310fixed term (regardless of how the transaction is characterized), the
311Corresponding Source conveyed under this section must be accompanied
312by the Installation Information. But this requirement does not apply
313if neither you nor any third party retains the ability to install
314modified object code on the User Product (for example, the work has
315been installed in ROM).
316
317 The requirement to provide Installation Information does not include a
318requirement to continue to provide support service, warranty, or updates
319for a work that has been modified or installed by the recipient, or for
320the User Product in which it has been modified or installed. Access to a
321network may be denied when the modification itself materially and
322adversely affects the operation of the network or violates the rules and
323protocols for communication across the network.
324
325 Corresponding Source conveyed, and Installation Information provided,
326in accord with this section must be in a format that is publicly
327documented (and with an implementation available to the public in
328source code form), and must require no special password or key for
329unpacking, reading or copying.
330
331 7. Additional Terms.
332
333 "Additional permissions" are terms that supplement the terms of this
334License by making exceptions from one or more of its conditions.
335Additional permissions that are applicable to the entire Program shall
336be treated as though they were included in this License, to the extent
337that they are valid under applicable law. If additional permissions
338apply only to part of the Program, that part may be used separately
339under those permissions, but the entire Program remains governed by
340this License without regard to the additional permissions.
341
342 When you convey a copy of a covered work, you may at your option
343remove any additional permissions from that copy, or from any part of
344it. (Additional permissions may be written to require their own
345removal in certain cases when you modify the work.) You may place
346additional permissions on material, added by you to a covered work,
347for which you have or can give appropriate copyright permission.
348
349 Notwithstanding any other provision of this License, for material you
350add to a covered work, you may (if authorized by the copyright holders of
351that material) supplement the terms of this License with terms:
352
353 a) Disclaiming warranty or limiting liability differently from the
354 terms of sections 15 and 16 of this License; or
355
356 b) Requiring preservation of specified reasonable legal notices or
357 author attributions in that material or in the Appropriate Legal
358 Notices displayed by works containing it; or
359
360 c) Prohibiting misrepresentation of the origin of that material, or
361 requiring that modified versions of such material be marked in
362 reasonable ways as different from the original version; or
363
364 d) Limiting the use for publicity purposes of names of licensors or
365 authors of the material; or
366
367 e) Declining to grant rights under trademark law for use of some
368 trade names, trademarks, or service marks; or
369
370 f) Requiring indemnification of licensors and authors of that
371 material by anyone who conveys the material (or modified versions of
372 it) with contractual assumptions of liability to the recipient, for
373 any liability that these contractual assumptions directly impose on
374 those licensors and authors.
375
376 All other non-permissive additional terms are considered "further
377restrictions" within the meaning of section 10. If the Program as you
378received it, or any part of it, contains a notice stating that it is
379governed by this License along with a term that is a further
380restriction, you may remove that term. If a license document contains
381a further restriction but permits relicensing or conveying under this
382License, you may add to a covered work material governed by the terms
383of that license document, provided that the further restriction does
384not survive such relicensing or conveying.
385
386 If you add terms to a covered work in accord with this section, you
387must place, in the relevant source files, a statement of the
388additional terms that apply to those files, or a notice indicating
389where to find the applicable terms.
390
391 Additional terms, permissive or non-permissive, may be stated in the
392form of a separately written license, or stated as exceptions;
393the above requirements apply either way.
394
395 8. Termination.
396
397 You may not propagate or modify a covered work except as expressly
398provided under this License. Any attempt otherwise to propagate or
399modify it is void, and will automatically terminate your rights under
400this License (including any patent licenses granted under the third
401paragraph of section 11).
402
403 However, if you cease all violation of this License, then your
404license from a particular copyright holder is reinstated (a)
405provisionally, unless and until the copyright holder explicitly and
406finally terminates your license, and (b) permanently, if the copyright
407holder fails to notify you of the violation by some reasonable means
408prior to 60 days after the cessation.
409
410 Moreover, your license from a particular copyright holder is
411reinstated permanently if the copyright holder notifies you of the
412violation by some reasonable means, this is the first time you have
413received notice of violation of this License (for any work) from that
414copyright holder, and you cure the violation prior to 30 days after
415your receipt of the notice.
416
417 Termination of your rights under this section does not terminate the
418licenses of parties who have received copies or rights from you under
419this License. If your rights have been terminated and not permanently
420reinstated, you do not qualify to receive new licenses for the same
421material under section 10.
422
423 9. Acceptance Not Required for Having Copies.
424
425 You are not required to accept this License in order to receive or
426run a copy of the Program. Ancillary propagation of a covered work
427occurring solely as a consequence of using peer-to-peer transmission
428to receive a copy likewise does not require acceptance. However,
429nothing other than this License grants you permission to propagate or
430modify any covered work. These actions infringe copyright if you do
431not accept this License. Therefore, by modifying or propagating a
432covered work, you indicate your acceptance of this License to do so.
433
434 10. Automatic Licensing of Downstream Recipients.
435
436 Each time you convey a covered work, the recipient automatically
437receives a license from the original licensors, to run, modify and
438propagate that work, subject to this License. You are not responsible
439for enforcing compliance by third parties with this License.
440
441 An "entity transaction" is a transaction transferring control of an
442organization, or substantially all assets of one, or subdividing an
443organization, or merging organizations. If propagation of a covered
444work results from an entity transaction, each party to that
445transaction who receives a copy of the work also receives whatever
446licenses to the work the party's predecessor in interest had or could
447give under the previous paragraph, plus a right to possession of the
448Corresponding Source of the work from the predecessor in interest, if
449the predecessor has it or can get it with reasonable efforts.
450
451 You may not impose any further restrictions on the exercise of the
452rights granted or affirmed under this License. For example, you may
453not impose a license fee, royalty, or other charge for exercise of
454rights granted under this License, and you may not initiate litigation
455(including a cross-claim or counterclaim in a lawsuit) alleging that
456any patent claim is infringed by making, using, selling, offering for
457sale, or importing the Program or any portion of it.
458
459 11. Patents.
460
461 A "contributor" is a copyright holder who authorizes use under this
462License of the Program or a work on which the Program is based. The
463work thus licensed is called the contributor's "contributor version".
464
465 A contributor's "essential patent claims" are all patent claims
466owned or controlled by the contributor, whether already acquired or
467hereafter acquired, that would be infringed by some manner, permitted
468by this License, of making, using, or selling its contributor version,
469but do not include claims that would be infringed only as a
470consequence of further modification of the contributor version. For
471purposes of this definition, "control" includes the right to grant
472patent sublicenses in a manner consistent with the requirements of
473this License.
474
475 Each contributor grants you a non-exclusive, worldwide, royalty-free
476patent license under the contributor's essential patent claims, to
477make, use, sell, offer for sale, import and otherwise run, modify and
478propagate the contents of its contributor version.
479
480 In the following three paragraphs, a "patent license" is any express
481agreement or commitment, however denominated, not to enforce a patent
482(such as an express permission to practice a patent or covenant not to
483sue for patent infringement). To "grant" such a patent license to a
484party means to make such an agreement or commitment not to enforce a
485patent against the party.
486
487 If you convey a covered work, knowingly relying on a patent license,
488and the Corresponding Source of the work is not available for anyone
489to copy, free of charge and under the terms of this License, through a
490publicly available network server or other readily accessible means,
491then you must either (1) cause the Corresponding Source to be so
492available, or (2) arrange to deprive yourself of the benefit of the
493patent license for this particular work, or (3) arrange, in a manner
494consistent with the requirements of this License, to extend the patent
495license to downstream recipients. "Knowingly relying" means you have
496actual knowledge that, but for the patent license, your conveying the
497covered work in a country, or your recipient's use of the covered work
498in a country, would infringe one or more identifiable patents in that
499country that you have reason to believe are valid.
500
501 If, pursuant to or in connection with a single transaction or
502arrangement, you convey, or propagate by procuring conveyance of, a
503covered work, and grant a patent license to some of the parties
504receiving the covered work authorizing them to use, propagate, modify
505or convey a specific copy of the covered work, then the patent license
506you grant is automatically extended to all recipients of the covered
507work and works based on it.
508
509 A patent license is "discriminatory" if it does not include within
510the scope of its coverage, prohibits the exercise of, or is
511conditioned on the non-exercise of one or more of the rights that are
512specifically granted under this License. You may not convey a covered
513work if you are a party to an arrangement with a third party that is
514in the business of distributing software, under which you make payment
515to the third party based on the extent of your activity of conveying
516the work, and under which the third party grants, to any of the
517parties who would receive the covered work from you, a discriminatory
518patent license (a) in connection with copies of the covered work
519conveyed by you (or copies made from those copies), or (b) primarily
520for and in connection with specific products or compilations that
521contain the covered work, unless you entered into that arrangement,
522or that patent license was granted, prior to 28 March 2007.
523
524 Nothing in this License shall be construed as excluding or limiting
525any implied license or other defenses to infringement that may
526otherwise be available to you under applicable patent law.
527
528 12. No Surrender of Others' Freedom.
529
530 If conditions are imposed on you (whether by court order, agreement or
531otherwise) that contradict the conditions of this License, they do not
532excuse you from the conditions of this License. If you cannot convey a
533covered work so as to satisfy simultaneously your obligations under this
534License and any other pertinent obligations, then as a consequence you may
535not convey it at all. For example, if you agree to terms that obligate you
536to collect a royalty for further conveying from those to whom you convey
537the Program, the only way you could satisfy both those terms and this
538License would be to refrain entirely from conveying the Program.
539
540 13. Remote Network Interaction; Use with the GNU General Public License.
541
542 Notwithstanding any other provision of this License, if you modify the
543Program, your modified version must prominently offer all users
544interacting with it remotely through a computer network (if your version
545supports such interaction) an opportunity to receive the Corresponding
546Source of your version by providing access to the Corresponding Source
547from a network server at no charge, through some standard or customary
548means of facilitating copying of software. This Corresponding Source
549shall include the Corresponding Source for any work covered by version 3
550of the GNU General Public License that is incorporated pursuant to the
551following paragraph.
552
553 Notwithstanding any other provision of this License, you have
554permission to link or combine any covered work with a work licensed
555under version 3 of the GNU General Public License into a single
556combined work, and to convey the resulting work. The terms of this
557License will continue to apply to the part which is the covered work,
558but the work with which it is combined will remain governed by version
5593 of the GNU General Public License.
560
561 14. Revised Versions of this License.
562
563 The Free Software Foundation may publish revised and/or new versions of
564the GNU Affero General Public License from time to time. Such new versions
565will be similar in spirit to the present version, but may differ in detail to
566address new problems or concerns.
567
568 Each version is given a distinguishing version number. If the
569Program specifies that a certain numbered version of the GNU Affero General
570Public License "or any later version" applies to it, you have the
571option of following the terms and conditions either of that numbered
572version or of any later version published by the Free Software
573Foundation. If the Program does not specify a version number of the
574GNU Affero General Public License, you may choose any version ever published
575by the Free Software Foundation.
576
577 If the Program specifies that a proxy can decide which future
578versions of the GNU Affero General Public License can be used, that proxy's
579public statement of acceptance of a version permanently authorizes you
580to choose that version for the Program.
581
582 Later license versions may give you additional or different
583permissions. However, no additional obligations are imposed on any
584author or copyright holder as a result of your choosing to follow a
585later version.
586
587 15. Disclaimer of Warranty.
588
589 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597
598 16. Limitation of Liability.
599
600 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608SUCH DAMAGES.
609
610 17. Interpretation of Sections 15 and 16.
611
612 If the disclaimer of warranty and limitation of liability provided
613above cannot be given local legal effect according to their terms,
614reviewing courts shall apply local law that most closely approximates
615an absolute waiver of all civil liability in connection with the
616Program, unless a warranty or assumption of liability accompanies a
617copy of the Program in return for a fee.
618
619 END OF TERMS AND CONDITIONS
620
621 How to Apply These Terms to Your New Programs
622
623 If you develop a new program, and you want it to be of the greatest
624possible use to the public, the best way to achieve this is to make it
625free software which everyone can redistribute and change under these terms.
626
627 To do so, attach the following notices to the program. It is safest
628to attach them to the start of each source file to most effectively
629state the exclusion of warranty; and each file should have at least
630the "copyright" line and a pointer to where the full notice is found.
631
632 <one line to give the program's name and a brief idea of what it does.>
633 Copyright (C) <year> <name of author>
634
635 This program is free software: you can redistribute it and/or modify
636 it under the terms of the GNU Affero General Public License as published by
637 the Free Software Foundation, either version 3 of the License, or
638 (at your option) any later version.
639
640 This program is distributed in the hope that it will be useful,
641 but WITHOUT ANY WARRANTY; without even the implied warranty of
642 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 GNU Affero General Public License for more details.
644
645 You should have received a copy of the GNU Affero General Public License
646 along with this program. If not, see <https://www.gnu.org/licenses/>.
647
648Also add information on how to contact you by electronic and paper mail.
649
650 If your software can interact with users remotely through a computer
651network, you should also make sure that it provides a way for users to
652get its source. For example, if your program is a web application, its
653interface could display a "Source" link that leads users to an archive
654of the code. There are many ways you could offer source, and different
655solutions will be better for different programs; see section 13 for the
656specific requirements.
657
658 You should also get your employer (if you work as a programmer) or school,
659if any, to sign a "copyright disclaimer" for the program, if necessary.
660For more information on this, and how to apply and follow the GNU AGPL, see
661<https://www.gnu.org/licenses/>.
diff --git a/static/bsd_license.txt b/static/bsd_license.txt
deleted file mode 100644
index ebc7cdc..0000000
--- a/static/bsd_license.txt
+++ /dev/null
@@ -1,24 +0,0 @@
1BSD 2-Clause License
2
3Copyright (c) 2024, Vineet Kumar
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
81. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10
112. Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/static/cc-by-4.0.txt b/static/cc-by-nc-sa-4.0.txt
index 4ea99c2..7cdbe0b 100644
--- a/static/cc-by-4.0.txt
+++ b/static/cc-by-nc-sa-4.0.txt
@@ -1,4 +1,4 @@
1Attribution 4.0 International 1Attribution-NonCommercial-ShareAlike 4.0 International
2 2
3======================================================================= 3=======================================================================
4 4
@@ -54,16 +54,18 @@ exhaustive, and do not form part of our licenses.
54 54
55======================================================================= 55=======================================================================
56 56
57Creative Commons Attribution 4.0 International Public License 57Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
58Public License
58 59
59By exercising the Licensed Rights (defined below), You accept and agree 60By exercising the Licensed Rights (defined below), You accept and agree
60to be bound by the terms and conditions of this Creative Commons 61to be bound by the terms and conditions of this Creative Commons
61Attribution 4.0 International Public License ("Public License"). To the 62Attribution-NonCommercial-ShareAlike 4.0 International Public License
62extent this Public License may be interpreted as a contract, You are 63("Public License"). To the extent this Public License may be
63granted the Licensed Rights in consideration of Your acceptance of 64interpreted as a contract, You are granted the Licensed Rights in
64these terms and conditions, and the Licensor grants You such rights in 65consideration of Your acceptance of these terms and conditions, and the
65consideration of benefits the Licensor receives from making the 66Licensor grants You such rights in consideration of benefits the
66Licensed Material available under these terms and conditions. 67Licensor receives from making the Licensed Material available under
68these terms and conditions.
67 69
68 70
69Section 1 -- Definitions. 71Section 1 -- Definitions.
@@ -82,7 +84,11 @@ Section 1 -- Definitions.
82 and Similar Rights in Your contributions to Adapted Material in 84 and Similar Rights in Your contributions to Adapted Material in
83 accordance with the terms and conditions of this Public License. 85 accordance with the terms and conditions of this Public License.
84 86
85 c. Copyright and Similar Rights means copyright and/or similar rights 87 c. BY-NC-SA Compatible License means a license listed at
88 creativecommons.org/compatiblelicenses, approved by Creative
89 Commons as essentially the equivalent of this Public License.
90
91 d. Copyright and Similar Rights means copyright and/or similar rights
86 closely related to copyright including, without limitation, 92 closely related to copyright including, without limitation,
87 performance, broadcast, sound recording, and Sui Generis Database 93 performance, broadcast, sound recording, and Sui Generis Database
88 Rights, without regard to how the rights are labeled or 94 Rights, without regard to how the rights are labeled or
@@ -90,29 +96,41 @@ Section 1 -- Definitions.
90 specified in Section 2(b)(1)-(2) are not Copyright and Similar 96 specified in Section 2(b)(1)-(2) are not Copyright and Similar
91 Rights. 97 Rights.
92 98
93 d. Effective Technological Measures means those measures that, in the 99 e. Effective Technological Measures means those measures that, in the
94 absence of proper authority, may not be circumvented under laws 100 absence of proper authority, may not be circumvented under laws
95 fulfilling obligations under Article 11 of the WIPO Copyright 101 fulfilling obligations under Article 11 of the WIPO Copyright
96 Treaty adopted on December 20, 1996, and/or similar international 102 Treaty adopted on December 20, 1996, and/or similar international
97 agreements. 103 agreements.
98 104
99 e. Exceptions and Limitations means fair use, fair dealing, and/or 105 f. Exceptions and Limitations means fair use, fair dealing, and/or
100 any other exception or limitation to Copyright and Similar Rights 106 any other exception or limitation to Copyright and Similar Rights
101 that applies to Your use of the Licensed Material. 107 that applies to Your use of the Licensed Material.
102 108
103 f. Licensed Material means the artistic or literary work, database, 109 g. License Elements means the license attributes listed in the name
110 of a Creative Commons Public License. The License Elements of this
111 Public License are Attribution, NonCommercial, and ShareAlike.
112
113 h. Licensed Material means the artistic or literary work, database,
104 or other material to which the Licensor applied this Public 114 or other material to which the Licensor applied this Public
105 License. 115 License.
106 116
107 g. Licensed Rights means the rights granted to You subject to the 117 i. Licensed Rights means the rights granted to You subject to the
108 terms and conditions of this Public License, which are limited to 118 terms and conditions of this Public License, which are limited to
109 all Copyright and Similar Rights that apply to Your use of the 119 all Copyright and Similar Rights that apply to Your use of the
110 Licensed Material and that the Licensor has authority to license. 120 Licensed Material and that the Licensor has authority to license.
111 121
112 h. Licensor means the individual(s) or entity(ies) granting rights 122 j. Licensor means the individual(s) or entity(ies) granting rights
113 under this Public License. 123 under this Public License.
114 124
115 i. Share means to provide material to the public by any means or 125 k. NonCommercial means not primarily intended for or directed towards
126 commercial advantage or monetary compensation. For purposes of
127 this Public License, the exchange of the Licensed Material for
128 other material subject to Copyright and Similar Rights by digital
129 file-sharing or similar means is NonCommercial provided there is
130 no payment of monetary compensation in connection with the
131 exchange.
132
133 l. Share means to provide material to the public by any means or
116 process that requires permission under the Licensed Rights, such 134 process that requires permission under the Licensed Rights, such
117 as reproduction, public display, public performance, distribution, 135 as reproduction, public display, public performance, distribution,
118 dissemination, communication, or importation, and to make material 136 dissemination, communication, or importation, and to make material
@@ -120,13 +138,13 @@ Section 1 -- Definitions.
120 public may access the material from a place and at a time 138 public may access the material from a place and at a time
121 individually chosen by them. 139 individually chosen by them.
122 140
123 j. Sui Generis Database Rights means rights other than copyright 141 m. Sui Generis Database Rights means rights other than copyright
124 resulting from Directive 96/9/EC of the European Parliament and of 142 resulting from Directive 96/9/EC of the European Parliament and of
125 the Council of 11 March 1996 on the legal protection of databases, 143 the Council of 11 March 1996 on the legal protection of databases,
126 as amended and/or succeeded, as well as other essentially 144 as amended and/or succeeded, as well as other essentially
127 equivalent rights anywhere in the world. 145 equivalent rights anywhere in the world.
128 146
129 k. You means the individual or entity exercising the Licensed Rights 147 n. You means the individual or entity exercising the Licensed Rights
130 under this Public License. Your has a corresponding meaning. 148 under this Public License. Your has a corresponding meaning.
131 149
132 150
@@ -140,9 +158,10 @@ Section 2 -- Scope.
140 exercise the Licensed Rights in the Licensed Material to: 158 exercise the Licensed Rights in the Licensed Material to:
141 159
142 a. reproduce and Share the Licensed Material, in whole or 160 a. reproduce and Share the Licensed Material, in whole or
143 in part; and 161 in part, for NonCommercial purposes only; and
144 162
145 b. produce, reproduce, and Share Adapted Material. 163 b. produce, reproduce, and Share Adapted Material for
164 NonCommercial purposes only.
146 165
147 2. Exceptions and Limitations. For the avoidance of doubt, where 166 2. Exceptions and Limitations. For the avoidance of doubt, where
148 Exceptions and Limitations apply to Your use, this Public 167 Exceptions and Limitations apply to Your use, this Public
@@ -172,7 +191,13 @@ Section 2 -- Scope.
172 Licensed Rights under the terms and conditions of this 191 Licensed Rights under the terms and conditions of this
173 Public License. 192 Public License.
174 193
175 b. No downstream restrictions. You may not offer or impose 194 b. Additional offer from the Licensor -- Adapted Material.
195 Every recipient of Adapted Material from You
196 automatically receives an offer from the Licensor to
197 exercise the Licensed Rights in the Adapted Material
198 under the conditions of the Adapter's License You apply.
199
200 c. No downstream restrictions. You may not offer or impose
176 any additional or different terms or conditions on, or 201 any additional or different terms or conditions on, or
177 apply any Effective Technological Measures to, the 202 apply any Effective Technological Measures to, the
178 Licensed Material if doing so restricts exercise of the 203 Licensed Material if doing so restricts exercise of the
@@ -204,7 +229,9 @@ Section 2 -- Scope.
204 Rights, whether directly or through a collecting society 229 Rights, whether directly or through a collecting society
205 under any voluntary or waivable statutory or compulsory 230 under any voluntary or waivable statutory or compulsory
206 licensing scheme. In all other cases the Licensor expressly 231 licensing scheme. In all other cases the Licensor expressly
207 reserves any right to collect such royalties. 232 reserves any right to collect such royalties, including when
233 the Licensed Material is used other than for NonCommercial
234 purposes.
208 235
209 236
210Section 3 -- License Conditions. 237Section 3 -- License Conditions.
@@ -249,14 +276,28 @@ following conditions.
249 reasonable to satisfy the conditions by providing a URI or 276 reasonable to satisfy the conditions by providing a URI or
250 hyperlink to a resource that includes the required 277 hyperlink to a resource that includes the required
251 information. 278 information.
252
253 3. If requested by the Licensor, You must remove any of the 279 3. If requested by the Licensor, You must remove any of the
254 information required by Section 3(a)(1)(A) to the extent 280 information required by Section 3(a)(1)(A) to the extent
255 reasonably practicable. 281 reasonably practicable.
256 282
257 4. If You Share Adapted Material You produce, the Adapter's 283 b. ShareAlike.
258 License You apply must not prevent recipients of the Adapted 284
259 Material from complying with this Public License. 285 In addition to the conditions in Section 3(a), if You Share
286 Adapted Material You produce, the following conditions also apply.
287
288 1. The Adapter's License You apply must be a Creative Commons
289 license with the same License Elements, this version or
290 later, or a BY-NC-SA Compatible License.
291
292 2. You must include the text of, or the URI or hyperlink to, the
293 Adapter's License You apply. You may satisfy this condition
294 in any reasonable manner based on the medium, means, and
295 context in which You Share Adapted Material.
296
297 3. You may not offer or impose any additional or different terms
298 or conditions on, or apply any Effective Technological
299 Measures to, Adapted Material that restrict exercise of the
300 rights granted under the Adapter's License You apply.
260 301
261 302
262Section 4 -- Sui Generis Database Rights. 303Section 4 -- Sui Generis Database Rights.
@@ -266,12 +307,14 @@ apply to Your use of the Licensed Material:
266 307
267 a. for the avoidance of doubt, Section 2(a)(1) grants You the right 308 a. for the avoidance of doubt, Section 2(a)(1) grants You the right
268 to extract, reuse, reproduce, and Share all or a substantial 309 to extract, reuse, reproduce, and Share all or a substantial
269 portion of the contents of the database; 310 portion of the contents of the database for NonCommercial purposes
311 only;
270 312
271 b. if You include all or a substantial portion of the database 313 b. if You include all or a substantial portion of the database
272 contents in a database in which You have Sui Generis Database 314 contents in a database in which You have Sui Generis Database
273 Rights, then the database in which You have Sui Generis Database 315 Rights, then the database in which You have Sui Generis Database
274 Rights (but not its individual contents) is Adapted Material; and 316 Rights (but not its individual contents) is Adapted Material,
317 including for purposes of Section 3(b); and
275 318
276 c. You must comply with the conditions in Section 3(a) if You Share 319 c. You must comply with the conditions in Section 3(a) if You Share
277 all or a substantial portion of the contents of the database. 320 all or a substantial portion of the contents of the database.
@@ -372,7 +415,6 @@ Section 8 -- Interpretation.
372 that apply to the Licensor or You, including from the legal 415 that apply to the Licensor or You, including from the legal
373 processes of any jurisdiction or authority. 416 processes of any jurisdiction or authority.
374 417
375
376======================================================================= 418=======================================================================
377 419
378Creative Commons is not a party to its public 420Creative Commons is not a party to its public
@@ -393,3 +435,4 @@ the avoidance of doubt, this paragraph does not form part of the
393public licenses. 435public licenses.
394 436
395Creative Commons may be contacted at creativecommons.org. 437Creative Commons may be contacted at creativecommons.org.
438
diff --git a/static/main.css b/static/main.css
new file mode 100644
index 0000000..ef28c74
--- /dev/null
+++ b/static/main.css
@@ -0,0 +1,203 @@
1/* fonts */
2@font-face {
3 font-family: "Comic Mono";
4 font-weight: normal;
5 font-style: normal;
6 font-display: swap;
7 src: url('https://dtinth.github.io/comic-mono-font/ComicMono.ttf');
8}
9
10@font-face {
11 font-family: "Comic Mono";
12 font-weight: bold;
13 font-style: normal;
14 font-display: swap;
15 src: url('https://dtinth.github.io/comic-mono-font/ComicMono-Bold.ttf');
16}
17
18@font-face {
19 font-family: 'Comic Neue';
20 src: local('Comic Neue Italic'), local('ComicNeue-Italic'),
21 url('https://github.com/crozynski/comicneue/raw/refs/heads/master/Fonts/WebFonts/ComicNeue-Italic.woff2') format('woff2');
22 font-weight: normal;
23 font-style: italic;
24 font-display: swap;
25}
26
27@font-face {
28 font-family: 'Comic Neue';
29 src: local('Comic Neue Bold'), local('ComicNeue-Bold'),
30 url('https://github.com/crozynski/comicneue/raw/refs/heads/master/Fonts/WebFonts/ComicNeue-Bold.woff2') format('woff2');
31 font-weight: bold;
32 font-style: normal;
33 font-display: swap;
34}
35
36@font-face {
37 font-family: 'Comic Neue';
38 src: local('Comic Neue Bold Italic'), local('ComicNeue-BoldItalic'),
39 url('https://github.com/crozynski/comicneue/raw/refs/heads/master/Fonts/WebFonts/ComicNeue-BoldItalic.woff2') format('woff2');
40 font-weight: bold;
41 font-style: italic;
42 font-display: swap;
43}
44
45@font-face {
46 font-family: 'Comic Neue';
47 src: local('Comic Neue Regular'), local('ComicNeue-Regular'),
48 url('https://github.com/crozynski/comicneue/raw/refs/heads/master/Fonts/WebFonts/ComicNeue-Regular.woff2') format('woff2');
49 font-weight: normal;
50 font-style: normal;
51 font-display: swap;
52}
53
54/* main */
55
56:root {
57 /* kaolin valley light */
58 --background: #faf2e9;
59 --brbackground: #ebd7be;
60 --foreground: #5e5854;
61 --brforeground: #6b6560;
62 --border: #f0dfca;
63
64 --black: #5e5854;
65 --brblack: #544b44;
66 --red: #d42215;
67 --green: #0d7a75;
68 --yellow: #d1832e;
69 --blue: #526af3;
70 --magenta: #cf44ac;
71 --cyan: #0bc9cf;
72 --white: #ebd7be;
73}
74
75@media (prefers-color-scheme: dark) {
76 :root {
77 /* kaolin valley dark */
78 --background: #1c1616;
79 --brbackground: #5e5854;
80 --foreground: #eee6d3;
81 --brforeground: #c7c2af;
82 --border: #2e2a29;
83
84 --black: #28211e;
85 --brblack: #544b44;
86 --red: #e84c58;
87 --green: #91f368;
88 --yellow: #eed891;
89 --blue: #41b0f3;
90 --magenta: #cea2ca;
91 --cyan: #6bd9db;
92 --white: #eee6d3;
93 }
94}
95
96html {
97 color: var(--foreground);
98 background-color: var(--background);
99}
100
101nav {
102 display: flex;
103 justify-content: space-between;
104 align-items: center;
105 margin-bottom: 1rem;
106}
107
108nav ul {
109 display: flex;
110 list-style: none;
111 margin: 0;
112 padding: 0;
113 gap: 1rem;
114}
115
116body {
117 max-width: 720px;
118 margin: 0 auto;
119 padding: 1rem;
120 font-family: "Comic Neue", "Comic Sans MS", sans-serif;
121}
122
123h2 {
124 margin-bottom: 0;
125}
126
127a {
128 color: var(--yellow);
129 text-decoration: none;
130}
131
132a:hover {
133 text-decoration: underline;
134}
135
136a:visited {
137 color: var(--green);
138}
139
140article {
141 margin: 0 auto;
142 line-height: 1.3;
143}
144
145article img {
146 display: block !important;
147 margin: 0 auto !important;
148 max-width: 90%;
149}
150
151@media (max-width: 640px) {
152 article img {
153 max-width: calc(100% - 2rem);
154 }
155}
156
157footer {
158 margin-top: 2rem;
159 text-align: center;
160 font-size: 0.8rem;
161 color: var(--brblack);
162}
163
164pre {
165 background-color: var(--brbackground);
166 padding: 0.25rem 1rem;
167 margin: 0 -1rem;
168 max-width: 100%;
169 overflow-x: auto;
170}
171
172pre, code {
173 font-family: "Comic Code", "Comic Mono", monospace;
174}
175
176summary {
177 cursor: pointer;
178 background-color: var(--brbackground);
179 padding: 0.25rem 1rem;
180 margin: 0 -1rem;
181}
182
183details[open] {
184 border-bottom: 1rem solid var(--border);
185 margin: 0 -1rem 1rem;
186 padding: 0 1rem;
187}
188
189blockquote {
190 border-left: 5px solid var(--border);
191 background-color: var(--brbackground);
192 padding: 0 1rem;
193 margin-left: calc(-1rem - 5px);
194 margin-right: -1rem;
195}
196
197.text-center {
198 text-align: center;
199}
200
201.date {
202 font-family: "Comic Code", "Comic Mono", monospace;
203}
diff --git a/theme.scm b/theme.scm
new file mode 100644
index 0000000..4485c62
--- /dev/null
+++ b/theme.scm
@@ -0,0 +1,73 @@
1(define-module (theme)
2 #:use-module (haunt artifact)
3 #:use-module (haunt asset)
4 #:use-module (haunt builder blog)
5 #:use-module (haunt html)
6 #:use-module (haunt post)
7 #:use-module (haunt site)
8 #:use-module (srfi srfi-19)
9 #:export (vin-theme))
10
11(define (link name uri)
12 `(a (@ (href ,uri)) ,name))
13
14(define vin-theme
15 (theme #:name "vin"
16 #:layout
17 (lambda (site title body)
18 `((doctype "html")
19 (head
20 (meta (@ (charset "utf-8")))
21 (meta (@ (name "viewport")
22 (content "width=device-width, initial-scale=1")))
23 (title ,(string-append title " - " (site-title site)))
24 (link (@ (rel "alternate")
25 (type "application/atom+xml")
26 (title "Atom feed")
27 (href "/feed.xml")))
28 (link (@ (rel "icon")
29 (type "image/png")
30 (href "/static/AT_terminus.png")))
31 (link (@ (rel "stylesheet")
32 (type "text/css")
33 (href "/static/main.css")))
34 (body
35 (div (@ (class "container"))
36 (nav
37 (ul (li ,(link "Vineet K" "/")))
38 (ul (li ,(link "About Me" "/about.html"))
39 (li ,(link "Blog" "/index.html"))
40 ;; (li ,(link "Projects" "/projects.html"))
41 ))
42 ,body
43 (footer (@ (class "text-center"))
44 (p "The content for the site is under the " ,(link "CC-BY-NC-SA-4.0 License" "/static/cc-by-nc-sa-4.0.txt") ". "
45 "The code for this site is under the " ,(link "GNU AGPLv3 License" "/static/agpl-3.0.txt") ".")))))))
46 #:post-template
47 (lambda (post)
48 `((article
49 (h1 (@ (class "title"))
50 ,(post-ref post 'title))
51 (div (@ (class "date"))
52 ,(date->string (post-date post)
53 "~B ~d, ~Y"))
54 (div (@ (class "post"))
55 ,(post-sxml post)))))
56 #:collection-template
57 (lambda (site title posts prefix)
58 (define (post-uri post)
59 (string-append prefix "/" (site-post-slug site post) ".html"))
60 `((h2 ,title " "
61 (a (@ (href "/feed.xml")) "(feed)"))
62 ,(map (lambda (post)
63 (let ((uri (post-uri post)))
64 `(div (@ (class "posts"))
65 (div (@ (class "post"))
66 (span (span (@ (class "date"))
67 ,(date->string
68 (post-date post)
69 "~Y-~m-~d"))
70 " - "
71 (a (@ (href ,uri))
72 ,(post-ref post 'title)))))))
73 posts)))))
diff --git a/update.sh b/update.sh
deleted file mode 100755
index 9853f61..0000000
--- a/update.sh
+++ /dev/null
@@ -1,4 +0,0 @@
1#!/bin/sh
2hugo
3#rsync --exclude="update.sh" --delete -ash . vineetk.net:/usr/local/www/vineetk_html/
4rsync --exclude="update.sh" --delete -ash public/ 10.0.13.1:/var/www/vineetk_html/