Hidden Poetry in Juniper's Junos

Oh Junos, oh Junos! Show me your poems!§

Much like many other bored programmers slaving away at their keyboards, Juniper Developers that work on Junos decided to add a few easter eggs.

One of which is rather commonly known, but one I believe to have found that isn't widely known, if known at all.

show version and haiku§

This one is the well known one. Just log on to any Junos device and and run that command and you'll be greeted with something like the following:

[email protected]> show version and haiku
Hostname: asprey.dh.blinken.space
Model: srx345
Junos: 22.1R1.10
JUNOS Software Release [22.1R1.10]


        IS-IS screams,
        BGP peers are flapping:
        I want my mommy!

Heh! I feel that.

Run it again, get a different Haiku!

How many are there? Certainly not gonna brute force that.

Where are the Haikus?§

Finding all of them wasn't that easy, actually.

First, I started by looking where the strings are located. That part's easy!

% grep -R "IS-IS screams" /
<snip>
Binary file /usr/lib/dd/libjunos-actions-impl.so matches
<snip>

Argh. Of course it's compiled into a binary.

After a minute long look with radare2, I figured out that they were just plain strings in the binary, stored line by line. After failing to find the reference to that string because I held radare wrong, I passed the binary over to a close friend of mine, Fridtjof, because he actually knows what he's doing. Though he used IDA, which made the whole thing rather painless.

The interesting part is just a bunch of pointers in an array named haiku_text. Three elements per Haiku, one for each line. Duh.

Displaying quotes The UNIX Way™!§

After reading through all of them and laughing very hard, I decided that I wanna put the haikus in a more accessible format.

Luckily, there is just the program for that: fortune(6)! First appearing in Version 7 UNIX, it's been showing people quotes, jokes and poetry since 1979!

It's using a simple database generated by strfile(8), which you can find in /usr/src/games/fortune/strfile on OpenBSD, as instructed by fortune(6).

The format is quite simple! It's just text, seperated by lines with just % in it.

vifino: mind if i quote you as an example of... quotes?
Stary: do it
vifino: thx
%
android is just boneless linux
                -- Stary, 2022

Afterwards, you can punch this theoretical my_quotes file through strfile(8) and you get my_quotes.dat. Then you can just run fortune my_quotes while being in that directory or install it to directory that contains the other fortune databases, on OpenBSD it is /usr/share/games/fortune/.

Fortune-ized Haikus§

After a little bit of magic with radare2, I came up with the following command.

r2 -a x86 -b 32 -qq \
    -c "s \`is ~ haiku_text[2]\`; ps @@= \`pxWq \$fl-4\`" \
    libjunos-actions-impl.so | \
    awk -v n=3 "1; NR % n == 0 { printf \"\t\t-- Junos 'show version and haiku'\n%\n\" }" \
    > junos_haiku
strfile junos_haiku

Yeah, it's not that easy, but basically, the following happens:

  1. Open libjunos-actions-impl.so as x86 32bit. (I stole this binary from a Juniper MX)
  2. Seek (s) to the address of symbol haiku_text (is ~ haiku_text[2]). It's an array with a fixed length containing pointers to strings, as mentioned earlier.
  3. Print a Zero-Terminated string (ps) located at every address described by the hex word dump (pxWq) from the current address (where we seeked to) for the length of the flag ($fl).
  4. With awk(1), print a small quote origin text followed by the seperator % every three lines.
  5. Convert it into a database fortune(6) can use with strfile(8).

Now, this is everything but intiuitive, however with the steep learning curve from both awk(1) and (even more so) radare2 comes great rewards like this.

And as strfile(8) proudly explains, there are 37 Haikus in Junos 22.1:

"junos_haiku.dat" created
There were 37 strings
Longest string: 133 bytes
Shortest string: 85 bytes

But wait, there is more!

show version and limerick§

While looking for the haikus, we actually found a lot more interesting strings.

In addition to haiku_text, there is lim_text. It didn't take me long to add that up.

[email protected]> show version and limerick
Hostname: asprey.dh.blinken.space
Model: srx345
Junos: 22.1R1.10
JUNOS Software Release [22.1R1.10]


        there once was a tool named CLI
        that terminal users would try
        they'd type out commands
        while wringing their hands
        and yell "it's pronounced C-L-I"

A Limerick! And a nice one, too.

Seemingly unknown to the internet, show version and limerick exists. Hereby, I claim to be the first one to announce finding it, 2022-06-12. :)

And thus, like with the Haiku array, the same thing for limericks, only with 5 lines per limerick:

r2 -a x86 -b 32 -qq \
    -c "s \`is ~ lim_text[2]\`; ps @@= \`pxWq \$fl-4\`" \
    libjunos-actions-impl.so | \
    awk -v n=5 "1; NR % n == 0 { printf \"\t\t-- Junos 'show version and limerick'\n%\n\" }" \
    > junos_limerick
strfile junos_limerick

And with the last line, strfile(8) announces there are 13 limericks hidden in Junos 22.1!

"junos_limerick.dat" created
There were 13 strings
Longest string: 195 bytes
Shortest string: 153 bytes

So long, and thanks for all the fish!§

Without a doubt there are more eastereggs in Junos. And I hope they keep adding more poetry! :)

Again, Fridtjof was a huge help in all of this. Without him, this would've taken a lot longer. You're awesome!

And Stary for letting me quote them, mainly. You're also awesome.

EDIT: Yes, Kate, you are awesome too.