You're right, but still there're cases when the attacker has to guess from
the first try (consider the web browser example).
And I forgot to mention one more requirement: the vulnerable binary has to
be dynamically linked for this exploit method to work. Otherwise only the
functions that the program actually uses are available in the exploit, so
that creating a generic exploit isn't possible. Also, it is only possible
to return into _one_ libc function (well, there's a special case when that
function got exactly one argument), so stuff like open() a file and write()
there will not work. This means some statically linked vulnerable programs
are likely not to contain suitable functions.
BTW, I have just made a generic buffer overflow exploit using this method:
it does PTRACE_SINGLESTEP to find system() entry point, and then fills the
buffer with the following pattern: {system_addr, system_addr, string_addr,
string_addr} -- 4 int's (16 bytes) total. This is a bit more complicated
than what I was telling earlier (I forgot about the return address, which
we have to leave space for), but still requires at most two tries until it
works on an aligned buffer, and up to 8 tries on an unaligned one (which is
the case for /usr/bin/lpr that I was testing with).
Signed,
Solar Designer