zoukankan      html  css  js  c++  java
  • IDF-CTF-简单的Elf逆向Writeup

    ElfCrackMe1

    简单的Elf逆向Writeup

    题目来源:IDF实验室 CTF训练营;题目链接http://ctf.idf.cn/index.php?g=game&m=article&a=index&id=39
    题目下载:http://pan.baidu.com/s/1kTl5wxD

    解法1:

    IDA查看伪代码法:

    1. 下载文件,现在Linux环境下运行,可以看到关键字符串u r wrongplz enter the flag:
    2. 把文件拖到IDA中,shift+F12查找字符串,双击u r right跳转到相应位置
    3. 如下图,双击调用关键字符串u r right的函数,
      跳转后F5查看伪代码如下
       1 int __cdecl main(int argc, const char **argv, const char **envp)
       2 {
       3   int v3; // ebx@6
       4   const char **v4; // rdx@22
       5   __int64 v6; // [sp+0h] [bp-C0h]@1
       6   __int64 v7; // [sp+8h] [bp-B8h]@1
       7   __int64 v8; // [sp+10h] [bp-B0h]@1
       8   __int64 v9; // [sp+18h] [bp-A8h]@1
       9   __int64 v10; // [sp+20h] [bp-A0h]@1
      10   __int64 v11; // [sp+28h] [bp-98h]@1
      11   __int64 v12; // [sp+30h] [bp-90h]@1
      12   __int64 v13; // [sp+38h] [bp-88h]@1
      13   int v14; // [sp+40h] [bp-80h]@1
      14   char v15[17]; // [sp+80h] [bp-40h]@2
      15   char v16; // [sp+91h] [bp-2Fh]@14
      16   char v17; // [sp+92h] [bp-2Eh]@15
      17   char v18; // [sp+93h] [bp-2Dh]@16
      18   char v19; // [sp+94h] [bp-2Ch]@17
      19   char v20; // [sp+95h] [bp-2Bh]@18
      20   int v21; // [sp+A4h] [bp-1Ch]@1
      21   int v22; // [sp+A8h] [bp-18h]@7
      22   int i; // [sp+ACh] [bp-14h]@9
      23 
      24   v21 = 0;
      25   memset(&v6, 0, 0x58uLL);
      26   v6 = 854698492143LL;
      27   v7 = 880468295913LL;
      28   v8 = 597000454391LL;
      29   v9 = 605590388953LL;
      30   v10 = 932007903423LL;
      31   v11 = 760209211613LL;
      32   v12 = 579820585151LL;
      33   v13 = 940597838039LL;
      34   v14 = 191;
      35   printf(
      36     "plz enter the flag:",
      37     argv,
      38     11LL,
      39     854698492143LL,
      40     880468295913LL,
      41     597000454391LL,
      42     605590388953LL,
      43     932007903423LL,
      44     760209211613LL,
      45     579820585151LL,
      46     940597838039LL,
      47     *(_QWORD *)&v14);
      48   while ( 1 )
      49   {
      50     v3 = v21;
      51     v15[v3] = getch();
      52     if ( !v15[v3] || v15[v21] == 10 )
      53       break;
      54     if ( v15[v21] == 8 )
      55     {
      56       printf("", v6, v7, v8, v9, v10, v11, v12, v13, *(_QWORD *)&v14);
      57       --v21;
      58     }
      59     else
      60     {
      61       putchar(v15[v21++]);
      62     }
      63   }
      64   v22 = 0;
      65   if ( v21 != 22 )
      66     v22 = 1;
      67   for ( i = 0; i <= 16; ++i )
      68   {
      69     if ( v15[i] != (*((_DWORD *)&v6 + i) - 1) / 2 )
      70     {
      71       v22 = 1;
      72       argv = (const char **)((*((_DWORD *)&v6 + i) - 1) / 2);
      73       printf("%d", argv, v6, v7, v8, v9, v10, v11, v12, v13, *(_QWORD *)&v14);
      74     }
      75   }
      76   if ( v16 != 48 || v17 != 56 || v18 != 50 || v19 != 51 || v20 != 125 )
      77     v22 = 1;
      78   v15[v21] = 0;
      79   puts("
      ");
      80   if ( v22 )
      81   {
      82     puts("u r wrong
      
      ");
      83     main((unsigned __int64)"u r wrong
      
      ", argv, v4);
      84   }
      85   else
      86   {
      87     puts("u r right!
      ");
      88   }
      89   return 0;
      90 }
      View Code

    分析这段伪代码,可以得到关键部分如下:

    • v22需为0,按'/'随手注释
    • 如上图中所示,要使v22==0,所有v22=1的语句均不能运行,则需要:v21==22,69行判断均不进入,既要 v15[i] != (*((_DWORD *)&v6 + i) - 1) / 2,同时,v16~v20依次等于48,56,50,51,125,即字符0823}(在相应数字上按r键把相应的ASCII码转换为字符)
      同样按'/'键随手注释
    • 找到定义v15的代码处,则根据上述的关键条件,初步猜测需要输入22位字符,其中前17位存入字符串v15中,后5位覆盖v16~v20的取值,使v16~v20分别等于0823}
    • 继续向下分析,找到输入的代码块,经过分析可得到关键信息如上图,其中v21即为输入的长度,通过关键条件v21==22验证了猜测输入字符串长度为22,同时需要保证输入的后五位为0823}
    • 向下分析v15需要满足的条件,着重分析v15[i] != (*((_DWORD *)&v6 + i) - 1) / 2

      &v6为取v6的地址;(_DWORD *)&v6强制转化为_DWORD型指针,即两个字节;((_DWORD *)&v6 + i)为从&v6向后取sizeof(_DWORD)*i个字节;*((_DWORD *)&v6 + i) - 1)为取从&v6向后取4i个字节的值
      关于地址与指针加减问题http://www.cnblogs.com/WangAoBo/p/6365114.html

    • 如上,分析v6的赋值段代码,v6~v13为_int64型,占8个字节,int型为4个字节,化为16进制如上图
    • v6~v14通过小端存储方式在内存中的存储情况如上

    则可写出python脚本解得flag: wctf{ElF_lnX_Ckm_0823}


    python脚本如下:

     1 v6=[0x0EF, 0x0C7, 0x0E9, 0x0CD, 0x0F7, 0x8B, 0x0D9,
     2     0x8D, 0x0BF, 0x0D9, 0x0DD, 0x0B1, 0x0BF, 0x87,
     3     0x0D7, 0x0DB, 0x0BF]
     4 
     5 L=[]
     6 for i in range(17):
     7     num = (v6[i] - 1)/2
     8     ans = chr(int(num))
     9     L.append(ans)
    10 
    11 
    12 flag = ''.join(L)
    13 flag+='0823}'
    14 
    15 print(flag)

      

  • 相关阅读:
    Linux基础(Ubuntu16.04):安装vim及配置
    Ubuntu16.04 安装ROS及其IDE
    python格式转换的记录
    python爬虫selenium相关
    【LAMP】搭建Web网站过程中的记录【Ubuntu18.04+Apache2.4+PHP7.2+MySQL5.7】
    【疯狂挖坑】linux服务器尝试中的问题(nohup等)
    逻辑回归与全连接神经网络联系的简单理解记录
    Unity3d开发中遇到的问题记录
    python中numpy库的一些使用
    Deep Learning论文翻译(Nature Deep Review)
  • 原文地址:https://www.cnblogs.com/WangAoBo/p/6365987.html
Copyright © 2011-2022 走看看