Vulnerability Analysis: A Closer Look at CVE-2015-7547
5 stars based on
For one of my research projects I had to wrap linux system calls and redirect them to another thread. In Linux system calls are not invoked directly, but rather via wrapper functions in glibc[ man 2 syscalls ]. The glibc wrapper is only copying arguments and unique system call number to the registers where the kernel expects them, then trapping to kernel mode and setting the errno if the system call returns an error number [ man 2 intro ]. It is possible to invoke system calls directly by using syscall [ man 2 syscall ].
But since most programs will rely on glibc functions for system calls, it will be enough to wrap those functions. There are two ways to wrap or override C functions in Tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc. I explain each approach later, but first lets write a very simple test file.
I plan to wrap write system call and count the total number of characters that is being written out. Lets write a very simple test file that tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc write and printf to tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc to standard output:.
Now I want to see what are the system calls that are being called when running the test file. I use strace to see the system calls responsible for writting to the standard tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc. Here is the result:.
As you can see lines 26 and 29 are where the write system call related to our code is being called. Since our goal is to wrap glibc functions, lets check output of ltrace as well. So we should be careful here, overriding only the write function from glibc will not cause the write system call from printf to be wrapped.
We need to differentiate between the final system call and the glibc library call. So in order to cover both of the cases, I need to override write and puts functions. Now lets jump into wrapping these functions. So all I need to do is to write a shared library that overrides write and puts functions. If we wrap these functions, we need a way to call the real functions to perform the system call. If the symbol is not found, in the specified library or any of the libraries that were automatically loaded by dlopen when that library was loaded, dlsym returns NULL….
So inside tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc wrapper function we can use dlsym to get the address of the related symbol in memory and call the glibc function. Another approach can be calling the syscall directly, both approaches will work.
Here is the code:. Tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc first declare pointers to hold the value of the glibc functions, we will use these later to get the pointer from dlsym. Then we simply implement the glibc functions that we want to wrap, add our code and finally call the real function to perform the intended task. We also need to link our library with Dynamically Loaded DL libraries -ldlsince we are using dlsym in our code. Another way of wrapping functions is by using linker at the link time.
GNU linker provides an tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc to wrap a tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc for a symbol [ man 1 ld ]:. Use a wrapper function for symbol. This can be used to provide a wrapper for a system function. The code is very straight forward, but now lets try to compile the code and link it with our test application.
I used gcc to pass the option to the linker with -Wlwhich is equal to calling ld with --wrap option. Now if I run the code I get:. In order to tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc system calls in Linux, one have to wrap related glibc function calls. You have tst-resolv-binaryc source code glibcresolvtst-resolv-binaryc be careful about the type of system calls you are tryting to override, since various functions might call different functions from glibc, e.
There are two ways to do this: I personally prefer the first approach since if the number of wrapper functions increases I do not have to specify them one by one, as in the second case.
You can find the source code and the related Makefile in the following github repository: Saman Barghi Trying to live a better life.
There are two ways to wrap or override C functions in Linux: This can be used to use a wrapper function for symbol. Any further reference to symbol will be resolved to the wrapper function. Test file Lets write a very simple test file that calls write and printf to write to standard output: Here is the result: If the symbol is not found, in the specified library or any of the libraries that were automatically loaded by dlopen when that library was loaded, dlsym returns NULL… So inside the wrapper function we can use dlsym to get the address of the related symbol in memory and call the glibc function.
Here is the code: Compiling the shared library We compile the shared library as follows: GNU linker provides an option to wrap a function for a symbol [ man 1 ld ]: Here is a trivial example: Now if I run the code I get: Conclusion In order to wrap system calls in Linux, one have to wrap related glibc function calls.