Evil code
#11
(02-10-2016, 12:21 AM)xoft Wrote: Tell me, Linux enthisiasts, how does this reflect the "Linux is safer" mantra that I hear oh so often? How could Linux be so safe if the default configuration allows programs to execute data, and thus is very prone to buffer over-/underflow attack vectors?

OK, I will answer you =) But before reading my explanation, try to answer by yourself: is there really any harm in executing read-only data?

Look at code. "main" is defined as const. That this means? Lets dig into C2011 standart, paragraph 6.7.3:
Quote:If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.
The implementation may place a const object that is not volatile in a read-only region of
storage. Moreover, the implementation need not allocate storage for such an object if its address is
never used.
So, basically, object with const modifier can't be directly modified through C code and that's all; anything beyond is up to compiler/OS. So, let's see how different toolchain handles this.
Simple code example:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char * const msg = "Hello, world!";

int main(int argc, char *argv[])
{
 memset(msg, 'T',strlen(msg));
 puts(msg);
 return 0;
}
What we doing here? We declared constant pointer to constant string ang trying to modify it with memset. Very strange, yes, but what this yields to?
Windows 7 64-bit, MSVC 14.0 (from Visual Studio 13, if I remember correctly) compiles code fine, but gives a warning about mismatch of types because memset isn't expect to take const memory location. If we a trying to run code, this is what we will get:
Code:
TTTTTTTTTTTTT
Working as we expected to. But is it secure? No. We can only assume that object is can't be modified by direct assigninment to it and nothing more. Word-by-word interpretation of standart. Someone who isn't familiar with standart (and most C coders isn't) can place something valuable, like RSA key, into const object and assume it's consistency. Very stupid thing to do, but I've seen that.
Now, Linux. Kernel 4.5.0 x86-64, GCC 4.9.3. Compiler emits the same warning about const qualifier, but code compiles. Let's run it:
Code:
Segmentation fault
What happened? Program crashed. Why? Well, it's all about const. By default, GCC on Linux put const objects in .rodata section. Then program is being loaded by dynamic linker this section goes into CODE segment on x86/x86-64. And, of course, it's read-only. But we are trying to modify it. That emits to instant program abort: you can't modify code. To the question "why const objects put together with code" I can't give resolutive answer. Maybe it's because speed: then code references const object in case both .text (code) and .rodata sections put in one x86 segment there will be no need to several segment checks (check for boundary, check for rights, etc) that are performed by CPU because all access goes within same segment. Maybe it's because there are only two segments for user programs by default in Linux x86/x86-64, code (read-only, executable) and data (read-write, not executable) and authors of dynamic linker decided to put .rodata in read-only region. But it's okay, because C2011 standart allows to do so.
Now, I can answer your second question:

(02-10-2016, 12:21 AM)xoft Wrote: On Windows, the original code doesn't work simply because the "code" for main is stored within the data segment, which is non-executable by default, thus making it safe. Why doesn't this happen on Linux, too?
Because on Linux .data section is modifiable. By the way, on Windows too, as you can see. Windows loads read-only data into DATA x86 segment, thus not restricting it to change. So, that is better - allow read-only data to be changed (Windows way) or to be executed (Linux-way)? I think Linux way is better, because answer to my question ("Is there any harm in executing read-only data?") is no. This data isn't going to change as program executes. It just can't. No stack or buffer overflows can do any harm to read-only segment. And there is no way in mistakingly run variable, don't you think? But this is very simple to modify read-only data by mistake. Linux will not allow you to do that. Windows will. Refer to my example with RSA key. It's bad practice, but it will work on Linux. On Windows someone can modify your key with buffer over/underflow. So, is Linux safer or not? =)
Reply
Thanks given by:


Messages In This Thread
Evil code - by xoft - 02-10-2016, 12:09 AM
RE: Evil code - by xoft - 02-10-2016, 12:21 AM
RE: Evil code - by LogicParrot - 02-10-2016, 12:37 AM
RE: Evil code - by Barracuda72 - 02-11-2016, 11:55 PM
RE: Evil code - by Schwertspize - 02-10-2016, 12:54 AM
RE: Evil code - by tonibm19 - 02-11-2016, 06:32 AM
RE: Evil code - by tigerw - 02-11-2016, 07:55 AM
RE: Evil code - by DrMasik - 02-11-2016, 08:09 AM
RE: Evil code - by xoft - 02-11-2016, 05:47 PM
RE: Evil code - by sphinxc0re - 02-11-2016, 06:06 PM
RE: Evil code - by xoft - 02-11-2016, 07:39 PM
RE: Evil code - by xoft - 02-12-2016, 05:12 AM
RE: Evil code - by Barracuda72 - 02-12-2016, 08:01 AM
RE: Evil code - by LogicParrot - 02-12-2016, 05:21 AM
RE: Evil code - by xoft - 02-12-2016, 06:44 PM
RE: Evil code - by xoft - 02-12-2016, 06:56 PM
RE: Evil code - by Barracuda72 - 02-12-2016, 10:14 PM
RE: Evil code - by xoft - 02-12-2016, 07:06 PM
RE: Evil code - by xoft - 02-12-2016, 07:21 PM
RE: Evil code - by LogicParrot - 02-12-2016, 11:30 PM



Users browsing this thread: 1 Guest(s)