I'm trying to compile c program on my Linux using make utility
this what happened if i try to create the .o file
#make size_of.o
cc -c -o size_of.o size_of.c
compiling process run correctly,but when i execute the executable file i got this error
#./size_of.o
bash: ./size_of.o: cannot execute binary file
Then once again i run make without .o suffix
#make size_of
cc size_of.o -o size_of
The compiling and executing process run as i expected.
is there any problem with the program or can you tell me what's wrong?
How can i fix this problem and is there any different between executable file in C?
This the program:
#include <stdio.h>
int main (void){
printf("char %d bytes\n",sizeof(char));
printf("short %d bytes\n",sizeof(short));
printf("int %d bytes\n",sizeof(int));
printf("long %d bytes\n",sizeof(long));
printf("float %d bytes\n",sizeof(float));
printf("double %d bytes\n",sizeof(double));
printf("long double %d bytes\n",sizeof(long double));
return 0;
}
and this is the output:
char 1 bytes
short 2 bytes
int 4 bytes
long 4 bytes
float 4 bytes
double 8 bytes
long double 12 bytes
.o files are object files, not executables. You have specifically told the compiler to only create object files, because you used the -c flag. You don't run object files, they feed into a linker (along with other things) to create the executable file.
The general (simplified) process is:
Phase
-----
+---------+
| main.c | (source)
+---------+
|
Compile........|............................
|
V
+---------+ +-----------+
| main.o | (object) | libs etc. |
+---------+ +-----------+
| |
Link...........|.........................|....
| |
+-------------------------+
|
V
+---------+
| main | (executable)
+---------+
You fix that by either using turning the object file into an executable as you've done later in the process, though I would do it as:
cc -o size_of size_of.o
Or simply create the executable directly from the source file:
cc -o size_of size_of.c
And, if you're using make, make sure you have an actual Makefile. Otherwise, you get default rules which may not be what you want. It could be as simple as:
size_of: size_of.c Makefile
gcc -o size_of size_of.c
In the first make invocation you are setting make target to be an object file (target has an .o extension). Built in make rule for object files is just to compile and assemble them (no linking) and that is what you get an object file.
Second invocation is actually asking make to build an executable file.
Gnumake has a set of built in rules for different targets. Please see this link for details:
https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html
Related
I am trying to understand how to make process stack executable with personality syscall, so I wrote this code that creates a new process with and runs a bash on the stack and I get segment fault because I don't have execute permission on the stack. What am I doing wrong?
#include <stdio.h>
#include <sys/personality.h>
int main()
{
setvbuf(stdout, 0, 2, 0);
unsigned char shellcode[] = "\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05"; // open bash
if(personality(READ_IMPLIES_EXEC | ADDR_NO_RANDOMIZE) == -1) // return 0
{
printf("personality failed");
exit(0);
}
int (*ret)() = (int(*)())shellcode;
if(fork() == 0) // child proces
ret();
return 0;
}
Compiled with gcc file.c -o file.o
$ uname -r
4.4.179-0404179-generic
$ readelf -l
...
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
There are two problems:
You cannot change the personality of a process after it's started. Doing personality(READ_IMPLIES_EXEC) is not going to do anything per se, it just sets the current process' personality value (a simple 32bit integer) and that's it. In order for the change to take effect a new program will need to be executed (i.e. through execve). The current process (and its children) will not be affected.
Linux will ignore the READ_IMPLIES_EXEC personality flag if the ELF includes a PT_GNU_STACK program header that specifies that the stack should not be executable, which is usually the default choice by compilers.
By default GCC will create ELFs with a PT_GNU_STACK program header whose flags are set to RW and not RWX. In order to have an executable stack, you will have to pass the -z execstack option to GCC when compiling, which will set PT_GNU_STACK to RWX. You can check this with readelf -l your_elf (note: readelf will show E instead of X for program header flags).
Therefore, in your case, gcc -zexecstack -o file file.c should do what you want, and you don't need to call personality() nor fork() really. Just put your shellcode on the stack and jump into it. In theory you could also locate the program headers in the ELF file and edit the flags for PT_GNU_STACK manually (7 = RWX) e.g. using an hex editor, but that'd be more work than needed.
So, at the end of the day:
I am trying to understand how to make process stack executable with personality syscall
You cannot. Personality only affects new executions, not already existing ones, and on top of that ELF properties such as the PT_GNU_STACK program header supersede personality. You can however re-compile your program as explained above.
NOTE: you can nonetheless use mprotect() to change the permissions of stack memory pages to RWX, given that you can somehow extrapolate the stack base address and size at runtime (e.g. taking the address of a local variable in a function and zeroing out the lowest 12 bits).
This is enough information for older kernels like yours (4.4), but since Linux v5.8 the situation is a bit more nuanced. Assuming you are on x86, you can take a look at this comment in the source code for an explanation:
/*
* An executable for which elf_read_implies_exec() returns TRUE will
* have the READ_IMPLIES_EXEC personality flag set automatically.
*
* The decision process for determining the results are:
*
* CPU: | lacks NX* | has NX, ia32 | has NX, x86_64 |
* ELF: | | | |
* ---------------------|------------|------------------|----------------|
* missing PT_GNU_STACK | exec-all | exec-all | exec-none |
* PT_GNU_STACK == RWX | exec-stack | exec-stack | exec-stack |
* PT_GNU_STACK == RW | exec-none | exec-none | exec-none |
*
* exec-all : all PROT_READ user mappings are executable, except when
* backed by files on a noexec-filesystem.
* exec-none : only PROT_EXEC user mappings are executable.
* exec-stack: only the stack and PROT_EXEC user mappings are executable.
*
* *this column has no architectural effect: NX markings are ignored by
* hardware, but may have behavioral effects when "wants X" collides with
* "cannot be X" constraints in memory permission flags, as in
* https://lkml.kernel.org/r/20190418055759.GA3155#mellanox.com
*
*/
#define elf_read_implies_exec(ex, executable_stack) \
(mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
I would like to expand include directives of a C file of my working directory only; not the system directory.
I tried the following:
gcc -E -nostdinc -I./ input.c
But it stops preprocessing when it fails to find the included system headers in input.c. I would like it to copy the include directive when it can't find it and keep preprocessing the file.
if your input.c file contains some system headers, it's normal that the preprocessor crashes when it cannot find them.
You could first use grep -v to remove all #include of system headers in your code, achieving something like this (list is non-exhaustive):
grep -vE "(stdio|stdlib)\.h" code.c > code_.c
you get for instance:
#define EXITCODE 0
int main(){
int i = EOF;
printf("hello\n");
return EXITCODE;
}
then pre-process:
S:\c>gcc -E code_.c
# 1 "code_.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "code_.c"
int main(){
int i = EOF;
printf("hello\n");
return 0;
}
note that the pre-processor doesn't care about functions or macros not defined. You get your code preprocessed (and your macros expanded), not the system ones.
You have to process all included files as well of course. That means an extra layer of tools to create temp source files and work from there.
I found a utility that does exactly what I was looking for:
$ cpphs --nowarn --nomacro -I./ input.c | sed -E 's|#line 1 "missing file: (.*)"|#include <\1>|'
I am trying to understand how to set the value of a string in the rodata segment as loading it using an environment variable gives me issues.
I want to externally set a constant string in the rodata section. This function should be independent of the code executed. So, when I do
"objdump -c foo"
the rodata section must enlist this string without the file foo.c having to do it.
How do I set a constant in the .rodata section ?
Edit: Linux OS and using GCC
I cannot use an environment var as that would mean that the c code is modified, I want the c code untouched and add the constant, say "Goo" to the rodata segment.
Then you need to write a program that lets you modify the binary file.
Read the ELF file specifications.
Then write a program that modifies the ELF program and section headers and adds the data to the .rodata section.
I've managed to write a small bash script that does more or less what I think you want.
First let's consider this sample program:
test.c
#include <stdio.h>
const char message[1024] = "world";
int main()
{
printf("hello %s\n", message);
}
The target variable will be message. Note that I will not change the size of the variable, that would be a mess, you be careful to reserve as much memory as you will ever need.
Now the script:
patchsym
#!/bin/bash
# usage: patchsym PROGRAM SYMBOL < NEWCONTENT
EXE="$1"
SYMBOL="$2"
OFFS=$((0x$(objdump -t "$EXE" | grep " $SYMBOL$" | cut -d ' ' -f 1)))
OFFS=2176
dd of="$EXE" bs=1 seek=$OFFS conv=notrunc
The new message content will be:
newmsg
universe^#
(where ^# is actually a NUL character).
Now just do:
$ gcc test.c -o test
$ ./test
hello world
$ ./patchsym test message < newmsg
$ ./test
hello universe
This question already has an answer here:
size of executable files?
(1 answer)
Closed 7 years ago.
I have a c source file with name simple.c (file size 68 bytes) and I compiled it using gcc. The output binary file size is 7151 bytes.
C Source code:
int main()
{
int a = 10;
int b = 34;
int c = a + b;
return c;
}
I haven't included any header files.
I don't know, how does the C binary file becomes bigger than the source file. Can anyone please explain?
test#test-desktop:~/Desktop/c$ ls -l
total 4
-rw-rw-r-- 1 test test 68 Jul 15 15:04 simple.c
test#test-desktop:~/Desktop/c$ gcc simple.c
test#test-desktop:~/Desktop/c$ ls -l
total 12
-rwxrwxr-x 1 test test 7151 Jul 15 15:04 a.out
-rw-rw-r-- 1 test test 68 Jul 15 15:04 simple.c
The above is the terminal output.
You have a certain one-time overhead even without including anything. There is code running before main() (which is setting up stdin, stdout, and stderr, signal handler tables etc.), and code running after that function returns (e.g. checking for anything registered with atexit() and similar things). This is called the C runtime, traditionally located in crt0.o, which is linked into any executable.
It'll be the debug and symbol information. Optimize and strip it:
Use gcc -Os to optimize for smallest size.
Use strip a.out to remove the symbols and debug info.
There are also the CRT startup files providing the bulk of your binary that process argc, argv etc and setup your environment. You can opt out of those using -nostartfiles but you probably don't want to do that.
I want to establish build-time cross-language ABI compatibility with Waf. How would I go about checking the size of a type (or any arbitrary type-like checks), and recording it into the build configuration?
You can create a program which outputs that size. I saw this apporach on several ./configure files:
cat << EOF > test.c
#include <stdio.h>
int main ()
{
printf("int %d\n", sizeof(int));
return 0;
}
EOF
$(CC) test.c -o out
./out >> sizes
rm -f test.c out
Of course, with testing of erroneous cases and such.
Edit: See the waf documentation. Specially, read the run_c_code method. For saving the value of sizeof you can write to a file instead and read it from Python/Waf. Or, see the define_ret argument.