-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
433 lines (402 loc) · 24.6 KB
/
Copy pathindex.html
File metadata and controls
433 lines (402 loc) · 24.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
<!DOCTYPE html>
<html lang="en" dir="auto">
<head>
<meta name="generator" content="Hugo 0.147.1"><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="index, follow">
<title>pshegger's blog</title>
<meta name="description" content="">
<meta name="author" content="">
<link rel="canonical" href="https://pshegger.github.io/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.f49d66caae9ea0fd43f21f29e71a8d3e284517ed770f2aa86fa012953ad3c9ef.css" integrity="sha256-9J1myq6eoP1D8h8p5xqNPihFF+13Dyqob6ASlTrTye8=" rel="preload stylesheet" as="style">
<link rel="icon" href="https://pshegger.github.io/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="https://pshegger.github.io/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="https://pshegger.github.io/favicon-32x32.png">
<link rel="apple-touch-icon" href="https://pshegger.github.io/apple-touch-icon.png">
<link rel="mask-icon" href="https://pshegger.github.io/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" type="application/rss+xml" href="https://pshegger.github.io/index.xml">
<link rel="alternate" hreflang="en" href="https://pshegger.github.io/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NKBPT9CS94"></script>
<script>
var doNotTrack = false;
if ( false ) {
var dnt = (navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack);
var doNotTrack = (dnt == "1" || dnt == "yes");
}
if (!doNotTrack) {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-NKBPT9CS94');
}
</script><meta property="og:url" content="https://pshegger.github.io/">
<meta property="og:site_name" content="pshegger's blog">
<meta property="og:title" content="pshegger's blog">
<meta property="og:locale" content="en-us">
<meta property="og:type" content="website">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="pshegger's blog">
<meta name="twitter:description" content="">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "pshegger's blog",
"url": "https://pshegger.github.io/",
"description": "",
"logo": "https://pshegger.github.io/favicon.ico",
"sameAs": [
"https://bsky.app/profile/pshegger.bsky.social", "https://github.com/PsHegger/", "https://stackoverflow.com/users/751482/pshegger", "https://ctftime.org/user/62391", "https://app.hackthebox.com/users/746408"
]
}
</script>
</head>
<body class="list" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="https://pshegger.github.io/" accesskey="h" title="pshegger's blog (Alt + H)">pshegger's blog</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)" aria-label="Toggle theme">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
</div>
</div>
<ul id="menu">
<li>
<a href="https://pshegger.github.io/categories/" title="Categories">
<span>Categories</span>
</a>
</li>
<li>
<a href="https://pshegger.github.io/tags/" title="Tags">
<span>Tags</span>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="first-entry home-info">
<header class="entry-header">
<h1>pshegger’s blog</h1>
</header>
<div class="entry-content">
</div>
<footer class="entry-footer">
<div class="social-icons" >
<a href="https://bsky.app/profile/pshegger.bsky.social" target="_blank" rel="noopener noreferrer me"
title="Bluesky">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-25 0 400 320" fill="none" stroke="currentColor" stroke-width="30">
<path
d="M180 141.964C163.699 110.262 119.308 51.1817 78.0347 22.044C38.4971 -5.86834 23.414 -1.03207 13.526 3.43594C2.08093 8.60755 0 26.1785 0 36.5164C0 46.8542 5.66748 121.272 9.36416 133.694C21.5786 174.738 65.0603 188.607 105.104 184.156C107.151 183.852 109.227 183.572 111.329 183.312C109.267 183.642 107.19 183.924 105.104 184.156C46.4204 192.847 -5.69621 214.233 62.6582 290.33C137.848 368.18 165.705 273.637 180 225.702C194.295 273.637 210.76 364.771 295.995 290.33C360 225.702 313.58 192.85 254.896 184.158C252.81 183.926 250.733 183.645 248.671 183.315C250.773 183.574 252.849 183.855 254.896 184.158C294.94 188.61 338.421 174.74 350.636 133.697C354.333 121.275 360 46.8568 360 36.519C360 26.1811 357.919 8.61012 346.474 3.43851C336.586 -1.02949 321.503 -5.86576 281.965 22.0466C240.692 51.1843 196.301 110.262 180 141.964Z" />
</svg>
</a>
<a href="https://github.com/PsHegger/" target="_blank" rel="noopener noreferrer me"
title="Github">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path
d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22">
</path>
</svg>
</a>
<a href="https://stackoverflow.com/users/751482/pshegger" target="_blank" rel="noopener noreferrer me"
title="Stackoverflow">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path
d="M2.913 16.041v6.848h17.599v-6.848M7.16 18.696h8.925M7.65 13.937l8.675 1.8M9.214 9.124l8.058 3.758M12.086 4.65l6.849 5.66M15.774 1.111l5.313 7.162" />
</svg>
</a>
<a href="https://ctftime.org/user/62391" target="_blank" rel="noopener noreferrer me"
title="Ctftime">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220.000000 200.000000" preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)" fill="currentColor" stroke="none">
<path d="M365 1499 c201 -275 365 -503 365 -507 0 -4 -84 -120 -188 -259 -103
-139 -263 -355 -356 -480 -93 -125 -173 -229 -178 -231 -45 -19 101 -22 992
-22 l1000 0 0 1000 0 1000 -1000 0 -999 0 364 -501z m1310 -509 l0 -305 -312
-3 -313 -2 0 310 0 310 313 -2 312 -3 0 -305z" />
<path d="M1150 1194 c0 -2 -1 -95 -1 -206 l0 -203 216 -3 215 -2 0 210 0 210
-157 0 -158 0 98 -98 c53 -53 97 -101 97 -106 0 -4 -42 -48 -92 -97 l-93 -88
-28 26 -27 27 65 66 65 66 -100 101 c-55 55 -100 99 -100 97z" />
</g>
</svg>
</a>
<a href="https://app.hackthebox.com/users/746408" target="_blank" rel="noopener noreferrer me"
title="Hackthebox">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" fill="currentColor"
stroke="none">
<g>
<path
d="M11.9959.0008a1.1187 1.1187 0 00-.057.002.8993.8993 0 00-.2358.0498.9067.9067 0 00-.1652.079L1.9357 5.675a.889.889 0 00-.4444.7699c0 .006.0004.0128.0006.0192-.0002.007 0 .014 0 .0212V17.556a.889.889 0 00.469.7837l9.5983 5.5416c.018.0102.036.0197.054.0287v.002a.8568.8568 0 00.083.0348c0 .001.01.003.012.004.028.01.056.0177.085.0245.01.001.011.003.016.004.028.006.057.0112.086.0146 0 .0005.01.0009.014.001.03.003.061.005.091.005s.061-.002.091-.005c0-.0005.01-.0009.014-.001a.6831.6831 0 00.086-.0146c.01-.001.011-.002.016-.004a.9404.9404 0 00.085-.0245c0-.001.01-.003.012-.004a.8818.8818 0 00.083-.0347v-.002a1.086 1.086 0 00.054-.0287l9.5986-5.5416a.889.889 0 00.4689-.7837V6.4786c0-.009-.0006-.0172-.0008-.0258h.0003v-.008a.8886.8886 0 00-.3117-.6755c-.01-.008-.019-.0162-.029-.0241 0-.002-.01-.005-.01-.007a.8988.8988 0 00-.1074-.0705L12.4533.1267a.8872.8872 0 00-.4646-.1266zm.01 2.2523c.072 0 .1443.0187.209.056l6.5366 3.774c.2789.161.2789.5633 0 .7243l-6.5367 3.774a.4182.4182 0 01-.4182 0L5.26 6.8074c-.2788-.1609-.2789-.5633 0-.7243l6.5368-3.774a.4193.4193 0 01.209-.056zm-8.0801 6.458a.4145.4145 0 01.215.0565l6.524 3.7666a.417.417 0 01.2086.3612v7.5326c0 .3212-.3477.522-.626.3613l-6.5237-3.7666a.4172.4172 0 01-.2086-.3613V9.1288c0-.2408.1955-.414.4107-.4177zm16.1599 0c.215.004.4107.1768.4107.4177v7.5325c0 .149-.08.2868-.2087.3614l-6.5239 3.7666c-.278.1606-.6258-.0401-.6258-.3614v-7.5325c0-.149.08-.2867.2086-.3613l6.5238-3.7666a.415.415 0 01.2152-.0565z">
</path>
</g>
</svg>
</a>
</div>
</footer>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">Instant - Machine Walkthrough
</h2>
</header>
<div class="entry-content">
<p>Introduction Instant is a medium difficulty Linux machine on HackTheBox.
To compromise the machine, we need to decompile an Android application, find credentials for a Swagger page, and discover an endpoint with a Local File Inclusion vulnerability. We can use this vulnerability to get the SSH private key for a user on the machine. Once we’re on the machine, we can discover a backup file for Solar PuTTY, which we can crack to recover the root password.
...</p>
</div>
<footer class="entry-footer"><span title='2025-05-06 00:00:00 +0000 UTC'>May 6, 2025</span> · 6 min · pshegger</footer>
<a class="entry-link" aria-label="post link to Instant - Machine Walkthrough" href="https://pshegger.github.io/posts/htb-instant/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">Cyber Apocalypse 2025
</h2>
</header>
<div class="entry-content">
<p>Coding Summoners Incantation It is a fairly simple task. The aim is to choose a number of tokens with the maximum possible sum. The twist is that we cannot use a token next to one that we’ve already chosen.
To solve it, we can create a recursive search with the following constraints:
if there are no tokens left, the max sum is 0 if there’s one token left, the max sum is the value of that token otherwise, we can check the first two tokens to decide which one we should use we take the 1st one and call the recursive function with the remaining ones (making sure to remove the 2nd token, since that’s the neighbor we cannot use) repeat previous step with the 2nd token; now we have to remove the 1st and 3rd tokens choose the one that has the higher sum def find_max_energy(tokens): if len(tokens) == 0: return 0 elif len(tokens) == 1: return tokens[0] e1 = tokens[0] + find_max_energy(tokens[2:]) e2 = tokens[1] + find_max_energy(tokens[3:]) return max(e1, e2) input_text = input() tokens = [int(t) for t in input_text[1:-1].split(',')] print(find_max_energy(tokens)) Dragon Fury For this task, we get a 2d array that contains possible “damage values” for rounds, and a target we need to reach. Our aim is to select a single value for each round in a way that adds up to our target in the end.
...</p>
</div>
<footer class="entry-footer"><span title='2025-04-16 00:00:00 +0000 UTC'>April 16, 2025</span> · 17 min · pshegger</footer>
<a class="entry-link" aria-label="post link to Cyber Apocalypse 2025" href="https://pshegger.github.io/posts/cyber-apocalypse-2025/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">IrisCTF 2024
</h2>
</header>
<div class="entry-content">
<p>IrisCTF has just ended, and since I was one of the participants, I decided to write a few thoughts about it, as well as write proper writeups for the challenges I managed to solve.
As a start, let’s go through the challenges by categories, and in the end, I’ll add some personal thoughts.
Cryptography Baby Charge For this challenge, we got access to the source code for a custom cipher. At startup, it generated a random key and nonce, and after that, there were two options for the user:
...</p>
</div>
<footer class="entry-footer"><span title='2024-01-08 00:00:00 +0000 UTC'>January 8, 2024</span> · 15 min · pshegger</footer>
<a class="entry-link" aria-label="post link to IrisCTF 2024" href="https://pshegger.github.io/posts/irisctf-2024/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">My First Gamejam
</h2>
</header>
<div class="entry-content">
<p> If you’re only here to try the game, you can do it on itch.io
I cannot even remember when was the first time I heard about Ludum Dare, but it was at least 5 years ago. Even back then, I was fascinated by the idea of creating a game in such a short time, but even though I wanted to try it, I had no game development experience at that time, so it always remained just a dream.
...</p>
</div>
<footer class="entry-footer"><span title='2023-05-02 00:00:00 +0000 UTC'>May 2, 2023</span> · 15 min · pshegger</footer>
<a class="entry-link" aria-label="post link to My First Gamejam" href="https://pshegger.github.io/posts/my-first-gamejam/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">Procedural Dungeon Generation
</h2>
</header>
<div class="entry-content">
<p>Procedural generation is incredible. It is the key to writing games with endless content. Without it, Minecraft couldn’t have (nearly) infinite worlds with infinite terrain. Spelunky would only contain a few rooms, and we could learn the layout and enemy placement instead of learning the game mechanics. These are only a few examples, but there are a lot of games that use this mechanic for generating content.
In this article, I’d like to show you my way of generating a random dungeon that can be later used in a game.
...</p>
</div>
<footer class="entry-footer"><span title='2022-03-10 00:00:00 +0000 UTC'>March 10, 2022</span> · 8 min · pshegger</footer>
<a class="entry-link" aria-label="post link to Procedural Dungeon Generation" href="https://pshegger.github.io/posts/procedural-dungeon/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">h@cktivitycon 2021 CTF
</h2>
</header>
<div class="entry-content">
<p>This year’s h@cktivitycon was held last Saturday, but even before it started, there was another event HackerOne had organized: this year’s CTF. It began on Thursday and ran for 48 hours. As I wasn’t following the events, it was already Friday when I realized it was running. I still had a bit more than a day to complete as many challenges as possible, so I decided to register and see how it goes.
...</p>
</div>
<footer class="entry-footer"><span title='2021-09-20 00:00:00 +0000 UTC'>September 20, 2021</span> · 15 min · pshegger</footer>
<a class="entry-link" aria-label="post link to h@cktivitycon 2021 CTF" href="https://pshegger.github.io/posts/hacktivitycon-2021-ctf/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">Advent of Code 2020
</h2>
</header>
<div class="entry-content">
<p>The 2020 Advent of Code ended less than a week ago, and I thought the best way to cope with the void it left behind is writing a post about how I’ve seen it. This was my 5th year I jumped into it, but only the first one I actually did all the tasks. Just a small warning, this post contains some minor spoilers.
This year my aim was to do all the tasks as fast as possible, so I didn’t use a new language. I started with Python, but after the second week, it became obvious that I don’t know it enough to be fast with it, as I had to look up things every day, which took some time. After that, I moved to Kotlin, which was a bit slower because of the compilation time, but my better knowledge of the language paid off. I also rewrote my existing solutions to Kotlin to have them all in one place. You can find it on GitHub, and as you can see, it has a few solutions for tasks from the previous years. I’m planning on going back and doing every task ever released, but that’ll take some time.
...</p>
</div>
<footer class="entry-footer"><span title='2020-12-30 00:00:00 +0000 UTC'>December 30, 2020</span> · 7 min · pshegger</footer>
<a class="entry-link" aria-label="post link to Advent of Code 2020" href="https://pshegger.github.io/posts/aoc-2020/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">Turning a Camera Feed into a Solved Sudoku
</h2>
</header>
<div class="entry-content">
<p>A few months ago, I stumbled upon a video that led me into a rabbit hole. It resulted in a simple application that overlays a sudoku’s solution into the camera image of the puzzle. This post is about the process of getting to the end result.
It all started with the idea of writing a sudoku solver. The first version was ready relatively quickly, but there was one big problem: entering the starting position was slow and tedious. That’s when I realized that I could use the camera on my phone as the input device. I’ve never worked with image processing before, but it sounded like a good challenge, so I dived into it.
...</p>
</div>
<footer class="entry-footer"><span title='2020-08-12 00:00:00 +0000 UTC'>August 12, 2020</span> · 9 min · pshegger</footer>
<a class="entry-link" aria-label="post link to Turning a Camera Feed into a Solved Sudoku" href="https://pshegger.github.io/posts/ar-sudoku/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">RenderScript is Still alive
</h2>
</header>
<div class="entry-content">
<p>I’m sure for most of you it’s not a surprise, but I also think that there are people out there who either doesn’t know what it is or simply tends to forget about it. The aim of this article is to show these people what it is and why should they use it.
So, what is RenderScript? RenderScript is an Android framework which can be used for running computationally heavy tasks at high performance. You will get the most benefit on using it for tasks which require a lot of computation that can be parallelized, as the framework will run your code on every available CPU and GPU cores.
...</p>
</div>
<footer class="entry-footer"><span title='2020-02-29 00:00:00 +0000 UTC'>February 29, 2020</span> · 10 min · pshegger</footer>
<a class="entry-link" aria-label="post link to RenderScript is Still alive" href="https://pshegger.github.io/posts/renderscript/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2 class="entry-hint-parent">gRPC for Kotliners
</h2>
</header>
<div class="entry-content">
<p>This is the talk I gave at the November 2019 Kotlin Budapest meetup. You can find the slides here and the sample code at GitHub.
</p>
</div>
<footer class="entry-footer"><span title='2019-11-14 00:00:00 +0000 UTC'>November 14, 2019</span> · 1 min · pshegger</footer>
<a class="entry-link" aria-label="post link to gRPC for Kotliners" href="https://pshegger.github.io/posts/grpc-talk/"></a>
</article>
<footer class="page-footer">
<nav class="pagination">
<a class="next" href="https://pshegger.github.io/page/2/">Next »
</a>
</nav>
</footer>
</main>
<footer class="footer">
<span>© 2025 <a href="https://pshegger.github.io/">pshegger's blog</a></span> ·
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>