Live data from Hacker News

Best of show – abuse of libc

ioccc.org

21–30 of 84 posts

Re: Best of show – abuse of libc

#21
post #20
post #2

General thread here: https://news.ycombinator.com/item?id=25651942

Personally I find it amusing that the 0-signal comment "Thanks for all dang" is upvoted while the opposite 0-signal comment "Thanks for nothing dang" is downvoted. I mean, I think dang is chill, but neither of these really contributes to the discussion any more than the other, so shouldn't they have the same score? Upvotes really are a popularity contest these days.

It's not clear what the votes are. However, the latter was written by someone who has banned for what appears to be their habit of leaving low-value comments.

Re: Best of show – abuse of libc

#22

Earlier quoted context omitted.

GNU's printf specifier language is Turing complete, I believe.

Theres a great example of what you can do with this, submitted and discussed on HN here: https://news.ycombinator.com/item?id=25690319

>Format specifiers can take extra “arguments”. - "%hhn": store the number of bytes written mod 256 to the char pointer ...

Oh boy. I'll put that down for my "thing I don't think I wanted to know" of the day.

Re: Best of show – abuse of libc

#23
post #16
post #9

Earlier quoted context omitted.

https://github.com/HexHive/printbf well this is a brainfuck interpreter inside printf. I’m pretty sure there are plenty of c-to-bf transpilers.

That's fun, but esoteric languages in general and brainfuck in specific tend to lack things you'd want out of c: file system access, system calls, etc.

Hm, I think you could add numeric syscalls, similar to what happens at the asm level. E.g. put the syscall id and some parameters on the "stack", then let the interpreter run the syscall with a new "instruction" e.g. '!'. This could even substitute '.' (putchar) and ',' (getchar), since these are very much just syscalls. So that would reduce the number of instructions by one (to 7).

Oh, getting to 6 would also be fun: One might replace '[' and ']' with a conditional branch '?'. It just needs two parameters: condition and (signed) number of instructions to jump. Adds the bonus (much like normal asm) to write moch more ~~horribly abusive~~ flexible control flow than a structured "while(*ptr)".

Re: Best of show – abuse of libc

#24
post #18
post #10

How did printf end up here in the first place? Decades of feature additions, or were these features a part of an early spec?

%n was defined in C89, the first C standard: http://port70.net/~nsz/c/c89/c89-draft.html#4.9.6.1 Looking at old source code, the earliest implementation I found is 4.3BSD Tahoe (1988). See https://www.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Tahoe/usr/... Second oldest I found was Tenth Edition [Research] Unix (1989). See ocvt_n at https://www.tuhs.org/cgi-bin/utree.pl?file=V10/libc/stdio/vf... I couldn't find support i…

> Looking at old source code, the earliest implementation I found is 4.3BSD Tahoe (1988).

You are the HN historian of the day.

Re: Best of show – abuse of libc

#25
post #3

awesome. I didn't know about that printf hack....time for some fun experiments

Be careful, though, you don't want anyone to hack you through printf ;)

In the late 90s, looking for "printf(string)" [0] in the code was a great way to discover remote code execution 0days ;-)

[0] should be "printf("%s", string)".

Re: Best of show – abuse of libc

#27
post #18

Earlier quoted context omitted.

%n was defined in C89, the first C standard: http://port70.net/~nsz/c/c89/c89-draft.html#4.9.6.1 Looking at old source code, the earliest implementation I found is 4.3BSD Tahoe (1988). See https://www.tuhs.org/cgi-bin/utree.pl?file=4.3BSD-Tahoe/usr/... Second oldest I found was Tenth Edition [Research] Unix (1989). See ocvt_n at https://www.tuhs.org/cgi-bin/utree.pl?file=V10/libc/stdio/vf... I couldn't find support i…

> Looking at old source code, the earliest implementation I found is 4.3BSD Tahoe (1988). You are the HN historian of the day.

Another interesting factoid is that macOS only supports %n if the format string is located in read-only memory. Per printf(3) on macOS:

> For this reason, a format argument containing %n is assumed to be untrustworthy if located in writable memory (i.e. memory with protection PROT_WRITE; see mprotect(2)) and any attempt to use such an argument is fatal. Practically, this means that %n is permitted in literal format strings but disallowed in format strings located in normal stack- or heap-allocated memory.

The manual page seems correct:

  % cat test.c
  #include 
  int main(void) {
    printf((char[]){ "%n" }, &(int){ 0 });
    return 0;
  }
  % cc -o test test.c                                          
  % ./test                                                     
  zsh: abort      ./test

Re: Best of show – abuse of libc

#28
For those interested in more Turing complete format strings, look no further than the "sprint" challenge from this year's Google CTF Quals: https://ctftime.org/task/12834. It's sprintf in a loop this time and the program simulates a maze: https://github.com/google/google-ctf/tree/master/2020/quals/...

Re: Best of show – abuse of libc

#29
post #20
post #2

General thread here: https://news.ycombinator.com/item?id=25651942

Personally I find it amusing that the 0-signal comment "Thanks for all dang" is upvoted while the opposite 0-signal comment "Thanks for nothing dang" is downvoted. I mean, I think dang is chill, but neither of these really contributes to the discussion any more than the other, so shouldn't they have the same score? Upvotes really are a popularity contest these days.

Always have been.

Re: Best of show – abuse of libc

#30
post #27

Earlier quoted context omitted.

> Looking at old source code, the earliest implementation I found is 4.3BSD Tahoe (1988). You are the HN historian of the day.

Another interesting factoid is that macOS only supports %n if the format string is located in read-only memory. Per printf(3) on macOS: > For this reason, a format argument containing %n is assumed to be untrustworthy if located in writable memory (i.e. memory with protection PROT_WRITE; see mprotect(2)) and any attempt to use such an argument is fatal. Practically, this means that %n is permitted in literal format s…

Someone should inform The Open Group about this violation of POSIX ;)

Another fun fact: glibc does this too, if you compile with -D_FORTIFY_SOURCE=2. However, since Linux lacks the nice vm_region APIs the code opens up /proc/self/maps :/

Post reply on HN