Re刷题记录(二)

  1. [FlareOn6]Overlong
  2. [ACTF新生赛2020]Oruga

[FlareOn6]Overlong

进入主函数:

int __stdcall start(int a1, int a2, int a3, int a4)
{
  char Text[128]; // [esp+0h] [ebp-84h] BYREF
  unsigned int v6; // [esp+80h] [ebp-4h]

  v6 = sub_401160(Text, (int)&unk_402008, 0x1Cu);
  //对unk_402008的前28格字符进行操作,unk_402008是给了的,含100多个字符
  Text[v6] = 0;
  MessageBoxA(0, Text, Caption, 0);
  return 0;
}

直接执行exe文件,输出:

image-20230726131750408

只输出了前28个字符,末尾有冒号,后面应该就是flag。

嵌套的sub_401160和sub_401000不需要看懂。两种解决方法:

法一:

因为函数不多,将所有的照着复制下来,修改传入的长度以及部分变量的数据类型:

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

int __cdecl sub_401000(char *a1, char *a2)
{
  int v3; // [esp+0h] [ebp-8h]
  char v4; // [esp+4h] [ebp-4h]

  if ( (int)(unsigned __int8)*a2 >> 3 == 30 )
  {
    v4 = a2[3] & 0x3F | ((a2[2] & 0x3F) << 6);
    v3 = 4;
  }
  else if ( (int)(unsigned __int8)*a2 >> 4 == 14 )
  {
    v4 = a2[2] & 0x3F | ((a2[1] & 0x3F) << 6);
    v3 = 3;
  }
  else if ( (int)(unsigned __int8)*a2 >> 5 == 6 )
  {
    v4 = a2[1] & 0x3F | ((*a2 & 0x1F) << 6);
    v3 = 2;
  }
  else
  {
    v4 = *a2;
    v3 = 1;
  }
  *a1 = v4;
  return v3;
}

unsigned int __cdecl sub_401160(char *a1, char *a2, unsigned int a3)
{
  unsigned int i; // [esp+4h] [ebp-4h]

  for ( i = 0; i < a3; ++i )
  {
    a2 += sub_401000(a1, a2);
    if ( !*a1++ )
      break;
  }
  return i;
}

int main(){
    char unk_402008[] =
    {
      0xE0, 0x81, 0x89, 0xC0, 0xA0, 0xC1, 0xAE, 0xE0, 0x81, 0xA5, 
      0xC1, 0xB6, 0xF0, 0x80, 0x81, 0xA5, 0xE0, 0x81, 0xB2, 0xF0, 
      0x80, 0x80, 0xA0, 0xE0, 0x81, 0xA2, 0x72, 0x6F, 0xC1, 0xAB, 
      0x65, 0xE0, 0x80, 0xA0, 0xE0, 0x81, 0xB4, 0xE0, 0x81, 0xA8, 
      0xC1, 0xA5, 0x20, 0xC1, 0xA5, 0xE0, 0x81, 0xAE, 0x63, 0xC1, 
      0xAF, 0xE0, 0x81, 0xA4, 0xF0, 0x80, 0x81, 0xA9, 0x6E, 0xC1, 
      0xA7, 0xC0, 0xBA, 0x20, 0x49, 0xF0, 0x80, 0x81, 0x9F, 0xC1, 
      0xA1, 0xC1, 0x9F, 0xC1, 0x8D, 0xE0, 0x81, 0x9F, 0xC1, 0xB4, 
      0xF0, 0x80, 0x81, 0x9F, 0xF0, 0x80, 0x81, 0xA8, 0xC1, 0x9F, 
      0xF0, 0x80, 0x81, 0xA5, 0xE0, 0x81, 0x9F, 0xC1, 0xA5, 0xE0, 
      0x81, 0x9F, 0xF0, 0x80, 0x81, 0xAE, 0xC1, 0x9F, 0xF0, 0x80, 
      0x81, 0x83, 0xC1, 0x9F, 0xE0, 0x81, 0xAF, 0xE0, 0x81, 0x9F, 
      0xC1, 0x84, 0x5F, 0xE0, 0x81, 0xA9, 0xF0, 0x80, 0x81, 0x9F, 
      0x6E, 0xE0, 0x81, 0x9F, 0xE0, 0x81, 0xA7, 0xE0, 0x81, 0x80, 
      0xF0, 0x80, 0x81, 0xA6, 0xF0, 0x80, 0x81, 0xAC, 0xE0, 0x81, 
      0xA1, 0xC1, 0xB2, 0xC1, 0xA5, 0xF0, 0x80, 0x80, 0xAD, 0xF0, 
      0x80, 0x81, 0xAF, 0x6E, 0xC0, 0xAE, 0xF0, 0x80, 0x81, 0xA3, 
      0x6F, 0xF0, 0x80, 0x81, 0xAD, 0x00
    };
    char Text[128]; // [esp+0h] [ebp-84h] BYREF
    int v6; // [esp+80h] [ebp-4h]

    v6 = sub_401160(Text, unk_402008, 128);
    Text[v6] = 0;
    for(int i=0; i<128; i++)
        printf("%c",Text[i]); 
    return 0;
} 

得到:

image-20230726132206846

法二:

ollydbg动态调试。找到需要修改的地址:

image-20230726140210961

这里不能双击用汇编直接修改,不然下面的push会被覆盖掉。具体操作:

在机器码处,右键,点击二进制直接修改:

image-20230726140619117

然后运行得到:

image-20230726140823557

法三:

用010打开exe文件,直接修改

image-20230726135631167

这里我已经把原本的1C修改为66了,保存后直接执行:

image-20230726135712600

[ACTF新生赛2020]Oruga

主要函数:

_BOOL8 __fastcall sub_78A(__int64 a1)
{
  int v2; // [rsp+Ch] [rbp-Ch]
  int v3; // [rsp+10h] [rbp-8h]
  int v4; // [rsp+14h] [rbp-4h]

  v2 = 0;
  v3 = 5;
  v4 = 0;
  while ( qword_201020[v2] != 33 )
  {
    v2 -= v4;
    if ( *(_BYTE *)(v3 + a1) != 87 || v4 == -16 )//87为W
    {
      if ( *(_BYTE *)(v3 + a1) != 69 || v4 == 1 )//69为E
      {
        if ( *(_BYTE *)(v3 + a1) != 77 || v4 == 16 )//77为M
        {
          if ( *(_BYTE *)(v3 + a1) != 74 || v4 == -1 )//74为J
            return 0LL;
          v4 = -1;
        }
        else
        {
          v4 = 16;
        }
      }
      else
      {
        v4 = 1;
      }
    }
    else
    {
      v4 = -16;
    }
    ++v3;
    while ( !qword_201020[v2] )
    {
      if ( v4 == -1 && (v2 & 0xF) == 0 )
        return 0LL;
      if ( v4 == 1 && v2 % 16 == 15 )
        return 0LL;
      if ( v4 == 16 && (unsigned int)(v2 - 240) <= 0xF )
        return 0LL;
      if ( v4 == -16 && (unsigned int)(v2 + 15) <= 0x1E )
        return 0LL;
      v2 += v4;
    }
  }
  return *(_BYTE *)(v3 + a1) == 125;/125为},判断最后一位是否为}
}

分析主要代码得知是迷宫题。

W向上,M向下,J向左,E向右。且遇到障碍会停下来。

进入qword_201020获取迷宫数据,0为能走的路,0x21为终点,其它值不能走:

#include <stdio.h>
char maze[256] = {
    0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x23, 0x23,
    0x00, 0x00, 0x00, 0x23, 0x23, 0x00, 0x00, 0x00, 0x4F, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x4F, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x4C, 0x00, 0x4F, 0x4F, 0x00, 0x4F, 0x4F, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x4C, 0x00, 0x4F, 0x4F, 0x00, 0x4F, 0x4F, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x4C, 0x4C, 0x00, 0x4F, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00,
    0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x45, 0x45,
    0x00, 0x00, 0x00, 0x30, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x45,
    0x54, 0x54, 0x54, 0x49, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00,
    0x00, 0x54, 0x00, 0x49, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00,
    0x00, 0x54, 0x00, 0x49, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x4D, 0x21, 0x00, 0x00, 0x00, 0x45, 0x45
};
int main(void)
{
    int i, j;
    for (i = 0; i < 16; i++)
    {
        for (j = 0; j < 16; j++)
        {
            if (i == 0 && j == 0)
                printf("☆");  //起点
            else if (maze[16 * i + j] == 0)
                printf("□");  //路
            else if (maze[16 * i + j] == 0x21)
                printf("★");  //终点
            else printf("■"); //障碍物
        }
        putchar('\n');
    }
}

image-20230726150421949

flag{MEWEMEWJMEWJM}

参考:

[(1条消息) re学习笔记(59)BUUCTF - re - [ACTF新生赛2020]Oruga_Forgo7ten的博客-CSDN博客](https://blog.csdn.net/Palmer9/article/details/105274167/?ops_request_misc=&request_id=&biz_id=102&utm_term=buuctf re [ACTF新生赛2020]Oruga&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-105274167.142^v91^koosearch_v1,239^v3^control&spm=1018.2226.3001.4187)


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1666739907@qq.com
github