arrow-left

All pages
gitbookPowered by GitBook
1 of 3

Loading...

Loading...

Loading...

Reversing

Blaise

I recovered a binary from my teacher's computer. I tried to reverse it but I couldn't.

hashtag
Analysis

hashtag
File Info

Running file blaise gives us this output:

Important thing here is it isn't stripped, that it is dynamically linked, and it's 64-bit, which will make the rev easier.

hashtag
Running the file

When we first run the file, we are given a two digit number, like so:

And we are promted for input. Inputting letters seems to end it, however typing a number keeps it running, and we can enter more:

hashtag
Ghidra

Let's throw it into ghidra to see the pseudo-c code of the file. I've prepared the decompilation by renaming functions and variable already. Here's what our main function looks like:

However there isn't much useful info here, although we know that it calls the functions display_number and process

Let's decompile display_number:

We see here that it basically:

  • generates a random number between 15 and 20 (0xf and 0x14)

  • prints it

  • returns it

Let's decompile process now:

This is most important function, and a lot is going on here:

  • Firstly, we basically create a for loop using counter and the random number as the end

  • Then we read the input with scanf

  • Then with counter, and random number, we call another function called c, and output is stored in output

So, in order to do this challenge, we need to write a script that constantly gives a number to the program, that equals the output of c, then reads the flag

hashtag
function c

Let's decompile c:

So it makes 3 variables, using the f function, and then returns a value based on those 3.

Lets' decompile f:

Just does some maths with the provided number.

hashtag
Scripting

To convert our two numbers (random and counter) to what is needed of the program, we'll port these functions to python, like so:

Using these, and pwntools, we can write our final script, like so:

Flag: csictf{y0u_d1sc0v3r3d_th3_p4sc4l's_tr14ngl3}

. We'll come back to this in a bit
  • Then it compares this output with our input, and if they aren't equal it sets flagcheck to false

  • Increments counter, and starts loop again

  • Finally, at the end, it checks if flagcheck is true, if it is, it gives us the flag

  • blaise: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=00fb13e98a303dff4159e894942e363208415ba1, for GNU/Linux 3.2.0, not stripped
    $ ./blaise
    15
    $ ./blaise
    19
    12
    24
    a
    $
    def f(num):
    	ret = 1
    	counter = 2
    	while counter <= num:
    		ret *= counter
    		counter += 1
    	return ret
    
    def c(ran, counter):
    	num1 = f(ran)
    	num2 = f(counter)
    	num3 = f(ran - counter)
    	return num1 / (num2 * num3)
    from pwn import *
    from sys import argv
    
    if argv[1] == "r": 
    	p = remote("chall.csivit.com", 30808)
    else:
    	e = ELF("./blaise")
    	p = e.process()
    
    
    rand = int(p.recvline())  # Recieves random number
    log.info(f"random number: {rand}")
    
    def f(num):
    	ret = 1
    	counter = 2
    	while counter <= num:
    		ret *= counter
    		counter += 1
    	return ret
    
    def c(ran, counter):
    	num1 = f(ran)
    	num2 = f(counter)
    	num3 = f(ran - counter)
    	return num1 / (num2 * num3)
    
    for i in range(0, rand + 1):
    	data = int(c(rand, i))  # Gets required number
    	p.sendline(str(data))   # Sends
    	flag = p.clean()
    	if flag:  # I was lazy :p
    		log.info(f"flag is: {flag.decode()}")
    		exit()

    RicknMorty

    Rick has been captured by the council of ricks and in this dimension Morty has to save him, the chamber holding Rick needs a key . Can you help him find the key?

    hashtag
    Analysis

    First, let's see what running the program does.

    circle-info

    The pairs of numbers are the program, the singular numbers are me typing back to it.

    There's nothing particularly clear here, so let's disassemble it in GHidra.

    It looks very complicated, but we can ignore the bulk of it. What we need to focus on is the random number generation and what happens to it.

    Two random numbers are generated. They are passed into function1, then we +3 to the result and pass it through function2. The result of that is then compared with the number we input. If they are not the same, the check is set to 0.

    At the end, if it's not 1 (and if takes under 30 seconds) the flag is read. So clearly we have to receive the numbers, work out what it does and then return the values (repeatedly) to get the flag.

    Let's check what the two functions do.

    hashtag
    function1

    We have a counter that loops until it is greater than a number; if both numbers are divisible by the counter the answer gets set to counter - this is clearly some sort of highest common factor function.

    hashtag
    function2

    This looks like a weird function, but if you write it in, say, python, it's much clearer what it does:

    This is a factorial function.

    Now we know what it does, the flow is simple:

    And we can write a script that does this for us.

    hashtag
    Solution

    Flag: csictf{h3_7u2n3d_h1m531f_1n70_4_p1ck13}

    int main(void)
    {
      int random;
      time_t tVar1;
      long result;
      long input;
      time_t local_40;
      time_t local_38;
      time_t local_30;
      long number2;
      long number1;
      char *time_to_execute;
      int counter;
      int check;
      
      setbuf(stdin,(char *)0x0);
      setbuf(stdout,(char *)0x0);
      setbuf(stderr,(char *)0x0);
      tVar1 = time(&local_30);
      srand((uint)tVar1);
      time(&local_38);
      check = 1;
      counter = 0;
      while( true ) {
        random = rand();
        if (random % 3 + 4 < counter) break;
        random = rand();
        number1 = (long)(random % 10 + 6);
        random = rand();
        number2 = (long)(random % 10 + 6);
        printf("%d %d\n",number1,number2);
        __isoc99_scanf(&DAT_0040200f,&input);
        result = function1(number1,number2);
        result = function2(result + 3);
        if (result != input) {
          check = 0;
        }
        counter = counter + 1;
      }
      time(&local_40);
      time_to_execute = (char *)(double)(local_40 - local_38);
      printf(time_to_execute,"fun() took %f seconds to execute \n");
      if ((check != 1) || (30.00000000 < (double)time_to_execute)) {
        printf("Nahh.");
      }
      else {
        puts("Hey, you got me!");
        system("cat flag.txt");
      }
      return 0;
    }
    number1 = (long) (random % 10 + 6);
    random = rand();
    number2 = (long) (random % 10 + 6);
    printf("%d %d\n", number1, number2);
    __isoc99_scanf(&DAT_0040200f, &input);
    result = function1(number1, number2);
    result = function2(result + 3);
    if (result != input) {
        check = 0;
    }
    if ((check != 1) || (30.00000000 < (double)time_to_execute)) {
        printf("Nahh.");
    }
    else {
        puts("Hey, you got me!");
        system("cat flag.txt");
    }
    long function1(long num1,long num2)
    
    {
      int counter;
      int answer;
      
      answer = 0;
      counter = 1;
      while ((counter <= num1 || (counter <= num2))) {
        if ((num1 % (long) counter == 0) && (num2 % (long) counter == 0)) {
          answer = counter;
        }
        counter = counter + 1;
      }
      return (long)answer;
    }
    long function2(long number)
    {
      long lVar1;
      
      if (number == 0) {
        lVar1 = 1;
      }
      else {
        lVar1 = function2(number - 1);
        lVar1 = lVar1 * number;
      }
      return lVar1;
    }
    def function2(number):
        if number == 0:
            return 1
        
        return number * function(number - 1)
    two numbers -> highest common factor -> +3 -> factorial -> compared to input
    from pwn import *
    from numpy import gcd
    import numpy
    
    p = remote('chall.csivit.com', 30827)
    
    while True:
        try:
            num1, num2 = map(int, p.recvline().decode().split()) # Cast and assign the two numbers
            log.info(f'{num1} {num2}')
        
            hcf = gcd(num1, num2)
            log.success(f'HCF of {num1} and {num2} is {hcf}')
    
            fact = numpy.math.factorial(hcf + 3)
            log.success(f'Factorial of {hcf + 3}: {fact}')
        
            p.sendline(f'{fact}')
        except ValueError:
            # If it's ValueError it can't be cast to an int, so we've received the flag
            break
    
    print(p.clean(1).decode())