macos 10 setuid failing for no reason - macos

I'm running this code to change the real uid if a process:
#include <cstdlib>
#include <cstdio>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
void printstat()
{
printf("uid: %d, euid: %d\n",getuid(),geteuid());
}
int main(int argc, char** argv)
{
if (argc < 2)
{
return -1;
}
int m_targetUid = atoi(argv[1]);
printstat();
uid_t realUID = getuid();
printf("Setting effective uid to %d\n",m_targetUid);
seteuid(m_targetUid);
printstat();
if (m_targetUid != realUID)
{
printf("Setting real uid to %d\n",m_targetUid);
int res = setuid(m_targetUid);
printf("setuid(%d) returned: %d\n",m_targetUid,res);
if (0 > setuid(m_targetUid))
{
printf("setuid(%d) failed: %d, getuid() returned %d, geteuid returned %d\n",m_targetUid,errno,realUID,geteuid());
exit(-1);
}
}
}
according to the man page, the setuid functino shouldn't fail if the effective userid is equal to the specified uid, but for some reason it fails. any ideas?
man page:
The setuid() function sets the real and effective user IDs and the saved set-user-ID of the current process to the specified value. The setuid() function is permitted if the effective user ID is that of the
super user, or if the specified user ID is the same as the effective user ID. If not, but the specified user ID is the same as the real user ID, setuid() will set the effective user ID to the real user ID.
and this is the output when i run it as root:
nnlnb-mm-041: root# /tmp/setuidBug 70
uid: 0, euid: 0
Setting effective uid to 70
uid: 0, euid: 70
Setting real uid to 70
setuid(70) returned: -1
setuid(70) failed: 1, getuid() returned 0, geteuid returned 70

I finally managed to solve it, apparently in macos you have to set the effective uid back to root for it to work. code below.
#include <cstdlib>
#include <cstdio>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
void printstat()
{
printf("uid: %d, euid: %d\n",getuid(),geteuid());
}
int main(int argc, char** argv)
{
if (argc < 2)
{
return -1;
}
int m_targetUid = atoi(argv[1]);
printstat();
uid_t realUID = getuid();
printf("Setting effective uid to %d\n",m_targetUid);
seteuid(m_targetUid);
printstat();
printf("Setting effective uid to 0\n");
seteuid(0);
printstat();
if (m_targetUid != realUID)
{
printf("Setting real uid to %d\n",m_targetUid);
int res = setuid(m_targetUid);
printf("setuid(%d) returned: %d\n",m_targetUid,res);
if (0 > setuid(m_targetUid))
{
printf("setuid(%d) failed: %d, getuid() returned %d, geteuid returned %d\n",m_targetUid,errno,realUID,geteuid());
exit(-1);
}
}
printstat();
}
and the output now is:
uid: 0, euid: 0
Setting effective uid to 70
uid: 0, euid: 70
Setting effective uid to 0
uid: 0, euid: 0
Setting real uid to 70
setuid(70) returned: 0
uid: 70, euid: 70

Related

`ioctl` to read and write GPIO: invalid argument

I'm imitating the gpio-hammer example in Linux source code. I'm using Raspberry Pi 3B+ and want an LED to blink.
Here's what I do:
#include <linux/gpio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, const char **argv) {
int fd, ret;
struct gpiohandle_request req;
struct gpiohandle_data data;
char *gpio_dev_name = "/dev/gpiochip0";
unsigned int gpio_line = 8;
memset(&data.values, 0, sizeof(data.values));
// open device
fd = open(gpio_dev_name, 0);
if (fd == -1) {
fprintf(stderr, "Failed to open %s, %s\n",
gpio_dev_name, strerror(errno));
}
// request gpio output
req.lineoffsets[0] = gpio_line;
req.flags = GPIOHANDLE_REQUEST_OUTPUT | GPIOHANDLE_REQUEST_ACTIVE_LOW;
strcpy(req.consumer_label, "blink");
req.lines = 1;
memcpy(req.default_values, &data, sizeof(req.default_values));
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1) {
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
}
// blink
while (1) {
// read data
ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno));
exit(ret);
}
// flip digits
data.values[0] = !data.values[0];
// set data
ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret, strerror(errno));
exit(ret);
}
// delay
sleep(1);
}
}
I can compile the gpio-hammer example on RPi and run it with ./gpio-hammer -n gpiochip0 -o 8. Attached to gpiochip0 line8 is an LED and it blinks.
But my program does not work. It fails with
Failed to issue GPIOHANDLE_GET_LINE_VALUES_IOCTL (-22), Invalid argument
I looked into the implement of gpiolib. The ioctl of gpio line handle returns EINVAL (22) if ioctl cmd is not GPIOHANDLE_GET_LINE_VALUES_IOCTL nor GPIOHANDLE_SET_LINE_VALUES_IOCTL. But that's not the case. What's going wrong?
In linux/gpio.h, the description of struct gpiohandle_request says:
/*
* ...
* #fd: if successful this field will contain a valid anonymous file handle
* after a GPIO_GET_LINEHANDLE_IOCTL operation, zero or negative value
* means error
*/
struct gpiohandle_request {
__u32 lineoffsets[GPIOHANDLES_MAX];
__u32 flags;
__u8 default_values[GPIOHANDLES_MAX];
char consumer_label[32];
__u32 lines;
int fd;
};
When use GPIO_GET_LINEHANDLE_IOCTL, the file handle of GPIO chip device is passed through the first argument of ioctl(), and another file handle will be sent back in gpiohandle_request::fd, if the operation successes. This new fd should be used in ioctl of GPIO_GET_LINE_VALUES_IOCTL or GPIO_SET_LINE_VALUES_IOCTL.
So the code should be
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1) {
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
}
else {
if (close(fd) == -1) {
fprintf(stderr, "Failed to close GPIO char dev.\n");
}
fd = req.fd;
}

gdb cracking && cryptanalysis CTF

hello guys i am playing CTF and i have to crack a program to get shell the source code is :
/*
* gcc ch21.c -lcrypt -o ch21
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crypt.h>
#include <sys/types.h>
#include <unistd.h>
int main (int argc, char *argv[]) {
char pid[16];
char *args[] = { "/bin/bash", "-p", 0 };
snprintf(pid, sizeof(pid), "%i", getpid());
if (argc != 2)
return 0;
printf("%s=%s",argv[1], crypt(pid, "$1$awesome"));
if (strcmp(argv[1], crypt(pid, "$1$awesome")) == 0) {
printf("WIN!\n");
execve(args[0], &args[0], NULL);
} else {
printf("Fail... :/\n");
}
return 0;
}
now i debugged it with gdb as i understood from the source i have to enter proccessid (PID) during runtime to get successful shell with GDB-PEDA i have tried getpid during breakpoint but how to continue with proccess id with gdb only run command pass input to the program any help !
any notify !
Not sure if I understood your question correctly, but PID is limited in range and cycle when there limit is reached and the max is usually around 2^15. You could simply run a loop that would run through the potential PID to match the one that will be assigned for the process.
Something like this would do:
import os, crypt, subprocess
pid = os.getpid()+50 #safe buffer for things created after python script was started
print "Selected: ",pid
for i in range(32768):
sp = subprocess.Popen(['./ch21', crypt.crypt(str(pid), "$1$awesome")], stdout=subprocess.PIPE)
output = sp.stdout.readline()
if "Fail" not in output:
print output
break

gcc using unlink and readdir, 7 days old files needs to be deleted

Using this code fetched from google.
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct dirent *entry;
DIR *dp;
chdir("/mnt/shared");
dp = opendir(".");
while( (entry = readdir(dp)) != NULL ) {
if ( strcmp(entry->d_name, ".") &&strcmp(entry->d_name, "..") ){
unlink(entry->d_name);
}
}
}`
In this could it be possible to delete files older than 7 days from the current date?
In perl i tried as follows, but wondering this could be achived with your help?
my $now = time();
my $DATEAGE = 60*60*24*7;
for my $file (#file_list) {
my #stats = stat($file);
if ($now-$stats[9] > $DATEAGE) {
print "$file\n";}
Build the full string of the file and use several syscalls(2) (notably stat(2)) ; read Advanced Linux Programming
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct dirent *entry;
DIR *dp;
time_t weekago;
time(&weekago);
weekago -= 86400*7;
dp = opendir("/mnt/shared");
if (!dp) { perror("/mnt/shared"); exit(EXIT_FAILURE); };
while( (entry = readdir(dp)) != NULL ) {
if ( strcmp(entry->d_name, ".")
&& strcmp(entry->d_name, "..") ){
char buf[256];
if (snprintf(buf, sizeof(buf),
"/mnt/shared/%s", entry->d_name)
>=sizeof(buf))
{ fprintf(stderr, "too long path %s\n", buf);
exit(EXIT_FAILURE);
};
struct stat st;
if (stat(buf,&st)) {
perror(buf);
exit(EXIT_FAILURE);
};
if ((st.st_mode & S_IFMT) == S_IFREG // a plain file
&& (st.st_mtime < weekago))
{
if (remove(buf)) perror(buf);
}
}
}
My untested code above is imperfect (and not very well indented): it don't handle file paths wider than 255. But you could improve it, e.g. using asprintf(3) to build the path in heap (then you'll need to free it).
Practically speaking, use find(1). If you need to recurse in a file tree in C, use nftw(3)

gethostbyname fails on OSX (Yosemite 10.10.4)

"gethostbyname" returns a pointer to this structure:
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
};
When I try to use it, h_name points to a valid string: the partial name I supply is expanded to the correct fully qualified host name.
The value of h_addr_list is 4
h_name is valid
h_aliasis is a valid pointer to a null pointer
h_addrtype is 2 (AF_INET, IPV4)
h_length is 0 (should be 4, or perhaps a multiple of 4)
h_addr_list is 4, fails when dereferenced.
I'm running a 32 bit process (MS Office), the h_name pointer is a valid 32 bit pointer. WTF am I doing wrong? Does gethostbyname work for other people, or on other versions of OSX?
I was able to run this small example successfully on 10.10.4 (taken from paulschreiber.com)
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: %s hostname", argv[0]);
exit(-1);
}
struct hostent *hp = gethostbyname(argv[1]);
if (hp == NULL) {
printf("gethostbyname() failed\n");
} else {
printf("%s = ", hp->h_name);
unsigned int i=0;
while ( hp -> h_addr_list[i] != NULL) {
printf( "%s ", inet_ntoa( *( struct in_addr*)( hp -> h_addr_list[i])));
i++;
}
printf("\n");
}
}
However, it did segfault on 64-bit without #include <arpa/inet.h: without that, no prototype for inet_ntoa is found, the return type is assumed to be an int (when it's actually a char *), and on 64-bit this truncates the pointer and causes a segfault.

Why is the output for the id variable 1?

#include <stdio.h>
#include <unistd.h>
int main()
{
int id;
printf("here comes the date.\n");
if (id = fork() == 0) {
printf(ā€œ%dā€, id);
printf ("PID is %d and ID is %d\n", getpid (),id);
execl ("/bin/date", "date", 0);
}
printf ("that was the date.\n");
}
OUTPUT:
here comes the date.
that was the date.
PID is 1414 and ID is 1
Tue Feb 10 14:03:02 PST 2015
Because you are setting it equal to the result of fork() == 0 which is a logical test.
Fork will succeed (return zero) inside of the forked thread. The outer thread will have the PID.

Resources