static variable size comparison - c

Consider the following 3 programs:
static1.c
int main(int argc, char * argv[])
{
return 0;
}
static2.c
int main(int argc, char * argv[])
{
static int i;
return 0;
}
static3.c
int main(int argc, char * argv[])
{
static int i = 2;
return 0;
}
Now the size for each program is invoked:
size static1.out
text data bss dec hex filename
1418 544 8 1970 7b2 static1.out
size static2.out
text data bss dec hex filename
1418 544 8 1970 7b2 static2.out
size static3.out
text data bss dec hex filename
1418 548 4 1970 7b2 static3.out
Why is the size output same for static1.c and static2.c, even if there is an uninitialised/zero initialised static variable in static2.out, which must go to .bss segment?
In all 3 programs the variable is never used. If the compiler is smart enough to deduce that, then why did the size information in static3.c different from other two?
If the .data and .bss are 544 and 8 respectively(without any variables), then only .data segment should change in the static3.c but from the output we can see that the int moved from .bss to .data(because the variable has an initial value now)

Related

Shellcode not running, despite disabling stack protections

I am exploring shellcode. I wrote an example program as part of my exploration.
Using objdump, I got the following shellcode:
\xb8\x0a\x00\x00\x00\xc
for the simple function:
int boo()
{
return(10);
}
I then wrote the following program to attempt to run the shellcode:
#include <stdio.h>
#include <stdlib.h>
unsigned char code[] = "\xb8\x0a\x00\x00\x00\xc3";
int main(int argc, char **argv) {
int foo_value = 0;
int (*foo)() = (int(*)())code;
foo_value = foo();
printf("%d\n", foo_value);
}
I am compiling using gcc, with the options:
-fno-stack-protector -z execstack
However, when I attempt to run, I still get a segfault.
What am I messing up?
You're almost there!
You have placed your code[] outside of main, it's a global array. Global variables are not placed on the stack. They can be placed:
In the BSS section if there are not initialized
In the data section if there are initialized and access in both
read/write
In the rodata section if there are only accessed in read
Let's verify this You can use readelf command to check all the sections of your binary (I only show the ones we are interested in):
$ readelf -S --wide <your binary>
There are 31 section headers, starting at offset 0x39c0:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[...]
[16] .text PROGBITS 0000000000001060 001060 0001a5 00 AX 0 0 16
[...]
[18] .rodata PROGBITS 0000000000002000 002000 000008 00
[...]
[25] .data PROGBITS 0000000000004000 003000 000017 00 WA 0 0 8
[...]
[26] .bss NOBITS 0000000000004017 003017 000001 00 WA 0 0 1
Then we can look for your symbol code in your binary:
$ readelf -s <your binary> | grep code
66: 0000000000004010 7 OBJECT GLOBAL DEFAULT 25 code
This confirms that your variable/array code is in .data section, which doesn't present the X flag, so you cannot execute code from it.
From there, the solution is obvious, place your array in your main function:
int main(int argc, char **argv) {
uint8_t code[] = "\xb8\x0a\x00\x00\x00\xc3";
int foo_value = 0;
int (*foo)() = (int(*)())code;
foo_value = foo();
printf("%d\n", foo_value);
}
However, this may also not work!
Your C compiler may find that yes, you are using code, but never reading from it anything, so it will optimize it and simply allocate it on the stack without initializing it. This is what happens with my version of GCC.
To force the compiler to not optimize the array, use volatile keyword.
int main(int argc, char **argv) {
volatile uint8_t code[] = "\xb8\x0a\x00\x00\x00\xc3";
int foo_value = 0;
int (*foo)() = (int(*)())code;
foo_value = foo();
printf("%d\n", foo_value);
}
In a real use-case, your array would be allocated on the stack and sent as a parameter to another function which itself would modify the array content with shellcode. So you wouldn't encounter such compiler optimization issue.

Why is BSS not increasing under the presence of a global static variable?

I am running on a 64-bit Windows system and currently trying to learn C. The codes are given below.
Code 1
#include<stdio.h>
int main() {
}
Size:
text data bss dec hex filename
9724 2200 2432 14356 3814 main.exe
Code 2
#include<stdio.h>
static int i;
int main() {
}
Size:
text data bss dec hex filename
9724 2200 2432 14356 3814 main.exe

Memory layout in BSS segment

In a 64-bit machine, I write a simple C program as follows:
#include <stdio.h>
int main(int argc,char* argv[])
{
printf("Hello,world!\n");
return 0;
}
Then gcc hello.c -o hello, size hello, I got:
text data bss dec hex filename
1156 492 16 1664 680 hello
Next, I add a global int variable in the source code:
#include <stdio.h>
int global;
int main(int argc,char* argv[])
{
printf("Hello,world!\n");
return 0;
}
Again compile and size, I got:
text data bss dec hex filename
1156 492 24 1672 688 hello
So, the question is, bss segment has got an increment of 8 bytes, but why? There is only an int variable global added. That should be 4.
BTW, gcc version is 4.4.7
The segment size is rounded up to the next multiple of 8, so that anything that follows it will be aligned on a 64 bit boundary. The startup routine that zeroes it will use 64 bit stores anyway.

Memory allocation for static variable in C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Where are static variables stored (in C/C++)?
I've read that all global variables that are initialized will be allocated space on the initialized data segment and all static and global variables that are not initialized are initialized to 0, and allocated on the BSS. In case of the following definition,
static int i = 0;
where will space for i be allocated? Will it be on the initialized data segment because i is initialized, or will it be on the BSS since the value of i is 0?
Yes, non-initialized static variables will be initialized to 0 by default, that's always true in C.
The storage location of the data will be implementation dependent... I've seen that it's the 0 initialized static variables (i in your case) that goes in .BSS (Block Started by Symbol).
Non-0 initialized statics go into .DATA static int i=2; for example.
To show the point:
int main(int argc, char * argv[])
{
return 0;
}
saved in "test.c"
> gcc test.c
> size a.out
text data bss dec hex filename
1056 252 8 1316 524 a.out
Then we update it as such:
int main(int argc, char * argv[])
{
static int i;
return 0;
}
> gcc test.c
> size a.out
text data bss dec hex filename
1056 252 12 1316 524 a.out
Change it again as such:
int main(int argc, char * argv[])
{
static int i = 2;
return 0;
}
> gcc test.c
> size a.out
text data bss dec hex filename
1056 256 8 1316 524 a.out
This really depends on the actual compiler/implementation, but yes, i would most likely be on the BSS because it's either on file level (i.e. outside any function) or static and inside a function and has a value of 0.
It's implementation dependant, on Linux with gcc 4.5.2 when I compile this program:
static int a[1000000] = {1}; void main() {}
I get executable with size 3.9M - first element of the array is initialized (with non-zero value) so array 'a' goes to .data segment.
When I initialize array with zeros:
static int a[1000000] = {0}; void main() {}
I get executable with size 8.2K - I guess that such difference in size indicates that this time 'a' array was located in .bss segment.

Data section in a.out

here is a simple code that I executed
int a;
int main()
{
return 0;
}
Then after compiling with gcc I did
size a.out
I got some output in bss and data section...Then I changed my code to this
int a;
int main()
{
char *p = "hello";
return 0;
}
Again when I saw the output by size a.out after compiling , size of data section remained same..But we know that string hello will be allocated memory in read only initialized part..Then why size of data section remained same?
#include <stdio.h>
int main()
{
return 0;
}
It gives
text data bss dec hex filename
960 248 8 1216 4c0 a.out
when you do
int a;
int main()
{
char *p = "hello";
return 0;
}
it gives
text data bss dec hex filename
982 248 8 1238 4d6 a.out
at that time hello is stored in .rodata and the location of that address is stored in char pointer p but here p is stored on stack
and size doesnt shows stack. And i am not sure but .rodata is here calculated in text or dec.
when you write
int a;
char *p = "hello";
int main()
{
return 0;
}
it gives
text data bss dec hex filename
966 252 8 1226 4ca a.out
now here again "hello" is stored in .rodata but char pointer takes 4 byte and stored in data so data is increment by 4
For more info http://codingfreak.blogspot.in/2012/03/memory-layout-of-c-program-part-2.html
Actually, that's an implementation detail. The compiler works by an as-is principle. Meaning that as long as the behavior of the program is the same, it's free to exclude any piece of code it wants. In this case, it can skip char* p = "hello" altogether.
The string "hello" is allocated in the section .rodata
Even if the total size doesn't changed, it doesn't mean that the code didn't.
I tested your example.
The string "hello" is a constant data, thus it is stored in the readonly .rodata section.
You can see this particular section using objdump, for example:
objdump -s -j .rodata <yourbinary>
With gcc 4.6.1 without any options, I got for your second code:
Contents of section .rodata:
4005b8 01000200 68656c6c 6f00 ....hello.
Since you don't use that char * in your code, the compiler optimized it away.

Resources