CTF-RE-What

首先我们用FileAnalysisv判断文件可能的格式,可知极有可能是win32下的Exe文件,于是我们加上拓展名.exe,于是可以正常打开这个程序,如下:

然后把它扔进ida进行反汇编,根据伪代码的特性可以大致断定是一个C++写出的程序,其中main函数的伪代码如下

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [esp+1Ch] [ebp-48h]
  int v5; // [esp+20h] [ebp-44h]
  char v6[32]; // [esp+24h] [ebp-40h]
  char v7; // [esp+44h] [ebp-20h]
  int v8; // [esp+45h] [ebp-1Fh]
  __int16 v9; // [esp+49h] [ebp-1Bh]
  char v10; // [esp+4Bh] [ebp-19h]
  int k; // [esp+4Ch] [ebp-18h]
  int j; // [esp+50h] [ebp-14h]
  int i; // [esp+54h] [ebp-10h]
  int v14; // [esp+58h] [ebp-Ch]
  int v15; // [esp+5Ch] [ebp-8h]

  __main();
  v8 = 0;
  v9 = 0;
  v10 = 0;
  memset(v6, 0, sizeof(v6));
  v7 = 0;
  v5 = 0;
  v4 = 0;
  v15 = 0;
  v14 = 0;
  printf("Please input your luck string:");
  scanf("%s", &v8);
  if ( strlen((const char *)&v8) != 6 )//限制输入的luckstring长度为6
    return 0;
  for ( i = 0; i <= 5; ++i )
  {
    if ( *((_BYTE *)&v8 + i) <= 96 || *((_BYTE *)&v8 + i) > 122 )
      return 0;
  }//限制luckstring全部由小写字母组成
  getMD5((char *)&v8, v6);//对luckstring进行md5加密存进V6数组
  for ( j = 0; j <= 31; ++j )//可初步断定加密后数组长度为32位
  {
    if ( v6[j] == 48 )//v15记录为0的位置个数
    {//v14记录所有为0的位置编号的和
      ++v15;
      v14 += j;
    }
  }
  if ( 10 * v15 + v14 == 403 )//表达式为403的时候进行加密和decode函数
  {
    for ( k = 0; k <= 3; ++k )
    {
      *((_BYTE *)&v5 + k) = v6[k];
      *((_BYTE *)&v4 + k) = v6[k + 28];
    }
    decode((unsigned __int8 *)&v4);
  }
  check((unsigned __int8 *)&v5);
  return 0;
}

虽然我们不知道flag是什么时候出现的,但是decode函数是编码函数这一点没有问题。所以我们首先探索什么样的luck string满足if表达式中的条件。

首要的任务是md5加密。这里有两种方法,第一种是点getMD5函数然后用C++逐层分析出来加密源代码,然后分6层枚举luckstring。但是由于本人代码能力较弱,还原出来的getMD5函数BUG太多,所以我选择了用Java里面自带的MD5加密方法:

package md5;
 
import java.math.BigInteger;
import java.security.MessageDigest;
 
public class AppMD5Util {
    public static String MD5(String s) {
        char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};   
        try {
            byte[] btInput = s.getBytes();
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
         public static void main(String[] args) {
              for(int i1=97;i1<=122;i1++)
            	  for(int i2=97;i2<=122;i2++)
            		  for(int i3=97;i3<=122;i3++)
            		  	  for(int i4=97;i4<=122;i4++)
            		  		  for(int i5=97;i5<=122;i5++)
            		  			  for(int i6=97;i6<=122;i6++) {
            		  				  char a=(char)i1,b=(char)i2,c=(char)i3;
            		  				  char d=(char)i4,e=(char)i5,f=(char)i6;
            		  				  String temp=a+""+b+""+c+""+d+""+e+""+f;
            		  				  String code=MD5(temp);
            		  				  char[] Code=code.toCharArray();
            		  				  int cnt2=0,cnt1=0;
            		  				  for(int i=0;i<=31;i++)
            		  					  if(Code[i]==48) {
            		  						  cnt2++;cnt1+=i;
            		  					  }
            		  				  System.out.println(temp);
            		  				  if(10*cnt2+cnt1==403) {
            		  					  System.out.println(temp);
            		  					  System.exit(0);
            		  				  }
            		  					
            		  			  }
        	 /*String temp="ozulmt";
        	 System.out.println(MD5(temp));*/
    }
}

等待的时间可能比较长,但是跑出来"ozulmt"还是没问题的,这就是我们需要的luckstring。在输入之后,程序又提示我们输入flag。

我们首先打印出md5加密后的luckstring(被程序存在v6中):0ec448d42dbf0000c020c0000048010e

接着我们把main函数里面的v4,v5数组计算出来,这个很容易知道他们分别是v6开头4个元素和结尾4个元素

v4="010e",v5="0ec4"

然后我们自然会想到点进后面的decode和check函数里面,但是进入decode之后我们发现它使用了check函数的指针,点进check函数之后发现竟然只有一个return。我们再来分析decode函数

// write access to const memory has been detected, the output may be wrong!
signed int __cdecl decode(unsigned __int8 *a1)
{
  signed int result; // eax
  signed int j; // [esp+24h] [ebp-14h]
  signed int i; // [esp+28h] [ebp-10h]
  unsigned int v4; // [esp+2Ch] [ebp-Ch]

  v4 = 0;
  for ( i = 0; i <= 3; ++i )
    v4 += a1[i];
  srand(v4);//种子是一定的,产生随机数的顺序是一定的,说明check函数在以后的进程中可以被还原
  *(_BYTE *)check ^= 0x96u;
  for ( j = 1; ; ++j )
  {
    result = j;
    if ( j >= 305 )
      break;
    *((_BYTE *)check + j) ^= rand();
  }
  return result;
}

我们发现这个decode函数居然是给check函数还原用的……不过总归找到了方向,我们在x32dbg中动态调试,跟到decode函数内部,并且密切关注Check函数地址。最后我们终于能够进入check函数的汇编代码

0040262 | 55                      | push ebp                                |
0040262 | 89 E5                   | mov ebp,esp                             |
0040262 | 57                      | push edi                                |
0040262 | 53                      | push ebx                                |
0040262 | 83 C4 80                | add esp,FFFFFF80                        |
0040262 | C7 45 F4 00 00 00 00    | mov dword ptr ss:[ebp-C],0              |
0040263 | C7 45 F0 00 00 00 00    | mov dword ptr ss:[ebp-10],0             |
0040263 | 83 7D F0 03             | cmp dword ptr ss:[ebp-10],3             |
0040264 | 7F 17                   | jg what.402659                          |
0040264 | 8B 55 F0                | mov edx,dword ptr ss:[ebp-10]           |
0040264 | 8B 45 08                | mov eax,dword ptr ss:[ebp+8]            |
0040264 | 01 D0                   | add eax,edx                             |
0040264 | 0F B6 00                | movzx eax,byte ptr ds:[eax]             |
0040264 | 0F B6 C0                | movzx eax,al                            |
0040265 | 01 45 F4                | add dword ptr ss:[ebp-C],eax            |
0040265 | 83 45 F0 01             | add dword ptr ss:[ebp-10],1             |
0040265 | EB E3                   | jmp what.40263C                         |
0040265 | 8B 45 F4                | mov eax,dword ptr ss:[ebp-C]            |
0040265 | 89 04 24                | mov dword ptr ss:[esp],eax              | [esp]:0ec40ec448d42dbf0000c020c0000048010e
0040265 | E8 C6 FD FF FF          | call what.40242A                        |
0040266 | 8D 45 95                | lea eax,dword ptr ss:[ebp-6B]           |
0040266 | B9 21 00 00 00          | mov ecx,21                              |
0040266 | BB 00 00 00 00          | mov ebx,0                               |
0040267 | 89 18                   | mov dword ptr ds:[eax],ebx              |
0040267 | 89 5C 08 FC             | mov dword ptr ds:[eax+ecx-4],ebx        |
0040267 | 8D 50 04                | lea edx,dword ptr ds:[eax+4]            |
0040267 | 83 E2 FC                | and edx,FFFFFFFC                        |
0040267 | 29 D0                   | sub eax,edx                             |
0040267 | 01 C1                   | add ecx,eax                             |
0040268 | 83 E1 FC                | and ecx,FFFFFFFC                        |
0040268 | C1 E9 02                | shr ecx,2                               |
0040268 | 89 D7                   | mov edi,edx                             |
0040268 | 89 D8                   | mov eax,ebx                             |
0040268 | F3 AB                   | rep stosd dword ptr es:[edi],eax        |
0040268 | C7 04 24 01 00 00 00    | mov dword ptr ss:[esp],1                | [esp]:0ec40ec448d42dbf0000c020c0000048010e
0040269 | E8 32 FD FF FF          | call what.4023CB                        |
0040269 | 8D 45 B6                | lea eax,dword ptr ss:[ebp-4A]           |
0040269 | 89 04 24                | mov dword ptr ss:[esp],eax              | [esp]:0ec40ec448d42dbf0000c020c0000048010e
0040269 | E8 AD FD FF FF          | call what.402451                        |
004026A | 8D 45 B6                | lea eax,dword ptr ss:[ebp-4A]           |
004026A | 89 04 24                | mov dword ptr ss:[esp],eax              | [esp]:0ec40ec448d42dbf0000c020c0000048010e
004026A | E8 BE FD FF FF          | call what.40246D                        |
004026A | C7 45 EC 00 00 00 00    | mov dword ptr ss:[ebp-14],0             |
004026B | 83 7D EC 1F             | cmp dword ptr ss:[ebp-14],1F            |
004026B | 7F 25                   | jg what.4026E1                          |
004026B | C7 04 24 10 00 00 00    | mov dword ptr ss:[esp],10               | [esp]:0ec40ec448d42dbf0000c020c0000048010e
004026C | E8 76 FD FF FF          | call what.40243E                        |
004026C | 0F B6 80 60 60 40 00    | movzx eax,byte ptr ds:[eax+406060]      | eax+406060:"0123456789abcdef"
004026C | 89 C1                   | mov ecx,eax                             |
004026D | 8D 55 95                | lea edx,dword ptr ss:[ebp-6B]           |
004026D | 8B 45 EC                | mov eax,dword ptr ss:[ebp-14]           |
004026D | 01 D0                   | add eax,edx                             |
004026D | 88 08                   | mov byte ptr ds:[eax],cl                |
004026D | 83 45 EC 01             | add dword ptr ss:[ebp-14],1             |
004026D | EB D5                   | jmp what.4026B6                         |
004026E | C7 45 F4 00 00 00 00    | mov dword ptr ss:[ebp-C],0              |
004026E | C7 45 E8 00 00 00 00    | mov dword ptr ss:[ebp-18],0             |
004026E | 8D 45 B6                | lea eax,dword ptr ss:[ebp-4A]           |
004026F | 89 04 24                | mov dword ptr ss:[esp],eax              | [esp]:0ec40ec448d42dbf0000c020c0000048010e
004026F | E8 BE FC FF FF          | call what.4023B8                        |
004026F | 3B 45 E8                | cmp eax,dword ptr ss:[ebp-18]           |
004026F | 0F 9F C0                | setg al                                 |
0040270 | 84 C0                   | test al,al                              |
0040270 | 74 2A                   | je what.40272E                          |
0040270 | 8D 55 B6                | lea edx,dword ptr ss:[ebp-4A]           |
0040270 | 8B 45 E8                | mov eax,dword ptr ss:[ebp-18]           |
0040270 | 01 D0                   | add eax,edx                             |
0040270 | 0F B6 10                | movzx edx,byte ptr ds:[eax]             |
0040270 | 8D 4D 95                | lea ecx,dword ptr ss:[ebp-6B]           |
0040271 | 8B 45 E8                | mov eax,dword ptr ss:[ebp-18]           |
0040271 | 01 C8                   | add eax,ecx                             |
0040271 | 0F B6 00                | movzx eax,byte ptr ds:[eax]             |
0040271 | 38 C2                   | cmp dl,al                               |
0040271 | 75 06                   | jne what.402724                         |
0040271 | 83 45 F4 01             | add dword ptr ss:[ebp-C],1              |
0040272 | EB 04                   | jmp what.402728                         |
0040272 | 83 45 F4 64             | add dword ptr ss:[ebp-C],64             |
0040272 | 83 45 E8 01             | add dword ptr ss:[ebp-18],1             |
0040272 | EB C1                   | jmp what.4026EF                         |
0040272 | 83 7D F4 20             | cmp dword ptr ss:[ebp-C],20             |
0040273 | 75 09                   | jne what.40273D                         |
0040273 | C7 45 F4 02 00 00 00    | mov dword ptr ss:[ebp-C],2              |
0040273 | EB 07                   | jmp what.402744                         |
0040273 | C7 45 F4 03 00 00 00    | mov dword ptr ss:[ebp-C],3              |
0040274 | 8B 45 F4                | mov eax,dword ptr ss:[ebp-C]            |
0040274 | 89 04 24                | mov dword ptr ss:[esp],eax              | [esp]:0ec40ec448d42dbf0000c020c0000048010e
0040274 | E8 7C FC FF FF          | call what.4023CB                        |
0040274 | 90                      | nop                                     |
0040275 | 83 EC 80                | sub esp,FFFFFF80                        |
0040275 | 5B                      | pop ebx                                 |
0040275 | 5F                      | pop edi                                 |
0040275 | 5D                      | pop ebp                                 |
0040275 | C3                      | ret                                     |

这段代码,确实特别恶心……但是这也确实是最后一个我们需要攻克的难关。这里我借鉴一下吾爱破解的一筐萝卜用户的check函数伪代码:

我们看到check函数内部有几个新的函数,不过这些函数都是没有加密的,在ida里可以直接进入这些函数(即便check函数没有恢复)。printfs函数根据参数的值输出不同的字符串提示内容,checkht函数是检查我们输入的flag的格式是否正确……这些都是小问题了(对比前面的过程)

最后大概就可以愉快的拿到flag辣!

总之,CTF比赛和OI比赛区别还是很大的,但是CTF比赛有的时候也需要OI功底。十分庆幸我选择了RE方向,还算不错的算法能力给我带来了很多的好处,但是知识面单一的问题也很限制我的发展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值