gdb cracking && cryptanalysis CTF - debugging

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

Related

Different results of program in different execution environments

I am using Ubuntu 18.04. I am currently doing a course on Operating Systems and was just getting used to fork() and exec() calls.
I am running the following C program
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
printf("hello world (pid:%d)\n", (int) getpid());
int rc = fork();
if (rc < 0) {
// fork failed; exit
fprintf(stderr, "fork failed\n");
exit(1);
} else if (rc == 0) {
// child (new process)
printf("hello, I am child (pid:%d)\n", (int) getpid());
} else {
// parent goes down this path (original process)
printf("hello, I am parent of %d (pid:%d)\n",
rc, (int) getpid());
}
return 0;
}
On running the code in Sublime Text Editor with the build file
{
"cmd" : ["gcc $file_name -o ${file_base_name} && ./${file_base_name}"],
"selector" : "source.c",
"shell": true,
"working_dir" : "$file_path"
}
I get the result
hello world (pid:16449)
hello, I am parent of 16450 (pid:16449)
hello world (pid:16449)
hello, I am child (pid:16450)
Whereas if I use the terminal and run the same code using gcc,
I get
hello world (pid:17531)
hello, I am parent of 17532 (pid:17531)
hello, I am child (pid:17532)
Now I know that the latter is the correct whereas the output I get in Sublime is the wrong one. How can the outputs when the compiler I am using remains the same can be different?

Explanation of the output of FORK with && operator

I'm trying to predict the output of the following code, any explanation of how many time a will be printed and why?
#include <stdio.h>
#include <unistd.h>
main() {
fork()&&fork()&&fork();
printf ("a\n");
}
I believe you had already figured out how many time it will print a which is 4 times.
So let now see why.
Let's add some for information to output to get more understanding.
#include <stdio.h>
#include <unistd.h>
void main() {
printf("Main pid:%d\n",getpid());
fork() && fork() && fork();
printf ("a\tpid:%d\tppid:%d\n",getpid(),getppid());
}
Output of this code will be looks like below. Note, value of pip and ppid in your case may be different.
Main pid:4417
a pid:4417 ppid:2398
a pid:4418 ppid:4417
a pid:4420 ppid:4417
a pid:4419 ppid:4417
Now you can see from pid details that printf() executed for one main(parent) process and three child process.
We rewrite line
fork() && fork() && fork();
as below
if(fork()){
if(fork()){
if(fork()){
}
}
}
Above both code doing same thing. With second code we can write flow chart as below.
I believe this will explain your question why.

The exit code, the return echo is different from the exit code of the program. Why?

I wrote a program that returns an error code using processes.
The result of the work of the program, if at the entrance to it provide the command of a false, is 255.
However the command
false; echo $?
returns 1
Why it happens?
Solaris, unix
I found the file false.c in the source code, it returns 255 (not sure if this is the right command)
https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/false/false.c
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <wait.h>
main(int argc, char *argv[])
{
int status;
pid_t pid = fork();
if (pid == -1){
perror("fork error");
exit(-1);
}
if (pid == 0) {
execvp(argv[1], &argv[1]);
perror(argv[1]);
exit(-5);
}
if( wait(&status) == -1){
perror("wait");
exit(-1);
}
if(WIFEXITED(status))
printf("exit status: %d\n",WEXITSTATUS(status));
exit(0);
}
UNIX (Linux, Solaris, BSD, etc.) exit codes may only be 0 - 255, where 0 is good and non-zero is an error. Exit codes are not signed, so the -1 may be converted to another (non-zero) value, as are values over 255.

Passing arguments to custom system call

I developed a custom system call to log killed processes. A C program kills the process and it invokes the custom system call, passes the process ID of the killed process and then the system call will print out the killed process's ID to the kernel's log. Here I'm just passing a dummy to test if the system call writes to the kernel log. The system call's number in the system call table is 329.
Below is my system call
#include <linux/kernel.h>
asmlinkage long sys_killa(char* proc_id)
{
printk("The process %s has been killed", proc_id);
return 0;
}
This is my C program to call my custom system call.
#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
int main()
{
char proc_id[5] = "3219";
long int sys = syscall(329, proc_id);
printf("System call sys_killa returned %ld\n", sys);
return 0;
}
Running the C program simply prints "Killed" in the terminal. Running the program again crashes my virtual machine. Nothing is printed out in the kernel log when I check using dmesg utility. What am I doing wrong?
Need to use pid_t variable instead of String.This is the modified system call:
#include <linux/kernel.h>
asmlinkage long sys_killa(pid_t pid)
{
long pid_l = (long) pid;
printk("The process %ld has been killed", pid_l);
return 0;
}
This is the modified C code to use the system call:
#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
int main()
{
pid_t pid = 3249;
long int sys = syscall(329, pid);
printf("System call sys_killa returned %ld\n", sys);
return 0;
}

Specific pipe command in Ubuntu's shell handling in C

I'm trying to simulate a pipe behavior on Ubuntu's Terminal, for example the command:
"echo hello | wc".
Please assume I got the tokens from stdin, handled everything correctly and now These are the commands I "received" from the user who typed them in the shell for me to handle.
I'm trying to create two processes. Using a pipe, in the first process, I point the file descriptor of the writing edge of the pipe to stdout. The second process should read into stdin with the reading edge of the pipe what execvp(..) returned.?
Here is the code I wrote:
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
char* fcmd[] = {"echo", "hello", NULL};
char* scmd[] = {"wc", NULL};
pid_t pid;
int pipe_des[2];
int i;
pipe(pipe_des);
for(i = 0; i < 2; i++)
{
pid = fork();
if (pid ==0)
{
switch (i)
{
case 0: // FIRST CHILD
{
dup2(pipe_des[1], STDOUT_FILENO);
close(pipe_des[0]);
execvp(fcmd[0], fcmd);
exit(0);
}
case 1: //SECOND CHILD
{
dup2(pipe_des[0], STDIN_FILENO);
close(pipe_des[1]);
execvp(scmd[0], scmd);
exit(0);
}
}
}
else if (pid < 0)
exit(EXIT_FAILURE);
return EXIT_SUCCESS;
}
I get: " amirla#ubuntu:~/Desktop/os/class/ex4$ 1 1 6 "
Like it should, but why he's printing the bash cwd first? The pipe seems to work because I get what I should, according to the length of the word I'm sending with the echo command(in the main()). After that the cursor just waits on the line below for another command without showing me the bash pwd. (maybe stdin is waiting?)
I've looked in many posts on here as well as on other websites and I still can't seem to find a solution to my problem. Any help would be appreciated. Thanks in advance.
Note: Please Ignore checking for errors, I've delete them to make the code shorter so assume they exist.
Why do I get a prompt before the output?
Your main process doesn't wait for the children to finish. What you see is:
Main starts
Main creates children
Main exits
BASH prints prompt
Children start their work
To prevent this, you need to wait for the children. See How to wait until all child processes called by fork() complete?
In your case, it's enough to add
waitpid(-1, NULL, 0);
after the loop.

Resources