2024-04-29
C main declarationIn the last couple of days, we can see people talking about the security aspect of this behaviour.
In C, we can in fact easily interact with shell variables with the char *getenv(const char *name) standard function:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("PATH: %s\r\n", getenv("PATH"));
return (0);
}
But the C offers a way to access them directly as passing argument into the main function, just like **argv.
The definition of main can indeed have 0, 2 or 3 arguments:
int main(void)int main(int argc, char **argv)int main(int argc, char **argv, char **envp)The third and option argument is then our way to access shell variables, e.g.:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv, char **envp)
{
unsigned short timeout = 0;
while ((*envp != NULL) && (timeout++ < (1 << 15))) {
if (strncmp(*(envp++), "PATH", 4) == 0) {
printf("%s\r\n", *(envp - 1));
return (0);
}
}
printf("Timeout error\r\n");
return (1);
}
Note that this third definition of main is not part of the C99 Standard (par. 5.1.2.2.1), making it de facto POSIX-specific though widely supported.
You could however achieve the same result by overflowing the **argv parameter:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
unsigned short timeout = 0;
argv += argc + 1;
while ((*argv != NULL) && (timeout++ < (1 << 15))) {
if (strncmp(*(argv++), "PATH", 4) == 0) {
printf("%s\r\n", *(argv - 1));
return (0);
}
}
printf("Timeout error\r\n");
return (1);
}
You can find many examples and applications of this new main argument online, sometimes with another name (e.g. **environ) as, again, it is not standard.