fixup content, add callout shortcode
This commit is contained in:
parent
056ffa2d81
commit
bc2f0fcb81
|
@ -1,4 +1,5 @@
|
|||
---
|
||||
title: Beets and Soulseek Or, How I Learned to Give Up and Love The Hoard
|
||||
date: 2025-02-03
|
||||
draft: true
|
||||
---
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: Reversing an image format
|
||||
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,
|
||||
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.
|
||||
|
||||
|
||||
# Introduction
|
||||
|
||||
*[ITAR]: International Traffic in Arms Regulations
|
||||
|
@ -19,16 +19,19 @@ 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,
|
||||
but
|
||||
|
||||
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. Therefore I wanted one that could be used in a dedicated fashion. The PC
|
||||
I got 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
|
||||
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.
|
||||
|
||||
For that reason, the Hikmicro line of portable imagers interested me. It's more expensive than the whitelabel Infiray
|
||||
products, but offers some pretty nice looking PC software and uses a Radiometric JPEG image format for data.
|
||||
Live USB is advertized and it supposedly also delivers radiometry over the USB (!). This is on
|
||||
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
|
||||
and there is no reverse engineering project that exists already, so we'll have to start from scratch.
|
||||
For that reason, the Hikmicro line of portable imagers interested me. It's more
|
||||
expensive than the whitelabel Infiray products, but offers some pretty nice
|
||||
looking PC software and uses a Radiometric JPEG image format for data.They
|
||||
advertise Live USB video and it supposedly also delivers radiometry over the
|
||||
USB (!). This is on 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 and there is no
|
||||
reverse engineering project that exists already, so we'll have to start from
|
||||
scratch.
|
||||
|
||||
|
||||
# Getting the picture
|
||||
|
|
|
@ -4,13 +4,16 @@ date: 2025-04-17
|
|||
tags: NixOS
|
||||
---
|
||||
|
||||
Note: this post assumes familiarity with the Nix Ecosystem.
|
||||
{% callout %}
|
||||
This post assumes familiarity with the Nix ecosystem.
|
||||
{% endcallout %}
|
||||
|
||||
Nix and NixOS make managing servers much easier than bespoke scripts or
|
||||
complex Ansible playbooks. While I don't think NixOS is ready for
|
||||
personal computers, it absolutely makes sense on less dynamic devices
|
||||
like servers or embedded-ish machines.
|
||||
|
||||
|
||||
We can use NixOS and nixpkgs to derive a fully defined operating system and services.
|
||||
Then, we can:
|
||||
|
||||
|
@ -19,7 +22,7 @@ Then, we can:
|
|||
- 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
|
||||
and push-deployments. `deploy-rs` is a glorified `nix copy` with some extra magic
|
||||
and push-deployments. `deploy-rs` is like `nix profile` with helper scripts
|
||||
to "activate" the copied closure. Activation typically means running `home-manager switch`
|
||||
or switching the NixOS profile.
|
||||
|
||||
|
@ -37,46 +40,60 @@ 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
|
||||
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.
|
||||
This method also ties sysadmin-tasks to our blog, which isn't keeping our concerns separate.
|
||||
|
||||
# Scaffolding the Solution
|
||||
|
||||
Let's recap:
|
||||
|
||||
1. Build the site using a nix derivation
|
||||
2. 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. Configure `nginx` to serve from this well known path.
|
||||
2. Configure `nginx` to serve from a well-known path (`/var/lib/site/public`)
|
||||
3. Copy the derivation to a server using a locked down non-root account.
|
||||
4. Symlink `/var/lib/site/public` to our static site in the nix store.
|
||||
|
||||
I'll do it manually to get an idea of how it should work.
|
||||
|
||||
## nix build blog
|
||||
|
||||
I build my blog using [11ty](https://www.11ty.dev), and I use `npm run build` to generate
|
||||
the static sources. Nix supports building npm-like packages with `buildNpmPackage`, which
|
||||
uses a [Fixed-output 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 `$out`. I need to add `vips` and `pkg-config` as well because 11ty processes my images.
|
||||
I build my blog using [11ty](https://www.11ty.dev), and I use `npm run build`
|
||||
to generate the static sources. Nix supports building npm-like packages with
|
||||
`buildNpmPackage`. This uses a [Fixed-output
|
||||
derivation](https://nix.dev/manual/nix/2.28/store/derivation/outputs/content-address#fixed)
|
||||
to store the dependencies of the project if it is stored elsewhere, but I found
|
||||
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:
|
||||
|
||||
```nix
|
||||
default = pkgs.buildNpmPackage {
|
||||
{
|
||||
nodejs,
|
||||
pkg-config,
|
||||
buildNpmPackage,
|
||||
importNpmLock,
|
||||
vips,
|
||||
}: buildNpmPackage {
|
||||
name = "myblog";
|
||||
version = "unstable";
|
||||
buildInputs = with pkgs; [
|
||||
buildInputs = [
|
||||
nodejs
|
||||
vips
|
||||
];
|
||||
nativeBuildInputs = with pkgs; [
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
];
|
||||
npmDepsHash = "sha256-Q7rhCjAPPn44DyUZ/uoD+7o4XH33IATfL+v1azEhuW0=";
|
||||
npmDeps = importNpmLock {
|
||||
npmRoot = ./.;
|
||||
};
|
||||
npmConfigHook = importNpmLock.npmConfigHook;
|
||||
src = ./.;
|
||||
installPhase = ''
|
||||
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.
|
||||
|
@ -109,9 +126,14 @@ module that will set this up:
|
|||
# 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.
|
||||
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:
|
||||
```nix
|
||||
|
@ -172,8 +194,9 @@ ln -sn $PROFILE/public /var/lib/static-site/public
|
|||
|
||||
Then when deploying with `deploy-rs`:
|
||||
|
||||
```
|
||||
error: cannot add path '/nix/store/2sad737aglfzmil72phv0j8s34zzmvzi-myblog' because it lacks a signature by a trusted key
|
||||
```bash
|
||||
error: cannot add path '/nix/store/2sad737aglfzmil72phv0j8s34zzmvzi-myblog'
|
||||
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
|
||||
|
@ -182,17 +205,14 @@ the nix store. We have two options:
|
|||
1. Make `static-site` a trusted user
|
||||
2. Create a trusted keypair to sign our closure when it's built.
|
||||
|
||||
Pick your poison - the keypair mechanism is slightly more secure.
|
||||
Pick your poison - the keypair mechanism is more secure, as it means that
|
||||
the `static-site` user can't upload arbitrary packages.
|
||||
|
||||
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
|
||||
[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.
|
||||
|
||||
Regardless of the outcome you choose, when you re-deploy, it should work properly.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Let's follow the symlink.
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
---
|
||||
title: Zig is Dark Souls
|
||||
description: This is both good and bad.
|
||||
|
|
|
@ -145,6 +145,14 @@ export default async function (eleventyConfig) {
|
|||
//eleventyConfig.addPairedShortcode("section", async (content, transition = "none") => {
|
||||
// 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)
|
||||
|
||||
|
|
26
package.nix
Normal file
26
package.nix
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
nodejs,
|
||||
pkg-config,
|
||||
buildNpmPackage,
|
||||
importNpmLock,
|
||||
vips,
|
||||
}: buildNpmPackage {
|
||||
name = "myblog";
|
||||
version = "unstable";
|
||||
buildInputs = [
|
||||
nodejs
|
||||
vips
|
||||
];
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
];
|
||||
npmDeps = importNpmLock {
|
||||
npmRoot = ./.;
|
||||
};
|
||||
npmConfigHook = importNpmLock.npmConfigHook;
|
||||
src = ./.;
|
||||
installPhase = ''
|
||||
mkdir -p $out/public
|
||||
cp -ar _site/* $out/public/
|
||||
'';
|
||||
}
|
|
@ -7,16 +7,41 @@
|
|||
|
||||
/* Theme colors */
|
||||
: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-50: #C0C0C0;
|
||||
--color-gray-90: #333;
|
||||
|
||||
--background-color: #fff;
|
||||
--background-color: var(--color-white);
|
||||
|
||||
--text-color: var(--color-gray-90);
|
||||
--text-color-link: #082840;
|
||||
--text-color-link-active: #5f2b48;
|
||||
--text-color-link-visited: #17050F;
|
||||
--text-color-link: var(--color-cyan);
|
||||
--text-color-link-active: var(--color-cyan-bright);
|
||||
--text-color-link-visited: var(--color-cyan);
|
||||
|
||||
--syntax-tab-size: 2;
|
||||
}
|
||||
|
@ -26,13 +51,16 @@
|
|||
--color-gray-20: #e0e0e0;
|
||||
--color-gray-50: #C0C0C0;
|
||||
--color-gray-90: #dad8d8;
|
||||
--background-color: var(--color-black);
|
||||
|
||||
/* --text-color is assigned to --color-gray-_ above */
|
||||
--text-color-link: #1493fb;
|
||||
--text-color-link-active: #6969f7;
|
||||
--text-color-link-visited: #a6a6f8;
|
||||
/* --text-color-link: #1493fb; */
|
||||
/* --text-color-link-active: #6969f7; */
|
||||
/* --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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,6 +173,9 @@ pre:not([class*="language-"]) {
|
|||
}
|
||||
code {
|
||||
word-break: break-all;
|
||||
|
||||
color: var(--color-black);
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
/* Header */
|
||||
|
@ -277,3 +308,45 @@ h1, h2, h3 {
|
|||
font-family: WO3;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,3 +21,6 @@ nixpkgs?
|
|||
NixOS
|
||||
|
||||
keypair
|
||||
|
||||
whitelabel
|
||||
|
||||
|
|
Loading…
Reference in a new issue