Podcast #128: We chat with Kent C Dodds about why he loves React and discuss what life was like in the dark days before Git. Listen now.
9 added 14 characters in body
source | link

To obtain this memory address, we can use multi-character character constants (mccc), which exhibit implementation-defined behavior. 0x400243 is (64)(2)(67) / @\2C in base 256 and gcc's mcccsmulti-character character constants use big-endian byte order, so `'@\2C''@\2C' yields the memory locationaddress of the desired string.

To obtain this memory address, we can use multi-character character constants (mccc), which exhibit implementation-defined behavior. 0x400243 is (64)(2)(67) / @\2C in base 256 and gcc's mcccs use big-endian byte order, so `'@\2C' yields the memory location of the desired string.

To obtain this memory address, we can use multi-character character constants, which exhibit implementation-defined behavior. 0x400243 is (64)(2)(67) in base 256 and gcc's multi-character character constants use big-endian byte order, so '@\2C' yields the memory address of the desired string.

8 added 4816 characters in body
source | link

Try it online!Try it online!

Different platforms will require a different memory address and possibly a different order for the bytes in the multi-character character constant.

For example, replacing @\2C with @\2\4 prints exec/ld-elf.so.1 and a newline on FreeBSD 11 with clang 3.8.0.

How it works

By default, ld uses 0x400000 as the base address of the text segment, meaning that we can find the ELF's content starting at memory address 0x400000.

The first 640 bytes of the ELF are largely independent of the actual source code. For example, if the declaration of f is followed by main(){f();} and nothing else, they look as follows.

00000000: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  .ELF............
00000010: 02 00 3e 00 01 00 00 00 00 04 40 00 00 00 00 00  ..>.......@.....
00000020: 40 00 00 00 00 00 00 00 e8 19 00 00 00 00 00 00  @...............
00000030: 00 00 00 00 40 00 38 00 09 00 40 00 1e 00 1b 00  ....@.8...@.....
00000040: 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00  ........@.......
00000050: 40 00 40 00 00 00 00 00 40 00 40 00 00 00 00 00  @.@.....@.@.....
00000060: f8 01 00 00 00 00 00 00 f8 01 00 00 00 00 00 00  ................
00000070: 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00  ................
00000080: 38 02 00 00 00 00 00 00 38 02 40 00 00 00 00 00  8.......8.@.....
00000090: 38 02 40 00 00 00 00 00 1c 00 00 00 00 00 00 00  8.@.............
000000a0: 1c 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
000000b0: 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00  ................
000000c0: 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00  ..@.......@.....
000000d0: 04 07 00 00 00 00 00 00 04 07 00 00 00 00 00 00  ................
000000e0: 00 00 20 00 00 00 00 00 01 00 00 00 06 00 00 00  .. .............
000000f0: 08 0e 00 00 00 00 00 00 08 0e 60 00 00 00 00 00  ..........`.....
00000100: 08 0e 60 00 00 00 00 00 1c 02 00 00 00 00 00 00  ..`.............
00000110: 20 02 00 00 00 00 00 00 00 00 20 00 00 00 00 00   ......... .....
00000120: 02 00 00 00 06 00 00 00 20 0e 00 00 00 00 00 00  ........ .......
00000130: 20 0e 60 00 00 00 00 00 20 0e 60 00 00 00 00 00   .`..... .`.....
00000140: d0 01 00 00 00 00 00 00 d0 01 00 00 00 00 00 00  ................
00000150: 08 00 00 00 00 00 00 00 04 00 00 00 04 00 00 00  ................
00000160: 54 02 00 00 00 00 00 00 54 02 40 00 00 00 00 00  T.......T.@.....
00000170: 54 02 40 00 00 00 00 00 44 00 00 00 00 00 00 00  T.@.....D.......
00000180: 44 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00  D...............
00000190: 50 e5 74 64 04 00 00 00 b0 05 00 00 00 00 00 00  P.td............
000001a0: b0 05 40 00 00 00 00 00 b0 05 40 00 00 00 00 00  ..@.......@.....
000001b0: 3c 00 00 00 00 00 00 00 3c 00 00 00 00 00 00 00  <.......<.......
000001c0: 04 00 00 00 00 00 00 00 51 e5 74 64 06 00 00 00  ........Q.td....
000001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000001f0: 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00  ................
00000200: 52 e5 74 64 04 00 00 00 08 0e 00 00 00 00 00 00  R.td............
00000210: 08 0e 60 00 00 00 00 00 08 0e 60 00 00 00 00 00  ..`.......`.....
00000220: f8 01 00 00 00 00 00 00 f8 01 00 00 00 00 00 00  ................
00000230: 01 00 00 00 00 00 00 00 2f 6c 69 62 36 34 2f 6c  ......../lib64/l
00000240: 64 2d 6c 69 6e 75 78 2d 78 38 36 2d 36 34 2e 73  d-linux-x86-64.s
00000250: 6f 2e 32 00 04 00 00 00 10 00 00 00 01 00 00 00  o.2.............
00000260: 47 4e 55 00 00 00 00 00 02 00 00 00 06 00 00 00  GNU.............
00000270: 20 00 00 00 04 00 00 00 14 00 00 00 03 00 00 00   ...............

Using, e.g., main(int c, char**v){f();} instead changes some bytes, but not the offset of the string /lib64/ld-linux-x86-64.so.2, which we'll use to produce output.

The offset of said string is 0x238 and it is 27 bytes long. We only want to print 17 bytes (and the last one will be a newline if we use puts), so we add 11 to the offset to get 0x243, the offset of inux-x86-64.so.2. Adding 0x400000 and 0x243 gives 0x400243, the memory location of inux-x86-64.so.2.

To obtain this memory address, we can use multi-character character constants (mccc), which exhibit implementation-defined behavior. 0x400243 is (64)(2)(67) / @\2C in base 256 and gcc's mcccs use big-endian byte order, so `'@\2C' yields the memory location of the desired string.

Finally, puts prints the (null-terminated) sting at that memory location and a trailing newline, creating 17 bytes of output.

Try it online!

Try it online!

Different platforms will require a different memory address and possibly a different order for the bytes in the multi-character character constant.

For example, replacing @\2C with @\2\4 prints exec/ld-elf.so.1 and a newline on FreeBSD 11 with clang 3.8.0.

How it works

By default, ld uses 0x400000 as the base address of the text segment, meaning that we can find the ELF's content starting at memory address 0x400000.

The first 640 bytes of the ELF are largely independent of the actual source code. For example, if the declaration of f is followed by main(){f();} and nothing else, they look as follows.

00000000: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  .ELF............
00000010: 02 00 3e 00 01 00 00 00 00 04 40 00 00 00 00 00  ..>.......@.....
00000020: 40 00 00 00 00 00 00 00 e8 19 00 00 00 00 00 00  @...............
00000030: 00 00 00 00 40 00 38 00 09 00 40 00 1e 00 1b 00  ....@.8...@.....
00000040: 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00  ........@.......
00000050: 40 00 40 00 00 00 00 00 40 00 40 00 00 00 00 00  @.@.....@.@.....
00000060: f8 01 00 00 00 00 00 00 f8 01 00 00 00 00 00 00  ................
00000070: 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00  ................
00000080: 38 02 00 00 00 00 00 00 38 02 40 00 00 00 00 00  8.......8.@.....
00000090: 38 02 40 00 00 00 00 00 1c 00 00 00 00 00 00 00  8.@.............
000000a0: 1c 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
000000b0: 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00  ................
000000c0: 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00  ..@.......@.....
000000d0: 04 07 00 00 00 00 00 00 04 07 00 00 00 00 00 00  ................
000000e0: 00 00 20 00 00 00 00 00 01 00 00 00 06 00 00 00  .. .............
000000f0: 08 0e 00 00 00 00 00 00 08 0e 60 00 00 00 00 00  ..........`.....
00000100: 08 0e 60 00 00 00 00 00 1c 02 00 00 00 00 00 00  ..`.............
00000110: 20 02 00 00 00 00 00 00 00 00 20 00 00 00 00 00   ......... .....
00000120: 02 00 00 00 06 00 00 00 20 0e 00 00 00 00 00 00  ........ .......
00000130: 20 0e 60 00 00 00 00 00 20 0e 60 00 00 00 00 00   .`..... .`.....
00000140: d0 01 00 00 00 00 00 00 d0 01 00 00 00 00 00 00  ................
00000150: 08 00 00 00 00 00 00 00 04 00 00 00 04 00 00 00  ................
00000160: 54 02 00 00 00 00 00 00 54 02 40 00 00 00 00 00  T.......T.@.....
00000170: 54 02 40 00 00 00 00 00 44 00 00 00 00 00 00 00  T.@.....D.......
00000180: 44 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00  D...............
00000190: 50 e5 74 64 04 00 00 00 b0 05 00 00 00 00 00 00  P.td............
000001a0: b0 05 40 00 00 00 00 00 b0 05 40 00 00 00 00 00  ..@.......@.....
000001b0: 3c 00 00 00 00 00 00 00 3c 00 00 00 00 00 00 00  <.......<.......
000001c0: 04 00 00 00 00 00 00 00 51 e5 74 64 06 00 00 00  ........Q.td....
000001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000001f0: 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00  ................
00000200: 52 e5 74 64 04 00 00 00 08 0e 00 00 00 00 00 00  R.td............
00000210: 08 0e 60 00 00 00 00 00 08 0e 60 00 00 00 00 00  ..`.......`.....
00000220: f8 01 00 00 00 00 00 00 f8 01 00 00 00 00 00 00  ................
00000230: 01 00 00 00 00 00 00 00 2f 6c 69 62 36 34 2f 6c  ......../lib64/l
00000240: 64 2d 6c 69 6e 75 78 2d 78 38 36 2d 36 34 2e 73  d-linux-x86-64.s
00000250: 6f 2e 32 00 04 00 00 00 10 00 00 00 01 00 00 00  o.2.............
00000260: 47 4e 55 00 00 00 00 00 02 00 00 00 06 00 00 00  GNU.............
00000270: 20 00 00 00 04 00 00 00 14 00 00 00 03 00 00 00   ...............

Using, e.g., main(int c, char**v){f();} instead changes some bytes, but not the offset of the string /lib64/ld-linux-x86-64.so.2, which we'll use to produce output.

The offset of said string is 0x238 and it is 27 bytes long. We only want to print 17 bytes (and the last one will be a newline if we use puts), so we add 11 to the offset to get 0x243, the offset of inux-x86-64.so.2. Adding 0x400000 and 0x243 gives 0x400243, the memory location of inux-x86-64.so.2.

To obtain this memory address, we can use multi-character character constants (mccc), which exhibit implementation-defined behavior. 0x400243 is (64)(2)(67) / @\2C in base 256 and gcc's mcccs use big-endian byte order, so `'@\2C' yields the memory location of the desired string.

Finally, puts prints the (null-terminated) sting at that memory location and a trailing newline, creating 17 bytes of output.

7 added 235 characters in body
source | link

C (gcc), 18 17 bytes

f(){puts('@C');}

Note that there's an STX byte (0x02) between @ and C.

Try it online!

Portability

This has been tested with gcc 6.3.1 and clang 3.9.1 on Fedora 25, gcc 4.8.4 on Ubuntu 14.04.4, and gcc 4.8.3 on openSUSE 13.2, where it prints the following output.

inux-x86-64.so.2

Try it online! I expect this to produce the same output with all versions of gcc, as long as it compiles to an executable of the following type.

ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2

Offline verification

$ printf "%b\n" "f(){puts('@\2C');}main(){f();}" > quine.c
$ gcc -w -o quine quine.c
$ ./quine
inux-x86-64.so.2
$ ./quine | wc -c
17

C (gcc), 18 17 bytes

f(){puts('@C');}

Note that there's an STX byte (0x02) between @ and C.

This has been tested with gcc 6.3.1 and clang 3.9.1 on Fedora 25, gcc 4.8.4 on Ubuntu 14.04.4, and gcc 4.8.3 on openSUSE 13.2, where it prints the following output.

inux-x86-64.so.2

Try it online!

Offline verification

$ printf "%b\n" "f(){puts('@\2C');}main(){f();}" > quine.c
$ gcc -w -o quine quine.c
$ ./quine
inux-x86-64.so.2
$ ./quine | wc -c
17

C (gcc), 18 17 bytes

f(){puts('@C');}

Note that there's an STX byte (0x02) between @ and C.

Try it online!

Portability

This has been tested with gcc 6.3.1 and clang 3.9.1 on Fedora 25, gcc 4.8.4 on Ubuntu 14.04.4, and gcc 4.8.3 on openSUSE 13.2, where it prints the following output.

inux-x86-64.so.2

I expect this to produce the same output with all versions of gcc, as long as it compiles to an executable of the following type.

ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2

Offline verification

$ printf "%b\n" "f(){puts('@\2C');}main(){f();}" > quine.c
$ gcc -w -o quine quine.c
$ ./quine
inux-x86-64.so.2
$ ./quine | wc -c
17
6 added 16 characters in body
source | link
5 portability
source | link
4 portability
source | link
3 added 269 characters in body
source | link
    Post Undeleted by Dennis
2 deleted 23 characters in body
source | link
    Post Deleted by Dennis
1
source | link