zoukankan      html  css  js  c++  java
  • 流浪者-CTF

    0x01

    拿到题目后是一个exe程序,首先看一下运行结果,那么一共有两种结果,一种是如果密码为空,则提示重新输入,如果输入错误,则提示加油,如下图:

    输入错误后程序会退出

    0x02

    放进IDA进行静态分析,看下主要代码是如何运行

    进入以后首先字符串查找 shift+F12,结果如图:

    那么我们看到了pass!,而且还有两串可疑的字符串,所以我们去看看

    BOOL sub_401770()
    {
      HANDLE hProcess; // ST5C_4
    
      MessageBoxA(0, "pass!", &Caption, 0);
      hProcess = GetCurrentProcess();
      return TerminateProcess(hProcess, 0);
    }
    

    这段代码就是返回pass的,所以我们看看谁调用了这段代码

    经过查找是我箭头处调用了这段代码,所以通过分析,我们知道,通过字符串比较,然后决定是返回sub_401770()—>PASS!还是sub_4017B0()—>错了,加油!

    BOOL __cdecl sub_4017F0(int a1)
    {
      BOOL result; // eax
      char Str1[28]; // [esp+D8h] [ebp-24h]
      int v3; // [esp+F4h] [ebp-8h]
      int v4; // [esp+F8h] [ebp-4h]
    
      v4 = 0;
      v3 = 0;
      while ( *(_DWORD *)(a1 + 4 * v4) < 62 && *(_DWORD *)(a1 + 4 * v4) >= 0 )
      {
        Str1[v4] = aAbcdefghiabcde[*(_DWORD *)(a1 + 4 * v4)];
        ++v4;
      }
      Str1[v4] = 0;
      if ( !strcmp(Str1, "KanXueCTF2019JustForhappy") )
        result = sub_401770();
      else
        result = sub_4017B0();
      return result;
    }
    

    所以我们知道它应该是将Str1和"KanXueCTF2019JustForhappy"作比较,所以我们就逆着去看看这个Str1怎么来的,向上看是这段代码:

    while ( *(_DWORD *)(a1 + 4 * v4) < 62 && *(_DWORD *)(a1 + 4 * v4) >= 0 )
      {
        Str1[v4] = aAbcdefghiabcde[*(_DWORD *)(a1 + 4 * v4)];
        ++v4;
      }
    

    很容易看出,是将aAbcdefghiabcde[*(_DWORD *)(a1 + 4 * v4)]赋值给了Str1

    那么知道赋值的字符串数组了,接下来要解决的就是下标问题了,下标解决了,那么也就知道了Str1了

    下标怎么来的呢?

    这段就是计算下标,然后进行赋值的关键代码

    int __thiscall sub_401890(CWnd *this)
    {
      struct CString *v1; // ST08_4
      CWnd *v2; // eax
      int v3; // eax
      int v5[26]; // [esp+4Ch] [ebp-74h]
      int i; // [esp+B4h] [ebp-Ch]
      char *Str; // [esp+B8h] [ebp-8h]
      CWnd *v8; // [esp+BCh] [ebp-4h]
    
      v8 = this;
      v1 = (CWnd *)((char *)this + 100);
      v2 = CWnd::GetDlgItem(this, 1002);
      CWnd::GetWindowTextA(v2, v1);
      v3 = sub_401A30((char *)v8 + 100);
      Str = CString::GetBuffer((CWnd *)((char *)v8 + 100), v3);
      if ( !strlen(Str) )
        return CWnd::MessageBoxA(v8, &byte_4035DC, 0, 0);
      for ( i = 0; Str[i]; ++i )
      {
        if ( Str[i] > '9' || Str[i] < '0' )
        {
          if ( Str[i] > 'z' || Str[i] < 'a' )
          {
            if ( Str[i] > 'Z' || Str[i] < 'A' )
              sub_4017B0();
            else
              v5[i] = Str[i] - 29;
          }
          else
          {
            v5[i] = Str[i] - 87;
          }
        }
        else
        {
          v5[i] = Str[i] - 48;
        }
      }
      return sub_4017F0((int)v5);
    }
    

    通过分析就是将我们输入的字符串进行了减法运算,然后赋值给Str1,再将Str1与"KanXueCTF2019JustForhappy"作比较,所以我们可以将"KanXueCTF2019JustForhappy"进行逆运算,得到Str1,就是获得flag

    0x03

    下面是我编写的脚本:

    str1 = 'KanXueCTF2019JustForhappy'
    str2 = 'abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ'
    flag = ''
    for i in range(int(len(str1))):
        for j in range(int(len(str2))):
            if str1[i] == str2[j]:
                if((j + 48 >= 48 ) and (j + 48 <= 57 )):
                    flag += chr(j + 48)
                elif((j + 87 >= 97 ) and (j + 87 <= 122 )):
                    flag += chr(j + 87)
                elif((j + 29 >= 65 ) and (j + 29 <= 90 )):
                    flag += chr(j + 29)
    
    print(flag)
    
    

    运行结果:

    拿到flag

  • 相关阅读:
    HDU Problem 1811 Rank of Tetris【拓扑排序+并查集】
    POJ Problem 2367 Genealogical tree【拓扑排序】
    HDU Problem 2647 Reward【拓扑排序】
    HDU Problem 1285 确定比赛名次【拓扑排序】
    HDU Problem HDU Today 【最短路】
    HDU Problem 3665 Seaside【最短路】
    HDU Problem 一个人的旅行 【最短路dijkstra】
    HDU Problem 1596 find the safest road【最短路dijkstra】
    Beyond Compare文本合并进行内容替换要注意什么
    用这些工具都可以比较代码的差异
  • 原文地址:https://www.cnblogs.com/Jleixin/p/13069837.html
Copyright © 2011-2022 走看看