why wait() return -1 on xcode Version 7.2.1 (7C1002) - xcode

guys, I have the following c code:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
int main (int argc, char *argv[])
{
int exit;
pid_t tc_pid, ret_pid;
tc_pid = fork();
if(tc_pid != 0){
ret_pid = wait(&exit);
printf("parent process done, tc_pid = %d, ret_pid = %d, errno = %d\n", tc_pid, ret_pid, errno);
fflush(stdout);
}
printf("parent process done, tcpid = %d, my_pid = %d\n", tc_pid, getpid());
fflush(stdout);
return 0;
}
the output on xcode is:
parent process done, tcpid = 0, my_pid = 74377
parent process done, tc_pid = 74377, ret_pid = -1, errno = 4
parent process done, tcpid = 74377, my_pid = 74374
where here the return value of wait() is -1(should be 74377 if correct), and errno is -4
However, when I use the same code run in terminal(I use zsh), the output is:
parent process done, tcpid = 0, my_pid = 74419
parent process done, tc_pid = 74419, ret_pid = 74419, errno = 0
parent process done, tcpid = 74419, my_pid = 74418
which is what I want. Does anyone knows why would this happen? Thanks guys.
my OSX is 10.11.3 and my machine is MBPR early 2015, xcode 7.2.1,
gcc 4.2.1, Apple LLVM version 7.0.2 (clang-700.1.81), Target: x86_64-apple-darwin15.3.0, Thread model: posix

According to errno.h, errno of 4 is EINTR which the man page for wait says is:
The call is interrupted by a caught signal or the signal does not have the SA_RESTART flag set.
You apparently are using a signal to get wait to exit. Perhaps you might need to rethink what are you ultimately trying to do here, and is there a way to do it without using wait?

Related

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

How to compile in Xcode C file with C11 language dialect?

I want to compile this source code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, const char *argv[]) {
While:
printf("MacBook-Pro-...:~ ...$ ");
char command[128];
gets_s(command);
if (strncmp(command, "exit", 4) == 0)
exit(0);
pid_t return_value = fork();
if (return_value == 0) {
int outfile;
if ((outfile = dup(1)) == -1)
return -1;
close(1);
if ((outfile = open("/Users/.../1.txt",
O_WRONLY | O_TRUNC | O_CREAT, 0644)) >= 0) {
execl("/bin/sh", "sh", "-c", command, NULL);
}
close(outfile);
exit(0);
} else {
wait();
FILE *fp;
char str[128];
fp = fopen("/Users/.../1.txt", "r");
while(!feof(fp)) {
if(fgets(str, 126, fp))
printf("%s", str);
}
fclose(fp);
goto While;
}
return 0;
}
But i have some errors:
Semantic Issue
Implicit declaration of function 'gets_s' is invalid in C99
Implicitly declaring library function 'exit' with type 'void (int) attribute((noreturn))'
Implicit declaration of function 'wait' is invalid in C99
Too few arguments to function call, expected 1, have 0
Project settings:
System:
ProductName: Mac OS X
ProductVersion: 10.12.1
BuildVersion: 16B2555
Xcode Version 8.0 (8A218a)
Apple LLVM version 8.0.0 (clang-800.0.38)
Target: x86_64-apple-darwin16.1.0
Thread model: posix
There are few problems:
Xcode doesn't see function definitions, that's why it says 'Implicit declaration of function 'foobar' is invalid in C99'. Even despite that Xcode attempts to compile your code assuming that unknown functions will be resolved during linking phase. In the case of exit and wait it will work, but to suppress the warning you just need to include stdlib: #include <stdlib.h>.
As of gets_s you need to do some extra actions to make it work (I don't know where it comes from).
Second problem is that signature of the wait function looks like this: int wait(int *), while you are not giving any parameters to it. Simply add 0 or NULL if you don't need to get exit code from a child process back.

How to make lldb ignore EXC_BAD_ACCESS exception?

I am writing a program on Mac OSX depending on the sigaction/sa_handler mechanism. Run a code snippet from user and get ready to catch signals/exceptions at any time. The program works fine, but the problem is I can't debug it with lldb. lldb seems not being able to ignore any exceptions even I set
proc hand -p true -s false SIGSEGV
proc hand -p true -s false SIGBUS
The control flow stops at the instruction that triggers the exception and does not jump to the sa_handler I installed earlier even I tried command c. The output was:
Process 764 stopped
* thread #2: tid = 0xf140, 0x00000001000b8000, stop reason = EXC_BAD_ACCESS (code=2, address=0x1000b8000)
How do I make lldb ignore the exception/signal and let the sa_handler of the program do its work?
EDIT: sample code
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
static void handler(int signo, siginfo_t *sigaction, void *context)
{
printf("in handler.\n");
signal(signo, SIG_DFL);
}
static void gen_exception()
{
printf("gen_exception in.\n");
*(int *)0 = 0;
printf("gen_exception out.\n");
}
void *gen_exception_thread(void *parg)
{
gen_exception();
return 0;
}
int main()
{
struct sigaction sa;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if(sigaction(/*SIGBUS*/SIGSEGV, &sa, NULL) == -1) {
printf("sigaction fails.\n");
return 0;
}
pthread_t id;
pthread_create(&id, NULL, gen_exception_thread, NULL);
pthread_join(id, NULL);
return 0;
}
I needed this in a recent project, so I just built my own LLDB. I patched a line in tools/debugserver/source/MacOSX/MachTask.mm from
err = ::task_set_exception_ports (task, m_exc_port_info.mask, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
to
err = ::task_set_exception_ports (task, m_exc_port_info.mask & ~EXC_MASK_BAD_ACCESS, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
which causes the debugserver to be unable to catch EXC_BAD_ACCESS exceptions. Now, my custom LLDB works just fine: it still catches SIGSEGV and SIGBUS but no longer enters a silly infinite loop when faced with EXC_BAD_ACCESS. Setting process handle options on the previously-fatal signals works fine too, and I can now debug SEGV handlers with impunity.
Apple really ought to make this an option in LLDB...seems like a really easy fix for them.
This is a long-standing bug in the debugger interface in Mac OS X (gdb had the same problem...) If you have a developer account, please file a bug with http://bugreport.apple.com. So few people actually use SIGSEGV handlers that the problem never gets any attention from the kernel folks, so more bugs is good...
We can do it easily. Just add this code.
#include <mach/task.h>
#include <mach/mach_init.h>
#include <mach/mach_port.h>
int ret = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS,
MACH_PORT_NULL,//m_exception_port,
EXCEPTION_DEFAULT,
0);
Don't forget to do this
proc hand -p true -s false SIGSEGV
proc hand -p true -s false SIGBUS
Full code:
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <mach/task.h>
#include <mach/mach_init.h>
#include <mach/mach_port.h>
static void handler(int signo, siginfo_t *sigaction, void *context)
{
printf("in handler.\n");
signal(signo, SIG_DFL);
}
static void gen_exception()
{
printf("gen_exception in.\n");
*(int *)0 = 0;
printf("gen_exception out.\n");
}
void *gen_exception_thread(void *parg)
{
gen_exception();
return 0;
}
int main()
{
task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS,
MACH_PORT_NULL,//m_exception_port,
EXCEPTION_DEFAULT,
0);
struct sigaction sa;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if(sigaction(/*SIGBUS*/SIGSEGV, &sa, NULL) == -1) {
printf("sigaction fails.\n");
return 0;
}
pthread_t id;
pthread_create(&id, NULL, gen_exception_thread, NULL);
pthread_join(id, NULL);
return 0;
}
Refer to (Chinese article): https://zhuanlan.zhihu.com/p/33542591
A little bit of example code can make a question like this a lot easier to answer ... I've never used the sigaction API before but I threw this together -
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void segv_handler (int in)
{
puts ("in segv_handler()");
}
void sigbus_handler (int in)
{
puts ("in sigbus_handler()");
}
int main ()
{
struct sigaction action;
action.sa_mask = 0;
action.sa_flags = 0;
action.sa_handler = segv_handler;
sigaction (SIGSEGV, &action, NULL);
action.sa_handler = sigbus_handler;
sigaction (SIGBUS, &action, NULL);
puts ("about to send SIGSEGV signal from main()");
kill (getpid(), SIGSEGV);
puts ("about to send SIGBUS signal from main()");
kill (getpid(), SIGBUS);
puts ("exiting main()");
}
% lldb a.out
(lldb) br s -n main
(lldb) r
(lldb) pr h -p true -s false SIGSEGV SIGBUS
(lldb) c
Process 54743 resuming
about to send SIGSEGV signal from main()
Process 54743 stopped and restarted: thread 1 received signal: SIGSEGV
in segv_handler()
about to send SIGBUS signal from main()
Process 54743 stopped and restarted: thread 1 received signal: SIGBUS
in sigbus_handler()
exiting main()
Process 54743 exited with status = 0 (0x00000000)
(lldb)
Everything looks like it's working correctly here. If I'd added -n false to the process handle arguments, lldb wouldn't have printed the lines about Process .. stopped and restarted.
Note that these signal settings do not persist across process executions. So if you're starting your debug session over (r once you've already started the process once), you'll need to re-set these. You may want to create a command alias shortcut and put it in your ~/.lldbinit file so you can set the process handling the way you prefer with a short cmd.

Why do my program with many forks not stop?

The Program which has many forks as below did not finish.
#include <unistd.h>
#include <iostream>
int main() {
static int fork_cnt = 0;
const unsigned kCnt = 4;
for (int i = 0; i < kCnt; ++i) {
fork();
}
std::cout << "fork_cnt=" << fork_cnt << std::endl;
return 0;
}
When I ran it, It stop as below. It seems that The main fork is finished, but other program is waitting for something.
fork_cnt=0
qingfeng#ubuntu:~$ fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
fork_cnt=0
...
Actually the program is not waiting for anything. What happens here is that you create child processes, that detach from your current stdin (at least I believe they do given their behavior). When your original process returns, sh regains the control over your stdin and prompts you for input - hence the qingfeng#ubuntu:~$ in the second line of your second listing. Anyway, your child processes keep writing to stdout, therefor the fork_cnt=0are output after the qingfeng#ubuntu:~$. When all processes have ended sh sees no reason for prompting you again for an input, therefor it seems to you as if the program's still running, but if you entered some command (or just hit Enter) you'd see it did.
To test this, please try the following: Create an infinite loop in each child process right after its creation.
#include <unistd.h>
#include <iostream>
int main() {
static int fork_cnt = 0;
const unsigned kCnt = 4;
for (int i = 0; i < kCnt; ++i) {
int pid = fork();
while(pid == 0);
}
std::cout << "fork_cnt=" << fork_cnt << std::endl;
return 0;
}
Now fork_cnt=0 is output only once and you regain the control over the terminal.
paul#www:~/Programming/playground/fork# ./a.out
fork_cnt=0
paul#www:~/Programming/playground/fork#
Anyway, the child processes are still running, which you can easily verify by entering ps in your shell.

C shell printing output infinitely without stopping at gets()

I am trying to use the SIGCHLD handler but for some reason it prints of the command I gave infinitely. If I remove the struct act it works fine.
Can anyone take a look at it, I am not able to understand what the problem is.
Thanks in advance!!
/* Simplest dead child cleanup in a SIGCHLD handler. Prevent zombie processes
but dont actually do anything with the information that a child died. */
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
typedef char *string;
/* SIGCHLD handler. */
static void sigchld_hdl (int sig)
{
/* Wait for all dead processes.
* We use a non-blocking call to be sure this signal handler will not
* block if a child was cleaned up in another part of the program. */
while (waitpid(-1, NULL, WNOHANG) > 0) {
}
}
int main (int argc, char *argv[])
{
struct sigaction act;
int i;
int nbytes = 100;
char my_string[nbytes];
string arg_list[5];
char *str;
memset (&act, 0, sizeof(act));
act.sa_handler = sigchld_hdl;
if (sigaction(SIGCHLD, &act, 0)) {
perror ("sigaction");
return 1;
}
while(1){
printf("myshell>> ");
gets(my_string);
str=strtok(my_string," \n");
arg_list[0]=str;
i =1;
while ( (str=strtok (NULL," \n")) != NULL){
arg_list[i]= str;
i++;
}
if (i==1)
arg_list[i]=NULL;
else
arg_list[i+1]=NULL;
pid_t child_pid;
child_pid=fork();
if (child_pid == (pid_t)-1){
printf("ERROR OCCURED");
exit(0);
}
if(child_pid!=0){
printf("this is the parent process id is %d\n", (int) getpid());
printf("the child's process ID is %d\n",(int)child_pid);
}
else{
printf("this is the child process, with id %d\n", (int) getpid());
execvp(arg_list[0],arg_list);
printf("this should not print - ERROR occured");
abort();
}
}
return 0;
}
I haven't run your code, and am merely hypothesizing:
SIGCHLD is arriving and interrupting fgets (I'll just pretend you didn't use gets). fgets returns before actually reading any data, my_string contains the tokenized list that it had on the previous loop, you fork again, enter fgets, which is interrupted before reading any data, and repeat indefinitely.
In other words, check the return value of fgets. If it is NULL and has set errno to EINTR, then call fgets again. (Or set act.sa_flags = SA_RESTART.)

Resources