KJCracks / Clutch

Fast iOS executable dumper
3.7k stars 647 forks source link

Clutch doesn't "exit" when run via SSH parameters #148

Closed radj closed 7 years ago

radj commented 8 years ago

If running Clutch from inside an SSH session, it works fine and exits. However, if I use Clutch as parameter to SSH, it doesn't seem to quit. Ex: ssh root@localhost Clutch -d 1

When done this way, Finished dumping com.app.bundle.id in x.x seconds is printed but nothing happens after that and the ssh call doesn't exit. While the ssh call is still blocking, I tried opening another separate ssh session and checked ps -ax but Clutch process is no longer there. The only way to exit the blocking ssh call is to press Ctrl+C.

eschultz commented 8 years ago

Does it exit properly when you use the -t ssh paramerter (Force pseudo-terminal allocation)? Ex: ssh -t root@localhost 'Clutch -d 1'

radj commented 8 years ago

@eschultz That worked! It exits with an extra message that goes Connection to localhost closed. but it's good enough for me.

Tatsh commented 8 years ago

This is not really resolved then. Clutch should work over SSH without a pseudo-terminal.

radj commented 8 years ago

@Tatsh I see. I closed it as it was sufficient enough for me. Can you guide me how to fix this? Would love to fork and contribute but I am not that familiar with TTY and pseudo-terminal concepts although I am a little familiar with pipes and EOF.

Tatsh commented 8 years ago

Keep trying with SSH without -t. Put debug lines in the code. Something in Clutch is making a call that requires a PTY.

See man 3 isatty. isatty(STDOUT_FILENO) (and STDERR_FILENO) will return 0 (false) when there is no PTY.

radj commented 8 years ago

Thanks. Should be enough to get me started.

Tatsh commented 7 years ago

This is because Clutch is leaving file handles open to stdin, stderr, stdout. OpenSSH will not exit until every single handle to these is closed on the process that ran, even after the process exits.

If you modify main.m and main() to have this:

int main (int argc, const char * argv[])
{
    fclose(stdin);
    fclose(stderr);
    fclose(stdout);
// ...
}

Then you will get no output, and SSH will exit properly once Clutch is done. Putting these lines at the end of main() does not work. My theory on that is that the operation queue is also leaving open handles in any threads, even after they exit. Every *Operation class must be modified to close these handles and maybe then it will work? That includes anything else that is launched in a thread and prints to stdout/sterr (whether that is using printf, NSLog, etc).

    self.completionBlock = ^{
        fclose(stdin);
        fclose(stderr);
        fclose(stdout);
    };

With the existing version, to not use -t, you can use < /dev/null >& /dev/null after your clutch command: ssh root@localhost -p 2222 './clutch -d 115 < /dev/null >& /dev/null'. This is mainly if you are limited by an API that does not support an equivalent to -t. Otherwise use -t with ssh.

More details: http://www.snailbook.com/faq/background-jobs.auto.html

Tatsh commented 7 years ago

This is fixed with #153. Re-exploring the issue can be another TODO.

Tatsh commented 7 years ago

True fix is something to do with how NSOperationQueue works. I thought it used normal threads, but now it appears it's akin to forking. In any case, when the multitude of things (frameworks, etc) are dumped (via the forking mechanism), those background processes (regardless of success) exit without closing stdout/stderr descriptors, and this makes SSH hang.

Tatsh commented 7 years ago

When frameworks are involved, this is where Clutch is re-invoked: https://github.com/Tatsh/Clutch/blob/master/Clutch/FrameworkDumper.m#L218

Tatsh commented 7 years ago

Should be reopened as this is not solved for iOS 9.3.3. Solved for iOS 10.1.1.

Tatsh commented 7 years ago

I no longer have an iOS 9 device. This issue seems to be gone with iOS 10.