diff --git a/404.html b/404.html index 4b479f85..313fbf05 100644 --- a/404.html +++ b/404.html @@ -1 +1 @@ -404 Page not found - lavafroth

404

\ No newline at end of file +404 Page not found - lavafroth

404

\ No newline at end of file diff --git a/about/index.html b/about/index.html index 77e91b41..c2c1bc2c 100644 --- a/about/index.html +++ b/about/index.html @@ -4,7 +4,7 @@ work. I’m doing a bachelors in data science at IITM. I’m decent with programming languages like C and Java, the latter of which was taught in school. I’m great at writing Golang and Rust. I render my YouTube videos with Python and the manim framework, so I’d argue I’m competent at it -as well.'>

Hi, this is Himadri!

I’m a self taught programmer and a digital artist. You might have arrived here +as well.'>

Hi, this is Himadri!

I’m a self taught programmer and a digital artist. You might have arrived here from my YouTube channel or my open source work. I’m doing a bachelors in data science at IITM.

I’m decent with programming languages like C and Java, the latter of which was taught in school. I’m great at writing Golang and Rust. I render my YouTube diff --git a/art/amateur-blender-sculpture/index.html b/art/amateur-blender-sculpture/index.html index c1ca5eea..890bf1cf 100644 --- a/art/amateur-blender-sculpture/index.html +++ b/art/amateur-blender-sculpture/index.html @@ -2,7 +2,7 @@ quality of the sculpt. I’m still pretty much in the learning stage. Big thank you to Nichole Sebastian for the reference photo. Also apologies if the empty eye sockets gave you a -jumpscare.'>

Aug 3, 2024

Amateur Blender Sculpture

This is my first time trying out sculpting in blender, so forgive me for the +jumpscare.'>

Aug 3, 2024

Amateur Blender Sculpture

This is my first time trying out sculpting in blender, so forgive me for the quality of the sculpt. I’m still pretty much in the learning stage. Big thank you to Nichole Sebastian for the reference photo. Also apologies if the empty eye sockets gave you a diff --git a/art/babe/index.html b/art/babe/index.html index 167a1fac..e89c6e7c 100644 --- a/art/babe/index.html +++ b/art/babe/index.html @@ -1 +1 @@ -Portrait study - lavafroth

Mar 11, 2026

Portrait study

I was playing with the pen pressure settings in Krita and tested it out with a portrait study of my significant other.

\ No newline at end of file +Portrait study - lavafroth

Mar 11, 2026

Portrait study

I was playing with the pen pressure settings in Krita and tested it out with a portrait study of my significant other.

\ No newline at end of file diff --git a/art/drawhearts/index.html b/art/drawhearts/index.html index 3fafef73..77ffb526 100644 --- a/art/drawhearts/index.html +++ b/art/drawhearts/index.html @@ -33,7 +33,7 @@ void main (void) { gl_FragColor = vec4(color,1.0); } I tinkered around for quite a while before discovering that I can intersect two xyxy skewed ellipses -with the absolute value operator. Here’s my custom equation for the heart shape.'>

Jan 18, 2026

Step to the 💗 beat

My first procedurally generated animation using shaders.

The shader can be visualized with glslViewer.

uniform vec2 u_mouse;
+with the absolute value operator. Here’s my custom equation for the heart shape.'>

Jan 18, 2026

Step to the 💗 beat

My first procedurally generated animation using shaders.

The shader can be visualized with glslViewer.

uniform vec2 u_mouse;
 uniform vec2 u_resolution;
 uniform float u_time;
 
diff --git a/art/drowning/index.html b/art/drowning/index.html
index 511e4837..87832226 100644
--- a/art/drowning/index.html
+++ b/art/drowning/index.html
@@ -1 +1 @@
-Drowning - lavafroth

Jun 18, 2024

Drowning

A cyborg head sinking in a pool of water. What more did you expect? Here’s a timelapse.

\ No newline at end of file +Drowning - lavafroth

Jun 18, 2024

Drowning

A cyborg head sinking in a pool of water. What more did you expect? Here’s a timelapse.

\ No newline at end of file diff --git a/art/index.html b/art/index.html index 2b41c365..90496d60 100644 --- a/art/index.html +++ b/art/index.html @@ -1,4 +1,4 @@ -Art - lavafroth

All the art I make is licensed under Creative Commons +Art - lavafroth

All the art I make is licensed under Creative Commons Attribution-ShareAlike 4.0 International license unless specified otherwise. Please read the legal code before redistributing, adapting diff --git a/art/shes-a-rebel/index.html b/art/shes-a-rebel/index.html index 2d19b177..7f549e15 100644 --- a/art/shes-a-rebel/index.html +++ b/art/shes-a-rebel/index.html @@ -1 +1 @@ -She's a Rebel - lavafroth

Apr 17, 2022

She's a Rebel

Clearly the title was an afterthought.

\ No newline at end of file +She's a Rebel - lavafroth

Apr 17, 2022

She's a Rebel

Clearly the title was an afterthought.

\ No newline at end of file diff --git a/art/sparkles/index.html b/art/sparkles/index.html index 145e547c..66fe339b 100644 --- a/art/sparkles/index.html +++ b/art/sparkles/index.html @@ -1 +1 @@ -✨ - lavafroth

Jul 15, 2025

\ No newline at end of file +✨ - lavafroth

Jul 15, 2025

\ No newline at end of file diff --git a/art/thiserror/index.html b/art/thiserror/index.html index 3c9d59c8..d9cc6fbb 100644 --- a/art/thiserror/index.html +++ b/art/thiserror/index.html @@ -1,5 +1,5 @@ This Error - lavafroth

Jun 18, 2024

This Error

My first hand drawn YouTube thumbnail, I’m might continue using +as well as the sheer memeworthiness of the debacle.'>

Jun 18, 2024

This Error

My first hand drawn YouTube thumbnail, I’m might continue using lawyer ferris as my mascot both due to ferris being in the public domain as well as the sheer memeworthiness of the debacle.

\ No newline at end of file diff --git a/art/tyler-joseph-portrait/index.html b/art/tyler-joseph-portrait/index.html index a0484473..f2725d90 100644 --- a/art/tyler-joseph-portrait/index.html +++ b/art/tyler-joseph-portrait/index.html @@ -1,3 +1,3 @@ Truce - lavafroth

Jul 23, 2022

Truce

A painting of the lead vocalist of Twenty Øne Piløts, named +after one of my favorite songs from their album Vessel.'>

Jul 23, 2022

Truce

A painting of the lead vocalist of Twenty Øne Piløts, named after one of my favorite songs from their album Vessel.

\ No newline at end of file diff --git a/art/wip-animation/index.html b/art/wip-animation/index.html index d5261f05..4768b7cf 100644 --- a/art/wip-animation/index.html +++ b/art/wip-animation/index.html @@ -1 +1 @@ -Throwing knives - lavafroth

Jan 19, 2024

Throwing knives

An unfinished animation with a focus on anatomy. Thank you Polina Tankilevitch for the reference video.

\ No newline at end of file +Throwing knives - lavafroth

Jan 19, 2024

Throwing knives

An unfinished animation with a focus on anatomy. Thank you Polina Tankilevitch for the reference video.

\ No newline at end of file diff --git a/favicon.png b/favicon.png deleted file mode 100644 index fd57e740..00000000 Binary files a/favicon.png and /dev/null differ diff --git a/favicon.svg b/favicon.svg new file mode 100644 index 00000000..46123b85 --- /dev/null +++ b/favicon.svg @@ -0,0 +1,54 @@ + + + + + + + + + + diff --git a/index.html b/index.html index 85a7daaa..bcede8a1 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ -lavafroth

Easy SSH Tunnel


SSH +lavafroth

Easy SSH Tunnel


SSH Proxy Tools Webapp diff --git a/page/2/index.html b/page/2/index.html index aab9c609..3dd679f5 100644 --- a/page/2/index.html +++ b/page/2/index.html @@ -1,4 +1,4 @@ -lavafroth

A Tale of a Frugal Home Server


NixOS +lavafroth

A Tale of a Frugal Home Server


NixOS Home Server Automation Jellyfin diff --git a/page/3/index.html b/page/3/index.html index 66bdf648..6c0634fe 100644 --- a/page/3/index.html +++ b/page/3/index.html @@ -1,4 +1,4 @@ -lavafroth

I Solemnly Swear to Never Buy a Gaming Laptop Again


Workflow +lavafroth

I Solemnly Swear to Never Buy a Gaming Laptop Again


Workflow Rant Linux Laptops diff --git a/page/4/index.html b/page/4/index.html index d15c181c..d4e80c0f 100644 --- a/page/4/index.html +++ b/page/4/index.html @@ -1,4 +1,4 @@ -lavafroth

Abstracting Structured Patterns in Concurrent Programming


Meta +lavafroth

Headache


AmateursCTF diff --git a/page/5/index.html b/page/5/index.html index 9b5c3e47..655c03a6 100644 --- a/page/5/index.html +++ b/page/5/index.html @@ -1,4 +1,4 @@ -lavafroth

Kringlecon 2022 Writeup


Binary Exploitation +lavafroth

Kringlecon 2022 Writeup


Binary Exploitation CI Exploitation Cloud Security Cryptography diff --git a/page/6/index.html b/page/6/index.html index 0bf35c1c..8aa78897 100644 --- a/page/6/index.html +++ b/page/6/index.html @@ -1,4 +1,4 @@ -lavafroth

Operation Oni, Operation Orchid


CTF +lavafroth

Operation Oni, Operation Orchid


CTF Forensics PicoCTF The Sleuth Kit diff --git a/post/2-afternoons-2-languages-2-tuis/index.html b/post/2-afternoons-2-languages-2-tuis/index.html index 12bf269f..d5c575ae 100644 --- a/post/2-afternoons-2-languages-2-tuis/index.html +++ b/post/2-afternoons-2-languages-2-tuis/index.html @@ -10,7 +10,7 @@ switching terminal panes and manually issuing a command. The idea is to have a tool running in the background that listens for filesystem events, like when a file gets created or modified, and if the file happens to contain an animation, renders it. On linux systems, it’s mostly a bunch of bindings to inotify but I -have used platform agnostic libraries for both the languages.'>

2 Afternoons, 2 Languages, 2 TUIs

Yesterday I created a tool in Golang to help me render my animations a little +have used platform agnostic libraries for both the languages.'>

2 Afternoons, 2 Languages, 2 TUIs

Yesterday I created a tool in Golang to help me render my animations a little faster. Although the alterior reason was to check my Golang proficiency, today I rewrote it in Rust and I was blown away by the differences in the final products.

When I’m rendering animations for a YouTube video, the general development diff --git a/post/a-sweet-little-config-parser/index.html b/post/a-sweet-little-config-parser/index.html index 7023d253..5c8efd94 100644 --- a/post/a-sweet-little-config-parser/index.html +++ b/post/a-sweet-little-config-parser/index.html @@ -3,7 +3,7 @@ be explanding upon that. I believe that to construct a good grammar, I should be and explain it well. So here goes. General Idea SWHKD’s grammar parser, although similar to tools before it like sxhkd, has a more coherent -syntax. For starters, every binding declaration is one or more accelerators followed by a composite key.'>

A SWEET Little Parser

A few days ago, I had announced my project for this year’s Google Summer of Code. Today I’ll +syntax. For starters, every binding declaration is one or more accelerators followed by a composite key.'>

A SWEET Little Parser

A few days ago, I had announced my project for this year’s Google Summer of Code. Today I’ll be explanding upon that. I believe that to construct a good grammar, I should be able to understand and explain it well. So here goes.

General Idea

SWHKD’s grammar parser, although similar to tools before it like sxhkd, has a more coherent syntax. For starters, every binding declaration is one or more accelerators followed by a composite key.

The line following the binding declaration must be a tab or space indented command to be run by the client.

Here’s a simple example to send a notification to myself using libnotify when I press Super a.

super + a
diff --git a/post/a-tale-of-a-frugal-home-server/index.html b/post/a-tale-of-a-frugal-home-server/index.html
index b96d91a1..50bd6bd9 100644
--- a/post/a-tale-of-a-frugal-home-server/index.html
+++ b/post/a-tale-of-a-frugal-home-server/index.html
@@ -3,7 +3,7 @@ matured enough to be worth talking about.
 At any point, you can check out the source code for the server’s infrastructure here for a concrete example.
 For each service I talk about, I will also link the respective definitions in my config.
 My minimalist mindset has unsurprisingly aided the architecture of my server.
-Throughout the rest of the post, you will come across the following broad strokes:'>

A Tale of a Frugal Home Server

Having run an on-premise server for the past two years, I think my setup has finally +Throughout the rest of the post, you will come across the following broad strokes:'>

A Tale of a Frugal Home Server

Having run an on-premise server for the past two years, I think my setup has finally matured enough to be worth talking about.

At any point, you can check out the source code for the server’s infrastructure here for a concrete example. For each service I talk about, I will also link the respective definitions in my config.

My minimalist mindset has unsurprisingly aided the architecture of my server. Throughout the rest of the post, you will come across the following broad strokes:

  • Easy is not always simple
  • Simple is better than easy
  • There must be one (and exactly one) way of doing something

Hardware

The server is an old laptop which was on the verge becoming e-waste. Despite having a touchscreen diff --git a/post/abstracting-structured-patterns-in-concurrent-programming/index.html b/post/abstracting-structured-patterns-in-concurrent-programming/index.html index e6045d4d..4421601c 100644 --- a/post/abstracting-structured-patterns-in-concurrent-programming/index.html +++ b/post/abstracting-structured-patterns-in-concurrent-programming/index.html @@ -5,7 +5,7 @@ If you have questions or feel that I have missed something, feel free to talk ab In recent months, I have come across multiple articles talking about the need of structured concurrency in modern programming languages as a built-in. Notably, in the article Notes on structured concurrency, or: Go statement considered harmful, the author compares the go statement used to spawn coroutines to goto statements used -for jumping to other parts of code in early languages like COBOL.'>

Abstracting Structured Patterns in Concurrent Programming

I hope this article provides a solid blueprint for building a concurrency management API. +for jumping to other parts of code in early languages like COBOL.'>

Abstracting Structured Patterns in Concurrent Programming

I hope this article provides a solid blueprint for building a concurrency management API. If you have questions or feel that I have missed something, feel free to talk about it in this repository’s issue tracker or the discussion board.

In recent months, I have come across multiple articles talking about the need of structured concurrency in modern programming languages as a built-in. Notably, in the article Notes on structured concurrency, or: Go statement considered harmful, the author compares the go statement used to spawn coroutines to goto statements used diff --git a/post/algebraic-python-enums/index.html b/post/algebraic-python-enums/index.html index 6fbe91f5..470621e5 100644 --- a/post/algebraic-python-enums/index.html +++ b/post/algebraic-python-enums/index.html @@ -9,7 +9,7 @@ versions, most tutorials will suggest Union types as the equivalent to Rust&rsqu enums. I highly encourage you to try out the code snippets and follow along with this article. -Use the collapse explanation button to copy multiple code blocks in one go.'>

Algebraic Python Enums

University has compelled me to use Python despite my preference for Rust, +Use the collapse explanation button to copy multiple code blocks in one go.'>

Algebraic Python Enums

University has compelled me to use Python despite my preference for Rust, primarily due to the machine learning and data science hype. One Rust feature that I dearly miss is enumerable data types that can encapsulate various other data types.

Although Python has the answer to creating structs as diff --git a/post/android-phone-for-webcam-nixos/index.html b/post/android-phone-for-webcam-nixos/index.html index 52c5afff..858ee5b6 100644 --- a/post/android-phone-for-webcam-nixos/index.html +++ b/post/android-phone-for-webcam-nixos/index.html @@ -1,7 +1,7 @@ Using an Android Phone as a webcam in NixOS - lavafroth

Using an Android Phone as a webcam in NixOS

I recently had to attend an online meeting for a software development event. +No, it’s not a close-up of the moon, it’s the refraction caused by the scuffs to the lens plus other sciency stuff I’m not qualified enough to explain to you.'>

Using an Android Phone as a webcam in NixOS

I recently had to attend an online meeting for a software development event. While my PC did have a decent microphone, the built-in camera has been damaged to the extent that the best it can capture is this:

A blurry image taken from my scuffed camera

No, it’s not a close-up of the moon, it’s the refraction caused by the scuffs to the lens plus other sciency stuff I’m not qualified enough to explain to you.

I was aware that one can use ADB to use an Android phone’s camera as a makeshift webcam. Since I would need this ability for any future meetings as well, it was worth having the functionality packaged into a one click tool.

Enter NixOS. I have praised NixOS before and I’ll do it again because of the sheer ease with which it allows me to create desktop entries for small scripts. This is going to be relevant later but I’m going to assume that you’re running NixOS with home-manager enabled if you’re following along. First we have to enable developer mode and USB debugging on our phone.

To interact with our phone, we will need adb and scrcpy as dependencies. If you have enabled flakes run the following:

nix shell nixpkgs#scrcpy nixpkgs#android-tools
diff --git a/post/changing-recents-provider-on-eos/index.html b/post/changing-recents-provider-on-eos/index.html
index 85b105cb..cb87e241 100644
--- a/post/changing-recents-provider-on-eos/index.html
+++ b/post/changing-recents-provider-on-eos/index.html
@@ -7,7 +7,7 @@ Icons can’t be rearranged
 Pull down from top opens search instead of notification shade
 Consumes a lot of RAM
 
-I started using Lawnchair as my default launcher but this did not change the recents provider (quickstep) from BlissLauncher to Lawnchair.'>

Guide: Changing Recents Provider on /e/OS

Overview

Over the past month I have been daily driving my new phone, the Nothing CMF 1 flashed with /e/OS after I unlocked its bootloader. It’s a very pleasant experience except for the default Bliss launcher (home app).

Reasons I do not prefer it:

  • iOS like feel
  • Icons can’t be rearranged
  • Pull down from top opens search instead of notification shade
  • Consumes a lot of RAM

I started using Lawnchair as my default launcher but this did not change the recents provider (quickstep) from BlissLauncher to Lawnchair.

Two problems with this:

  • Bliss has to keep running in the background to act as the recents provider.
  • When the screen is horizontally oriented and gesture navigation is used to go to the home screen, Bliss keeps crashing.

Note for Bliss devs: This behavior only occurs when using a different launcher as default.

I read a post on the forums about replacing Bliss completely but there was no step by step guide. Here, I document the steps I took to get Lawnchair as my default launcher and recents provider.

Guide

This guide assumes you have a basic understanding of adb and fastboot. Ensure that USB debugging is enabled and your device is visible in the output of adb devices.

Apatch

Extracting boot.img

Assuming you have the image used to flash /e/OS on your phone, extract the boot.img from it. This can be done with the 7zip command

7z e IMG-e-3.0.4-a14-20250708507308-official-tetris.zip -o. boot.img
+I started using Lawnchair as my default launcher but this did not change the recents provider (quickstep) from BlissLauncher to Lawnchair.'>

Guide: Changing Recents Provider on /e/OS

Overview

Over the past month I have been daily driving my new phone, the Nothing CMF 1 flashed with /e/OS after I unlocked its bootloader. It’s a very pleasant experience except for the default Bliss launcher (home app).

Reasons I do not prefer it:

  • iOS like feel
  • Icons can’t be rearranged
  • Pull down from top opens search instead of notification shade
  • Consumes a lot of RAM

I started using Lawnchair as my default launcher but this did not change the recents provider (quickstep) from BlissLauncher to Lawnchair.

Two problems with this:

  • Bliss has to keep running in the background to act as the recents provider.
  • When the screen is horizontally oriented and gesture navigation is used to go to the home screen, Bliss keeps crashing.

Note for Bliss devs: This behavior only occurs when using a different launcher as default.

I read a post on the forums about replacing Bliss completely but there was no step by step guide. Here, I document the steps I took to get Lawnchair as my default launcher and recents provider.

Guide

This guide assumes you have a basic understanding of adb and fastboot. Ensure that USB debugging is enabled and your device is visible in the output of adb devices.

Apatch

Extracting boot.img

Assuming you have the image used to flash /e/OS on your phone, extract the boot.img from it. This can be done with the 7zip command

7z e IMG-e-3.0.4-a14-20250708507308-official-tetris.zip -o. boot.img
 

Here IMG-e-3.0.4-a14-20250708507308-official-tetris.zip is the image for my phone. Replace this with the appropriate image name.This extract the boot.img to the current directory.

Push this image to your device with

adb push boot.img /storage/emulated/0/Download/
 

NOTE: You could also push the image over MTP (file transfer) but it may corrupt files and is hence discouraged.

Installing APatch

These instructions are also available in the APatch Docs.

  1. Download the latest version of APatch Manager from GitHub.
  2. Click on the patch button at the top right corner, and click Select a boot image to patch.
  3. Select the boot.img we pushed to the Download directory.
  4. Set a SuperKey at “SuperKey” card. The SuperKey should be 8-63 characters long and include numbers and letters, but no special characters. It will be used later to unlock root privileges.
  5. Click on “Start” and wait for a minute. After the patch is successful, the patched boot.img path will be displayed. For example: /storage/emulated/0/Download/apatch_version_version_randomletter.img.

Flashing

  1. Pull the patched boot.img with the command. Replace apatch_version_version_randomletter.img with the appropriate filename.
adb pull /storage/emulated/0/Download/apatch_version_version_randomletter.img
 
  1. Reboot into fastboot mode.
adb reboot bootloader
diff --git a/post/compact-xor-crypto-challenge-amateursctf-2023/index.html b/post/compact-xor-crypto-challenge-amateursctf-2023/index.html
index 101aaef7..795f2dcd 100644
--- a/post/compact-xor-crypto-challenge-amateursctf-2023/index.html
+++ b/post/compact-xor-crypto-challenge-amateursctf-2023/index.html
@@ -13,7 +13,7 @@ fn main() -> Result<(), Box> {
     println!("{:?}", stream);
     Ok(())
 }
-To execute the code, issue the following.'>

Compact XOR

Description

I found some hex in a file called fleg, but I’m not sure how it’s encoded. I’m pretty sure it’s some kind of xor…

Exploration

We begin by creating a new rust project.

cargo new amateurs
+To execute the code, issue the following.'>

Compact XOR

Description

I found some hex in a file called fleg, but I’m not sure how it’s encoded. I’m pretty sure it’s some kind of xor…

Exploration

We begin by creating a new rust project.

cargo new amateurs
 cd amateurs
 cargo add hex
 cargo add itertools
diff --git a/post/cuda-on-nixos-without-sacrificing-ones-sanity/index.html b/post/cuda-on-nixos-without-sacrificing-ones-sanity/index.html
index a93717e5..600e1d50 100644
--- a/post/cuda-on-nixos-without-sacrificing-ones-sanity/index.html
+++ b/post/cuda-on-nixos-without-sacrificing-ones-sanity/index.html
@@ -8,7 +8,7 @@ TL;DR: Save this flake, run nix develop and setup PyTorch as described
 CUDA is a proprietary vendor lock-in for machine learning folks.
 Training ML models is incredibly fast with CUDA as compared to CPUs due to the parallel
 processing. So if you’re doing something serious, you have no other choice besides CUDA as of writing.
-Although, OpenAI’s Triton and ZLUDA are worth keeping an eye on.'>

Painlessly setting up ML tooling on NixOS

Note: Use the following method only if you wish to have the latest version of CUDA that is +Although, OpenAI’s Triton and ZLUDA are worth keeping an eye on.'>

Painlessly setting up ML tooling on NixOS

Note: Use the following method only if you wish to have the latest version of CUDA that is not yet available in the nix-community cache, otherwise follow this.

TL;DR: Save this flake, run nix develop and setup PyTorch as described

CUDA is a proprietary vendor lock-in for machine learning folks. Training ML models is incredibly fast with CUDA as compared to CPUs due to the parallel processing. So if you’re doing something serious, you have no other choice besides CUDA as of writing. diff --git a/post/detecting-stripped-go-binaries/index.html b/post/detecting-stripped-go-binaries/index.html index 9689816e..11593144 100644 --- a/post/detecting-stripped-go-binaries/index.html +++ b/post/detecting-stripped-go-binaries/index.html @@ -2,7 +2,7 @@ When all else fails, the Go GC provides a few different specific traces that provide much deeper insights into GC behavior. These traces are always printed directly to STDERR, one line per GC cycle, and are configured through the GODEBUG environment variable that all Go programs recognize. -An environment variable that all Go programs recognize, you say? I had a sneaking suspicion that I could just perform a string search for this term, given all Go programs would need to look for this environment variable definition. This way, we could guess if a binary was written in Go.'>

Easy grep to detect stripped Go binaries

A couple of days ago when I was reading the guide to the Go garbage collector, I came across the following excerpt:

When all else fails, the Go GC provides a few different specific traces that provide much deeper insights into GC behavior. These traces are always printed directly to STDERR, one line per GC cycle, and are configured through the GODEBUG environment variable that all Go programs recognize.

An environment variable that all Go programs recognize, you say? I had a sneaking suspicion that I could just perform a string search for this term, given all Go programs would need to look for this environment variable definition. This way, we could guess if a binary was written in Go.

I created a program called hello to test this out. To make sure the binary is stripped, I compiled it with go build -ldflags '-w -s'.

grep GODEBUG hello
+An environment variable that all Go programs recognize, you say? I had a sneaking suspicion that I could just perform a string search for this term, given all Go programs would need to look for this environment variable definition. This way, we could guess if a binary was written in Go.'>

Easy grep to detect stripped Go binaries

A couple of days ago when I was reading the guide to the Go garbage collector, I came across the following excerpt:

When all else fails, the Go GC provides a few different specific traces that provide much deeper insights into GC behavior. These traces are always printed directly to STDERR, one line per GC cycle, and are configured through the GODEBUG environment variable that all Go programs recognize.

An environment variable that all Go programs recognize, you say? I had a sneaking suspicion that I could just perform a string search for this term, given all Go programs would need to look for this environment variable definition. This way, we could guess if a binary was written in Go.

I created a program called hello to test this out. To make sure the binary is stripped, I compiled it with go build -ldflags '-w -s'.

grep GODEBUG hello
 
grep: hello: binary file matches
 

Sure enough, looks like this does provide a decent heuristic for Go programs! Of course, there’s the caveat that another binary can “pretend” to be a Go binary by simply having this string present in it.

We could try this technique with other environment variables like GOGC, available in all binaries and GOMEMLIMIT, available for Go 1.19 and up.

So if you have a hunch that a binary is written in Go 1.19 and above, try grepping with all the aforementioned variables.

grep -P '(GOGC|GOMEMLIMIT|GODEBUG)' hello
 

Ok bye.