zhukai055 发表于 2018-7-16 08:46

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

本帖最后由 zhukai055 于 2018-7-16 09:09 编辑

REVERSE-ASONG:
0x01:
下载三个文件,分别是 asong linux程序 out输出that_girl 原文
   

0x02:开始分析asong



Sub_400AAA:
int __fastcall sub_400AAA(const char *a1, __int64a2)//入栈内容:字符串指针,处理后的字符串长度{int v2; // eax@3int result; // eax@4__int64 v4; // rcx@4__int64 v5; // @1char buf; // @2int fd; // @1__int64 v8; // @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++; 密码表用A数组表示。 }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; // @1int v4; // @1char v5[56]; // @3__int64 v6; // @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)];

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]; // @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]];
}result = (unsigned __int8)v2[0];a1[*(signed int *)&v2[1]] = v2[0];return result;
}//dword_6020A0在汇编上显示的是,4 * v1+地址,就是说,在一个数组中取一个下标为4*v1的内容。
//读内存,发现 其中的二位数组,按照这个表来 决定着下一个位置如何更换。





其结果是这样更换。
整理成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@4char v3; // @1int i; // @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.爆破最后一个函数,

因为是或运算,所以得爆破前面一位和后面一位,才能确定中间的内容。最终得到的结果为。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; // @1    int v4; // @1    int v5[56]; // @3    __int64 v6; // @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;      } }
爆破出来的结果发现,不区分大小写,都能通过。那就先来大写吧。THAT_GIRL_SAYING_NO_FOR_YOUR_VINDICATEQCTF{THAT_GIRL_SAYING_NO_FOR_YOUR_VINDICATE}4.用VS c++ 恢复全部源码后,填入字符串,运行。完全一致。Getflag,不区分大小写,都试了下。QCTF{THAT_GIRL_SAYING_NO_FOR_YOUR_VINDICATE}QCTF{that_girl_saying_no_for_your_vindicate}


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

QCTF 是TX出的比赛吗,楼主大佬

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

好复杂,半天没看懂
页: [1] 2 3 4 5
查看完整版本: 【QCTF】 Xman Reverse asong题目(That girl)