2023 Spring and Autumn Cup Network Security League Spring Competition Reverse topic reappears

One.sum

1. Analyze program logic

Paste the results of the analysis at that time directly here. According to the behavior of the program, it is not difficult to guess that it is a Sudoku problem (you have to guess)
main:

int __cdecl main(int argc, const char **argv, const char **envp)
{
    
    
  char *mart; // rbp
  int flagValue; // r14d
  int sum; // r12d
  __int64 i; // rbx
  char chr; // al
  int tmp; // eax
  char *md5str; // rax

  mart = matrix;
  flagValue = 1;
  sum = 0;
  puts("Welcome to Solver!");
  do
  {
    
    
    for ( i = 0LL; i != 9; ++i )
    {
    
    
      if ( !mart[i] )                           // 如果矩阵元素为零则输入字符
      {
    
    
        chr = getchar();
        if ( (chr - '1') > 8u )                 // 所以输入的必须是数字,否则错误
          flagValue = 0;
        else
          mart[i] = chr - '0';                  // 数字
      }
      tmp = mart[i];
      sum += tmp;
    }
    mart += 9;                                  // 一次处理九个字符
  }
  while ( mart != &matrix[81] );                // 一共81
  if ( flagValue && verify() )                  // 盲猜是数独
  {
    
    
    puts("You Win!");
    __snprintf_chk(buf, 32LL, 1LL, 32LL, "%d"); // 405
    md5str = str2md5(buf, strlen(buf));
    __printf_chk(1LL, "flag is: flag{%s}\n\n", md5str);// flag{bbcbff5c1f1ded46c25d28119a85c6c2}
    exit(0);
  }
  puts("Again~");
  return 0;
}

verify (verification):
especially when I saw a group of nine and checked by column, I realized that it should be Sudoku

__int64 verify()
{
    
    
  char *matr; // rsi
  __int64 j; // rcx
  _DWORD *CHECK; // rdi
  __int64 tmp; // rdi
  char *matr2; // rsi
  __int64 k; // rcx
  _DWORD *check2; // rdi
  __int64 chr; // rdi
  __int64 iii; // r8
  char *matr3; // r9
  __int64 len3; // rcx
  _DWORD *check3; // rdi
  int cout; // r10d
  char *matr4; // rdi
  __int64 i; // rcx
  __int64 tmpchr; // rbx

  matr = matrix;
LABEL_2:
  j = 10LL;
  CHECK = check;
  while ( j )
  {
    
    
    *CHECK++ = 0;                               // 初始化空间
    --j;
  }
  while ( 1 )
  {
    
    
    tmp = matr[j];
    if ( check[tmp] )                           // 不能访问已访问过的
      return 0LL;
    ++j;
    check[tmp] = 1;                             // 置一
    if ( j == 9 )
    {
    
    
      matr += 9;                                // 九个一组
      if ( matr != &matrix[81] )
        goto LABEL_2;
      matr2 = matrix;
LABEL_9:
      k = 10LL;
      check2 = check;
      while ( k )
      {
    
    
        *check2++ = 0;                          // 再次清空check数组
        --k;
      }
      while ( 1 )
      {
    
    
        chr = matr2[9 * k];                     // 检查第一列
        if ( check[chr] )
          return 0LL;
        ++k;
        check[chr] = 1;
        if ( k == 9 )
        {
    
    
          if ( ++matr2 != &matrix[9] )
            goto LABEL_9;
          iii = 0LL;
          while ( 2 )
          {
    
                                         // 检查第二列
            matr3 = &matrix[iii];
            do
            {
    
    
              len3 = 10LL;
              check3 = check;
              cout = 3;
              while ( len3 )                    // 清空check
              {
    
    
                *check3++ = 0;
                --len3;
              }
              matr4 = matr3;
              while ( 2 )
              {
    
    
                for ( i = 0LL; i != 3; ++i )
                {
    
    
                  tmpchr = matr4[i];
                  if ( check[tmpchr] )          // 也是不能有1
                    return 0LL;
                  check[tmpchr] = 1;
                }
                matr4 += 9;
                if ( --cout )
                  continue;
                break;
              }
              matr3 += 3;
            }
            while ( matr3 != &matr2[iii] );
            iii += 27LL;
            if ( iii != 81 )
              continue;
            break;
          }
          return 1LL;
        }
      }
    }
  }
}

2. Solving Sudoku Matrix

Follow up with martix first and then read the data,
insert image description here
then ask ChatGpt to get the answer directly
insert image description here
, and give the problem-solving code and running results:
insert image description here
then fill in Sudoku and you’re done

3. Problem-solving script

#include<stdio.h>
int main()
{
    
    
    int sum = 0;
    unsigned char matrix[81] =
    {
    
    
        5,   3,   0,   0,   7,   0,   0,   0,   0,   6,
        0,   0,   1,   9,   5,   0,   0,   0,   0,   9,
        8,   0,   0,   0,   0,   6,   0,   8,   0,   0,
        0,   6,   0,   0,   0,   3,   4,   0,   0,   8,
        0,   3,   0,   0,   1,   7,   0,   0,   0,   2,
        0,   0,   0,   6,   0,   6,   0,   0,   0,   0,
        2,   8,   0,   0,   0,   0,   4,   1,   9,   0,
        0,   5,   0,   0,   0,   0,   8,   0,   0,   7,
        9
    };
    int grid[81] = {
    
    
    5, 3, 4, 6, 7, 8, 9, 1, 2,
    6, 7, 2, 1, 9, 5, 3, 4, 8,
    1, 9, 8, 3, 4, 2, 5, 6, 7,
    8, 5, 9, 7, 6, 1, 4, 2, 3,
    4, 2, 6, 8, 5, 3, 7, 9, 1,
    7, 1, 3, 9, 2, 4, 8, 5, 6,
    9, 6, 1, 5, 3, 7, 2, 8, 4,
    2, 8, 7, 4, 1, 9, 6, 3, 5,
    3, 4, 5, 2, 8, 6, 1, 7, 9
    };
     int len = 0;
    for (int i = 0; i < 81; i++)
    {
    
    
        if (!matrix[i])
        {
    
    
            len++;
            printf("%d", grid[i]);//输出需要填充的序列
            //468912723481342575971422657913948591537428763345261
        }
    }
    return 0;
}

Run the program under linux, enter the sequence: 468912723481342575971422657913948591537428763345261
to get the answer:
insert image description here

二.Poisoned_tea_CHELL

1. Re-identify functions and program logic analysis

This may be an identification problem. Find the three red areas and check the assembly
insert image description here
, and you can find that four bytes of data are defined here inexplicably. Press u to cancel the definition of the instruction below,
insert image description here
and then press p from the data header (0x763) to identify it as a function. You can see the tea logic.
insert image description here
The other two red areas are the same. After re-identification, you can see the main function (if you can’t see it, look up the cross-reference of the tea function).
insert image description here
Here is the main function after my analysis and beautification:
but A key problem here is that its key and key data cannot be seen through static analysis , so dynamic analysis is required

__int64 __fastcall Main()
{
    
    
  __int64 result; // rax
  int i; // [rsp+Ch] [rbp-464h]
  int j; // [rsp+10h] [rbp-460h]
  int chr1; // [rsp+14h] [rbp-45Ch] BYREF
  int chr2; // [rsp+18h] [rbp-458h]
  int v5; // [rsp+1Ch] [rbp-454h]
  int key[8]; // [rsp+20h] [rbp-450h] BYREF
  int d1; // [rsp+40h] [rbp-430h]
  int d2; // [rsp+44h] [rbp-42Ch]
  int b1; // [rsp+48h] [rbp-428h]
  int b2; // [rsp+4Ch] [rbp-424h]
  int v11; // [rsp+50h] [rbp-420h]
  int buffer[258]; // [rsp+60h] [rbp-410h] BYREF
  unsigned __int64 v13; // [rsp+468h] [rbp-8h]

  v13 = __readfsqword(0x28u);
  key[0] = 5;
  key[1] = 2;
  key[2] = dword_7FA16F6F8464;                  // 猜测也是一位数,可以爆破
  key[3] = dword_7FA16F6F8454;
  key[4] = 0;
  memset(buffer, 0, 0x400uLL);
  sub_7FA16F6F5524();
  sub_7FA16F6F5554();
  sub_7FA16F6F5594();                           // 这几个函数找不到
  sub_7FA16F6F5574(&unk_7FA16F6F6469, buffer);
  chr1 = 0;
  chr2 = 0;
  v5 = 0;
  for ( i = 0; buffer[i]; i += 2 )              // 也就是每次对buffer的两个字符进行tea加密
  {
    
    
    chr1 = buffer[i];
    chr2 = buffer[i + 1];
    Tea(dword_7FA16F6F8474, &chr1, key);        // 一次加密两个字符
    buffer[i] = chr1;                           // 更新buffer串
    buffer[i + 1] = chr2;
  }
  d1 = 0;
  d2 = 0;
  b1 = 0;
  b2 = 0;
  v11 = 0;
  for ( j = 0; buffer[j]; j += 2 )              // 比较函数
  {
    
    
    d1 = desStr[j];
    d2 = desStr[j + 1];
    b1 = buffer[j];
    b2 = buffer[j + 1];
    if ( d1 != b1 || d2 != b2 )
      break;
  }
  sub_7FA16F6F5524();
  result = 0LL;
  if ( v13 != __readfsqword(0x28u) )
    return sub_7FA16F6F5544();
  return result;
}

2.IDA dynamic debugging (attach additional debugging)

If you directly use ida remote adjustment, an error will be displayed:
Input file is a dynamic library, it cannot be run by itself.
Please specify the host application (Debugger, Process options) It will
insert image description here
prompt that this is a dynamic library file and an additional process is required for debugging, then We can use IDA's additional debugging features

  1. The linux virtual machine uses root privileges to run ida's linux_server64
    must use root privileges, otherwise subsequent additional debugging will fail, because the IDA server has insufficient privileges
    insert image description here
  2. run the program
    insert image description here
  3. Additional debugging
    Debugger>Attach to process
    insert image description hereand then find the poison tea process, double-click to
    insert image description here
    select the same
    insert image description here

3. Enter options to step through

After successfully attaching, you will find that there is no response to pressing f7 or f8. At this time, the program is waiting for the output. First, enter an option in the linux virtual machine.
If you enter 1, it will be difficult to find the subsequent debugging. In short, you can find the Loading string, and be careful not to skip it
( You can’t find it by searching the string directly. This question should be that there is an SMC operation to decrypt the program code.)
The call sun_7f006f7c2536 below is the main function. Follow up and re-identify to see the logic (I won’t do a detailed introduction here, take option 2 as the main function) host)
insert image description here

If you input 2
and press f7 all the time, you can finally find that the program will get stuck, and you can still see the InputFlag string, here is the main function. Scroll up to find the
insert image description here
starting address, and press p to identify loc_loc_7F3BB0FB6536 as a function, and you can see the logic of the main function Then
insert image description here
there are still some functions that have not been correctly identified. You need to manually follow up and press p to identify them as functions, and then return to the disassembly interface and press f5 to re-identify
insert image description here
them
insert image description here
. times instead of 32 times):
insert image description here
encrypted data, follow-up can extract the data
insert image description here

4. Problem-solving script

#include<stdio.h>
void Tea(int len, unsigned int* buffer, int* key)
{
    
    
	int i; // [rsp+24h] [rbp-14h]
	unsigned int v5; // [rsp+28h] [rbp-10h]
	unsigned int v6; // [rsp+2Ch] [rbp-Ch]
	unsigned int v7; // [rsp+30h] [rbp-8h]

	v5 = *buffer;
	v6 = buffer[1];
	v7 = 0xd9b6d99c;
	for (i = 0; i < len; ++i)
	{
    
    
		v6 -= (v5 + ((v5 >> 5) ^ (16 * v5))) ^ (key[(v7 >> 11) & 3] + v7);
		v7 += 0x41104111;
		v5 -= (v6 + ((v6 >> 5) ^ (16 * v6))) ^ (key[v7 & 3] + v7);
	}
	*buffer = v5;
	buffer[1] = v6;
}
int main()
{
    
    
	int  buffer[14] =
	{
    
    
	  -318921983,
	  1639894517,
	  -1197577091,
	  -835265432,
	  1265521566,
	  1680782596,
	  1425658684,
	  1829167973,
	  -360235693,
	  -1537112825,
	  -676229584,
	  -1000652734,
	  0,
	  0,
	};
	int key[5] = {
    
     5,2,9,7,0 };
	int chr[2] = {
    
     0 };
	for (int i = 0; buffer[i]; i += 2)              // 也就是每次对buffer的两个字符进行tea加密
	{
    
    
		chr[0] = buffer[i];
		chr[1] = buffer[i + 1];
		Tea(36, chr, key);						// 一次加密两个字符
		buffer[i] = chr[0];                           // 更新buffer串
		buffer[i + 1] = chr[1];
	}
	unsigned char* p = (unsigned char*)buffer;
	printf("%s", p);
	//Thisisflag{cdfec405-3f4b-457e-92fe-f6446098ee2e}
	return 0;
}

BWBA

After a brief analysis of the program logic,
insert image description here
I asked ChatGpt to answer me about the FFT algorithm instead of DCT when I reproduced it here, and the output decryption script was always wrong. It seems that I should learn more about this algorithm. Refer to the article: 2023 Spring and Autumn Cup
Spring Competition WP-REVERSE (AK)
can be processed with cv2 library functions

import numpy as np
import cv2

x = np.array([370.75,234.362,-58.0834,59.8212,88.8221,-30.2406,21.8316,49.9781,-33.5259,2.69675,43.5386,-30.2925,-28.0754,27.593,-2.53962,-27.1883,-5.60777,-0.263937,6.80326,8.03022,-6.34681,-0.89506,-6.80685,-13.6088,27.0958,29.8439,-21.7688,-20.6925,-13.2155,-37.0994,2.23679,37.6699,-3.5,9.85188,57.2806,13.5715,-20.7184,8.6816,3.59369,-4.5302,4.22203,-28.8166,-23.695,31.2268,6.58823,-39.9966,-20.7877,-19.7624,-22.031,16.3285,2.07557,-26.2521,16.1914,18.3976,-26.9295,3.03769,41.0412,20.2598,14.991,6.99392,-22.3752,-7.24466,8.96299,-10.4874], dtype=np.float64)
x = cv2.idct(x)
x = x.ravel()
flag=''

for i in range(len(x)):
    flag+=chr(round(x[i]))
print(flag)#flag{9ab488a7-5b11-1b15-04f2-c230704ecf72}

There are a few good articles about the DCT algorithm:

  1. DCT Discrete Cosine Transform
  2. Detailed Discrete Cosine Transform (DCT)

OldSymbolicCode

Guess you like

Origin blog.csdn.net/OrientalGlass/article/details/130956132