吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12765|回复: 40
收起左侧

[CTF] 【QCTF】 Xman Reverse asong题目(That girl)

  [复制链接]
zhukai055 发表于 2018-7-16 08:46
本帖最后由 zhukai055 于 2018-7-16 09:09 编辑

REVERSE-ASONG
0x01:
下载三个文件,分别是 asong linux程序 out输出  that_girl 原文
1.png    2.png
3.png
0x02:开始分析asong
4.png


Sub_400AAA:
int __fastcall sub_400AAA(const char *a1, __int64a2)//入栈内容:字符串指针,处理后的字符串长度
{
  int v2; // eax@3
  int result; // eax@4
  __int64 v4; // rcx@4
  __int64 v5; //[sp+0h] [bp-20h]@1  char buf; //[sp+13h] [bp-Dh]@2  int fd; //[sp+14h] [bp-Ch]@1  __int64 v8; //[sp+18h] [bp-8h]@1
  v8 = *MK_FP(__FS__, 40LL);
  fd = open(a1, 0, a2, a1);//打开that_girl文件
  while ( read(fd, &buf, 1uLL) == 1 )//按单字符读入,读入成功,即循环
  {
    v2 =sub_400936((unsigned int)buf, &buf);//读取到的内容进入sub_400936函数
++*(_DWORD *)(4LL * v2 + v5);//v5是密码对应表的首地址,A[4*v2]++; 密码表用A数组表示。
5.png
  }
  result = close(fd);
  v4 = *MK_FP(__FS__, 40LL) ^ v8;
  return result;

}
-----------------------------------------------------------------------------------
__int64 __fastcall sub_400936(char a1)//一个算法
{
  __int64 result; // rax@1
  result = (unsigned int)(a1 - 10);
  switch ( a1 )
  {
    case 95:
      result = (unsigned int)(a1 - 49);
      break;
    case 10:
      result = (unsigned int)(a1 + 35);
      break;
    case 32:
    case 33:
    case 34:
      result = (unsigned int)(a1 + 10);
      break;
    case 39:
      result = (unsigned int)(a1 + 2);
      break;
    case 44:
      result = (unsigned int)(a1 - 4);
      break;
    case 46:
      result = (unsigned int)(a1 - 7);
      break;
    case 58:
    case 59:
      result = (unsigned int)(a1 - 21);
      break;
    case 63:
      result = (unsigned int)(a1 - 27);
      break;
    default:
      if ( a1 <= 47 || a1 > 57 )
      {
        if ( a1 <= 64 || a1 > 90 )
        {
          if ( a1 > 96 && a1 <= 122 )
            result = (unsigned int)(a1 - 87);
        }
        else
        {
          result = (unsigned int)(a1 - 55);
        }
      }
      else
      {
        result = (unsigned int)(a1 - 48);
      }
      break;
  }
  return result;

}
-----------------------------------------------------------------------------------
__int64 __fastcall sub_400E54(const char *a1, __int64a2)//入栈内容:字符串指针,处理后的字符串长度
{
  int i; //[sp+18h] [bp-48h]@1  int v4; //[sp+1Ch] [bp-44h]@1  char v5[56]; //[sp+20h] [bp-40h]@3  __int64 v6; //[sp+58h] [bp-8h]@1
  v6 = *MK_FP(__FS__, 40LL);
  v4 = strlen(a1);
  for ( i = 0; i < v4; ++i )
v5[i] = *(_DWORD *)(4LL * (signed int)sub_400936(a1[i]) + a2);//v5= A[4 * sub_400936(str1)];
6.png
  sub_400D33(v5);//调整数组内位置函数
  sub_400DB4((unsigned __int8 *)v5, v4);
  sub_400CC0(v5, "out", (unsigned int)v4);
  return *MK_FP(__FS__, 40LL) ^ v6;

}
-----------------------------------------------------------------------------------
__int64 __fastcall sub_400D33(_BYTE *a1)
{
  __int64 result; // rax@4
  _BYTE v2[5]; //[sp+13h] [bp-5h]@1
  v2[4] = 0;
  *(_DWORD *)v2 = *a1;
  while (dword_6020A0[*(signed int *)&v2[1]] )
  {
    a1[*(signed int *)&v2[1]] = a1[dword_6020A0[*(signed int *)&v2[1]]];
*(_DWORD *)&v2[1] =dword_6020A0[*(signed int *)&v2[1]];
7.png
  }
  result = (unsigned __int8)v2[0];
  a1[*(signed int *)&v2[1]] = v2[0];
  return result;

}//dword_6020A0在汇编上显示的是,4 * v1+地址,就是说,在一个数组中取一个下标为4*v1的内容。
//读内存,发现 其中的二位数组,按照这个表来 决定着下一个位置如何更换。
8.png
9.png
20.png


其结果是这样更换。
整理成C++代码
void sub_400D33(int asdstr[])
{
     int v1 = 0;
     int v0 = 0;
     int newstr[39];
     v1 = B[(4 * v1) / 16][(4 * v1) % 16];
     while (v1)
     {
         newstr[v0] = asdstr[v1];
        cout << v0 << "" << v1 << endl;
         v0 = v1;
         v1 = B[(4 * v1) / 16][(4 * v1) % 16];
         
         
     }
     newstr[1] = asdstr[0];
}

-----------------------------------------------------------------------------------
继续看下个函数
unsigned __int8 *__fastcallsub_400DB4(unsigned __int8 *a1, int a2)//最后一个算法,内容为,这一位和下一位经过左移和右移再或一下得到最终结果。
{
  unsigned __int8 *result; // rax@4
  char v3; // [sp+17h] [bp-5h]@1
  int i; // [sp+18h] [bp-4h]@1
  v3 = *a1 >> 5;
  for ( i = 0; a2 - 1 > i; ++i )
    a1[i] = 8 * a1[i] | (a1[i + 1] >> 5);
  result = &a1[i];
  *result = 8 * *result | v3;
  return result;
}
打开out文件,我们已经知道最终结果为:ec 29 e3 41 e1 f7 aa 1d 29 ed 29 99 39 f3 b7 a9 e7 ac 2b b7 ab40 9f a9 31 35 2c 29 ef A8 3d 4b b0 e9 e1 68 7b 41
开始我们的逆向爆破:
1.  爆破最后一个函数,
11.png
因为是或运算,所以得爆破前面一位和后面一位,才能确定中间的内容。最终得到的结果为。int key[] = { 61, 133, 60, 104, 60, 62, 245, 67,165, 61, 165, 51, 39, 62, 118, 245, 60, 245,133, 118, 245, 104, 19, 245, 38,38, 165, 133, 61, 245, 7, 169, 118, 29, 60, 45, 15, 104, 32 };这其中第一位没爆破出来,在可能的几个数字中一个一个试的。{29, 61, 93, 125, 157, 189, 221, 253 };
2.  根据换位表,反推原数组 我是手动填数字的没用算法。
{ 133, 67, 104, 133, 245, 38, 60, 61, 39, 245, 51,104, 62, 60, 118, 38, 245, 118, 165, 245, 19, 165, 61, 245, 62, 165, 45, 61,245, 7, 60, 118, 29, 60, 15, 104, 133, 169 };
3.  爆破我们的字符串。

void sub_400E54baopo()
{
    int i; // [sp+18h][bp-48h]@1    int v4; // [sp+1Ch][bp-44h]@1
    int v5[56]; // [sp+20h] [bp-40h]@3
    __int64 v6; // [sp+58h] [bp-8h]@1
    int ls;
    int DS[] = { 133, 67, 104, 133, 245, 38, 60, 61, 39, 245, 51, 104, 62, 60, 118, 38, 245, 118, 165, 245, 19, 165, 61, 245, 62, 165, 45, 61, 245, 7, 60, 118, 29, 60, 15, 104, 133, 169 };
    v4 = 38;
    int adsad[] = { 29, 61, 93, 125, 157, 189, 221, 253 };//开始爆破的时候,不确定是哪个就一个一个试的。
   
        for (int ia = 0; ia < 38; ia++)
        {
            
        
                for (i = 0; i < 360; i++)
                {
                    ls = A[(4 * sub_400936(i))];//进入密码对应表。读取出结果。
                    if (ls == DS[ia])
                    {
                        cout << (char)i << ""<<ia<<""<<endl;
                    }
                    
                }
            
            
            cout << endl;
        }
}

12.png 爆破出来的结果发现,不区分大小写,都能通过。
那就先来大写吧。
THAT_GIRL_SAYING_NO_FOR_YOUR_VINDICATE
QCTF{THAT_GIRL_SAYING_NO_FOR_YOUR_VINDICATE}
4.  VS c++ 恢复全部源码后,填入字符串,运行。
13.png
14.png
  完全一致。
Getflag,不区分大小写,都试了下。
QCTF{THAT_GIRL_SAYING_NO_FOR_YOUR_VINDICATE}
QCTF{that_girl_saying_no_for_your_vindicate}



免费评分

参与人数 16吾爱币 +13 热心值 +16 收起 理由
C_Ryan + 1 + 1 我很赞同!
羽月莉音 + 1 + 1 我很赞同!
SinerSAMA + 1 + 1 用心讨论,共获提升!
Dispa1r + 1 + 1 用心讨论,共获提升!
jnez112358 + 1 谢谢@Thanks!
thegonedays + 1 谢谢@Thanks!
测试中…… + 1 + 1 用心讨论,共获提升!
soyiC + 1 + 1 谢谢@Thanks!
yushan8603 + 1 + 1 谢谢@Thanks!
vince991 + 1 我很赞同!
sunnylds7 + 1 + 1 谢谢@Thanks!
QB56 + 1 + 1 热心回复!
莫流云 + 1 + 1 谢谢@Thanks!
dspowj + 1 + 1 我很赞同!
poisonbcat + 1 + 1 我很赞同!
lookerJ + 1 + 1 热心回复!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

v1gle 发表于 2018-7-16 09:27
天使3号 发表于 2018-7-16 09:15
QCTF 是TX出的比赛吗,楼主大佬

是xctf夏令营的
 楼主| zhukai055 发表于 2018-7-22 10:10
voyage1969 发表于 2018-7-22 00:16
CTF萌新前来学习(想问下楼主爆破是用python语言写的嘛)

都可以啊,我一般用c++ 因为翻译过来的 伪代码 稍微改改就可以放在 VSc++中用
天使3号 发表于 2018-7-16 09:15
surpriseMF 发表于 2018-7-16 10:25
感谢分享  谢谢大佬
头像被屏蔽
awzs7758520 发表于 2018-7-16 14:27
随贴有经验常来常看看 一次0.5
头像被屏蔽
awzs7758520 发表于 2018-7-16 14:27
跟贴有经验,常来,常看看 一次0.5 两次才一分
CcCody 发表于 2018-7-16 20:23
不错  学习了  逆向还得靠耐心
浮云半盏 发表于 2018-7-17 16:30
感谢大佬分享,学习了
whatiwhere 发表于 2018-7-17 20:32
大佬多少名  ? 进营了吧  你去哪个营?
caoxin 发表于 2018-7-18 00:04
好复杂,半天没看懂
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 13:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表