I'm new to Software security and I'm studying it now at the university. I had some doubts about the Format String exploit, in particular how to count the length (in number of bytes) of a format string exploit.
Suppose that I have the following vulnerable code:
int guess(char *user) {
struct {
int n;
char usr[16];
char buf[16];
} s;
snprintf (s.usr, 16, "%s", user);
do {
scanf ("%s", s.buf);
if ( strncmp (s.buf, "DEBUG", 5) == 0) {
scanf ("%d", &s.n);
for ( int i = 0; i < s.n; i++) {
printf ("%x", s.buf[i]);
}
} else {
if ( strncmp (s.buf, "pass", 4) == 0 && s.usr[0] == '_') {
return 1;
} else {
printf ("Sorry User: ");
printf (s.usr); //#line 26 vulnerable line
printf ("\nThe secret is wrong! \n");
abort ();
}
}
} while ( strncmp (s.buf, "DEBUG", 5) == 0);
}
int main(int argc, char** argv) {
guess(argv[1]);
}
And the code is compiled in an IA-32 architecture (32 bit) with cdecl calling convention and there's no attack mitigation implemented (no stack canary, no ALSR etc..., I'm in a complete vulnerable machine)
At line 26 there's a format string vulnerability since the placeholder is missing ( printf (s.usr); ).
I'd like to overwrite the EIP with the address of an environmental variable that contains my shellcode.
I'm supposing (this is a theoretical exercise, I'm aware that in practice there are many other implications) that the address of my environmental variable is 0x44674234, the address of the EIP is 0x42414515 and the displacement on the stack of my format string is 7.
So my format string exploit will be \x15\x45\x41\x42\x17\x45\x41\x42%16940c%7$hn%563c%8$hn, I'll place it into user and then it will be copied into s.usr and executed by printf (s.usr);
Now what I noticed is that only 15 characters are copied into s.usr from user.
Is my format string not exploitable? I counted 30 characters in my exploit, therefore the strcpy will copy only half of my exploit.
Is the number of characters I counted correct? How should I count them?
snprintf (s.usr, 16, ...)only copies 16 bytes intos.usr? (It copies only 15, actually, since it saves space for a NUL.)user?snprintf (s.usr, 31, "%s", user);to copy it all.