aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README173
1 files changed, 173 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..db08afe
--- /dev/null
+++ b/README
@@ -0,0 +1,173 @@
+ _ _ _
+ | | | | | |
+ | |__ | |_ _ ___ __| |_ __ ___ __ _ _ __ ___
+ | '_ \| | | | |/ _ \/ _` | '__/ _ \/ _` | '_ ` _ \
+ | |_) | | |_| | __/ (_| | | | __/ (_| | | | | | |
+ |_.__/|_|\__,_|\___|\__,_|_| \___|\__,_|_| |_| |_|
+
+================================================================================
+
+ i went on a [47d1] and all i got was this lousy vscode worm...
+
+ (or)
+
+ i tried to write a README and all i got was this lousy writeup
+
+ NOTE: some of this writeup had to be redacted for, uh, reasons. any redactions
+ will be replaced with a relevant sha256 tag, which will be expanded at
+ the end of the file. example: [480b2b30]
+
+ INTRO
+ late one night, i had an idea. 'memba xcodeghost? pepperidge farm
+ remembers. what about vscodeghost? except, instead of infecting *OS apps,
+ it infects vscode. hmm?
+
+ it's a vscode worm. alice installs an infected extension, and any
+ extensions (packaged or minified) become infected. once uploaded to the
+ marketplace, or otherwise distributed, each install becomes a new alice.
+
+ i will readily admit that i [084a1631cd59ed1a3244305b6fbc28a2d93c97a7df]
+
+ this worm was written over the course of a 3-week [47d1] in which i
+ [e6400ef383e6509261b52d3f16e466752487a27e19d0579a3eb5567bb7244055]. lmao
+
+ it was bad... [e2b5ed016720f26e10bc200c8c528241298f9a64db8559b9ad8276b8]
+ shit. [affa8bd6c29038c52a423488d1b037615d7bb8a8384736d46837c662887303f]...
+ i know i gotta sleep in a few hours. welp. note from future spv: you're a
+ dick. it's half past 2 and i'm copy editing your shit. fuck you. <3
+
+ with that out of the way, let's begin with the writeup & description. i
+ think the only real way to do this is to go through the architecture
+ first. otherwise idk that any of this will make sense. it took me a couple
+ readthroughs of the source to understand what the fuck was going on...
+
+ ARCHITECTURE
+ bluedream is made up of two interlinked components, with separate
+ directories for each. cnc holds the command-and-control server, with inf
+ containing the src for the local infection, and its custom build system.
+ these components will be referred to by their respective directory names,
+ cnc, and inf.
+
+ inf is built by build_payload.js & gen_pwnage.js. build_payload is
+ passed a payload descriptor (pd) file, which contains a reference to each
+ JS file to be included. this allows one to easily configure of the exact
+ features of a payload. build_payload also requires the specification of an
+ output file, to which the payload, minified & brotli compressed, will be
+ written.
+
+ after this, gen_pwnage wraps the payload. to ease identification of the
+ infection, as will be described in detail further on. in the end, one will
+ be left with inf.
+
+ cnc is also a custom job. cnc accepts a block descriptor (bd) file,
+ which is used to serve different payloads to different victims. a bd file
+ is composed of one or more entries of the form
+ `(ip)[/(block_size)]:(payload)[,(script)]`. any ip within said block will
+ be served the payload specified, with the script (if) specified being ran
+ upon each serving.
+
+ with the basics of bluedream's architecture covered, let's get into the
+ nitty-griddy details of what makes her tick.
+
+ TICK TICK TICK
+ inf runs every time an infected extension is triggered, often at
+ startup. upon being triggered, inf phones home to cnc at most once a day,
+ which provides an updated copy of inf. after this, it spreads to any files
+ in the workspace which contain (compiled) extension code. following this,
+ inf spreads to all other currently installed extensions, in case the
+ original vector is removed. lastly, inf will spread to any packaged
+ extensions in the current workspace.
+
+ in the following sections, we will discuss in (potentially excruciating)
+ detail, how each of these vectors of spread work.
+
+ SENTINELS
+ the packaged infection is stored within extensions. much like a
+ biological virus, it needs a host. to separate inf from the legitimate
+ code, two markers are used. the specifics do not matter, but my commie ass
+ used /*瑲慮猠*/ and /*物杨瑳*/. these are entirely gibberish Chinese characters.
+
+ however, pipe them into a hex dump, and they are -- still garbage.
+ codepoints, though? U+7472, U+616E, etc. interesting. interpret UTF-16 as
+ ASCII, and they spell out "trans rights" :P
+
+ THE MINI
+ extensions are fun things. while you may write your neat and clean
+ typescript, at the end of the day, it's javascript all the way down... and
+ because we decided to take a technology hacked together in under two weeks
+ and use it to power the entire fucking internet and most user-facing
+ applications, we developed minification. even then, discord takes up
+ ~100MB because it's its own damned chromium install... i fucking hate
+ javascript.
+
+ minification also provides some convenience for malware developers, like
+ us. several megabyte, one line, obfuscated javascript isn't "a major cause
+ for concern", it's just "webpack"! yay!
+
+ we pick a spot to insert inf. either between two lines of typescript
+ boilerplate, in a known location for webpack, or just at the end. this
+ procedure is used to infect all extensions -- including local output
+ files, as in `extension_js_spread`, local extension persistence as in
+ `extension_spread`, and packaged extensions as in `vsix_spread`. what is a
+ vsix, anyway?
+
+ WHAT IS A VSIX, ANYWAY?
+ vscode uses the vsix format to package extensions. vsix is, in essence,
+ a glorified zip file. the relevant files for this writeup being
+ extension.vsixmanifest, extension/package.json*, and
+ extension/out/extension.js*.
+
+ a vsixmanifest is an XML-formatted file that is, (i believe), used in
+ both visual studio, and vscode. the relevant key in this file is
+ "Microsoft.VisualStudio.Code.Manifest", which points at the package.json.
+
+ within package.json, the key "main" points at the javascript code ran
+ when the extension is triggered. with this knowledge, we are able to use
+ the procedure described in THE MINI in order to pwn packaged extensions.
+ the only difference being that we need logic to process zip files. the
+ relevant code is in inf/mal/spread/vsix.js. this is a combination of YAZL,
+ and an utterly nightmarish artisan-rolled zip file parser that to cope
+ with imma need some artisan-rolled shit of my own...
+
+ *these are the file names by convention. they do not technically have to
+ be present at these particular locations.
+
+ CONCLUSION(s)
+ what would have stopped this attack from working? for one, signing
+ vscode extensions upon packaging would have helped. vsce, the main tool
+ used to package (, and often publish) vscode extensions, has had a github
+ issue for this very topic since july of 2017. vscode never implemented
+ support, though. [vsce_issue]
+
+ i recall reading that extensions are signed upon being uploaded to the
+ marketplace, but this would not prevent this attack, as extensions are
+ already pwned by the time they're sent to the marketplace.
+
+ and lastly, you are not an APT. sorry. this worm was written over the
+ course of a 3 week [47d1] -- a coping mechanism after some interpersonal
+ termoil, in which i experienced such delusions of grandeur that i
+ genuinely believed that this worm was my golden ticket -- that i would be
+ set for life, money wise. this is of course, utterly laughable. i threw
+ away the plan immediately after deployment anyway, as i had recently
+ [82821f1ccb55943a67b2d7689e08f7c6e548d3778b0835d2d0eebaf43c81e2bd], and i
+ proceeded to [1c747f5c1eac42e9eb77c538a4f77b3b4c18b0bd8ce62dc88637e585a2].
+
+ SHA_TAGS
+ ==========
+ 084a1631cd59ed1a3244305b6fbc28a2d93c97a7df8dc117c90955a728b00d35
+ 1c747f5c1eac42e9eb77c538a4f77b3b4c18b0bd8ce62dc88637e585a2701298
+ 47d140cbea401190e9612d5c7e3bd78a5fbb63def20832036a1b2c4fbbac636b
+ 480b2b30b0c14c30d3f130561a44c77cba580910d2789593e4e379c2d26bc3f8
+ 82821f1ccb55943a67b2d7689e08f7c6e548d3778b0835d2d0eebaf43c81e2bd
+ affa8bd6c29038c52a423488d1b037615d7bb8a8384736d46837c662887303f9
+ e2b5ed016720f26e10bc200c8c528241298f9a64db8559b9ad8276b859a660ac
+ e6400ef383e6509261b52d3f16e466752487a27e19d0579a3eb5567bb7244055
+
+
+ OG: 6628738fac546ec9cf6193e2b3ab753e11f62f4fff8348ee4e0f499e00167210
+
+ LINKS
+ =======
+ vsce_issue: https://github.com/Microsoft/vscode-vsce/issues/191
+
+ ~ spv, 2025. \ No newline at end of file