This is the mail archive of the
cygwin
mailing list for the Cygwin project.
Integer overflow in functions from scanf() family in MinGW, Cygwin, Borland/Embarcadero C environments (Windows)
- From: "Lukas' Home Page" <lukas dot home dot page at gmail dot com>
- To: <cygwin at sourceware dot org>
- Date: Sun, 5 Mar 2017 20:48:00 +0100
- Subject: Integer overflow in functions from scanf() family in MinGW, Cygwin, Borland/Embarcadero C environments (Windows)
- Authentication-results: sourceware.org; auth=none
Good morning,
I find out a strange and bad beaviour in functions from scanf() family when
reading one-byte int variable in MinGW, Cygwin and Borland/Embarcadero C
environments (on Windows, on Linux this doesn't happen). This bug is
corelated with MSVCRT library which isn't written in C99 standard (it's
written in C89 i think).
So, the point is, when you're reading one byte using scanf() function, AND
you are using %hhu format specifier, you have Integer Overflow bug in your
code, because MinGW links to old MSVCRT (C89 version) even if you compile
with -std=c99 parameter.
This works, because scanf() in old MSVCRT library doesn't know "h" format
specifier. BUT! The problem is, that scanf try to interpret format specifier
anyway, omits unsupported "h" specifier and it's loading full integer ("u")
to memory (it should omit not supported part of format - whole "%hhu" format
part, not just only "h"). The C99 specification says on 361 page: "If a
conversion specification is invalid, the behavior is undefined." - but it is
WRONG, because the behaviour SHOULD BE DEFINED AS OMITING THE WHOLE
UNSUPPORTED PART OF FORMAT (not only single specifier, but whole part).
In exploit (below), compiler doesn't even display warnings (event if you
compile program with -std=c99 and -Wextra parameters). I compile on Windows
7 using that command:
gcc main.c -o main.exe -Wextra
Exploit example:
===============================
#include <stdio.h>
#include <stdbool.h>
typedef volatile unsigned char uint8_t;
int main()
{
bool allowAccess = false; // allowAccess should be always FALSE
uint8_t userNumber;
char format[] = "%hhu";
char buffer[] = "257\n";
sscanf(buffer, format, &userNumber);
if (allowAccess)
{
printf("Access granted: secret information - Lech Walesa was a Bolek
agent\n");
}
printf("Entered number is: %d\n", userNumber);
return 0;
}
Best regards,
---
Łukasz "Lukas" Wyporek
lukas.home.page@gmail.com
http://www.lukashp.pl
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple