攻防世界-逆向题-IgniteMe

题目描述:
一个pe文件
运行截图
运行截图
如果乱输入,回车后就退出了,没有循环输入的机制,也没有输入错误提示。

解题过程:
用exeinfo pe检测有
检测结果
这是一个32位没有壳的文件。

用IDA打开有:
下面是文件的main函数结构,根据提示可以确定程序正确执行步骤
IDAmain函数结构图汇编语言不好读,点击F5查看main函数伪代码有:



int __cdecl main(int argc, const char **argv, const char **envp)

{

  void *v3; // eax

  int v4; // edx

  void *v5; // eax

  int result; // eax

  void *v7; // eax

  void *v8; // eax

  void *v9; // eax

  size_t i; // [esp+4Ch] [ebp-8Ch]

  char v11[4]; // [esp+50h] [ebp-88h]

  char v12[28]; // [esp+58h] [ebp-80h]

  char v13; // [esp+74h] [ebp-64h]

 

  v3 = (void *)sub_402B30((int)&unk_446360, "Give me your flag:");

  sub_4013F0(v3, (int (__cdecl *)(void *))sub_403670);

  sub_401440((int)&dword_4463F0, v4, (int)v12, 127);

  if ( strlen(v12) < 30 && strlen(v12) > 4 )    // if条件要吻合

  {

    strcpy(v11, "EIS{");

    for ( i = 0; i < strlen(v11); ++i )

    {

      if ( v12[i] != v11[i] )            // v12是输入的值,要求以“EIS{”开头

      {

        v7 = (void *)sub_402B30((int)&unk_446360, "Sorry, keep trying! ");

        sub_4013F0(v7, (int (__cdecl *)(void *))sub_403670);

        return 0;

      }

    }

    if ( v13 == '}' )       // if条件吻合,v13 = '}',v13是v12后一个字节

    {

      if ( sub_4011C0(v12) )       // if条件要吻合,sub_4011c0(v11)返回为真

//byte_4420B0[]={0Dh,13h,17h,11h,2,1,20h,1Dh,0Ch,2,19h,2Fh,17h,2Bh,24h,1Fh,1Eh,16h,9,0Fh,15h,27h,13h,26h,0Ah,2Fh,1Eh,1Ah,2Dh,0Ch,22h,4}
// sub_4013c0 = (v8[i] ^ 0x55) + 72
// "GONDPHyGjPEKruv{{pj]X@rF" == byte_4420B0[] ^ sub_4013c0

        v9 = (void *)sub_402B30((int)&unk_446360, "Congratulations! ");
// Congratulations!这个应该就是要求的最后输出界面结果

      else

        v9 = (void *)sub_402B30((int)&unk_446360, "Sorry, keep trying! ");

      sub_4013F0(v9, (int (__cdecl *)(void *))sub_403670);

      result = 0;

    }

    else

    {

      v8 = (void *)sub_402B30((int)&unk_446360, "Sorry, keep trying! ");

      sub_4013F0(v8, (int (__cdecl *)(void *))sub_403670);

      result = 0;

    }

  }

  else

  {

    v5 = (void *)sub_402B30((int)&unk_446360, "Sorry, keep trying!");

    sub_4013F0(v5, (int (__cdecl *)(void *))sub_403670);

    result = 0;

  }

  return result;

}

里面有一个很关键的函数sub_4011C0(),函数结构如下:



bool __cdecl sub_4011C0(char *a1)

{

  size_t v2; // eax

  signed int v3; // [esp+50h] [ebp-B0h]

  char v4[32]; // [esp+54h] [ebp-ACh]

  int v5; // [esp+74h] [ebp-8Ch]

  int v6; // [esp+78h] [ebp-88h]

  size_t i; // [esp+7Ch] [ebp-84h]

  char v8[128]; // [esp+80h] [ebp-80h]

 

  if ( strlen(a1) <= 4 )                        // 不能成立, strlen > 4

    return 0;

  i = 4;

  v6 = 0;

  while ( i < strlen(a1) - 1 )

    v8[v6++] = a1[i++];                         // v8[0++] = a1[4++]

  v8[v6] = 0;                                 //v8[strlen(a1)] = 0

  v5 = 0;

  v3 = 0;

  memset(v4, 0, 32u);                           // v4[32]被初始化为0

  for ( i = 0; ; ++i )

  {

    v2 = strlen(v8);                            // v2 = strlen(a1) - 4

    if ( i >= v2 )

      break;

    if ( v8[i] >= 97 && v8[i] <= 122 )

    {

      v8[i] -= 32;                              // 小写字符转大写字符

      v3 = 1;

    }

    if ( !v3 && v8[i] >= 65 && v8[i] <= 90 )

      v8[i] += 32;                              // 大写转小写

v4[i] = byte_4420B0[i] ^ sub_4013C0(v8[i]);
//byte_4420B0[]={0Dh,13h,17h,11h,2,1,20h,1Dh,0Ch,2,19h,2Fh,17h,2Bh,24h,1Fh,1Eh,16h,9,0Fh,15h,27h,13h,26h,0Ah,2Fh,1Eh,1Ah,2Dh,0Ch,22h,4}
// sub_4013c0 = (v8[i] ^ 0x55) + 72

    v3 = 0;

  }

  return strcmp("GONDPHyGjPEKruv{{pj]X@rF", v4) == 0;

}

程序逻辑:

  1. 输入一串字符str[],要求4 < strlen(str[]) < 30;
  2. Str[]以 “EIS{” 开头, “}” 结尾;
  3. 计算满足:“GONDPHyGjPEKruv{{pj]X@rF” == byte_4420B0[] ^ sub_4013c0;即
    “GONDPHyGjPEKruv{{pj]X@rF” == ((Str[4++] ^ 0x55) + 72)^ byte_4420B0[0++],其中:byte_4420B0[]={0Dh,13h,17h,11h,2,1,20h,1Dh,0Ch,2,19h,2Fh,17h,2Bh,24h,1Fh,1Eh,16h,9,0Fh,15h,27h,13h,26h,0Ah,2Fh,1Eh,1Ah,2Dh,0Ch,22h,4};
    sub_4013c0 = (v8[i] ^ 0x55) + 72 ;
  4. 做逆运算:
    ((“GONDPHyGjPEKruv{{pj]X@rF” ^ byte_4420B0[0++]) – 72) ^ 0x55 == Str[4++]
#include<stdio.h>
#include<string.h>
int main()
{
    char str1[] = "GONDPHyGjPEKruv{{pj]X@rF";
    int str2[] = {0x0D, 0x13, 0x17, 0x11, 2, 1, 0x20, 0x1D, 0x0C, 2, 0x19, 0x2F, 0x17, 0x2B, 0x24, 0x1F,
               0x1E, 0x16, 9, 0x0F, 0x15, 0x27, 0x13, 0x26, 0x0A, 0x2F, 0x1E, 0x1A, 0x2D, 0x0C, 0x22, 4};
    int len = strlen(str1);
// printf("%d", len);
    char flag[24];
    int i;
    for(i = 0; i < len; i++)
    {
           flag[i] = ((str1[i] ^ str2[i]) - 72) ^ 0x55;
           printf("%c", flag[i]);
    }
    printf("\n");
}

运行程序可以得出:WADX_TDGK_AIHC_IHKN_PJLM
最终答案:EIS{wadx_tdgk_aihc_ihkn_pjlm}

题目总结:
这个题目函数还是蛮多蛮长的,从头看的话难免会厌烦。可以先大概地看一遍,捋一捋大概流程,因为它给出了详细的提示信息,所以我们可以直接判断出函数的正确执行路线,然后根据最后的正确输出提示倒推,从最后面的函数一步步倒着看上去,然后就可以很高效地得到具体转换方式。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值