8 ms·
Anguish: Invisible Programming Language and Invisible Data Theft
- _kst_ 10y agoIt uses "U+FEFF ZERO WIDTH NO-BREAK SPACE", also known as "BYTE ORDER MARK" -- which means that an Anguish program that starts with that character might not survive translation to or from UTF-16.
- Null-Set 10y agoBuries the lede. The interesting part is the abuse of invisible characters to sneak malicious code into pull requests. The language is just a cute transliteration of brainfuck to use invisible zero width characters.
- gwern 10y agoYeah, I was like 'well, that's kinda amusing' and then I saw the screenshot of the diff and went 'AHHHHH!!!' The worst part is, it's totally plausible. 'What's with the whitespace changes in your patch?' 'You had some trailing whitespace in there so my text editor automatically cleaned it up.'
- detaro 10y agoDiff views probably should replace invisible characters with visible place-holder glyphs. Is that something that can be done on a font level, or does it require extra code? As in, can I assign a glyph to an RTL mark and have it automatically show up?
- dang 10y agoSince the article's title doesn't have that weakness and should have been used anyhow, we'll use it. (Submitted title was "Anguish: A language written in zero-width characters".) Anyone who uses 'lede' correctly gets express treatment here...
- labster 10y agoI chose that title because "invisible" has a lot of meanings and "zero-width" is more precise here. Brainfuck is an invisible language -- and so is COBOL because so few people think about its widespread use today.
- function_seven 10y agoTrue, but your title leaves out the important part, the data theft POC.
- danharaj 10y ago> Anyone who uses 'lede' correctly gets express treatment here... is that a hint of weariness? :3
- deleted 10y ago[deleted]
- Twirrim 10y agoThis is delightfully evil
- undershirt 10y ago"Hush" immediately came to mind as a useful name for an invisible language.
- solox3 10y agogit makes Anguish code look more readable than the rest of the file: http://imgur.com/AHavQor http://imgur.com/AHavQor
- vsviridov 10y agoThis look like vi, which is probably the default $EDITOR, git defers to.
- lolc 10y agoUnicode has stubbornly refused to become Turing complete. Will it ever be more than a bunch of character tables? I think Unicode Emoji were a great step forward but we must redouble our efforts.
- ChristianBundy 10y agoI genuinely can't decide whether or not this is sarcasm.
- unimpressive 10y agoIt's sarcasm.
- TazeTSchnitzel 10y agoUnicode could be a stack machine. Implementing bi-directional text already requires a stack which can be pushed onto and popped from (https://en.wikipedia.org/wiki/Bi-directional_text#Unicode_bidi_support https://en.wikipedia.org/wiki/Bi-directional_text#Unicode_bi...), we just need to add more operations!
- yigitozkavci 10y agoHmm. Readability is high on this one.
- Bromskloss 10y agoYes, very transparent!
- jegoodwin3 10y agoIt also has the interesting property that all the programs are quines except those that print themselves. In other words, the programs are quines if and only if they aren't. Androids dream of quined Anguish.
- renownedmedia 10y agoThis is nothing more than a string replace on top of Brainfuck.
- ChrisClark 10y agoIn the first half of the article. The real reason for the post is in the second half, and the actual scary part that could affect developers.
- danra 10y agoSomeone needs to make a script which runs through a git repo's commit history and looks for commits which add invisible Unicode characters. Maybe some existing exploits could be found in the wild.
- vvanders 10y agoWow, that's truly evil. Would other languages like Ruby that support overloads like that be susceptible(I'm no Ruby expert)?
- Freaky 10y agoYou can name methods invisible unicode characters so calling them is basically invisible. Quick example: https://gist.github.com/Freaky/51086f3c97784bdd6dfbd31913cd1af3 https://gist.github.com/Freaky/51086f3c97784bdd6dfbd31913cd1... You don't need to use define_method, it just makes it more obvious what's going on.
- geofft 10y agoAt first glance, I'd consider it a (security) bug in Perl 6 that it permits tokens containing invisible characters, let alone consisting solely of invisible characters. Are there any other languages with this behavior? As a random example: titan:~ geofft$ python3 -c "$(printf "\u2063") = 1" File "<string>", line 1 = 1 ^ SyntaxError: invalid character in identifier If you change it to e.g. 00e9 ("é"), Python 3 permits the character, so it's not just a lower-ASCII thing.
- kbenson 10y agoWhat about carriage return. newline,form feed, etc? Those are invisible character, and those are just plain ASCII.
- chias 10y agoThose aren't invisible, merely transparent: they take up space, and alter the location of the cursor when inserted. Invisible characters don't.
- logfromblammo 10y agoAlso, some text-displaying programs will insert glyphs for them, to make them visible, which would make them somewhat more detectable. And the BEL character, while non-spacing and invisible, is sometimes audible.
- geofft 10y agoThose aren't valid tokens. "<newline> = 10" won't assign to a variable named <newline>. If the language wants to parse non-ASCII invisible characters as whitespace, or permit them inside comments or strings, that's fine.
- labster 10y agohttps://rt.perl.org/Public/Bug/Display.html?id=128159 https://rt.perl.org/Public/Bug/Display.html?id=128159 was filed by the author of this piece. The take-home to me is that supporting Unicode to a great depth in a language is really hard.
- zimbatm 10y agoThis is the next generation of shell code right there. Why try to obfuscate programs in base64-encoded strings when you have it invisibly lying around in plain light.
- Retr0spectrum 10y agoHere's one I made earlier: alert(String.fromCharCode.apply(null,String.fromCharCode.apply(null,"".split("").map(function(c){return(c.charCodeAt(0)>>2)^2098})).match(/.{8}/g).map(function(c){return parseInt(c,2)})))
- pairoffeet 10y agoLua, or at least LuaJIT, allows these characters to be used as identifiers, which has led to some pretty interesting looking obfuscated code: https://facepunch.com/showthread.php?t=1463260&p=47712658&viewfull=1#post47712658 https://facepunch.com/showthread.php?t=1463260&p=47712658&vi...
- sillysaurus3 10y agoThe following code uses this technique. It's valid Lua. If you highlight this and copy it to your system clipboard, running `pbpaste | luajit` will count to 5 three times: =print =function() for =1,5 do () end end ((()))
- gleenn 10y agoHmmm, running pasted code that is explicitly obfuscated from the internet probably isn't a great idea.
- sillysaurus3 10y agoIndeed not, but it's pretty amazing that it's copy-pastable via HN.
- allthetime 10y agotrue, but in this case, the invisible characters are simply names and the rest is verifiably benign code. It's not like we're copy pasting a binary or anything.
- sillysaurus3 10y agoI've been thinking of ways to make it seem like verifiably benign code, while doing something "interesting." For example: print("") This is benign, but that's not an empty string. The string contains a bunch of U+200e and U+200f characters, even though it appears empty. It proves that you can have strings with invisible characters in them. Since we have two types of invisible characters, U+200e and U+200f, we can use those as binary digits -- 1 and 0. Thus, we can write a function that takes an invisible string as input, and returns a normal string as output. So, what kind of string could we feed it? One possibility would be to convert something like "echo 'command-line injection'" into an invisible string. We'd pass that into our decoder function, and pass the result into os.execute. Since the conversion function mentioned above can be identified with an invisible variable name, it would look similar to this: os.execute(("")) That looks very suspicious, but we can do better. In Lua, you can index into tables with strings. And we have a function which can take invisible strings and produce normal strings. The final PoC could look similar to this: _G[(""))][(""))]((""))) That's non-working code, as I haven't put this together. But the idea is to convert the following (working) code into invisible strings: _G["os"]["execute"]("echo 'command-line injection'") Making this work is left as an exercise for the reader. :) Another interesting approach would be to iterate through the "os" table a fixed number of times, until reaching the "execute" key. The iteration order isn't guaranteed, but given a certain version of LuaJIT, I think it's stable. That means you'd be able to do the equivalent of "os.execute" while making it look like you're "counting to 5."
- gohrt 10y agoThe language is perfect for literate programming. All human-readable characters are comments by default, so you can write completely human-friendly prose, and make the machine-readable content invisible to humans.
- jegoodwin3 10y agoOr you could put the comments in the invisible fork and pass a Turing test. 'I passed the Turing test. No one believed me. Honest.' passes Turing test by sounding like a petulant child
- krylon 10y agoThis is probably a stupid question, but could somebody explain to me why one would add invisible characters to Unicode?
- nine_k 10y agoFor instance, Zero-width spaces and other word-break characters can help reasonable text layout, but should be invisible. RTL and LTR marks help rendering text of different directionality, but obviously need to be invisible.
- krylon 10y agoThanks!
- astrobe_ 10y agoBecause a character encoding standard is considered worthless if you can't make ANSI bombs with it...
- tshtf 10y agoIgnorable (invisible) unicode characters have caused security vulnerabilities in the past, especially on HFS+ filesystems running on OS X (due to normalization): * https://git-blame.blogspot.com.es/2014/12/git-1856-195-205-214-and-221-and.html https://git-blame.blogspot.com.es/2014/12/git-1856-195-205-2... * https://www.cvedetails.com/cve/CVE-2013-0966/ https://www.cvedetails.com/cve/CVE-2013-0966/
- yokohummer7 10y agoIt might be useful to have an option to turn all the "non-obvious" Unicode characters into the form of <U+XXXX> in programming editors. One concern is that some legitimate text will break, but it would be worth it considering most code is written in English anyways.
- chungy 10y agoIt's trivial to convert between this and regular Brainfuck syntax: just replace characters. The article even gives an example using a Perl one-liner :) Revision: I believe I misinterpreted the intention of your post, instead wanting to expose tricks like these. I'd be fine with this.
- LionessLover 10y agoJetbrains: "Zero Width Characters locator" plugin (https://plugins.jetbrains.com/plugin/7448 https://plugins.jetbrains.com/plugin/7448)
- jlg23 10y agoZero-width unicode chars have been used in exploit kits for a while now; just use hd (or something similar) when debugging.
- deleted 10y ago[deleted]
- hollander 10y agoWhere is this more dangerous, on the web or in Github and open source programming?