2

I am playing a CTF wargame and unfortunatley got stuck at this level, so I want to "crowdsource" it. No need for complete answer, but hints would be enough.

How can I:

  1. Make strcmp to be 0 (evaluate if to false)
  2. Somehow surpress singals?

I want shell to be executed:

execl("/bin/sh", "sh", NULL);

Any ideas?

Binary is setuid and /levels/level08.pass is readable only on higher level.

-r-sr-x---  1 level9  level8   7696 Apr 25  2015 level08
-r--------  1 level8  level8    412 Apr 25  2015 level08.c
-r--------  1 level9  level9     13 Apr 25  2015 level08.pass

Program code for level08.c is below.

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
        char buf[64];
        FILE *fp;
    signal(SIGABRT, SIG_DFL);
    fp = fopen("/levels/level08.pass", "r");
        fgets(buf, 64, fp);
        buf[strcspn(buf, "\n")] = '\0';
        if(strcmp(buf, argv[1]))
                raise(SIGABRT);
        execl("/bin/sh", "sh", NULL);
}
5
  • What happens if you run the program? Does it dump a core file?
    – Sjoerd
    Commented May 25, 2016 at 13:40
  • Can you make it dump a core file by using ulimit -c unlimited?
    – Sjoerd
    Commented May 25, 2016 at 13:45
  • @android_dev May be you can read the .pass file using some kernel exploit? Whats the kernel version? Check thiis one exploit-db.com/exploits/33824. And let us know
    – Sravan
    Commented May 25, 2016 at 13:55
  • I want to exploit the code, not the system. There must be a bug in this code, unfortunately I don't see it yet.
    – dev
    Commented May 25, 2016 at 14:00
  • @Sravan Negative integers are truthy in C. The only way to fail the if condition is by getting strcmp() to return zero, which means the strings must be equal.
    – grc
    Commented May 25, 2016 at 15:26

3 Answers 3

2

The strcmp call and what leads to it is correct. Your second hunch, to somewhat suppress the signal, is the right one.

signal(SIGABRT, SIG_DFL);
…
raise(SIGABRT);

The call to raise raises a signal whose default action is to kill the program. The prior call to signal ensures that the default action is taken. When a process signals itself, this is synchronous: the signal is received before the raise function returns.

What's the catch? In addition to being ignored, signals can be blocked. When an ignored signal is delivered, nothing happens. When a blocked signal is received, the kernel merely makes a note of it, but does not deliver it, so the program keeps running normally. When the signal becomes unblocked, it is delivered, and the action associated with the signal at the time of delivery is taken.

Blocked signals cross execve boundaries. There's a note of that in the POSIX rationale for execve. The function to manage signal blocking is sigprocmask.

So invoke the program with SIGABRT blocked and you'll bypass the password check.

perl -MPOSIX -we 'sigprocmask(SIG_BLOCK, POSIX::SigSet->new(SIGABRT), POSIX::SigSet->new()); exec "level08", ""'
2
  1. Make strcmp to be 0

Assuming a correct implementation of strcmp, this means argv[1] must match the contents of level08.pass exactly for 63 bytes or until the first newline/null byte.

Since we don't know the contents of the file, our only option would be to manipulate argv[1] to point to an address in memory containing the correct string (e.g. buf). The absence of any argc checks made me wonder about this, but it isn't possible the way argv is handled.

  1. Somehow suppress signals

Have a look at the process signal mask.

There are a couple of key points in this paragraph from the docs:

The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent’s mask. You can block or unblock signals with total flexibility by modifying the signal mask.

0

It seems like it execs the shell if you enter the first line of /levels/level08.pass. Maybe you can use a timing attack to check where strcmp exits, and use that to guess one character at a time.

1
  • I don't think there's any way to time with that level of accuracy (while keeping setuid).
    – grc
    Commented May 25, 2016 at 13:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .