National preliminary re set

Posted by hearn on Tue, 08 Feb 2022 20:31:02 +0100

glass.apk

Functions for direct analysis of jni:


Here, there are three useful functions, the first sub_ FFC((int)&v7, (int)&v6, v4); Is the initialization function of RC4 algorithm, and the second sub_ 1088((int)&v7, v3, 39); RC4 algorithm encryption function, the third sub_ 10D4((int)v3, 39, (int)&v6, v4); Do some XOR operation, that is, just analyze the third function. The first two functions use tools directly

 for ( i = 0; i < a2; i += 3 )
  {
    v5 = result + i;
    v6 = *(_BYTE *)(result + i + 2);
    v7 = *(_BYTE *)(result + i + 1);
    v8 = *(_BYTE *)(result + i) ^ v6;
    *(_BYTE *)(result + i) = v8;
    *(_BYTE *)(v5 + 2) = v6 ^ v7;
    *(_BYTE *)(v5 + 1) = v7 ^ v8;
  }
  for ( j = 0; j < a2; j += a4 )
  {
    for ( k = 0; (a4 & ~(a4 >> 31)) != k && j + k < a2; ++k )
      *(_BYTE *)(result + k) ^= *(_BYTE *)(a3 + k);
    result += a4;
  }

baby.bc

. bc to executable

Get it for the first time bc file

Check, LLVM IR bitcode, binary file. Find a way to convert into s. Then turn it into an executable file. (it cannot be converted into elf in windows, but it needs to be compiled into elf in linux



It can be seen that the input length is 25; The size of array elements can be 0 ~ 5

fill_number(__int64)input)

v1 = (char *)(a1 + 4);
  v2 = 0LL;
  do
  {
    v3 = *(v1 - 4);
    if ( map[5 * v2] )
    {
      if ( v3 != 48 )
        return 0;
    }
    else
    {
      map[5 * v2] = v3 - 48;
    }
    v4 = *(v1 - 3);
    if ( byte_601051[5 * v2] )
    {
      if ( v4 != 48 )
        return 0;
    }
    else
    {
      byte_601051[5 * v2] = v4 - 48;
    }
    v5 = *(v1 - 2);
    if ( byte_601052[5 * v2] )
    {
      if ( v5 != 48 )
        return 0;
    }
    else
    {
      byte_601052[5 * v2] = v5 - 48;
    }
    v6 = *(v1 - 1);
    if ( byte_601053[5 * v2] )
    {
      if ( v6 != 48 )
        return 0;
    }
    else
    {
      byte_601053[5 * v2] = v6 - 48;
    }
    v7 = *v1;
    if ( byte_601054[5 * v2] )
    {
      if ( v7 != 48 )
        return 0;
    }
    else
    {
      byte_601054[5 * v2] = v7 - 48;
    }
    ++v2;
    v1 += 5;
  }
  while ( v2 < 5 );
  return 1;
}
unsigned char map[] =
{
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
    0,   0,   4,   0,   0,   0,   0,   0,   3,   0, 
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
    0,   0,   0,   0,   0,   1,   1,   0,   0,   0, 
    2,   0,   0,   1,   0,   0,   0,   0,   1,   0, 
    1,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
    0,   0,   0,   0
};

This function is also used to fill the 0 in the map array as described in the function name

 if ( map[5 * v2] )
    {
      if ( v3 != '0' )
        return 0;
    }
    else
    {
      map[5 * v2] = v3 - 48;
    }

The starting address of the map is 0x601050. That is, if the map element is 0, v3 is used to fill in the corresponding information, and v3 here is our input. Subtracting 48 from else is to convert a character element into a number element and assign it to the map array

 if ( v3 != '0' )
    return 0;

According to the logic here, I think it is to judge the corresponding input position of input when the element in the map is not 0. The input position must be character 0, otherwise exit

docheck(input, input): z3 constraint

	v25 = 0;
    v24 = 0;
    v1 = (unsigned __int8)map[5 * v0];
    if ( *((_BYTE *)&v24 + v1) )
      break;
    *((_BYTE *)&v24 + v1) = 1;
    v2 = (unsigned __int8)byte_601051[5 * v0];
    if ( *((_BYTE *)&v24 + v2) )
      break;
    *((_BYTE *)&v24 + v2) = 1;
    v3 = (unsigned __int8)byte_601052[5 * v0];
    if ( *((_BYTE *)&v24 + v3) )
      break;
    *((_BYTE *)&v24 + v3) = 1;
    v4 = (unsigned __int8)byte_601053[5 * v0];
    if ( *((_BYTE *)&v24 + v4) )
      break;
    *((_BYTE *)&v24 + v4) = 1;
    if ( *((_BYTE *)&v24 + (unsigned __int8)byte_601054[5 * v0]) )
      break;

At the beginning, I didn't see any use here. I didn't know until debugging. The function here is to divide five consecutive elements into five groups, and then judge that there can be no duplication in this group of values.

		v23 = 0;
        v22 = 0;
        v6 = (unsigned __int8)map[v5];
        if ( *((_BYTE *)&v22 + v6) )
          break;
        *((_BYTE *)&v22 + v6) = 1;
        v7 = (unsigned __int8)byte_601055[v5];
        if ( *((_BYTE *)&v22 + v7) )
          break;
        *((_BYTE *)&v22 + v7) = 1;
        v8 = (unsigned __int8)byte_60105A[v5];
        if ( *((_BYTE *)&v22 + v8) )
          break;
        *((_BYTE *)&v22 + v8) = 1;
        v9 = (unsigned __int8)byte_60105F[v5];
        if ( *((_BYTE *)&v22 + v9) )
          break;
        *((_BYTE *)&v22 + v9) = 1;
        if ( *((_BYTE *)&v22 + (unsigned __int8)byte_601064[v5]) )
          break;

In this case, five consecutive elements are divided into a group, a total of five groups, each group has five elements, and then each group selects an element with the same subscript at the same time. It is judged that the five elements selected by the five groups cannot be repeated in pairs.

unsigned char row[] =
{
    0,   0,   0,   1,   1,   0,   0,   0,   2,   0, 
    0,   1,   0,   0,   0,   0,   1,   0,   1,   0, 
    0,   0,   0,   0,   0
};
			v11 = row[4 * v10];
            if ( v11 == 2 )
            {
              if ( (unsigned __int8)map[5 * v10] > (unsigned __int8)byte_601051[5 * v10] )
                return 0;
            }
            else if ( v11 == 1 && (unsigned __int8)map[5 * v10] < (unsigned __int8)byte_601051[5 * v10] )
            {
              return 0;
            }
            v12 = byte_601071[4 * v10];
            if ( v12 == 1 )
            {
              if ( (unsigned __int8)byte_601051[5 * v10] < (unsigned __int8)byte_601052[5 * v10] )
                return 0;
            }
            else if ( v12 == 2 && (unsigned __int8)byte_601051[5 * v10] > (unsigned __int8)byte_601052[5 * v10] )
            {
              return 0;
            }
            v13 = byte_601072[4 * v10];
            if ( v13 == 2 )
            {
              if ( (unsigned __int8)byte_601052[5 * v10] > (unsigned __int8)byte_601053[5 * v10] )
                return 0;
            }
            else if ( v13 == 1 && (unsigned __int8)byte_601052[5 * v10] < (unsigned __int8)byte_601053[5 * v10] )
            {
              return 0;
            }
            v14 = byte_601073[4 * v10];
            if ( v14 == 2 )
            {
              if ( (unsigned __int8)byte_601053[5 * v10] > (unsigned __int8)byte_601054[5 * v10] )
                return 0;
            }
            else if ( v14 == 1 && (unsigned __int8)byte_601053[5 * v10] < (unsigned __int8)byte_601054[5 * v10] )
            {
              return 0;
            }

Here, the map array is still divided into five groups, with five consecutive elements as a group, and then the row is divided into four elements as a group (five elements. If two adjacent elements are compared, they only need to be compared four times). Because the input length is 25, the map is 25. The map group can be divided into five groups, and the row can be divided into five groups:

  1. The fourth element of row group 1 is 1;
 else if ( v14 == 1 && (unsigned __int8)byte_601053[5 * v10] < (unsigned __int8)byte_601054[5 * v10] )
            {
              return 0;
            }

This is the first group, which means map [3] > map [4];

  1. row the first element of group 2 is 1;
 else if ( v11 == 1 && (unsigned __int8)map[5 * v10] < (unsigned __int8)byte_601051[5 * v10] )
            {
              return 0;
            }

This is the second group, which means map [5] > map [6];

  1. row the first element of group 3 is 2; The fourth element is 1
 if ( v11 == 2 )
            {
              if ( (unsigned __int8)map[5 * v10] > (unsigned __int8)byte_601051[5 * v10] )
                return 0;
            }



 else if ( v14 == 1 && (unsigned __int8)byte_601053[5 * v10] < (unsigned __int8)byte_601054[5 * v10] )
            {
              return 0;
            }

This is the third group, which represents map [10] < map [11]; map[13]>map[14]

  1. row the first element of group 5 is 1; The third element is 1
 else if ( v11 == 1 && (unsigned __int8)map[5 * v10] < (unsigned __int8)byte_601051[5 * v10] )
            {
              return 0;
            }

 else if ( v13 == 1 && (unsigned __int8)byte_601052[5 * v10] < (unsigned __int8)byte_601053[5 * v10] )
            {
              return 0;
            }

This is the fifth group, which represents map [20] > map [21]; map[22]>map[23]

The row [] constraint is summarized as:

map[3]>map[4];
map[5]>map[6];
map[10]<map[11];map[13]>map[14];
map[20]>map[21];map[22]>map[23]
unsigned char col[] =
{
  0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 
  0, 0, 0, 1, 0, 0, 1, 0, 0, 1
};
				v17 = col[5 * v15];
                if ( v17 == 2 )
                {
                  if ( (unsigned __int8)map[5 * v15] < (unsigned __int8)byte_601055[5 * v15] )
                    return 0;
                }
                else if ( v17 == 1 && (unsigned __int8)map[5 * v15] > (unsigned __int8)byte_601055[5 * v15] )
                {
                  return 0;
                }
                v18 = byte_601091[5 * v15];
                if ( v18 == 1 )
                {
                  if ( (unsigned __int8)byte_601051[5 * v15] > (unsigned __int8)byte_601056[5 * v15] )
                    return 0;
                }
                else if ( v18 == 2 && (unsigned __int8)byte_601051[5 * v15] < (unsigned __int8)byte_601056[5 * v15] )
                {
                  return 0;
                }
                v19 = byte_601092[5 * v15];
                if ( v19 == 2 )
                {
                  if ( (unsigned __int8)byte_601052[5 * v15] < (unsigned __int8)byte_601057[5 * v15] )
                    return 0;
                }
                else if ( v19 == 1 && (unsigned __int8)byte_601052[5 * v15] > (unsigned __int8)byte_601057[5 * v15] )
                {
                  return 0;
                }
                v20 = byte_601093[5 * v15];
                if ( v20 == 2 )
                {
                  if ( (unsigned __int8)byte_601053[5 * v15] < (unsigned __int8)byte_601058[5 * v15] )
                    return 0;
                }
                else if ( v20 == 1 && (unsigned __int8)byte_601053[5 * v15] > (unsigned __int8)byte_601058[5 * v15] )
                {
                  return 0;
                }
                v21 = byte_601094[5 * v15];
                if ( v21 == 2 )
                {
                  if ( (unsigned __int8)byte_601054[5 * v15] < (unsigned __int8)byte_601059[5 * v15] )
                    return 0;
                }
                else if ( v21 == 1 && (unsigned __int8)byte_601054[5 * v15] > (unsigned __int8)byte_601059[5 * v15] )
                {
                  return 0;
                }

Here, the map array is still divided into five groups, with five consecutive elements as a group, and then col is divided into five elements as a group (five elements need to be compared with the corresponding group for five times). Because the input length is 25, the map is 25. The map group can be divided into five groups. Between the five groups, the corresponding elements only need to be compared for four times, so col can be divided into four groups, 5 elements per group:

  1. col the third element of the first group is 2; The fifth element is 2
if ( v19 == 2 )
                {
                  if ( (unsigned __int8)byte_601052[5 * v15] < (unsigned __int8)byte_601057[5 * v15] )
                    return 0;
                }

if ( v21 == 2 )
                {
                  if ( (unsigned __int8)byte_601054[5 * v15] < (unsigned __int8)byte_601059[5 * v15] )
                    return 0;
                }

This is the first group, which means map [2] > map [7]; map[4]>map[9]

  1. col the fourth element of the third group is 1;
 i else if ( v20 == 1 && (unsigned __int8)byte_601053[5 * v15] > (unsigned __int8)byte_601058[5 * v15] )
                {
                  return 0;
                }

This is the third group, which represents map [13] < map [18];

  1. col the second element of group 4 is 1; The fifth element is 1
 if ( v18 == 1 )
                {
                  if ( (unsigned __int8)byte_601051[5 * v15] > (unsigned __int8)byte_601056[5 * v15] )
                    return 0;
                }
                
else if ( v21 == 1 && (unsigned __int8)byte_601054[5 * v15] > (unsigned __int8)byte_601059[5 * v15] )
                {
                  return 0;
                }

This is the third group, which represents map [16] < map [21]; map[19]<map[24]

col [] constraints are summarized as follows:

map[2]>map[7];map[4]>map[9]
map[13]<map[18];
map[16]<map[21];map[19]<map[24]

Topics: CTF