mirror of
https://github.com/andwati/andwati.com.git
synced 2026-10-29 22:12:15 +00:00
Replace Astro/Strapi site with Next.js static export
- Fresh structure: Next.js App Router + Tailwind v4 at the repo root, exported as static files (output: export) and served by static-web-server - Remove the Strapi CMS, Astro app, Pagefind search, comments, old scripts, Lighthouse config and compose files; content in content/ is now plain markdown with YAML frontmatter - Pages: About, Writing, Reading (3D bookshelf) and Portfolio, styled after adammaj.com - SEO: metadata and canonicals, JSON-LD, generated OG images, sitemap, robots, RSS and JSON feeds, llms.txt - Umami via PUBLIC_UMAMI_SCRIPT_URL / PUBLIC_UMAMI_WEBSITE_ID (build args) - Dockerfile builds the export and serves it with sws.toml (security headers, clean URLs, .well-known, OG image content type, immutable asset caching) - Prettier and cspell for content with a husky/lint-staged pre-commit hook - Old redirect list dropped to start from a clean slate
This commit is contained in:
@@ -1,118 +0,0 @@
|
||||
# content/
|
||||
|
||||
This directory is the canonical source of truth for all site content. It is
|
||||
shared between `apps/site` (Astro reads it directly at build time) and
|
||||
`apps/cms` (Strapi's custom provider reads/writes these same files — its
|
||||
SQLite database is only a disposable cache/index, never the source of
|
||||
record). The site must always be buildable straight from this directory with
|
||||
Strapi entirely absent.
|
||||
|
||||
Frontmatter is TOML (`+++ ... +++`), matching the legacy Zola posts under
|
||||
`content/posts/` to ease migration. Each content type below is one file (or a
|
||||
directory with `index.md` for entries with co-located assets), one frontmatter
|
||||
schema.
|
||||
|
||||
## `writings/` (blog / essays)
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "..."
|
||||
description = "..."
|
||||
author = "andwati"
|
||||
date = 2026-04-08
|
||||
updated = 2026-04-10 # optional, only when the post has been revised
|
||||
draft = false
|
||||
canonical_url = "" # optional, only if first published elsewhere
|
||||
[taxonomies]
|
||||
tags = ["..."]
|
||||
[extra]
|
||||
series = "..." # optional
|
||||
series_index = 1 # required if `series` is set
|
||||
llms_description = "..." # optional per-post override of the site-wide one
|
||||
+++
|
||||
```
|
||||
|
||||
## `portfolio/` (projects / professional work)
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "..."
|
||||
description = "..."
|
||||
role = "..."
|
||||
date_start = 2025-01-01
|
||||
date_end = 2025-06-01 # optional, omit if ongoing
|
||||
outcome = "one-line result"
|
||||
draft = false
|
||||
[[links]]
|
||||
label = "Live"
|
||||
url = "https://..."
|
||||
[[links]]
|
||||
label = "Source"
|
||||
url = "https://..."
|
||||
[taxonomies]
|
||||
tags = ["..."] # stack / tech tags
|
||||
+++
|
||||
```
|
||||
|
||||
Body is a free-form Markdown case study.
|
||||
|
||||
## `bookshelf/` (books *and* papers)
|
||||
|
||||
`kind` selects which identifier fields apply — books use `isbn`, papers use
|
||||
`doi`/`arxiv_id`. Book covers are fetched from Open Library by ISBN and
|
||||
cached into `apps/site/public/covers/` (served at `/covers/...`), never
|
||||
fetched at page-render time. Papers have no reliable cover source, so
|
||||
`cover_image` is set manually for them, if at all; Semantic Scholar is only
|
||||
used to backfill a missing title/authors by DOI/arXiv id.
|
||||
|
||||
Note: the field is named `read_status`, not `status` — Strapi's
|
||||
content-manager API treats a top-level `status` key as its own reserved
|
||||
draft/publish parameter even with `draftAndPublish` disabled, so an
|
||||
attribute literally named `status` silently breaks writes. Don't rename it
|
||||
back.
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "..."
|
||||
kind = "book" # "book" | "paper"
|
||||
authors = ["..."]
|
||||
isbn = "9780000000000" # books only
|
||||
doi = "10.1000/xyz123" # papers only
|
||||
arxiv_id = "2101.00001" # papers only, optional
|
||||
url = "https://..." # papers only: landing page / source link
|
||||
cover_image = "/covers/slug.jpg"
|
||||
rating = 5 # optional, 1-5
|
||||
read_status = "read" # "reading" | "read" | "abandoned"
|
||||
date_started = 2026-01-01
|
||||
date_finished = 2026-01-20 # optional, omit if still in progress
|
||||
[taxonomies]
|
||||
tags = ["..."] # genre / topic
|
||||
+++
|
||||
```
|
||||
|
||||
Body is a free-form personal review/notes.
|
||||
|
||||
## `blogs/` (curated external blogs)
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "..." # the blog/site's name
|
||||
url = "https://..."
|
||||
feed_url = "https://.../rss.xml"
|
||||
+++
|
||||
```
|
||||
|
||||
Body is a one-to-two sentence blurb on why you follow it. No live feed
|
||||
fetching — this list is hand-curated and static.
|
||||
|
||||
## Markdown extras (all body content)
|
||||
|
||||
- **LaTeX**: `$inline$` and `$$block$$` math renders to static HTML/MathML
|
||||
at build time (`marked-katex-extension` in `toml-content-loader.ts`) — no
|
||||
client-side JS shipped for it.
|
||||
- **Callouts**: `{% <note> %} ... {% </note> %}` (also `tip`/`warning`/
|
||||
`danger`) renders as a styled callout box.
|
||||
- **YouTube embeds**: paste a plain `<iframe src="https://www.youtube-
|
||||
nocookie.com/embed/VIDEO_ID" ...></iframe>` — it's automatically wrapped
|
||||
in a responsive 16:9 container, gets `loading="lazy"`, and emits
|
||||
`VideoObject` structured data. No shortcode needed.
|
||||
@@ -1,6 +0,0 @@
|
||||
+++
|
||||
template = "index.html"
|
||||
page_template = "page.html"
|
||||
+++
|
||||
|
||||
spend my free time working on hobby projects and sometimes I write about my experiences. In particular, I enjoy learning about offensive security and reverse engineering.
|
||||
+25
-23
@@ -1,31 +1,33 @@
|
||||
+++
|
||||
title = "About"
|
||||
template = "page.html"
|
||||
+++
|
||||
---
|
||||
title: "About"
|
||||
---
|
||||
|
||||
spend my free time working on hobby projects and sometimes I write about my experiences. In particular, I enjoy learning about offensive security and reverse engineering.
|
||||
# Ian Andwati
|
||||
|
||||
## PGP
|
||||
## Some things about me:
|
||||
|
||||
- I'm a software engineer by day. Cyber Security is my hobby and my side work.
|
||||
- I have a degree in computer science, and most of what I do for fun still centres on it.
|
||||
- I'm the captain of the [**binarysith**](https://ctftime.org/team/379200) CTF team. I play CTFs on the weekends under the alias **mockingspectre**.
|
||||
- I like infrastructure-level software: the code that other code runs on.
|
||||
- I write essays on software development, from personal experience to opinion pieces (with varying degrees of "success"). The blog has been going since 2021 and has moved around a lot: different domains, Medium, dev.to, Hashnode. This site is where I keep the originals.
|
||||
|
||||
## Some things I'm interested in:
|
||||
|
||||
- The intersection of software engineering and cyber security.
|
||||
- Low-level programming, because it's where performance and security meet.
|
||||
- Distributed systems and performance at scale.
|
||||
- Compiler design.
|
||||
- Database internals.
|
||||
- Reading, fiction and non-fiction alike, especially the classics.
|
||||
- Art, history and science.
|
||||
|
||||
Check out my [reading](/reading), [writing](/writing) and [portfolio](/portfolio).
|
||||
|
||||
### PGP
|
||||
|
||||
For anything sensitive, you can reach me encrypted.
|
||||
|
||||
```txt
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mDMEalcjtBYJKwYBBAHaRw8BAQdA55X1mRCKw9DA35kCAy+7Z30ye0rUHWBZsl7O
|
||||
Wmar+RS0IklhbiBBbmR3YXRpIDxhbmR3YXRpaWFuQGdtYWlsLmNvbT6IkwQTFgoA
|
||||
OxYhBK1YqreiDYUjy/WaeR8g/tCqBbDaBQJqVyO0AhsDBQsJCAcCAiICBhUKCQgL
|
||||
AgQWAgMBAh4HAheAAAoJEB8g/tCqBbDace8BAN1SpkEMSYll+XupKHiaIUwnhm4N
|
||||
eS79G1i+345Gl6CyAQDjgn+3rzG6sexjKh+10EKiy5omsQEGzUW03s7gS0T1Drg4
|
||||
BGpXI7QSCisGAQQBl1UBBQEBB0CXofBIYYXG2+dZqgllhsbkNPF4qlyfPgbRW+zb
|
||||
7Kw3IAMBCAeIeAQYFgoAIBYhBK1YqreiDYUjy/WaeR8g/tCqBbDaBQJqVyO0AhsM
|
||||
AAoJEB8g/tCqBbDauMkA/RG4iqtPZOI3DQzFJYu7SnxaD81vdP0LyTLKDQkynySu
|
||||
AQDrlWyF8LRlad4iX1yQPCuOV0aUpTNq5kPlWurtX99/BQ==
|
||||
=uKsS
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
||||
|
||||
- Fingerprint: `AD58 AAB7 A20D 8523 CBF5 9A79 1F20 FED0 AA05 B0DA`
|
||||
- Public key: [/.well-known/pgp-key.txt](/.well-known/pgp-key.txt)
|
||||
- Also on: [keys.openpgp.org](https://keys.openpgp.org/search?q=AD58AAB7A20D8523CBF59A791F20FED0AA05B0DA) and [keyserver.ubuntu.com](https://keyserver.ubuntu.com/pks/lookup?op=vindex&search=0xAD58AAB7A20D8523CBF59A791F20FED0AA05B0DA)
|
||||
- Also see: [/.well-known/security.txt](/.well-known/security.txt) (signed)
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
+++
|
||||
title = "Attention Is All You Need"
|
||||
kind = "paper"
|
||||
authors = ["Ashish Vaswani", "Noam Shazeer", "Niki Parmar"]
|
||||
doi = "10.48550/arXiv.1706.03762"
|
||||
arxiv_id = "1706.03762"
|
||||
url = "https://arxiv.org/abs/1706.03762"
|
||||
cover_image = "/covers/attention-is-all-you-need.jpg"
|
||||
rating = 5
|
||||
read_status = "read"
|
||||
date_started = 2026-02-01
|
||||
date_finished = 2026-02-03
|
||||
[taxonomies]
|
||||
tags = ["machine-learning", "papers"]
|
||||
+++
|
||||
|
||||
Placeholder review establishing the `bookshelf` schema for `kind = "paper"`.
|
||||
@@ -1,15 +0,0 @@
|
||||
+++
|
||||
title = "Designing Data-Intensive Applications, 2nd Edition"
|
||||
kind = "book"
|
||||
authors = [ "Martin Kleppmann", "Chris Riccomini" ]
|
||||
isbn = "9781098119058"
|
||||
url = "https://www.oreilly.com/library/view/designing-data-intensive-applications/9781098119058/"
|
||||
cover_image = "/covers/designing-data-intensive-applications-2nd-edition.webp"
|
||||
rating = 5
|
||||
read_status = "reading"
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "distributed-systems" ]
|
||||
+++
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
+++
|
||||
title = "Structure and Interpretation of Computer Programs"
|
||||
kind = "book"
|
||||
authors = ["Harold Abelson", "Gerald Jay Sussman"]
|
||||
isbn = "9780262510875"
|
||||
cover_image = "/covers/structure-and-interpretation-of-computer-programs.jpg"
|
||||
rating = 5
|
||||
read_status = "read"
|
||||
date_started = 2026-01-01
|
||||
date_finished = 2026-01-20
|
||||
[taxonomies]
|
||||
tags = ["computer-science", "programming"]
|
||||
+++
|
||||
|
||||
Placeholder review establishing the `bookshelf` schema for `kind = "book"`.
|
||||
@@ -1,15 +1,11 @@
|
||||
+++
|
||||
title = "Example Project"
|
||||
description = "Placeholder portfolio entry establishing the schema."
|
||||
role = "Author"
|
||||
date_start = 2026-01-01
|
||||
outcome = "Established the portfolio content schema."
|
||||
draft = false
|
||||
[[links]]
|
||||
label = "Source"
|
||||
url = "https://github.com/andwati"
|
||||
[taxonomies]
|
||||
tags = ["placeholder"]
|
||||
+++
|
||||
|
||||
Placeholder case study body establishing the `portfolio` content schema.
|
||||
---
|
||||
title: "Example Project"
|
||||
description: "Placeholder portfolio entry establishing the schema."
|
||||
role: "Author"
|
||||
dateStart: "2026-01-01"
|
||||
outcome: "Established the portfolio content schema."
|
||||
links:
|
||||
- label: "Source"
|
||||
url: "https://github.com/andwati"
|
||||
tags: ["placeholder"]
|
||||
---
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: "Attention Is All You Need"
|
||||
kind: "paper"
|
||||
authors: ["Ashish Vaswani", "Noam Shazeer", "Niki Parmar"]
|
||||
url: "https://arxiv.org/abs/1706.03762"
|
||||
coverImage: "/covers/attention-is-all-you-need.jpg"
|
||||
rating: 5
|
||||
status: "read"
|
||||
dateFinished: "2026-02-03"
|
||||
tags: ["machine-learning", "papers"]
|
||||
---
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "Designing Data-Intensive Applications, 2nd Edition"
|
||||
kind: "book"
|
||||
authors: ["Martin Kleppmann", "Chris Riccomini"]
|
||||
url: "https://www.oreilly.com/library/view/designing-data-intensive-applications/9781098119058/"
|
||||
coverImage: "/covers/designing-data-intensive-applications-2nd-edition.webp"
|
||||
rating: 5
|
||||
status: "reading"
|
||||
tags: ["distributed-systems"]
|
||||
---
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "Structure and Interpretation of Computer Programs"
|
||||
kind: "book"
|
||||
authors: ["Harold Abelson", "Gerald Jay Sussman"]
|
||||
coverImage: "/covers/structure-and-interpretation-of-computer-programs.jpg"
|
||||
rating: 5
|
||||
status: "read"
|
||||
dateFinished: "2026-01-20"
|
||||
tags: ["computer-science", "programming"]
|
||||
---
|
||||
+6
-11
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "A Fresh Coat Of Paint"
|
||||
description = "Migrating to Zola"
|
||||
author = "mockigspectre"
|
||||
date = 2023-08-24
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "zola", "blog", "tera", "rust" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "A Fresh Coat Of Paint"
|
||||
description: "Migrating to Zola"
|
||||
date: "2023-08-24"
|
||||
tags: ["zola", "blog", "tera", "rust"]
|
||||
---
|
||||
|
||||
Using Zola as my preferred static site generator
|
||||
|
||||
+124
-126
@@ -1,18 +1,13 @@
|
||||
+++
|
||||
title = "From C to Machine Code: What Actually Runs"
|
||||
description = "Before diving into how to break a program, we need to understand what the computer is actually executing"
|
||||
author = "andwati"
|
||||
date = 2026-04-08
|
||||
draft = false
|
||||
---
|
||||
title: "From C to Machine Code: What Actually Runs"
|
||||
description: "Before diving into how to break a program, we need to understand what the computer is actually executing"
|
||||
date: "2026-04-08"
|
||||
tags: ["assembly", "rev", "pwn"]
|
||||
---
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "assembly", "rev", "pwn" ]
|
||||
<div class="youtube"><iframe src="https://www.youtube-nocookie.com/embed/KbH239zvDtM" title="YouTube video" loading="lazy" allowfullscreen></iframe></div>
|
||||
|
||||
+++
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/KbH239zvDtM" title="YouTube video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
Before diving into how to break a program, we need to understand what the computer is actually executing. When you write a C program, the processor doesn't understand a single line of it. The C language exists for *our* benefit, allowing us to write logic without having to manually shuffle bits around in the processor.
|
||||
Before diving into how to break a program, we need to understand what the computer is actually executing. When you write a C program, the processor doesn't understand a single line of it. The C language exists for _our_ benefit, allowing us to write logic without having to manually shuffle bits around in the processor.
|
||||
|
||||
To bridge this gap, we use a compiler (like `GCC`), which translates our human-readable C code into machine code—raw binary instructions. Assembly language is simply the human-readable representation of that machine code.
|
||||
|
||||
@@ -20,43 +15,44 @@ Because we usually don't have the original C source code when analyzing malware
|
||||
|
||||
Let's look at what a basic `printf("Hello World!");` program actually turns into.
|
||||
|
||||
```c
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main(){
|
||||
printf("hello world\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
We will compile the hello world C program, then dump the assembly in Intel syntax(it defaults to AT&T syntax, a cancer).
|
||||
int main(){
|
||||
printf("hello world\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
```sh
|
||||
gcc -o hello hello.c && objdump -d -M intel hello | grep -A 15 "**<main>:**"
|
||||
We will compile the hello world C program, then dump the assembly in Intel syntax(it defaults to AT&T syntax, a cancer).
|
||||
|
||||
```sh
|
||||
gcc -o hello hello.c && objdump -d -M intel hello | grep -A 15 "**<main>:**"
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
```asm
|
||||
0000000000001139 <main>:
|
||||
1139: 55 push rbp
|
||||
113a: 48 89 e5 mov rbp,rsp
|
||||
113d: 48 8d 05 c0 0e 00 00 lea rax,[rip+0xec0] # 2004 <_IO_stdin_used+0x4>
|
||||
1144: 48 89 c7 mov rdi,rax
|
||||
1147: e8 e4 fe ff ff call 1030 <puts@plt>
|
||||
114c: b8 00 00 00 00 mov eax,0x0
|
||||
1151: 5d pop rbp
|
||||
```asm
|
||||
0000000000001139 <main>:
|
||||
1139: 55 push rbp
|
||||
113a: 48 89 e5 mov rbp,rsp
|
||||
113d: 48 8d 05 c0 0e 00 00 lea rax,[rip+0xec0] # 2004 <_IO_stdin_used+0x4>
|
||||
1144: 48 89 c7 mov rdi,rax
|
||||
1147: e8 e4 fe ff ff call 1030 <puts@plt>
|
||||
114c: b8 00 00 00 00 mov eax,0x0
|
||||
1151: 5d pop rbp
|
||||
1152: c3 ret
|
||||
|
||||
Disassembly of section .fini:
|
||||
|
||||
0000000000001154 <_fini>:
|
||||
1154: 48 83 ec 08 sub rsp,0x8
|
||||
1158: 48 83 c4 08 add rsp,0x8
|
||||
0000000000001154 <_fini>:
|
||||
1154: 48 83 ec 08 sub rsp,0x8
|
||||
1158: 48 83 c4 08 add rsp,0x8
|
||||
115c: c3 ret
|
||||
|
||||
```
|
||||
|
||||
Notice how different this looks from C. The processor executes different instruction sets depending on its architecture. The two most common architectures you will encounter are 32-bit (x86) and 64-bit (x86_64 or just x64/AMD64/Intel 64).
|
||||
Notice how different this looks from C. The processor executes different instruction sets depending on its architecture. The two most common architectures you will encounter are 32-bit (x86) and 64-bit (x86_64 or just x64/AMD64/Intel 64).
|
||||
|
||||
## **The Processor's Workbench: Registers**
|
||||
|
||||
@@ -64,9 +60,9 @@ To process data rapidly, the CPU doesn't want to constantly reach all the way ou
|
||||
|
||||
Here are the critical x64 registers you need to know:
|
||||
|
||||
* **`rip` (Instruction Pointer):** The most important register for exploitation. It points to the exact memory address of the *next* instruction the CPU is supposed to execute.
|
||||
* **`rsp` (Stack Pointer):** Points to the very top of your current stack frame.
|
||||
* **`rbp` (Base Pointer):** Points to the bottom of your current stack frame.
|
||||
- **`rip` (Instruction Pointer):** The most important register for exploitation. It points to the exact memory address of the _next_ instruction the CPU is supposed to execute.
|
||||
- **`rsp` (Stack Pointer):** Points to the very top of your current stack frame.
|
||||
- **`rbp` (Base Pointer):** Points to the bottom of your current stack frame.
|
||||
|
||||
### **General Purpose Registers & Calling Conventions**
|
||||
|
||||
@@ -74,16 +70,18 @@ There are also general-purpose registers (`rax`, `rbx`, `rcx`, `rdx`, `rsi`, `rd
|
||||
|
||||
In x64 Linux, when a function is called, the arguments are passed directly into registers in this specific order:
|
||||
|
||||
1. `rdi` (First argument)
|
||||
2. `rsi` (Second argument)
|
||||
3. `rdx` (Third argument)
|
||||
4. `rcx` (Fourth argument)
|
||||
5. `r8` (Fifth argument)
|
||||
1. `rdi` (First argument)
|
||||
2. `rsi` (Second argument)
|
||||
3. `rdx` (Third argument)
|
||||
4. `rcx` (Fourth argument)
|
||||
5. `r8` (Fifth argument)
|
||||
6. `r9` (Sixth argument)
|
||||
|
||||
{% <note> %}
|
||||
<aside class="callout callout-note">
|
||||
|
||||
In older x86 32-bit binaries, arguments aren't passed in registers at all; they are pushed onto the stack. When a function finishes and returns a value, that return value is almost always placed in the **`rax`** register (or `eax` in 32-bit).
|
||||
{% </note> %}
|
||||
|
||||
</aside>
|
||||
|
||||
### **Register Sizes and "Words"**
|
||||
|
||||
@@ -98,29 +96,28 @@ Registers have different sizes depending on the architecture, and you can refere
|
||||
Here is how x64 registers break down into smaller accessible chunks:
|
||||
|
||||
| 8-Byte (Qword)[64 bit] | Lower 4-Bytes (Dword)[lower 32 bits] | Lower 2-Bytes (Word)[lower 16 bits] | Lower 1-Byte[lower 8 bits] |
|
||||
| :---- | :---- | :---- | :---- |
|
||||
| rax | eax | ax | al |
|
||||
| rbx | ebx | bx | bl |
|
||||
| rcx | ecx | cx | cl |
|
||||
| rdx | edx | dx | dl |
|
||||
| rdi | edi | di | dil |
|
||||
| rsi | edi | si | sil |
|
||||
| rsp | esp | sp | spl |
|
||||
| rbp | ebp | bp | bpl |
|
||||
| rip | eip | - | - |
|
||||
| r8 | r8d | r8w | r8b |
|
||||
| r9 | r9d | r9w | r9b |
|
||||
| r10 | r10d | r10w | r10b |
|
||||
| r11 | r11d | r11w | r11b |
|
||||
| r12 | r12d | r12w | r12b |
|
||||
| r13 | r13d | r13w | r13b |
|
||||
| r14 | r14d | r14w | r14b |
|
||||
| r15 | r15d | r15w | r15b |
|
||||
| :--------------------- | :----------------------------------- | :---------------------------------- | :------------------------- |
|
||||
| rax | eax | ax | al |
|
||||
| rbx | ebx | bx | bl |
|
||||
| rcx | ecx | cx | cl |
|
||||
| rdx | edx | dx | dl |
|
||||
| rdi | edi | di | dil |
|
||||
| rsi | edi | si | sil |
|
||||
| rsp | esp | sp | spl |
|
||||
| rbp | ebp | bp | bpl |
|
||||
| rip | eip | - | - |
|
||||
| r8 | r8d | r8w | r8b |
|
||||
| r9 | r9d | r9w | r9b |
|
||||
| r10 | r10d | r10w | r10b |
|
||||
| r11 | r11d | r11w | r11b |
|
||||
| r12 | r12d | r12w | r12b |
|
||||
| r13 | r13d | r13w | r13b |
|
||||
| r14 | r14d | r14w | r14b |
|
||||
| r15 | r15d | r15w | r15b |
|
||||
|
||||
<br>
|
||||
<p>If you are dealing with a 32-bit (x86) binary, the 8-byte 'R' registers don't exist. The largest buckets you have are the 4-byte 'E' registers (`eax`, `ebp`, etc.).</p>
|
||||
|
||||
|
||||
## **The Stack**
|
||||
|
||||
The stack is a segment of memory heavily used during execution. It's primarily used to store local variables, keep track of function calls, and manage control flow. It operates as a LIFO (Last-In, First-Out) structure—meaning you can only add (push) to the top of it, and remove (pop) from the top of it.
|
||||
@@ -179,13 +176,14 @@ Disassembly of section .fini:
|
||||
1160: 48 83 ec 08 sub rsp,0x8
|
||||
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
In your output, you'll see an instruction moving the value `0x5` into a memory location relative to the base pointer, usually something like `[rbp-0x4]`. That is your local variable resting on the stack.
|
||||
|
||||
## **The Heap**
|
||||
|
||||
We will just do an overview of this section. It can get quite complex very fast. We will eventually cover them in future articles.
|
||||
We will just do an overview of this section. It can get quite complex very fast. We will eventually cover them in future articles.
|
||||
|
||||
If the stack is the CPU’s fast, tightly organized workbench, the heap is the massive, slightly chaotic warehouse out back.
|
||||
|
||||
@@ -199,28 +197,28 @@ In C, this is done using the `malloc()` (memory allocate) and `free()` functions
|
||||
|
||||
Consider heap.c
|
||||
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
// Ask the warehouse for 64 bytes of space
|
||||
char *buffer = (char *)malloc(64);
|
||||
|
||||
// Put some data into that space
|
||||
strcpy(buffer, "hello heap");
|
||||
|
||||
// Give the space back to the warehouse
|
||||
free(buffer);
|
||||
|
||||
return 0;
|
||||
int main() {
|
||||
// Ask the warehouse for 64 bytes of space
|
||||
char *buffer = (char *)malloc(64);
|
||||
|
||||
// Put some data into that space
|
||||
strcpy(buffer, "hello heap");
|
||||
|
||||
// Give the space back to the warehouse
|
||||
free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
Now we do the necessary:
|
||||
|
||||
```sh
|
||||
```sh
|
||||
gcc -o heap heap.c && objdump -d -M intel heap | grep -A 20 "<main>:"
|
||||
|
||||
```
|
||||
@@ -228,23 +226,23 @@ gcc -o heap heap.c && objdump -d -M intel heap | grep -A 20 "<main>:"
|
||||
<br>
|
||||
|
||||
```asm
|
||||
0000000000001149 **<main>:**
|
||||
1149: 55 push rbp
|
||||
114a: 48 89 e5 mov rbp,rsp
|
||||
114d: 48 83 ec 10 sub rsp,0x10
|
||||
1151: bf 40 00 00 00 mov edi,0x40
|
||||
1156: e8 e5 fe ff ff call 1040 <malloc@plt>
|
||||
115b: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
|
||||
115f: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
|
||||
1163: 48 ba 68 65 6c 6c 6f movabs rdx,0x6568206f6c6c6568
|
||||
116a: 20 68 65
|
||||
116d: 48 89 10 mov QWORD PTR [rax],rdx
|
||||
1170: c7 40 07 65 61 70 00 mov DWORD PTR [rax+0x7],0x706165
|
||||
1177: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
|
||||
117b: 48 89 c7 mov rdi,rax
|
||||
117e: e8 ad fe ff ff call 1030 <free@plt>
|
||||
1183: b8 00 00 00 00 mov eax,0x0
|
||||
1188: c9 leave
|
||||
0000000000001149 **<main>:**
|
||||
1149: 55 push rbp
|
||||
114a: 48 89 e5 mov rbp,rsp
|
||||
114d: 48 83 ec 10 sub rsp,0x10
|
||||
1151: bf 40 00 00 00 mov edi,0x40
|
||||
1156: e8 e5 fe ff ff call 1040 <malloc@plt>
|
||||
115b: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
|
||||
115f: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
|
||||
1163: 48 ba 68 65 6c 6c 6f movabs rdx,0x6568206f6c6c6568
|
||||
116a: 20 68 65
|
||||
116d: 48 89 10 mov QWORD PTR [rax],rdx
|
||||
1170: c7 40 07 65 61 70 00 mov DWORD PTR [rax+0x7],0x706165
|
||||
1177: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
|
||||
117b: 48 89 c7 mov rdi,rax
|
||||
117e: e8 ad fe ff ff call 1030 <free@plt>
|
||||
1183: b8 00 00 00 00 mov eax,0x0
|
||||
1188: c9 leave
|
||||
1189: c3 ret
|
||||
|
||||
Disassembly of section .fini:
|
||||
@@ -262,54 +260,54 @@ Assembly might look like gibberish at first, but it essentially boils down to mo
|
||||
|
||||
### **Moving Data**
|
||||
|
||||
* **`mov dest, src`**: Copies data from the source to the destination. (`mov rax, rdx` copies the value in `rdx` into `rax`).
|
||||
* **Dereferencing `[]`**: Brackets act like pointers in C. `mov rax, [rdx]` doesn't move `rdx` itself; it goes to the memory address stored in `rdx` and grabs the value sitting there. Conversely, `mov [rax], rdx` takes the value in `rdx` and writes it into the memory address pointed to by `rax`.
|
||||
* **`lea dest, src`**: Load Effective Address. It calculates a memory address and stores the *address itself* in the destination, rather than the data at that address. (`lea rdi, [rbx+0x10]`).
|
||||
- **`mov dest, src`**: Copies data from the source to the destination. (`mov rax, rdx` copies the value in `rdx` into `rax`).
|
||||
- **Dereferencing `[]`**: Brackets act like pointers in C. `mov rax, [rdx]` doesn't move `rdx` itself; it goes to the memory address stored in `rdx` and grabs the value sitting there. Conversely, `mov [rax], rdx` takes the value in `rdx` and writes it into the memory address pointed to by `rax`.
|
||||
- **`lea dest, src`**: Load Effective Address. It calculates a memory address and stores the _address itself_ in the destination, rather than the data at that address. (`lea rdi, [rbx+0x10]`).
|
||||
|
||||
### **Math and Logic**
|
||||
|
||||
* **`add dest, src` / `sub dest, src`**: Adds or subtracts the source from the destination, storing the result in the destination.
|
||||
* **`xor dest, src`**: Performs a bitwise exclusive OR. (You will frequently see `xor rax, rax`—this is simply an optimized way to set `rax` to 0).
|
||||
- **`add dest, src` / `sub dest, src`**: Adds or subtracts the source from the destination, storing the result in the destination.
|
||||
- **`xor dest, src`**: Performs a bitwise exclusive OR. (You will frequently see `xor rax, rax`—this is simply an optimized way to set `rax` to 0).
|
||||
|
||||
### **Stack Operations**
|
||||
|
||||
* **`push reg`**: Subtracts from `rsp` to grow the stack, then places the register's value onto the new top of the stack.
|
||||
* **`pop reg`**: Takes the value from the top of the stack, puts it into the register, and adds to `rsp` to shrink the stack.
|
||||
|
||||
- **`push reg`**: Subtracts from `rsp` to grow the stack, then places the register's value onto the new top of the stack.
|
||||
- **`pop reg`**: Takes the value from the top of the stack, puts it into the register, and adds to `rsp` to shrink the stack.
|
||||
|
||||
### **Control Flow**
|
||||
|
||||
* **`jmp address`**: Unconditionally redirects code execution to a new memory address.
|
||||
* **`call address`**: Used to invoke functions. It pushes the current `rip` onto the stack (so the program remembers where it was) and then jumps to the new address.
|
||||
* **`ret`**: Pops the saved address off the stack and places it back into `rip`, seamlessly resuming execution where it left off before the `call`.
|
||||
- **`jmp address`**: Unconditionally redirects code execution to a new memory address.
|
||||
- **`call address`**: Used to invoke functions. It pushes the current `rip` onto the stack (so the program remembers where it was) and then jumps to the new address.
|
||||
- **`ret`**: Pops the saved address off the stack and places it back into `rip`, seamlessly resuming execution where it left off before the `call`.
|
||||
|
||||
### **Conditionals and Flags**
|
||||
|
||||
The CPU has a special register dedicated to **Flags**—individual bits that indicate the state of the processor (e.g., the Zero Flag, Carry Flag, Sign Flag).
|
||||
|
||||
* **`cmp arg1, arg2`**: Compares two values by silently subtracting them. It doesn't save the mathematical result; instead, it updates the CPU Flags (like setting the Zero Flag if the two values were equal).
|
||||
* **`jz` / `jnz`**: Jump if Zero / Jump if Not Zero. These look at the CPU flags set by a previous `cmp` instruction. If the Zero Flag is set, `jz` will take the jump. If not, the program just continues to the next instruction.
|
||||
- **`cmp arg1, arg2`**: Compares two values by silently subtracting them. It doesn't save the mathematical result; instead, it updates the CPU Flags (like setting the Zero Flag if the two values were equal).
|
||||
- **`jz` / `jnz`**: Jump if Zero / Jump if Not Zero. These look at the CPU flags set by a previous `cmp` instruction. If the Zero Flag is set, `jz` will take the jump. If not, the program just continues to the next instruction.
|
||||
|
||||
There is one register that contains flags. A flag is a particular bit of this register. If it is set or not, will typically mean something. Here is the list of flags.
|
||||
|
||||
```txt
|
||||
00: Carry Flag
|
||||
01: always 1
|
||||
02: Parity Flag
|
||||
03: always 0
|
||||
04: Adjust Flag
|
||||
05: always 0
|
||||
06: Zero Flag
|
||||
07: Sign Flag
|
||||
08: Trap Flag
|
||||
09: Interruption Flag
|
||||
10: Direction Flag
|
||||
11: Overflow Flag
|
||||
12: I/O Privilege Field lower bit
|
||||
13: I/O Privilege Field higher bit
|
||||
14: Nested Task Flag
|
||||
15: Resume Flag
|
||||
00: Carry Flag
|
||||
01: always 1
|
||||
02: Parity Flag
|
||||
03: always 0
|
||||
04: Adjust Flag
|
||||
05: always 0
|
||||
06: Zero Flag
|
||||
07: Sign Flag
|
||||
08: Trap Flag
|
||||
09: Interruption Flag
|
||||
10: Direction Flag
|
||||
11: Overflow Flag
|
||||
12: I/O Privilege Field lower bit
|
||||
13: I/O Privilege Field higher bit
|
||||
14: Nested Task Flag
|
||||
15: Resume Flag
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
There are other flags then the one listed, however we really don't deal with them too much (and out of these, there are only a few we actively deal with).
|
||||
+6
-11
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "Django Secret Key Tutorial"
|
||||
description = "Managing secrets"
|
||||
author = "andwati"
|
||||
date = 2022-11-11
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "tutorial", "django", "python", ".env" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Django Secret Key Tutorial"
|
||||
description: "Managing secrets"
|
||||
date: "2022-11-11"
|
||||
tags: ["tutorial", "django", "python", ".env"]
|
||||
---
|
||||
|
||||
Managing the Django SECRET_KEY variable.
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "Hello World"
|
||||
description = "Hello world"
|
||||
author = "andwati"
|
||||
date = 2022-11-04
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "hugo", "blog", "go" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Hello World"
|
||||
description: "Hello world"
|
||||
date: "2022-11-04"
|
||||
tags: ["hugo", "blog", "go"]
|
||||
---
|
||||
|
||||
How it begins
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "cognitive inertia"
|
||||
description = "inertia"
|
||||
author = "andwati"
|
||||
date = 2025-02-26
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "cognition" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "cognitive inertia"
|
||||
description: "inertia"
|
||||
date: "2025-02-26"
|
||||
tags: ["cognition"]
|
||||
---
|
||||
|
||||
Staring at the void
|
||||
|
||||
+8
-13
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "Install PostgreSQL on Arch | Manjaro | Garuda Linux"
|
||||
description = "Getting PostgreSQL up and running on Arch Linux-based distros"
|
||||
author = "andwati"
|
||||
date = 2023-02-16
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "postgresql", "archlinux", "manjaro", "garuda", "linux" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Install PostgreSQL on Arch | Manjaro | Garuda Linux"
|
||||
description: "Getting PostgreSQL up and running on Arch Linux-based distros"
|
||||
date: "2023-02-16"
|
||||
tags: ["postgresql", "archlinux", "manjaro", "garuda", "linux"]
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
@@ -46,7 +41,7 @@ Postgres offers a lot of advantages that make it an excellent choice for highly
|
||||
|
||||
Now with all that fluff out of the way, let's get to business. The steps have been tested on Arch Linux with the KDE desktop.
|
||||
|
||||
> **Note:** Commands that should be run as the *postgres* user are prefixed by `[postgres]$` in this article.
|
||||
> **Note:** Commands that should be run as the _postgres_ user are prefixed by `[postgres]$` in this article.
|
||||
|
||||
## Step 1: Installing the PostgreSQL Package
|
||||
|
||||
@@ -54,7 +49,7 @@ Now with all that fluff out of the way, let's get to business. The steps have be
|
||||
sudo pacman -Syu postgresql
|
||||
```
|
||||
|
||||
This command will update the package database and update all packages on the system then install the PostgreSQL package from your distribution mirrors. Never install a package without updating the system first. On a rolling release, this can lead to an unbootable system. Installing the package will also create a system user called *postgres*. You can now switch to the *postgres* user using a privilege elevation program.
|
||||
This command will update the package database and update all packages on the system then install the PostgreSQL package from your distribution mirrors. Never install a package without updating the system first. On a rolling release, this can lead to an unbootable system. Installing the package will also create a system user called _postgres_. You can now switch to the _postgres_ user using a privilege elevation program.
|
||||
|
||||
You can switch to the PostgreSQL user by executing the following command:
|
||||
|
||||
+6
-11
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "Integrating Netlify CMS"
|
||||
description = "Integrating netlify cms"
|
||||
author = "andwati"
|
||||
date = 2022-11-24
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "blog", "hugo", "netlify", "netlify-cms", "github" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Integrating Netlify CMS"
|
||||
description: "Integrating netlify cms"
|
||||
date: "2022-11-24"
|
||||
tags: ["blog", "hugo", "netlify", "netlify-cms", "github"]
|
||||
---
|
||||
|
||||
Migrating to a better content management system through Netlify CMS
|
||||
|
||||
+6
-11
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "Export default and module.exports in Javascript"
|
||||
description = "Modules are the building blocks of modern JavaScript applications, allowing for the encapsulation of code into reusable components. Two primary systems govern the exportation of these modules: export default in ES6 and module.exports in CommonJS. "
|
||||
author = "andwati"
|
||||
date = 2024-01-17
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "javascript", "node" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Export default and module.exports in Javascript"
|
||||
description: "Modules are the building blocks of modern JavaScript applications, allowing for the encapsulation of code into reusable components. Two primary systems govern the exportation of these modules: export default in ES6 and module.exports in CommonJS. "
|
||||
date: "2024-01-17"
|
||||
tags: ["javascript", "node"]
|
||||
---
|
||||
|
||||
Modules are the building blocks of modern JavaScript applications, allowing for the encapsulation of code into reusable components. Two primary systems govern the exportation of these modules: export default in ES6 and module.exports in CommonJS.
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
+++
|
||||
title = "mmuctf 2025 writeup"
|
||||
description = "mmuctf 2025 challenges writeup"
|
||||
date = 2025-08-03
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "ctf", "rev", "web", "forensics" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "mmuctf 2025 writeup"
|
||||
description: "mmuctf 2025 challenges writeup"
|
||||
date: "2025-08-03"
|
||||
tags: ["ctf", "rev", "web", "forensics"]
|
||||
---
|
||||
|
||||
Over the weekend, I had the opportunity to participate in the mmuctf 2025. It was an individual jeopardy style CTF targeted towards beginners and intermediate people in cybersecurity. This is a write-up to explore some challenges I did, or at least almost did.
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "Setting up Obsidian sync in Windows"
|
||||
description = "Syncing Obsidian in Windows with Windows Task Scheduler with git"
|
||||
author = "andwati"
|
||||
date = 2023-10-01
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "obsidian", "git", "sync", "windows", "cron", "task-scheduler", "powershell" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Setting up Obsidian sync in Windows"
|
||||
description: "Syncing Obsidian in Windows with Windows Task Scheduler with git"
|
||||
date: "2023-10-01"
|
||||
tags: ["obsidian", "git", "sync", "windows", "cron", "task-scheduler", "powershell"]
|
||||
---
|
||||
|
||||
Syncing Obsidian in Windows with Windows Task Scheduler and git
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "ScriptCTF 2025 Writeup"
|
||||
description = "ScriptCTF 2025 Writeup"
|
||||
author = "andwati"
|
||||
date = 2025-08-18
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "ctf", "rev", "web", "forensics" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "ScriptCTF 2025 Writeup"
|
||||
description: "ScriptCTF 2025 Writeup"
|
||||
date: "2025-08-18"
|
||||
tags: ["ctf", "rev", "web", "forensics"]
|
||||
---
|
||||
|
||||
![ScriptCTF mascot illustration of a wizard coding at a laptop, with the tagline "scriptCTF makes CTFs fun and approachable for all skill levels!"][image1]
|
||||
Over the weekend, I participated in ScriptCTF, a capture-the-flag competition packed with diverse challenges spanning cryptography, forensics, reverse engineering, and web exploitation.
|
||||
+16
-15
@@ -1,13 +1,9 @@
|
||||
+++
|
||||
title = "Self-Hosting Gitea and Automating GitHub Mirrors"
|
||||
description = "Self-Hosting Gitea and Automating GitHub Mirrors (and Everything Cloudflare Broke Along the Way)"
|
||||
date = 2026-08-19
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "self-hosting", "gitea", "dokploy", "cloudflare", "github-actions", "bash" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Self-Hosting Gitea and Automating GitHub Mirrors"
|
||||
description: "Self-Hosting Gitea and Automating GitHub Mirrors (and Everything Cloudflare Broke Along the Way)"
|
||||
date: "2026-08-19"
|
||||
tags: ["self-hosting", "gitea", "dokploy", "cloudflare", "github-actions", "bash"]
|
||||
---
|
||||
|
||||
I run a Hetzner box with [Dokploy](https://docs.dokploy.com) for most of my personal infrastructure. I'd been meaning to get a self-hosted git server on it for a while, mainly so I have a durable mirror of my GitHub repos that doesn't depend on GitHub staying up, staying free, or staying interested in hosting my code. This is the log of actually doing it: what I picked, what broke, and the debugging trail for the parts that took longer than they should have.
|
||||
|
||||
@@ -166,9 +162,11 @@ A few decisions worth explaining.
|
||||
|
||||
**SSH on 2222, not 22.** The host's own sshd already owns port 22, so Gitea's internal SSH got mapped to 2222, with [`SSH_PORT`](https://docs.gitea.com/administration/config-cheat-sheet/) set to match so Gitea generates correct clone URLs.
|
||||
|
||||
{% <note> %}
|
||||
<aside class="callout callout-note">
|
||||
|
||||
I later set `GITEA__server__DISABLE_SSH=true` (see [`DISABLE_SSH`](https://docs.gitea.com/administration/config-cheat-sheet/) in Gitea's config cheat sheet) and dropped the port mapping entirely. Cloudflare's proxy only forwards HTTP and HTTPS traffic, not arbitrary TCP, so SSH on 2222 was simply unreachable once `gitea.andwati.com` sat behind the orange cloud. The two ways around that were a DNS-only subdomain, which leaks the origin IP to anyone who runs `dig`, or a Cloudflare Tunnel, which is more moving parts than a personal git server's SSH clone was worth. HTTPS clone already worked fine through the proxy, so disabling SSH was the simpler trade.
|
||||
{% </note> %}
|
||||
|
||||
</aside>
|
||||
|
||||
**Traefik/Dokploy terminates TLS, Gitea speaks plain HTTP internally.** [Dokploy's domain manager](https://docs.dokploy.com/docs/core/domains) handles the Let's Encrypt cert and routes to the container on port 3000. `REVERSE_PROXY_TRUSTED_PROXIES` is set so Gitea trusts the forwarded headers instead of thinking every request comes from the internal Docker network.
|
||||
|
||||
@@ -180,13 +178,16 @@ I later set `GITEA__server__DISABLE_SSH=true` (see [`DISABLE_SSH`](https://docs.
|
||||
|
||||
Two tokens drive the mirror script, and both need to be scoped correctly or the migrate call fails in ways that look unrelated to permissions.
|
||||
|
||||
### **GitHub token (`GH_PAT`).**
|
||||
### **GitHub token (`GH_PAT`).**
|
||||
|
||||
A classic Personal Access Token with the `repo` scope, generated at [github.com/settings/tokens](https://github.com/settings/tokens). This is the scope GitHub's own docs point to for reading private repositories, and it's also what Gitea's own migration guide recommends when the source is GitHub. A fine-grained token works too, provided it has read access to Contents and Metadata across all the repos you want mirrored, but classic `repo` is simpler to reason about for a personal account with dozens of repos rather than picking them one by one.
|
||||
|
||||
### **Gitea token (`GITEA_TOKEN`).**
|
||||
### **Gitea token (`GITEA_TOKEN`).**
|
||||
|
||||
Needs the `write:repository` scope, generated from your Gitea instance at Settings → Applications → Generate New Token (`https://<your-gitea-domain>/user/settings/applications`). `write:repository` covers both the `/repos/migrate` call that creates new mirrors and the `PATCH` call the script uses to sync visibility on existing ones. `read:repository` alone isn't enough since both of those are write operations.
|
||||
|
||||
### **Where they get set.**
|
||||
### **Where they get set.**
|
||||
|
||||
Both live as encrypted secrets on the `gitea-mirror-sync` repo, not in the script or the workflow file: Settings → Secrets and variables → Actions → New repository secret, alongside `GITEA_URL` and `GITEA_OWNER`. The workflow references them only as `${{ secrets.GH_PAT }}` and `${{ secrets.GITEA_TOKEN }}`, so neither value is ever visible in a log or checked into the repo itself.
|
||||
|
||||
## Bot Fight Mode: the wall you can't route around
|
||||
+7
-12
@@ -1,20 +1,15 @@
|
||||
+++
|
||||
title = "Semantic Versioning(SemVer) and Conventional Commits"
|
||||
description = "Adopting best practices in your git and build workflows."
|
||||
author = "andwati"
|
||||
date = 2023-01-24
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "git", "semver", "workflow", "conventional-commits" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Semantic Versioning(SemVer) and Conventional Commits"
|
||||
description: "Adopting best practices in your git and build workflows."
|
||||
date: "2023-01-24"
|
||||
tags: ["git", "semver", "workflow", "conventional-commits"]
|
||||
---
|
||||
|
||||
Adopting best practices in your git and build workflows.
|
||||
|
||||
# What is Semver?
|
||||
|
||||
Semantic versioning or just SemVer is a dependency naming guidline that aims to bring some sanity into naming libraries and packages in software development. It is a standard versioning system created by **Tom Preston Werner** (co-founder of Github) that’s used to communicate what changes are in a release.
|
||||
Semantic versioning or just SemVer is a dependency naming guideline that aims to bring some sanity into naming libraries and packages in software development. It is a standard versioning system created by **Tom Preston Werner** (co-founder of Github) that’s used to communicate what changes are in a release.
|
||||
|
||||
An efficient and smooth versioning becomes crucial for efficient software delivery expecially for projects that expose a public API. This saves the developers the chaos that is **dependency hell**.Dependency hell is a colloquial term for the frustration of some software users who have installed software packages which have dependencies on specific versions of other software packages.
|
||||
|
||||
+6
-11
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "Subresource Integrity"
|
||||
description = "Understanding Subresource Integrity"
|
||||
author = "andwati"
|
||||
date = 2023-04-29
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "subresource-integrity", "csp", "cors" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Subresource Integrity"
|
||||
description: "Understanding Subresource Integrity"
|
||||
date: "2023-04-29"
|
||||
tags: ["subresource-integrity", "csp", "cors"]
|
||||
---
|
||||
|
||||
Understanding Subresource Integrity
|
||||
|
||||
+6
-10
@@ -1,13 +1,9 @@
|
||||
+++
|
||||
title = "The Single Byte That Kills Your Exploit: Understanding Endianness"
|
||||
description = "Problem: Computers speak different languages, like people"
|
||||
date = 2025-11-09
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "blog" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "The Single Byte That Kills Your Exploit: Understanding Endianness"
|
||||
description: "Problem: Computers speak different languages, like people"
|
||||
date: "2025-11-09"
|
||||
tags: ["blog"]
|
||||
---
|
||||
|
||||
If you’ve ever crafted a perfect shellcode and ROP chain only to have your exploit immediately crash with a SIGSEGV(a signal sent by the operating system to a program when it attempts to access a protected or invalid memory location) or EIP(a 32-bit CPU register in the x86 architecture that holds the memory address of the next machine instruction to be executed) pointing to garbage, you’ve likely met the silent killer of beginners: Endianness.
|
||||
|
||||
+6
-11
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "What say you?"
|
||||
description = "Adding a comment system by utterances"
|
||||
author = "andwati"
|
||||
date = 2023-08-24
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "blog", "utterances" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "What say you?"
|
||||
description: "Adding a comment system by utterances"
|
||||
date: "2023-08-24"
|
||||
tags: ["blog", "utterances"]
|
||||
---
|
||||
|
||||
Free speech enhanced
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
+++
|
||||
title = "Configure Vue.js app With Tailwind CSS"
|
||||
description = "Tailwindcss in vuejs "
|
||||
author = "andwati"
|
||||
date = 2021-06-12
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "javascript", "vuejs", "tailwindcss" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "Configure Vue.js app With Tailwind CSS"
|
||||
description: "Tailwindcss in vuejs "
|
||||
date: "2021-06-12"
|
||||
tags: ["javascript", "vuejs", "tailwindcss"]
|
||||
---
|
||||
|
||||
A guide on how to use [Tailwind CSS](https://tailwindcss.com/) in your Vue project.
|
||||
|
||||
> **Note**
|
||||
> This article was originaly published on my old medium blog. I moved it here for archival purposes.
|
||||
> This article was originally published on my old medium blog. I moved it here for archival purposes.
|
||||
|
||||
Tailwind is a utility-first CSS framework for rapidly building custom user interfaces. It is an un-opinionated framework which means that it doesn't come with custom configurations like Bootstrap or Bulma(Yeah, I know, no one should tell you how to live your life).
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
+++
|
||||
title = "What is pwn?"
|
||||
description = "No not that one"
|
||||
date = 2025-09-03
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "blog" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "What is pwn?"
|
||||
description: "No not that one"
|
||||
date: "2025-09-03"
|
||||
tags: ["blog"]
|
||||
---
|
||||
|
||||
> Binary Exploitation is a broad topic within Cyber Security which really comes down to finding a vulnerability in the program and exploiting it to gain control of a shell or modifying the program's functions ~ctf101
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
+++
|
||||
title = "The One Thing Nobody Tells You About WiFi Hotspots on Arch Linux"
|
||||
description = "A minimal Arch install is great until NetworkManager silently fails to find a binary you didn't know you needed"
|
||||
author = "andwati"
|
||||
date = 2026-04-16
|
||||
draft = false
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "arch", "linux", "networking", "kde" ]
|
||||
|
||||
+++
|
||||
---
|
||||
title: "The One Thing Nobody Tells You About WiFi Hotspots on Arch Linux"
|
||||
description: "A minimal Arch install is great until NetworkManager silently fails to find a binary you didn't know you needed"
|
||||
date: "2026-04-16"
|
||||
tags: ["arch", "linux", "networking", "kde"]
|
||||
---
|
||||
|
||||
I spent longer than I'd like to admit trying to get a simple WiFi hotspot running on Arch. Not because it's hard — it genuinely isn't — but because of one missing piece that the NetworkManager documentation buries so deep you'd think it was classified.
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
+++
|
||||
title = "File over app"
|
||||
description = "Take control of your artifacts"
|
||||
author = "andwati"
|
||||
date = 2023-12-18
|
||||
draft = true
|
||||
|
||||
[taxonomies]
|
||||
tags = [ "obsidian", "entropy", "notes" ]
|
||||
|
||||
+++
|
||||
|
||||
Take control of your artifacts
|
||||
|
||||
In my endless endevours to find the perfect note taking app led me to obsidian, a note taking software that uses markdown files as the file format. All software is ephemereal in nature and yoour artifacts need to survive the decline of your favorite app. The files you create should be available to you and shouldt rrequire specialized software to access.
|
||||
|
||||
Your data shouldt be locked behind a paywall or an authentication system that is not under your control.
|
||||
Reference in New Issue
Block a user