1
0
Fork 0

Compare commits

..

No commits in common. "521af2d17abadfc2118c1d374eb6f95452afd82b" and "056ffa2d818b9aa87886e7195574f7ef36d18723" have entirely different histories.

9 changed files with 68 additions and 199 deletions

View file

@ -1,5 +1,4 @@
--- ---
title: Beets and Soulseek Or, How I Learned to Give Up and Love The Hoard title: Beets and Soulseek Or, How I Learned to Give Up and Love The Hoard
date: 2025-02-03 date: 2025-02-03
draft: true
--- ---

View file

@ -1,14 +1,14 @@
--- ---
title: Reversing an image format title: Reversing an image format
date: 2025-01-15 date: 2025-01-15
tags: [reverse-engineering, hacking-hikmicro] tags: reverse-engineering, hacking-hikmicro
drafts: true
--- ---
This post is the first in a series on reverse engineering binary file formats using an array of tools, This post is the first in a series on reverse engineering binary file formats using an array of tools,
mainly to serve as insight into how to approach these kinds of challenges as they can be daunting. mainly to serve as insight into how to approach these kinds of challenges as they can be daunting.
Part one focuses on the image format. Part one focuses on the image format.
# Introduction # Introduction
*[ITAR]: International Traffic in Arms Regulations *[ITAR]: International Traffic in Arms Regulations
@ -19,19 +19,16 @@ to a host of other companies (TOPDON, Vevor, HTI, UNI-T) to relabel and sell und
form factors: Phone add-on and gun-grip unit. Existing work has documented and reverse-engineered the phone communication protocols, form factors: Phone add-on and gun-grip unit. Existing work has documented and reverse-engineered the phone communication protocols,
but but
I got burned once by the phone-dongle style before with Seek Thermal. Simply put, the pace of smartphones is longer than I've been burned once by the phone-dongle style before with Seek Thermal. Simply put, the pace of smartphones is longer than
the target lifespan of these products. This time, I wanted one that was standalone. The PC the target lifespan of these products. Therefore I wanted one that could be used in a dedicated fashion. The PC
connectivity was still important to me, since there are certain operations that can only be done with access to raw connectivity was still important to me, since there are certain operations that can only be done with access to raw
data, like Lock-In Thermography. data, like Lock-In Thermography.
For that reason, the Hikmicro line of portable imagers interested me. It's more For that reason, the Hikmicro line of portable imagers interested me. It's more expensive than the whitelabel Infiray
expensive than the whitelabel Infiray products, but offers some pretty nice products, but offers some pretty nice looking PC software and uses a Radiometric JPEG image format for data.
looking PC software and uses a Radiometric JPEG image format for data.They Live USB is advertized and it supposedly also delivers radiometry over the USB (!). This is on
advertise Live USB video and it supposedly also delivers radiometry over the top of being a standalone unit so you don't need to use an odd phone app. However this choice seems less popular on forums
USB (!). This is on top of being a standalone unit so you don't need to use an and there is no reverse engineering project that exists already, so we'll have to start from scratch.
odd phone app. However this choice seems less popular on forums and there is no
reverse engineering project that exists already, so we'll have to start from
scratch.
# Getting the picture # Getting the picture

View file

@ -4,16 +4,13 @@ date: 2025-04-17
tags: NixOS tags: NixOS
--- ---
{% callout %} Note: this post assumes familiarity with the Nix Ecosystem.
This post assumes familiarity with the Nix ecosystem.
{% endcallout %}
Nix and NixOS make managing servers much easier than bespoke scripts or Nix and NixOS make managing servers much easier than bespoke scripts or
complex Ansible playbooks. While I don't think NixOS is ready for complex Ansible playbooks. While I don't think NixOS is ready for
personal computers, it absolutely makes sense on less dynamic devices personal computers, it absolutely makes sense on less dynamic devices
like servers or embedded-ish machines. like servers or embedded-ish machines.
We can use NixOS and nixpkgs to derive a fully defined operating system and services. We can use NixOS and nixpkgs to derive a fully defined operating system and services.
Then, we can: Then, we can:
@ -22,7 +19,7 @@ Then, we can:
- push the new configuration to a remote server using [deploy-rs]() - push the new configuration to a remote server using [deploy-rs]()
The latter is interesting. With a bit of setup, we can do GitOps with rollback The latter is interesting. With a bit of setup, we can do GitOps with rollback
and push-deployments. `deploy-rs` is like `nix profile` with helper scripts and push-deployments. `deploy-rs` is a glorified `nix copy` with some extra magic
to "activate" the copied closure. Activation typically means running `home-manager switch` to "activate" the copied closure. Activation typically means running `home-manager switch`
or switching the NixOS profile. or switching the NixOS profile.
@ -40,60 +37,46 @@ And then have `nginx` use `/home/blog/_site/` as the site root. This works, but
Other users have tied their blog to the NixOS system-level configuration, like [this user](https://jeancharles.quillet.org/posts/2023-08-01-Deploying-a-static-website-with-nix.html). While I think this Other users have tied their blog to the NixOS system-level configuration, like [this user](https://jeancharles.quillet.org/posts/2023-08-01-Deploying-a-static-website-with-nix.html). While I think this
is a good solution, it has the issue of relying on root access for updating the site. is a good solution, it has the issue of relying on root access for updating the site.
To me, this feels excessive. I should be able to deploy my site from a lesser-privileged user. To me, this feels excessive. I should be able to deploy my site from a lesser-privileged user.
This method also ties sysadmin-tasks to our blog, which isn't keeping our concerns separate.
# Scaffolding the Solution # Scaffolding the Solution
Let's recap: Let's recap:
1. Build the site using a nix derivation 1. Build the site using a nix derivation
2. Configure `nginx` to serve from a well-known path (`/var/lib/site/public`) 2. Copy the derivation to a server using a locked down non-root account.
3. Copy the derivation to a server using a locked down non-root account. 3. Create well-known path that points to the latest version of the site in the nix store.
4. Symlink `/var/lib/site/public` to our static site in the nix store. 4. Configure `nginx` to serve from this well known path.
I'll do it manually to get an idea of how it should work. I'll do it manually to get an idea of how it should work.
## nix build blog ## nix build blog
I build my blog using [11ty](https://www.11ty.dev), and I use `npm run build` I build my blog using [11ty](https://www.11ty.dev), and I use `npm run build` to generate
to generate the static sources. Nix supports building npm-like packages with the static sources. Nix supports building npm-like packages with `buildNpmPackage`, which
`buildNpmPackage`. This uses a [Fixed-output uses a [Fixed-output derivation](https://nix.dev/manual/nix/2.28/store/derivation/outputs/content-address#fixed)
derivation](https://nix.dev/manual/nix/2.28/store/derivation/outputs/content-address#fixed) to store the dependencies of the project. Then, for the `installPhase`, we just copy the built contents
to store the dependencies of the project if it is stored elsewhere, but I found to `$out`. I need to add `vips` and `pkg-config` as well because 11ty processes my images.
a better method that imports the `package.lock` directly. Then, for the
`installPhase`, we just copy the built contents to `$out`. I need to add `vips`
and `pkg-config` as well because 11ty processes my images. You should add any
other tools you'd need to build your site.
The end result looks like this: The end result looks like this:
```nix ```nix
{ default = pkgs.buildNpmPackage {
nodejs,
pkg-config,
buildNpmPackage,
importNpmLock,
vips,
}: buildNpmPackage {
name = "myblog"; name = "myblog";
version = "unstable"; version = "unstable";
buildInputs = [ buildInputs = with pkgs; [
nodejs nodejs
vips vips
]; ];
nativeBuildInputs = [ nativeBuildInputs = with pkgs; [
pkg-config pkg-config
]; ];
npmDeps = importNpmLock { npmDepsHash = "sha256-Q7rhCjAPPn44DyUZ/uoD+7o4XH33IATfL+v1azEhuW0=";
npmRoot = ./.;
};
npmConfigHook = importNpmLock.npmConfigHook;
src = ./.; src = ./.;
installPhase = '' installPhase = ''
mkdir -p $out/public mkdir -p $out/public
cp -ar _site/* $out/public/ cp -ar _site/ $out/public
''; '';
} };
``` ```
Then, running `nix build` I get my site files in `result/public`, which is what we want. Then, running `nix build` I get my site files in `result/public`, which is what we want.
@ -126,14 +109,9 @@ module that will set this up:
# TODO: write this # TODO: write this
``` ```
Now we have a scoped user, with an ssh key authorized. It needs a shell so we can actually log
in remotely.
The last step is creating that symlink. This is where the concept of "activation" comes into play. The last step is creating that symlink. This is where the concept of "activation" comes into play.
For NixOS, `deploy-rs` activation just calls `switch-to-configuration` to make the system change the profile.
We can effectively do whatever we want here.
For NixOS, `deploy-rs` activation just calls `switch-to-configuration` to make
the system change the profile. We can effectively do whatever we want here.
Reading the [custom activator](https://github.com/serokell/deploy-rs/blob/aa07eb05537d4cd025e2310397a6adcedfe72c76/flake.nix#L58C13-L96C17) source: Reading the [custom activator](https://github.com/serokell/deploy-rs/blob/aa07eb05537d4cd025e2310397a6adcedfe72c76/flake.nix#L58C13-L96C17) source:
```nix ```nix
@ -194,9 +172,8 @@ ln -sn $PROFILE/public /var/lib/static-site/public
Then when deploying with `deploy-rs`: Then when deploying with `deploy-rs`:
```bash ```
error: cannot add path '/nix/store/2sad737aglfzmil72phv0j8s34zzmvzi-myblog' error: cannot add path '/nix/store/2sad737aglfzmil72phv0j8s34zzmvzi-myblog' because it lacks a signature by a trusted key
because it lacks a signature by a trusted key
``` ```
Drat. This makes sense though, since it would be a bit dangerous to allow any old user write access to Drat. This makes sense though, since it would be a bit dangerous to allow any old user write access to
@ -205,14 +182,17 @@ the nix store. We have two options:
1. Make `static-site` a trusted user 1. Make `static-site` a trusted user
2. Create a trusted keypair to sign our closure when it's built. 2. Create a trusted keypair to sign our closure when it's built.
Pick your poison - the keypair mechanism is more secure, as it means that Pick your poison - the keypair mechanism is slightly more secure.
the `static-site` user can't upload arbitrary packages.
I just want to get this working, so I made `static-site` a trusted user. I just want to get this working, so I made `static-site` a trusted user.
Note that if you wanted to use the keypair instead, `deploy-rs` has a Note that if you wanted to use the keypair instead, `deploy-rs` has a
[secret environment variable](https://github.com/serokell/deploy-rs/blob/aa07eb05537d4cd025e2310397a6adcedfe72c76/src/push.rs#L131) [secret environment variable](https://github.com/serokell/deploy-rs/blob/aa07eb05537d4cd025e2310397a6adcedfe72c76/src/push.rs#L131)
called `LOCAL_KEY` which is a file that contains the signing key. called `LOCAL_KEY` which is a file that contains the signing key.
Regardless of the outcome you choose, when you re-deploy, it should work properly.
Let's follow the symlink.

View file

@ -1,3 +1,4 @@
--- ---
title: Zig is Dark Souls title: Zig is Dark Souls
description: This is both good and bad. description: This is both good and bad.

View file

@ -145,14 +145,6 @@ export default async function (eleventyConfig) {
//eleventyConfig.addPairedShortcode("section", async (content, transition = "none") => { //eleventyConfig.addPairedShortcode("section", async (content, transition = "none") => {
// return `<section data-transition=${transition}> ${mdIt.renderInline(content)} </section>`; // return `<section data-transition=${transition}> ${mdIt.renderInline(content)} </section>`;
//}) //})
//
// Paired shortcode for callout
eleventyConfig.addPairedShortcode("callout", function(content) {
// The 'content' variable holds the text/HTML placed between
// {% callout %} and {% endcallout %}
// We wrap it with our div structure.
return `<div class="callout">${content}</div>`;
});
// Features to make your build faster (when you need them) // Features to make your build faster (when you need them)

View file

@ -16,21 +16,29 @@
)); ));
in { in {
apps = forAllSystems (pkgs: { packages = forAllSystems (pkgs: rec {
"deploy" = { default = pkgs.buildNpmPackage {
type = "app"; name = "myblog";
program = let version = "unstable";
ci = (pkgs.writeShellApplication { buildInputs = with pkgs; [
name = "ci.sh"; nodejs
text = '' vips
nix build ];
''; nativeBuildInputs = with pkgs; [
}); pkg-config
in "${ci}/ci.sh"; ];
# npmDepsHash = "sha256-rMU1q2BPvPihovOyjbCezd1UyEODSrtCLr9TJedOVl0=";
npmDeps = pkgs.importNpmLock {
npmRoot = ./.;
};
npmConfigHook = pkgs.importNpmLock.npmConfigHook;
src = ./.;
installPhase = ''
mkdir -p $out/public
cp -ar _site/* $out/public/
'';
}; };
});
packages = forAllSystems (pkgs: {
default = pkgs.callPackage ./package.nix {};
}); });
deploy.nodes.myblog = { deploy.nodes.myblog = {
hostname = "saji.dev"; hostname = "saji.dev";

View file

@ -1,32 +0,0 @@
{
nodejs,
pkg-config,
buildNpmPackage,
importNpmLock,
vips,
lib,
}: buildNpmPackage {
name = "myblog";
version = "unstable";
buildInputs = [
];
nativeBuildInputs = [
pkg-config
nodejs
vips
];
npmDeps = importNpmLock {
npmRoot = ./.;
};
npmConfigHook = importNpmLock.npmConfigHook;
src = ./.;
installPhase = ''
mkdir -p $out/public
cp -ar _site/* $out/public/
'';
meta = {
description = "My blog, yay";
homepage = "https://saji.dev";
platforms = lib.platforms.all;
};
}

View file

@ -7,41 +7,16 @@
/* Theme colors */ /* Theme colors */
:root { :root {
--color-black: #000000;
--color-black-bright: #5a4e51;
--color-red: #cf5080;
--color-red-bright: #e26b95;
--color-green: #7b8d39;
--color-green-bright: #8fa445;
--color-yellow: #b57235;
--color-yellow-bright: #cf8544;
--color-blue: #3c8cbf;
--color-blue-bright: #4fa1d7;
--color-magenta: #9468d8;
--color-magenta-bright: #a782e5;
--color-cyan: #a782e5;
--color-cyan-bright: #47ac9b;
--color-white: #c2bdbd;
--color-white-bright: #ffffff;
--color-gray-20: #e0e0e0; --color-gray-20: #e0e0e0;
--color-gray-50: #C0C0C0; --color-gray-50: #C0C0C0;
--color-gray-90: #333; --color-gray-90: #333;
--background-color: var(--color-white); --background-color: #fff;
--text-color: var(--color-gray-90); --text-color: var(--color-gray-90);
--text-color-link: var(--color-cyan); --text-color-link: #082840;
--text-color-link-active: var(--color-cyan-bright); --text-color-link-active: #5f2b48;
--text-color-link-visited: var(--color-cyan); --text-color-link-visited: #17050F;
--syntax-tab-size: 2; --syntax-tab-size: 2;
} }
@ -51,16 +26,13 @@
--color-gray-20: #e0e0e0; --color-gray-20: #e0e0e0;
--color-gray-50: #C0C0C0; --color-gray-50: #C0C0C0;
--color-gray-90: #dad8d8; --color-gray-90: #dad8d8;
--background-color: var(--color-black);
/* --text-color is assigned to --color-gray-_ above */ /* --text-color is assigned to --color-gray-_ above */
/* --text-color-link: #1493fb; */ --text-color-link: #1493fb;
/* --text-color-link-active: #6969f7; */ --text-color-link-active: #6969f7;
/* --text-color-link-visited: #a6a6f8; */ --text-color-link-visited: #a6a6f8;
--text-color-link: var(--color-cyan);
--text-color-link-active: var(--color-cyan-bright);
--text-color-link-visited: var(--color-cyan);
--background-color: #15202b;
} }
} }
@ -173,9 +145,6 @@ pre:not([class*="language-"]) {
} }
code { code {
word-break: break-all; word-break: break-all;
color: var(--color-black);
background-color: var(--color-white);
} }
/* Header */ /* Header */
@ -308,45 +277,3 @@ h1, h2, h3 {
font-family: WO3; font-family: WO3;
letter-spacing: .1rem; letter-spacing: .1rem;
} }
/* Callout styles */
.callout {
padding: 2em; /* Adjust padding as needed */
position: relative; /* Needed for positioning pseudo-elements */
border: none; /* Ensure no default border */
margin: 1em 0; /* Add some margin for spacing */
overflow: hidden; /* Prevents pseudo-elements from causing scrollbars if they slightly exceed bounds */
}
.callout p {
margin: 0; /* Remove default paragraph margin inside callout */
}
/* Top-left corner bracket */
.callout::before {
content: '';
position: absolute;
top: 0.5em; /* Adjust position */
left: 0.5em; /* Adjust position */
width: 1.5em; /* Adjust size */
height: 1.5em; /* Adjust size */
border-top: 3px solid #ffffff; /* White border, adjust thickness */
border-left: 3px solid #ffffff; /* White border, adjust thickness */
box-sizing: border-box;
}
/* Bottom-right corner bracket */
.callout::after {
content: '';
position: absolute;
bottom: 0.5em; /* Adjust position */
right: 0.5em; /* Adjust position */
width: 1.5em; /* Adjust size */
height: 1.5em; /* Adjust size */
border-bottom: 3px solid #ffffff; /* White border, adjust thickness */
border-right: 3px solid #ffffff; /* White border, adjust thickness */
box-sizing: border-box;
}

View file

@ -21,6 +21,3 @@ nixpkgs?
NixOS NixOS
keypair keypair
whitelabel