From 202d50be92c4e14aa81044d227c55513b420a37d Mon Sep 17 00:00:00 2001 From: Charlotte Som Date: Fri, 20 Mar 2026 05:00:43 +0000 Subject: [PATCH] nix + spruce up --- cv.typ | 81 +++++++++++++++++++++++++++++------------------------- flake.lock | 27 ++++++++++++++++++ flake.nix | 26 ++++++++++++++++++ layout.typ | 68 +++++++++++++++++++++++++++------------------ 4 files changed, 137 insertions(+), 65 deletions(-) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/cv.typ b/cv.typ index 9f16f1a..96b6a53 100644 --- a/cv.typ +++ b/cv.typ @@ -2,7 +2,7 @@ #show: doc => cv( name: "Charlotte Som", - tagline: "Systems programmer, videogame cheat developer, reverse engineer, multispecialist.", + tagline: [Systems programmer, videogame cheat developer, #linebreak() reverse engineer, multispecialist.], links: ( (icon: "email", link: "mailto:charlotte@som.codes", text: "charlotte@som.codes"), (icon: "github", link: "https://github.com/char", text: "@char"), @@ -13,6 +13,16 @@ ) #grid(columns: (1fr, 2fr), column-gutter: 1cm, [ +== Writing + +#article(title: "Circumventing the JVM Classfile Verifier", date: 2019, url: "som.codes/jvm-force-no-verify") +#divider() +#article(title: "Game Science: GTA V's Stunt Jumps", date: 2021, url: "som.codes/gta-v-stunt-jumps") +#divider() +#article(title: "Circumventing Cisco Duo's Authenticator App", date: 2021, url: "som.codes/cisco-duo-bypass") +#divider() +#article(title: "Extracting API Keys from a Minecraft Launcher", date: 2022, url: "som.codes/mmc-msaclientid") + == Competitions #event[Google Hash Code 2020][Google][February 2020][] @@ -36,79 +46,74 @@ Participated as a university team of six. #divider() -#event[BLÅHAJ CTF Team][][2021 -- Present][] - -Casual infosec competition team. Since I joined: +#event[BLÅHAJ CTF Team][][2021 -- 2022][] - *Hack-A-Sat 2 CTF*: Organised by the _US Air Force & US Space Force_. Placed 15#super[th] out of 697 teams. - *corCTF 2021*: Placed 11#super[th] out of 904 teams. -== Writing - -#article(title: "Circumventing the JVM Classfile Verifier", date: 2019, url: "som.codes/jvm-force-no-verify") -#divider() -#article(title: "Reverse Engineering GTA V's Stunt Jumps", date: 2021, url: "hackery.site/writing/gta-v-stunt-jumps") -#divider() -#article(title: "Circumventing Cisco Duo's Authenticator App", date: 2021, url: "som.codes/cisco-duo-bypass") -#divider() -#article(title: "Extracting API Keys from a Minecraft Launcher", date: 2022, url: "som.codes/mmc-msaclientid") +== Languages +- *English* (native, primary) +- *French* (maternal) +- *Spanish* (since 2013) +- *Korean* (since 2016) ], [ == Experience #event[Multiplayer game technology][WorldQL Corporation][April 2022 -- Present][] -I currently work at WorldQL, building technology to reduce the barrier between singleplayer and multiplayer game development techniques. +I currently work at WorldQL, where the mission is to reduce the barrier between singleplayer and multiplayer game development. -The work is varied and has involved machine learning models, image processing pipelines, high-performance networking software, and 3D programming. +Here, I've worked on EVM-based transaction processing / smart contracts (writing a hot wallet transaction scheduler in Rust), +written a multiplayer web game engine in TypeScript (with several interesting netcode paradigms) & backend web services in Rust +(at one point embedding `deno_core` in a Rust application for sandboxed multitenant user code exec on the server-side) +as well as a (Git-based) beginner-oriented version control system. -I mainly work with *Rust*, *TypeScript*, *Python*, *PyTorch*, *CUDA*, and *ONNX*. +To facilitate prototype art we also experimented with Blender automation and machine learning in production, +so I've also written & deployed Python / CUDA / ONNX backed services. #divider() -#event[Game modding / game-hacking][Self-employed][2016 -- Present][] +#event[Game modding / game-hacking][Self-employed][2016 -- 2025][] -- _GTA Online_: *C++*, Rust -- _Minecraft_: *Java*, Kotlin, Scala, JVM Bytecode -- _Counter-Strike: Global Offensive_: *C++*, Rust -- Various Unity3D: *C\#*, .NET MSIL, C++ (for `il2cpp` games) +- _GTA Online_: C++ (primarily), Rust +- _Minecraft_: Java, Kotlin (primarily), Scala, JVM Bytecode +- _Counter-Strike: Global Offensive_: C++ (primarily), Rust +- Unity3D (various): C\# (primarily), .NET MSIL, and C++ (for `il2cpp` games) -Professionally, I used to sell a custom client for Minecraft +In my teens, I used to sell a custom client for Minecraft (5-figure USD revenue from 2016 -- 2019), -and a subscription trainer menu for GTA Online -(4-figure annually recurring USD revenue until 2020). +and a subscription trainer menu for GTA Online. #divider() #event(company_newline: true)[Commercial obfuscator for JVM programs][paramorphism.dev (Self-employed)][2017 -- 2022][] -Java bytecode is one of my specialist areas. +This solo project involved writing the product itself, internal tooling around JVM bytecode to aid debugging, +and the sales site in SvelteKit (then-_Sapper_, actually). -Involved writing the product itself and internal tooling around JVM bytecode to aid debugging. -Working primarily with *Kotlin* and *Java*. - -- _Paramorphism_: Bytecode obfuscator for JVM programs written in *Kotlin*. +- _Paramorphism_: Bytecode obfuscator for JVM programs written in Kotlin. - _libparamorphism_: Optional native runtime opaque library for programs - obfuscated by Paramorphism written in *Zig* and *Rust*. -- _Koffee_: Domain-specific language for *Kotlin* for Java classfile generation. -- _Aksara_ (internal): Bytecode assembly language and assembly/disassembly toolchain written in *Kotlin*. -- _Katon_ (internal): Bytecode viewer and editor with a GUI written in *Rust* and interfacing via *Java Native Interface* to *Kotlin* (_Aksara_) and *Java* (_Fernflower_). + obfuscated by Paramorphism written in Rust first and then Zig later. +- _Koffee_: Domain-specific language for Kotlin for Java classfile generation. +- _Aksara_ (internal): Bytecode assembly language and assembly/disassembly toolchain written in Kotlin. +- _Katon_ (internal): Bytecode viewer and editor with a GUI written in Rust and interfacing via Java Native Interface to Kotlin (_Aksara_) and Java (_Fernflower_). +- _Citadel_: An experimental custom-instruction-set VM with a _libparamorphism_-backed native executor (+ some compilers), focusing on self-modifying code. #divider() #event["Splashforce"][Force Software LLC][November 2020 -- October 2021][] -At Force Software, I was a "Software developer and strategy coordinator". -The flagship "Splashforce" product is an end-user e-commerce automation suite +The flagship "Splashforce" product was an end-user e-commerce automation suite for various sneaker sites. My duties included: - `cronet`: Custom patches for & isolation of Chromium's HTTP stack. (To evade TLS fingerprinting.) -- Pairing an Electron (node.js / web *JavaScript*) frontend to a *Go* backend. -- Anti-piracy, reverse-engineer-deterrent releases for the *Go* backend. +- Pairing an Electron (node.js / web JavaScript) frontend to a Go backend. +- Anti-piracy, reverse-engineer-deterrent releases for the Go backend. (Code virtualization, `cgo` FFI bindings, etc.). - Reverse engineering bot protection measures on websites. -- Reverse engineering & circumventing bot prevention measures on Android apps. (*Java*, *Smali*, etc). +- Reverse engineering & circumventing bot prevention measures on Android apps. (Java, Smali, etc). ]) #pagebreak() diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..d98f5a2 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1773628058, + "narHash": "sha256-hpXH0z3K9xv0fHaje136KY872VT2T5uwxtezlAskQgY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f8573b9c935cfaa162dd62cc9e75ae2db86f85df", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..40c8dc4 --- /dev/null +++ b/flake.nix @@ -0,0 +1,26 @@ +{ + description = "Typst CV document"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + }; + + outputs = + { self, nixpkgs }: + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + in + { + devShells.${system}.default = pkgs.mkShell { + packages = with pkgs; [ + typst + inter + ]; + + shellHook = '' + export TYPST_FONT_PATHS="${pkgs.inter}/share/fonts:/x/fonts/tx02" + ''; + }; + }; +} diff --git a/layout.typ b/layout.typ index 3f816fc..615a9d9 100644 --- a/layout.typ +++ b/layout.typ @@ -15,7 +15,7 @@ accent: rgb("#870c66"), heading_font: "Inter", body_font: "Inter", - mono_font: "BerkeleyMono", + mono_font: "TX-02", doc, ) = { set text(size: 9pt, font: body_font, weight: "medium") @@ -54,32 +54,46 @@ block[#it] ) - [= #name] - - text( - font: body_font, - fill: accent, - size: 1.2em, - weight: "semibold", - block[#{tagline}] - ) - - v(-0.5em) - - links.map(l => { - link(l.link)[ - #set text(weight: "medium") - #icon(l.icon) - #if "text" in l.keys() { l.text } else { l.link } - ] - h(1em) - }).join() + [ + #grid( + columns: (1fr, 1fr), + gutter: 1em, + { + [= #name] + + text( + font: body_font, + size: 1em, + block[#{tagline}] + ) + }, + [ + #box[ + #h(4em) + #grid( + columns: 2, + gutter: 0.75em, + ..links.map(l => { + [#h(2em)] + link(l.link)[ + #set text(weight: "medium") + #icon(l.icon) + #if "text" in l.keys() { l.text } else { l.link } + ] + }) + ) + ] + ] + ) + ] doc } #let divider(accent: rgb("#870c66")) = { + v(-0.25em) line(length: 100%, stroke: (paint: accent, thickness: 1pt, dash: "dotted")) + v(-0.25em) } #let event( @@ -117,16 +131,16 @@ #text(weight: "semibold")[ #text(size: 1.2em)["#title"] ]\ - #text(size: 0.85em, style: "italic", weight: "bold", tracking: -0.025em, fill: accent)[ - #icon("link", shift: 0.25em) - #h(-0.25em) - #link("https://" + url)[#url] - ] - #v(-0.85em) #text(size: 0.85em, style: "italic", weight: "semibold", tracking: -0.025em)[ #icon("calendar", shift: 0.15em) #h(0.1em) #date ] + #h(0.75em) + #text(size: 0.85em, style: "italic", weight: "bold", tracking: -0.025em, fill: accent)[ + #icon("link", shift: 0.25em) + #h(-0.25em) + #link("https://" + url)[#url] + ] ] ]