攻防世界 流浪者

附件是可执行文件,运行会弹出窗口

在这里插入图片描述

在这里插入图片描述

放入IDA中看看

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
}

main函数是WinMain,并不是判断输入的逻辑函数。

在IDA中搜索字符串"请输入pass"的位置
在这里插入图片描述

按x找到引用这个字符串的汇编代码,再反编译

int __thiscall sub_401890(CWnd *this)
{
  CWnd *v1; // eax
  int v2; // eax
  struct CString *v4; // [esp-4h] [ebp-C4h]
  int v5[26]; // [esp+4Ch] [ebp-74h] BYREF
  int i; // [esp+B4h] [ebp-Ch]
  char *Str; // [esp+B8h] [ebp-8h]
  CWnd *v8; // [esp+BCh] [ebp-4h]

  v8 = this;
  v4 = (CWnd *)((char *)this + 100);
  v1 = CWnd::GetDlgItem(this, 1002);
  CWnd::GetWindowTextA(v1, v4);
  v2 = sub_401A30((char *)v8 + 100);
  Str = CString::GetBuffer((CWnd *)((char *)v8 + 100), v2);
  if ( !strlen(Str) )
    return CWnd::MessageBoxA(v8, "请输入pass!", 0, 0);
  for ( i = 0; Str[i]; ++i )
  {
    if ( Str[i] > 57 || Str[i] < 48 )
    {
      if ( Str[i] > 122 || Str[i] < 97 )
      {
        if ( Str[i] > 90 || Str[i] < 65 )
          sub_4017B0();
        else
          v5[i] = Str[i] - 29;
      }
      else
      {
        v5[i] = Str[i] - 87;
      }
    }
    else
    {
      v5[i] = Str[i] - 48;
    }
  }
  return sub_4017F0(v5);
}

就看到了判断函数sub_401890。分析它的逻辑,逐个判断输入的字母

if ( Str[i] > 57 || Str[i] < 48 ) // 如果不是数字
if ( Str[i] > 122 || Str[i] < 97 )//如果不是小写字母
if ( Str[i] > 90 || Str[i] < 65 )//如果不是大写字母

分析出输入只能有数字和字母。

并且数字、小写字母、大写字母的ASCII码分别减去48、87、29,然后将结果放入v5中交给sub_4017F0函数判断

int __cdecl sub_4017F0(int a1)
{
  int result; // eax
  char Str1[28]; // [esp+D8h] [ebp-24h] BYREF
  int v3; // [esp+F4h] [ebp-8h]
  int v4; // [esp+F8h] [ebp-4h]

  v4 = 0;
  v3 = 0;
  while ( *(int *)(a1 + 4 * v4) < 62 && *(int *)(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;
}

转为可运行的C代码

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

a1中的值作为下标检索字符串aAbcdefghiabcde的内容,然后将检索结果与"KanXueCTF2019JustForhappy"比较,相同表示输入正确。

写逆转脚本

def repair(c: int):
    if 48 <= c+48 <= 57:
        return chr(c+48)
    elif 97 <= c+87 <= 122:
        return chr(c+87)
    else:
        return chr(c+29)


aAbcdefghiabcde = 'abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ'
str = 'KanXueCTF2019JustForhappy'
flag = ''
for c in str:
    flag += repair(aAbcdefghiabcde.index(c))
print('flag{'+flag+'}')

得到flag{j0rXI4bTeustBiIGHeCF70DDM}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值