1

I'm playing around doing a few challenges of reverse engineering with ghidra.

I have analyzed a bin file, which should contain some information about a password. When you run the file, you can give it some input, and it will check if it's the correct password. Here is the pseudo-c code that is responsible for doing this (The comments are me):

  __isoc99_scanf(&DAT_00400a82,local_28); // input scanned from user
  __s2 = (char *)FUN_0040078d(0x14); // password retrieved from function
  iVar1 = strcmp(local_28,__s2); // comparing strings
  if (iVar1 == 0) { // if they are equal, do this
    FUN_00400978(&local_48);
  }

Ok, so i tried looking up the function FUN_0040078d:

void * FUN_0040078d(int param_1)

{
  int iVar1;
  time_t tVar2;
  void *pvVar3;
  int local_c;
  
  tVar2 = time((time_t *)0x0);
  DAT_00601074 = DAT_00601074 + 1;
  srand(DAT_00601074 + (int)tVar2 * param_1);
  pvVar3 = malloc((long)(param_1 + 1));
  if (pvVar3 != (void *)0x0) {
    local_c = 0;
    while (local_c < param_1) {
      iVar1 = rand();
      *(char *)((long)local_c + (long)pvVar3) = (char)(iVar1 % 0x5e) + '!';
      local_c = local_c + 1;
    }
    *(undefined *)((long)pvVar3 + (long)param_1) = 0;
    return pvVar3;
  }
                    /* WARNING: Subroutine does not return */
  exit(1);
}

So theres a lot of information here. But overall, what I think happens is that an array of chars is constructed, by doing the operation:

(char)(iVar1 % 0x5e) + '!';

Which I have no idea what means (what does modulo on chars do? and does + '!' ) just mean concatenate a "!".

Overall I'm haivng some issues reading this, and I'm wondering if it's possible to predict what this function would output for specific inputs. In this case the function is given 14 as input.

Maybe the use of the rand() means that it cannot be deconstructed?

Can anyone give a guess/tell me whatthis function would likely output for input 14?

Garsty100
  • 133
  • 9
  • Given that part of the calculation involves a random number I'd say it'd be difficult to predict the output. Sorry! – Bob Jarvis - Слава Україні May 08 '21 at 13:43
  • yes, that was my fear as well. But since i'm fairly new tot this i thoguht that there might be a way around. thx! – Garsty100 May 08 '21 at 13:44
  • Modulo never works on `char` — a `char` value is promoted to `int` and then the modulo operation is applied to the `int` value. But the code shown has `iVar1` as an `int` anyway. The result of the modulo operation is in the range 0x00..0x5D; the cast to `char` is a no-op; the addition of `!` (ASCII 33, 0x21) leaves the value in the range 0x21..0x7E, which are all printable, graphic characters in ASCII and related code sets (including ISO 8859-1 and Unicode). – Jonathan Leffler May 08 '21 at 14:07

2 Answers2

1

you got to remember that every char is a character representation of an 8bit value. Thus every operator is valid within the realm of chars.

I made this example for you to understand it better.

#include <stdio.h>
#include <stdlib.h>


int main(int argc, char **argv) 
{
    char character = 'A'; // 65 in dec
    char bang = '!'; // 33 in dec


    printf("'A' in dec: %d\n", (int)character);
    printf("'!' in dec: %d\n", (int)bang);


    
    // now the modulo operator works the same in chars
    character = 'a';
    char new_value = (char)character%64;
    printf("a %% 64 : char_value: %c, int_value: %d\n", new_value, (int)new_value);
    
    // you got to remember that chars are just a coded 8bit value
    
    char at_symbol = '@'; // 64 in dec

    // now the modulo operator works the same in chars
    character = 'a';
    new_value = (char)character%at_symbol;
    printf("a %% @ : char_value: %c, int_value: %d\n", new_value, (int)new_value);


    // it works the same with every other operator 
    

    
    int value1 = 300; //this is your random value

    char hex_value = 0x5E; //94 in dec or ^ in char

    new_value = (char)(value1%hex_value); //300 % 94 = 18;

    new_value += bang; //18 + 33 = 51 in dec or the number 3 symbol in char;

    printf("dec_val: %d, char encoding: %c\n", (int)new_value, new_value);


}
VictorJimenez99
  • 323
  • 2
  • 9
  • nice, this definitiely clears up the issue regarding chars. Do you know of any way that I could provoke this binary to enter the conditional that I show at the top of my question? eventhough I cannot predict the value of `__s2` – Garsty100 May 08 '21 at 14:41
0

as per your previous comment, here's a simplified version of your function

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

long GLOBAL_COUNTER = 0;

typedef char undefined;

void * array_constructor(int size);

int main(int argc, char **argv) 
{

    char* random_string = (char*)array_constructor(0x14);
    printf("%s", random_string);
    free(random_string);
}


void * array_constructor(int size)
{
    int random_value;
    //time_t cur_time;
    void *array;
    int counter;

    //cur_time = time(NULL);
    GLOBAL_COUNTER = GLOBAL_COUNTER + 1;
    srand(0);//srand(GLOBAL_COUNTER + (int)cur_time * param_1);
    array = malloc((long)(size + 1));//returns a void array of param_1 + 1 elements 
    if (array == NULL) 
      exit(1);
    
    counter = 0;
    while (counter < size) {
    random_value = rand();
    int char_value = (char)(random_value % 0x5e) + '!';//Range of possible values 33-127
    // This is due to the fact that random value can have any value given the seed
    // but its truncated to a modulo 0x5e so its new range is 0 - 0x5e(94 in dec) 
    // and you add the bang symbol at the end so 0 + 33 = 33 and 94 + 33 = 127 

    *(char *)((long)counter + (long)array) = char_value;    
    // this statement is the same as
    // array[counter] = char_value
    counter++;
    }
    *(undefined *)((long)array + (long)size) = 0; //it puts the \0 at the end of the string
    return array;
}

now the only problem that you had was with the undefined typedef. this code is a simplification of yours. but it works.

VictorJimenez99
  • 323
  • 2
  • 9