diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index eb21bdd..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "themes/thunderball"]
- path = themes/thunderball
- url = https://git.umbrella.haus/ae/thunderball.git
diff --git a/content/_index.md b/content/_index.md
new file mode 100644
index 0000000..bec1581
--- /dev/null
+++ b/content/_index.md
@@ -0,0 +1,5 @@
+---
+title: ""
+date: 2025-02-16T16:36:41+02:00
+draft: false
+---
diff --git a/content/blog/_index.md b/content/blog/_index.md
deleted file mode 100644
index e6d7336..0000000
--- a/content/blog/_index.md
+++ /dev/null
@@ -1,6 +0,0 @@
-+++
-title = 'Blog'
-date = 2023-11-13T13:23:38+02:00
-draft = false
-menu = 'main'
-+++
diff --git a/content/blog/dockerized-onion-service.md b/content/blog/dockerized-onion-service.md
deleted file mode 100644
index 2d00f5a..0000000
--- a/content/blog/dockerized-onion-service.md
+++ /dev/null
@@ -1,158 +0,0 @@
-+++
-title = 'Spinning up a Dockerized Onion Mirror'
-date = 2024-04-07T20:21:17+03:00
-author = ''
-draft = false
-tags = ['tor', 'docker', 'privacy']
-categories = ['self-hosting']
-+++
-
-I decided to spin up an [onion mirror of this website](http://golfed6fzytoktol4de4o4nerap3xuykhfm5makfzscib65df3khnpyd.onion) just for the fun of it. Funnily enough hosting an onion service is actually easier than hosting a clearweb site.
-
-When searching for information about Dockerizing onion services, I noticed that the guides found with quick web searches vary significantly in quality, especially from a security standpoint. This prompted me to compile my own notes and thoughts on the topic into this compact post.
-
-## TL;DR
-
-If you only want to use Tor as a rewriting proxy (i.e. client types in the v3 address, and the proxy serves the upstream clearweb site through Tor), [Onionspray](https://gitlab.torproject.org/tpo/onion-services/onionspray/) is a great choice.
-
-For those who aren't concerned about fine-tuning or more in-depth details of the configuration, here's [a great repository to get started with](https://github.com/ha1fdan/hidden-service-docker) that I also used as the base for my setup. The compose configuration found in the repository manually installs the newest available version of Tor, which is much better than relying on the image's contributors to update it in a premade image.
-
-If you want a vanity v3 address, you can use a tool like [mkp2240](https://github.com/cathugger/mkp224o).
-
-## Setup
-
-Here's the slightly modified `docker-compose.yml` I use:
-
-```yaml
-services:
- tor:
- image: alpine:latest
- container_name: tor
- command: sh -c "apk update && apk add --no-cache tor && chmod 700 /var/lib/tor/onion-service && chown -R root:root /var/lib/tor && (cat /var/lib/tor/onion-service/hostname || echo 'Hostname not available.') && tor -f /etc/tor/torrc"
- volumes:
- - ./tor:/etc/tor:rw
- - ./onion-mirror:/var/lib/tor/onion-service:rw
- - nginx-tor-socket:/var/run/onion-sockets:rw
- depends_on:
- - nginx
- restart: unless-stopped
-
- nginx:
- image: nginx:latest
- container_name: nginx-onion
- command:
- volumes:
- - ./web/config/onion-default.conf:/etc/nginx/conf.d/default.conf:rw
- - ./web/public:/usr/share/nginx/html:ro
- - nginx-tor-socket:/var/run/onion-sockets:rw
- healthcheck:
- test:
- [
- "CMD",
- "curl",
- "-f",
- "--unix-socket",
- "/var/run/onion-sockets/site.sock",
- "||",
- "exit 1",
- ]
- interval: 10s
- timeout: 5s
- retries: 5
- restart: unless-stopped
-
-volumes:
- nginx-tor-socket:
-```
-
-Combined with a minimal nginx configuration and `torrc`:
-
-```text
-server {
- listen unix:/var/run/onion-sockets/site.sock;
- server_name golfed6fzytoktol4de4o4nerap3xuykhfm5makfzscib65df3khnpyd.onion;
-
- access_log off;
- server_tokens off;
-
- add_header X-Content-Type-Options "nosniff";
- add_header X-Frame-Options SAMEORIGIN;
- proxy_hide_header X-Powered-By;
-
- location / {
- root /usr/share/nginx/html;
- index index.html index.htm;
- }
-}
-```
-
-```text
-HiddenServiceDir /var/lib/tor/onion-service/
-HiddenServicePort 80 unix:/var/run/onion-sockets/site.sock
-```
-
-## In-depth configuration
-
-Despite my use case being quite casual, I still wanted to follow [the best practices of hosting an onion service](https://riseup.net/en/security/network-security/tor/onionservices-best-practices).
-
-### Service isolation
-
-As recommended in the Riseup guide, it's crucial to carefully isolate clearweb services from the onion ones to prevent any unwanted information leaks. For more critical services, it's definitely worth hosting them in a completely different location with only a minimal number of public-facing ports open. Personally, I solved this by spinning up an individual nginx container that essentially hosts a separate copy of this site.
-
-### Sockets over TCP
-
-Since Tor doesn't require binding to physical ports, there's no need to worry about conflicting ports. Instead, it's worth to consider using Unix sockets for local communication rather than TCP. Unix sockets can reduce the overhead of TCP/IP networking by allowing local inter-process communication to occur through the file system. They can also offer a bit more security by not accidentally exposing services through network ports (although this is already quite easily manageable with containers as long as you don't mix up the ports of different services).
-
-```text
-HiddenServicePort 80 unix:/var/run/onion-sockets/site.sock
-```
-
-```text
-server {
- listen unix:/var/run/onion-sockets/site.sock;
- server_name golfed6fzytoktol4de4o4nerap3xuykhfm5makfzscib65df3khnpyd.onion;
-}
-```
-
-### Do you need TLS?
-
-Most of the time, there's no need for a TLS certificate with an onion service. As [this section](https://community.torproject.org/onion-services/advanced/https/) well describes, you might lose more than you gain: many CAs don't support the .onion TLD, and third-party certificates might unintentionally leak .onion names. Fortunately, you can now get DV certificates (instead of EV certificates) for onion sites from the Greek non-profit HARICA. However, support from Let's Encrypt CA is still missing.
-
-The few benefits of having a certificate include using the `https` URI scheme and ensuring the traffic from your web server to Tor is encrypted (which could be especially useful if the instances aren't running on the same machine).
-
-### Onionscan
-
-[Onionscan](https://onionscan.org/) is the Tor Project's contributors' recommendation for detecting possible misconfigurations or information leaks. The original project is practically abandoned, but here's [an up-to-date fork](https://github.com/415ALS/onionscanv3) with v3 address support.
-
-### Onion-Location
-
-To take advantage of Tor Browser's Onion-Location redirection, you should add the following response header to your clearweb site's configuration:
-
-```text
-add_header Onion-Location http://golfed6fzytoktol4de4o4nerap3xuykhfm5makfzscib65df3khnpyd.onion$request_uri;
-```
-
-Or alternatively include an HTML `` attribute:
-
-```html
-
-```
-
-Notably, with proxying enabled through Cloudflare, I encountered difficulties in getting the response headers to pass through to the client, necessitating the use of the `` attribute instead.
-
-## Resources
-
-I highly recommend checking out the sites I browsed while figuring this stuff out, especially [The Onion Services Ecosystem](https://tpo.pages.torproject.net/onion-services/ecosystem/):
-
-- [Tor Project's Guide on Setting Up Onion Service](https://community.torproject.org/onion-services/setup/)
-- [Tor Project's Tips on Operational Security](https://community.torproject.org/onion-services/advanced/opsec/)
-- [Tor Project's Tips on HTTPS for Onion Services](https://community.torproject.org/onion-services/advanced/https/)
-- [Riseup's Best Practices Guide](https://riseup.net/en/security/network-security/tor/onionservices-best-practices)
-- [Introduction to Onionspray](https://tpo.pages.torproject.net/onion-services/ecosystem/apps/web/onionspray/)
-- [Tor Project's Onionsite Checklist](https://tpo.pages.torproject.net/onion-services/ecosystem/apps/web/checklist/)
-- ["Connect two NGINX's through UNIX sockets" by David Sierra](https://blog.davidsierra.dev/posts/connect-nginxs-through-sockets/)
-- ["Create a complete Tor Onion Service with Docker and OpenSUSE in less than 15 minutes" by Jason S. Evans](https://www.youtube.com/watch?v=iUxiTk6w1sc)
-- [Onionscan Documentation](https://onionscan.org/)
diff --git a/content/blog/i2p-on-vps.md b/content/blog/i2p-on-vps.md
deleted file mode 100644
index 2734a3e..0000000
--- a/content/blog/i2p-on-vps.md
+++ /dev/null
@@ -1,55 +0,0 @@
-+++
-title = 'Welcome to the Invisible Internet! — Setting up I2P on a VPS'
-date = 2024-11-17T18:49:59+02:00
-author = ''
-draft = false
-tags = ['i2p', 'docker', 'privacy']
-categories = ['self-hosting']
-+++
-
-A major hurdle for the wider adoption of the I2P protocol is the same as with many other purely P2P protocols: you need to reach a certain peer connectivity level before anything becomes usable. For example, [this Mental Outlaw video](https://youtu.be/KhG29riqVUE) about I2P shows that it can take many hours of waiting before most eepsites become accessible. This is drastically different from e.g. Tor, which is basically plug-and-play.
-
-Setting up I2P on a remote VPS and port forwarding that connection with SSH provides a robust solution to this problem, as the client being online 24/7 guarantees excellent connectivity.
-
-## Setting up I2P
-
-It's advisable to create a separate `.env` file and set the `EXT_PORT` environment variable there (this is the exposed host port where I2NP will be reachable, i.e. it must also be unblocked from the firewall).
-
-The advertised memory usage for I2P's JVM is 128 MB, but it's still good to set a cap using the `JVM_XMX` environment variable. Additionally, the `i2ptorrents:i2psnark` volume can be commented out if you don't need BitTorrent support. See the [official documentation](https://github.com/i2p/i2p.i2p/blob/master/Docker.md) for more information on possible configuration options.
-
-```yaml
-services:
- i2p:
- image: geti2p/i2p
- container_name: i2p
- restart: unless-stopped
- ports:
- - ${EXT_PORT}:${EXT_PORT}/tcp
- - ${EXT_PORT}:${EXT_PORT}/udp
- volumes:
- - ${PWD}/i2pconfig:/i2p/.i2p:rw # Mandatory configs
- - ${PWD}/i2ptorrents:/i2psnark:rw # Torrenting support
- environment:
- JVM_XMX: 256m
- EXT_PORT: ${EXT_PORT:?host port must be manually set}
-```
-
-Once the container is fully configured, run `docker compose up -d` and check the `i2p` container's logs. You should see something like this (there should be no warnings about the connection being firewalled):
-
-```
-Starting I2P
-[startapp] Running in container
-[startapp] Running in docker network
-[startapp] setting reachable IP to container IP 172.18.0.1
-Starting I2P 2.7.0-0
-```
-
-## Connecting via an SSH tunnel
-
-The `AllowTcpForwarding` variable in the OpenSSH configuration (`/etc/ssh/sshd_config`) defaults to `yes`, but must be modified if explicitly set to `no`. After this the following command can be used to start the tunnel in the background (implied by `-f` and `-n` flags):
-
-```shell
-ssh -fnN -L [LOCAL_PORT]:[CONTAINER_LOCAL_IP]:[REMOTE_PORT] [USERNAME]@[VPS_IP]
-```
-
-Once the container is booted up for the first time, the installation setup must be completed by accessing the router console via port `7657`. Then, configure the I2P proxy via port `4444` to your browser and you're ready to go. If you want to configure any additional services, here's the [complete list of the ports used by I2P](https://geti2p.net/en/docs/ports).
diff --git a/content/blog/metamask-phishing-exploration.md b/content/posts/metamask-phishing-exploration.md
similarity index 66%
rename from content/blog/metamask-phishing-exploration.md
rename to content/posts/metamask-phishing-exploration.md
index 313a379..857cf7e 100644
--- a/content/blog/metamask-phishing-exploration.md
+++ b/content/posts/metamask-phishing-exploration.md
@@ -1,5 +1,5 @@
+++
-title = 'Exploration of a Random MetaMask Phishing Campaign'
+title = 'Exploring a Telegram-based MetaMask phishing campaign'
date = 2024-10-27T21:04:50+02:00
author = ''
draft = false
@@ -7,13 +7,11 @@ tags = ['phishing']
categories = ['random']
+++
-A few days ago, I received a pretty credible-looking MetaMask phishing email stating that my account had been locked due to an attempt to connect a new device to it. Too bad I don't even own a MetaMask account, but despite that, I decided to spend a bit of time and look into how the whole campaign worked, as I rarely receive any kind of spam nowadays.
-
-
+A few days ago, I received a pretty credible-looking MetaMask phishing email stating that my account had been locked due to an attempt to connect a new device to it. I don't use such wallet, but this sparked my interest and I decided to spend a bit of time and look into how the phishing campaign was structured.
## Email attachment
-The attached HTML file `RemovedDevice.html` contained a bare-bones HTML structure with a bit of JS and a long Base64 encoded string which the attached script would decode and use jQuery to attach it back to the website body.
+The attached HTML file `RemovedDevice.html` contained a barebones HTML structure with a bit of JS and a long Base64 encoded string which the attached script would decode and use jQuery to attach it back to the website body.
```javascript
$(document).ready(function () {
@@ -40,7 +38,7 @@ function saveFile(name, type, data) {
The resulting webpage would display 12/15/18/21/24 input fields for a crypto wallet seed phrases of various lengths.
-The campaign operator was using Telegram as the backend, but didn't apparently care enough to even attempt to hide the API token and chat ID from the source with some obfuscation logic. Additionally it's also clear that the data was being exfiltrated into a private chat based on the chat ID format (private chats don't have a dash prefix, whereas supergroups and channels have a `-100` prefix).
+The backend of this campaign relied on Telegram, and to my surprise the utilized API token and chat ID weren't obfuscated in any way. Also the fact that the comments were still present in the source code indicate that the campaign was just pasted from a public template. The visible chat ID tells us that the data was being exfiltrated into a private chat as Telegram's supergroup and channel IDs would have a `-100` prefix.
```javascript
// Add your telegram token,chatid
@@ -48,7 +46,7 @@ const token = "7686154983:AAFtpdY6iTjT7UiTK6cXh0fM2T4CKfjRHl0";
const chatId = "7839331161";
```
-Before sending the collected information to the Telegram chat, the JavaScript code would also make a quick `GET` request to `ipinfo.io` to get the victim's public IP and related location data. This information would probably be used to pick a proxy for the wallet draining stage.
+Before sending the collected information to the Telegram chat, the JavaScript code would also make a quick GET request to get the victim's public IP and related location data. I couldn't really figure out the point of this as MetaMask is a self-custodial wallet and doesn't utilize any kind of fraud prevention system that could stop the attacker from draining the targeted account if their geolocation didn't match with the wallet's owner.
```javascript
wordForm1.addEventListener("submit", (e) => {
@@ -99,7 +97,7 @@ wordForm1.addEventListener("submit", (e) => {
## Greetings
-After discovering the valid token from the source, I had a sudden urge to try it out 🤔. I began with a simple `getMe` request:
+Using the visible API token and chat ID I was able to find out a bit more about the bot itself via a `getMe` request and even send out randomly generated data to make it more difficult to detect any working seed phrases from large amount of responses:
```json
{
@@ -118,8 +116,6 @@ After discovering the valid token from the source, I had a sudden urge to try it
}
```
-And then proceeded to something a bit more interesting:
-
```python
import random
import requests
@@ -159,4 +155,6 @@ while True:
sleep(random.randint(1, 10))
```
-In the end I was able to send roughly 10k messages before the person behind the campaign revoked the API token. I hope he'll have a fun time trying to sort out the legitimate responses from the ones I sent.
+I left the bot running in a Docker container for some time, and in the end I was able to send roughly 10k messages before the campaign operator revoked the API token.
+
+Next time I get a cryptocurrency related phishing email like this, I'd like to try tracking the stolen funds by giving out the seed phrase of a fresh wallet with e.g. $5-10 USD worth of funds inside and see what kind of anti-forensic methods would the attacker utilize (although given the quality of this campaign, they'd probably just deposit immediately into a full-KYC CEX).
diff --git a/content/blog/understanding-srdi.md b/content/posts/understanding-srdi.md
similarity index 96%
rename from content/blog/understanding-srdi.md
rename to content/posts/understanding-srdi.md
index 8bc27db..8efa380 100644
--- a/content/blog/understanding-srdi.md
+++ b/content/posts/understanding-srdi.md
@@ -1,15 +1,13 @@
+++
-title = 'Walkthrough of Shellcode Reflective DLL Injection (sRDI)'
+title = 'Walkthrough of shellcode reflective DLL injection (sRDI)'
date = 2023-12-09T20:42:26+02:00
author = ''
draft = false
tags = ['windows', 'srdi']
-categories = ['exploits']
+categories = ['malware']
+++
-In the ever-evolving landscape of malware, Shellcode Reflective DLL Injection (RDI) stands as a formidable technique despite its age, distinguished by its stealth and efficiency. Unlike traditional DLL injection methods, which often leave apparent traces for AV systems to detect, RDI operates on a more subtle level. Basically it challenges typical defensive solutions such as behavior monitoring, heuristics, or signature-based detection.
-
-Implementing a reflective loader myself provided a great insight into PE files and Windows API, and it is definitely a good initial foothold into more advanced techniques.
+In the ever-evolving landscape of malware, Shellcode Reflective DLL Injection (RDI) still stands as a formidable technique despite its age. What differentiates it from traditional DLL injection methods is that it doesn't leave apparent traces to the targeted filesystem, which is why it has a chance to bypass basic defensive solutions relying on behavior monitoring, heuristics, or signature-based detection.
## Steps
@@ -23,7 +21,7 @@ Implementing a reflective loader myself provided a great insight into PE files a
## Implementation
-The complete implementation can be found from [the Gitea repository](https://git.umbrella.haus/ae/airborne). The following explanations focus on the loader itself as the supporting components (process injector, shellcode generator, and payload) are basically just pasted from existing implementations mentioned in the [references](#references).
+The complete implementation can be found from [a Gitea repository](https://git.umbrella.haus/ae/airborne). The following explanations focus on the loader itself as the supporting components (process injector, shellcode generator, and payload) are basically just pasted from existing implementations mentioned in the [references](#references).
The following helper functions are utilized to make the RVA calculations a bit easier to read:
@@ -125,8 +123,6 @@ After locating the base address of `kernel32.dll`, our next step is to identify
A PE file is structured into various components, including the DOS Header, DOS Stub, NT Headers, and a Section Table, which houses the actual file contents in segments like `.text` and `.data`. Our focus is on the Export Directory located within the NT Headers, a section that lists exported functions and their addresses. We can access the Export Directory by utilizing the `IMAGE_DIRECTORY_ENTRY_EXPORT` offset within the `IMAGE_DATA_DIRECTORY`.
-
-
Similar to how we navigated through modules, we now iterate through the Export Directory entries to locate our required functions. This way we're able to bypass the usual API call mechanisms that could trigger security alerts:
```rust
diff --git a/hugo.yaml b/hugo.yaml
index d6649a5..dd277e7 100644
--- a/hugo.yaml
+++ b/hugo.yaml
@@ -2,55 +2,18 @@ baseURL: https://golfed.xyz
title: Golfed
language: en-GB
-theme: thunderball
+theme: nostyleplease
params:
- contacts:
- - name: email
- url: mailto:hello@golfed.xyz
- display: hello(at)golfed.xyz
- - name: matrix
- url: https://matrix.to/#/@ae:golfed.xyz
- display: "@ae:golfed.xyz"
- - name: signal
- url: https://signal.me/#eu/9aAt0tk36ErVZygWxf_dk81_r_2jTaxUxVCuvl_h6LONUyREI7hLm42Oa8RYJgoz
- display: "@xmr.02"
- - name: telegram
- url: https://t.me/shrlis
- display: "@shrlis"
- - name: xmr
- url: /xmr.txt
- display: 83B5pK...FHe23Y
- - name: pgp
- url: https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x1530f5132a1228578d2b4168995efd5c1b532b3e
- display: 1530F5...32B3E
-
- services:
- - name: blog
- url: /blog
- display: Blog
- - name: umbrella.haus
- url: https://umbrella.haus
- display: Umbrella
- - name: .onion
- url: http://golfed6fzytoktol4de4o4nerap3xuykhfm5makfzscib65df3khnpyd.onion/
- display: golfed...khnpyd.onion
+ theme_config:
+ appearance: dark
+ back_home_text: <<
+ date_format: 2006-01-02
+ isListGroupByDate: false
assets:
favicon: /images/favicon.ico
- favicon16: /images/favicon-16x16.png
- favicon32: /images/favicon-32x32.png
+ faviconsvg: /images/favicon.svg
+ favicon96: /images/favicon-96x96.png
appleTouchIcon: /images/apple-touch-icon.png
- safariPinnedTabIcon: /images/safari-pinned-tab.svg
- safariPinnedTabColor: /images/"#5bbad5"
- manifest: /images/manifest.json
- msTileColor: /images/"#2b5797"
- msTileIcon: /images/mstile-150x150.png
- themeColor: /images/"#040404"
- logo: /images/logo.svg
-
- opengraph:
- # only include website title + 30 word abstract into embeds
- description: "{{ substr .Summary 0 30 }} ..."
- twitter:image:src: ""
- og:image: ""
+ manifest: /manifest.json
diff --git a/static/images/android-chrome-192x192.png b/static/images/android-chrome-192x192.png
deleted file mode 100644
index 8eaeca7..0000000
Binary files a/static/images/android-chrome-192x192.png and /dev/null differ
diff --git a/static/images/android-chrome-512x512.png b/static/images/android-chrome-512x512.png
deleted file mode 100644
index fe74613..0000000
Binary files a/static/images/android-chrome-512x512.png and /dev/null differ
diff --git a/static/images/apple-touch-icon.png b/static/images/apple-touch-icon.png
index 6fe1d5a..489ac93 100644
Binary files a/static/images/apple-touch-icon.png and b/static/images/apple-touch-icon.png differ
diff --git a/static/images/favicon-16x16.png b/static/images/favicon-16x16.png
deleted file mode 100644
index 8a9481f..0000000
Binary files a/static/images/favicon-16x16.png and /dev/null differ
diff --git a/static/images/favicon-32x32.png b/static/images/favicon-32x32.png
deleted file mode 100644
index 7fa0481..0000000
Binary files a/static/images/favicon-32x32.png and /dev/null differ
diff --git a/static/images/favicon-96x96.png b/static/images/favicon-96x96.png
new file mode 100644
index 0000000..fab7309
Binary files /dev/null and b/static/images/favicon-96x96.png differ
diff --git a/static/images/favicon.ico b/static/images/favicon.ico
index f592df3..ac2b342 100644
Binary files a/static/images/favicon.ico and b/static/images/favicon.ico differ
diff --git a/static/images/favicon.svg b/static/images/favicon.svg
new file mode 100644
index 0000000..2ce0f22
--- /dev/null
+++ b/static/images/favicon.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/static/images/metamask-phishing-exploration/email.png b/static/images/metamask-phishing-exploration/email.png
deleted file mode 100644
index a7c567c..0000000
Binary files a/static/images/metamask-phishing-exploration/email.png and /dev/null differ
diff --git a/static/images/metamask-phishing-exploration/tg-bot.png b/static/images/metamask-phishing-exploration/tg-bot.png
deleted file mode 100644
index 8227244..0000000
Binary files a/static/images/metamask-phishing-exploration/tg-bot.png and /dev/null differ
diff --git a/static/images/mstile-144x144.png b/static/images/mstile-144x144.png
deleted file mode 100644
index a91db65..0000000
Binary files a/static/images/mstile-144x144.png and /dev/null differ
diff --git a/static/images/mstile-150x150.png b/static/images/mstile-150x150.png
deleted file mode 100644
index 5f17af2..0000000
Binary files a/static/images/mstile-150x150.png and /dev/null differ
diff --git a/static/images/mstile-310x150.png b/static/images/mstile-310x150.png
deleted file mode 100644
index d84826a..0000000
Binary files a/static/images/mstile-310x150.png and /dev/null differ
diff --git a/static/images/mstile-310x310.png b/static/images/mstile-310x310.png
deleted file mode 100644
index 44bf6ee..0000000
Binary files a/static/images/mstile-310x310.png and /dev/null differ
diff --git a/static/images/mstile-70x70.png b/static/images/mstile-70x70.png
deleted file mode 100644
index 54f2dd4..0000000
Binary files a/static/images/mstile-70x70.png and /dev/null differ
diff --git a/static/images/safari-pinned-tab.svg b/static/images/safari-pinned-tab.svg
deleted file mode 100644
index 77fb433..0000000
--- a/static/images/safari-pinned-tab.svg
+++ /dev/null
@@ -1,189 +0,0 @@
-
-
-
diff --git a/static/images/understanding-srdi/pe-file-structure.png b/static/images/understanding-srdi/pe-file-structure.png
deleted file mode 100755
index eb5d359..0000000
Binary files a/static/images/understanding-srdi/pe-file-structure.png and /dev/null differ
diff --git a/static/images/web-app-manifest-192x192.png b/static/images/web-app-manifest-192x192.png
new file mode 100644
index 0000000..279ad69
Binary files /dev/null and b/static/images/web-app-manifest-192x192.png differ
diff --git a/static/images/web-app-manifest-512x512.png b/static/images/web-app-manifest-512x512.png
new file mode 100644
index 0000000..d5eb03d
Binary files /dev/null and b/static/images/web-app-manifest-512x512.png differ
diff --git a/static/manifest.json b/static/manifest.json
index e9473ad..45c00f5 100644
--- a/static/manifest.json
+++ b/static/manifest.json
@@ -4,15 +4,16 @@
"start_url": "https://golfed.xyz",
"icons": [
{
- "src": "/android-chrome-192x192.png",
+ "src": "/images/web-app-manifest-192x192.png",
"sizes": "192x192",
"type": "image/png",
- "purpose": "any maskable"
+ "purpose": "maskable"
},
{
- "src": "/android-chrome-512x512.png",
+ "src": "/images/web-app-manifest-512x512.png",
"sizes": "512x512",
- "type": "image/png"
+ "type": "image/png",
+ "purpose": "maskable"
}
],
"theme_color": "#242424",
diff --git a/static/xmr.txt b/static/xmr.txt
deleted file mode 100644
index 4afeaa2..0000000
--- a/static/xmr.txt
+++ /dev/null
@@ -1 +0,0 @@
-83B5pKorh2J58RZvF3oyxhZcxpbYnpRDCcQeETzhSKUZFvyHRWmMzepeg5NksY6f1DcCfUtQ6wphF3x3cT4bhXvWSFHe23Y
\ No newline at end of file
diff --git a/themes/nostyleplease/assets/css/main.scss b/themes/nostyleplease/assets/css/main.scss
new file mode 100644
index 0000000..7a85bee
--- /dev/null
+++ b/themes/nostyleplease/assets/css/main.scss
@@ -0,0 +1,185 @@
+// -------------- THEME SWITCHER -------------- //
+@mixin theme($--bg-color, $--primary-text-color, $--secondary-text-color, $--link-color, $--visited-link-color, $--highlight) {
+ background-color: $--bg-color;
+
+ color: $--primary-text-color;
+
+ a {
+ color: $--link-color;
+ &:visited { color: $--visited-link-color; }
+ }
+
+ details {
+ border: thin solid $--primary-text-color;
+ }
+
+ details summary {
+ color: $--primary-text-color;
+ }
+
+ details[open] summary {
+ border-bottom: 1px solid $--primary-text-color;
+ }
+
+ pre {
+ background: $--bg-color;
+ }
+
+ code:not(pre > code) {
+ background-color: $--primary-text-color;
+ color: $--bg-color;
+ }
+
+ *:target {
+ background: $--highlight;
+ color: $--primary-text-color;
+ }
+
+ table, th, td {
+ border: thin solid $--primary-text-color;
+ }
+
+ .toc {
+ border: thin solid $--primary-text-color;
+ padding: 1rem;
+ }
+
+ figcaption { color: $--secondary-text-color; }
+
+ blockquote {
+ border: thin solid $--primary-text-color;
+ }
+}
+
+@mixin dark-appearance {
+ @include theme(#000300, #f1fffa, #000300, #8b9556, #d1603d, #53917e); // modus-vivendi
+}
+
+@mixin light-appearance {
+ @include theme(#ffffff, #000000, #595959, #3548cf, #8f0075, #dae5ec); // modus-operandi
+}
+
+body[a="dark"] { @include dark-appearance; }
+body[a="light"] { @include light-appearance; }
+
+@media (prefers-color-scheme: dark) {
+ body[a="auto"] { @include dark-appearance; }
+}
+
+@media (prefers-color-scheme: light) {
+ body[a="auto"] { @include light-appearance; }
+}
+
+// -------------------------------------------- //
+
+html { height: 100%; }
+
+body {
+ font-family: monospace;
+ font-size: 16px;
+ line-height: 1.4;
+ margin: 0;
+ min-height: 100%;
+ overflow-wrap: break-word;
+}
+
+h2, h3, h4, h5, h6 { margin-top: 1.5rem; }
+
+p { margin: 1rem 0; }
+
+li { margin: 0.4rem 0; }
+
+a {
+ text-decoration: none;
+ &:hover { text-decoration: underline; }
+}
+
+hr {
+ text-align: center;
+ border: 0;
+ margin: 2rem 0;
+
+ &:before { content: '/////' }
+ &:after { content: attr(data-content) '/////' }
+}
+
+pre {
+ padding: 1em;
+ overflow-x: auto; /* Fix pre content overflowing parent without scroll bar */
+}
+
+table { width: 100%; }
+
+table, th, td {
+ border-collapse: collapse;
+ padding: 0.4rem;
+}
+
+code {
+ text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+ -moz-text-size-adjust: 100%;
+ -webkit-text-size-adjust: 100%;
+}
+
+code:not(pre > code) {
+ padding: 0.1em 0.2em;
+ font-size: 90%;
+}
+
+code.has-jax {
+ -webkit-font-smoothing: antialiased;
+ background: inherit !important;
+ border: none !important;
+ font-size: 100%;
+}
+
+blockquote {
+ padding: 1rem;
+
+ p { margin: 0; }
+}
+
+img {
+ max-width: 100%;
+ display: block;
+ margin: 0 auto;
+}
+
+figcaption {
+ text-align: center;
+ opacity: 0.5;
+}
+
+details {
+ padding: 1rem;
+}
+
+details summary {
+ text-decoration: none;
+}
+
+details[open] summary {
+ margin-bottom: 0.5em;
+ padding-bottom: 0.5em;
+}
+
+.post-meta {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.w {
+ max-width: 640px;
+ margin: 0 auto;
+ padding: 4rem 2rem;
+}
+
+.toc {
+ padding: 1rem;
+}
+
+.site-footer {
+ margin-top: 2em;
+}
diff --git a/themes/nostyleplease/data/menu.toml b/themes/nostyleplease/data/menu.toml
new file mode 100644
index 0000000..5ea187a
--- /dev/null
+++ b/themes/nostyleplease/data/menu.toml
@@ -0,0 +1,16 @@
+[[entries]]
+title = "posts"
+ [entries.post_list]
+ limit = 5
+ show_more = true
+ show_more_text = "see more ..."
+ show_more_url = "posts"
+
+[[entries]]
+title = "contacts"
+entries = [
+ { title = "email (hello at golfed.xyz)", url = "mailto:hello@golfed.xyz" },
+ { title = "pgp (1530F5...32B3E)", url = "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x1530f5132a1228578d2b4168995efd5c1b532b3e" },
+ { title = "matrix (@ae:golfed.xyz)", url = "https://matrix.to/#/@ae:golfed.xyz" },
+ { title = "signal (xmr.02)", url = "https://signal.me/#eu/9aAt0tk36ErVZygWxf_dk81_r_2jTaxUxVCuvl_h6LONUyREI7hLm42Oa8RYJgoz" },
+]
diff --git a/themes/nostyleplease/layouts/404.html b/themes/nostyleplease/layouts/404.html
new file mode 100644
index 0000000..eb600b4
--- /dev/null
+++ b/themes/nostyleplease/layouts/404.html
@@ -0,0 +1,8 @@
+{{ define "main" }}
+
+{{- partial "back_link.html" . -}}
+
+404 Not Found
+
{{ $.Site.Params.description }}
+ {{- end -}} +{{ .Key }}
+