这个 ghidra 生成的伪 c 代码生成什么?

问题描述

我正在尝试使用 ghidra 进行逆向工程的一些挑战。

我分析了一个 bin 文件,其中应该包含一些有关密码的信息。 当你运行这个文件时,你可以给它一些输入,它会检查它是否是正确的密码。 这是负责执行此操作的伪c代码(注释是我):

  __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);
  }

好的,所以我尝试查找函数 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);
}

这里有很多信息。但总的来说,我认为发生的是通过执行操作构造了一个字符数组:

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

我不知道是什么意思(对字符取模有什么作用?+ '!' )只是意味着连接一个“!”。

总的来说,我在阅读这篇文章时遇到了一些问题,我想知道是否有可能预测这个函数对于特定输入会输出什么。在这种情况下,函数被指定为 14 作为输入。

也许使用 rand() 意味着它不能被解构?

谁能猜测/告诉我这个函数可能会为输入 14 输出什么?

解决方法

您必须记住,每个字符都是 8 位值的字符表示。因此,每个运算符在字符范围内都是有效的。

我做了这个例子是为了让你更好地理解它。

#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)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);


}
,

根据您之前的评论,这是您的函数的简化版本

#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;
}

现在您遇到的唯一问题是未定义的 typedef。这段代码是你的简化版。但它有效。