BUUCTF--[GWCTF 2019]xxor

谁说我不能喝 提交于 2020-05-04 17:37:57

测试文件:https://www.lanzous.com/ib5y9cb

 

代码分析

 1 __int64 __fastcall main(__int64 a1, char **a2, char **a3)
 2 {
 3   signed int i; // [rsp+8h] [rbp-68h]
 4   signed int j; // [rsp+Ch] [rbp-64h]
 5   __int64 v6; // [rsp+10h] [rbp-60h]
 6   __int64 v7; // [rsp+18h] [rbp-58h]
 7   __int64 v8; // [rsp+20h] [rbp-50h]
 8   __int64 v9; // [rsp+28h] [rbp-48h]
 9   __int64 v10; // [rsp+30h] [rbp-40h]
10   __int64 v11; // [rsp+40h] [rbp-30h]
11   __int64 v12; // [rsp+48h] [rbp-28h]
12   __int64 v13; // [rsp+50h] [rbp-20h]
13   __int64 v14; // [rsp+58h] [rbp-18h]
14   __int64 v15; // [rsp+60h] [rbp-10h]
15   unsigned __int64 v16; // [rsp+68h] [rbp-8h]
16 
17   v16 = __readfsqword(0x28u);
18   puts("Let us play a game?");
19   puts("you have six chances to input");
20   puts("Come on!");
21   v6 = 0LL;
22   v7 = 0LL;
23   v8 = 0LL;
24   v9 = 0LL;
25   v10 = 0LL;
26   for ( i = 0; i <= 5; ++i )
27   {
28     printf("%s", "input: ", (unsigned int)i);
29     __isoc99_scanf("%d", (char *)&v6 + 4 * i);
30   }
31   v11 = 0LL;
32   v12 = 0LL;
33   v13 = 0LL;
34   v14 = 0LL;
35   v15 = 0LL;
36   for ( j = 0; j <= 4; j += 2 )                 // 0,2,4
37   {
38     dword_601078 = *((_DWORD *)&v6 + j);        // 下标0,2,4
39     dword_60107C = *((_DWORD *)&v6 + j + 1);    // 下标1,3,5
40     sub_400686((unsigned int *)&dword_601078, &unk_601060);
41     *((_DWORD *)&v11 + j) = dword_601078;
42     *((_DWORD *)&v11 + j + 1) = dword_60107C;
43   }
44   if ( (unsigned int)sub_400770(&v11) != 1 )
45   {
46     puts("NO NO NO~ ");
47     exit(0);
48   }
49   puts("Congratulation!\n");
50   puts("You seccess half\n");
51   puts("Do not forget to change input to hex and combine~\n");
52   puts("ByeBye");
53   return 0LL;
54 }
55 /* Orphan comments:
56 a2指向v6的空间
57 2234
58 */

这段代码,对输入数字的处理,我们可以分成两部分

  1. 第36~43行代码,输入整型数组变换
  2. 第44行代码,判断变换后的数组是否满足要求

 

第二部分

打开sub_400770函数

__int64 __fastcall sub_400770(_DWORD *a1)
{
  __int64 result; // rax

  if ( a1[2] - a1[3] != 2225223423LL || a1[3] + a1[4] != 4201428739LL || a1[2] - a1[4] != 1121399208LL )
  {
    puts("Wrong!");
    result = 0LL;
  }
  else if ( *a1 != 0xDF48EF7E || a1[5] != 0x84F30420 || a1[1] != 550153460 )
  {
    puts("Wrong!");
    result = 0LL;
  }
  else
  {
    puts("good!");
    result = 1LL;
  }
  return result;
}

整理信息,我们可以获取到变换后的数组a1的相关信息

a1[2] - a1[3] == 2225223423
a1[3] + a1[4] == 4201428739
a1[2] - a1[4] == 1121399208
a1[0] == 0xDF48EF7E
a1[1] == 550153460
a1[5] == 0x84F30420




用z3解方程

# -*- coding:utf-8 -*-

from z3 import *

a2,a3,a4 = BitVecs('a2 a3 a4',64)
s = Solver()
s.add(a2 - a3 == 2225223423)
s.add(a3 + a4 == 4201428739)
s.add(a2 - a4 == 1121399208)
if s.check() == sat:
    m = s.model()
    for i in m:
        print("%s = %ld" % (i, m[i].as_long()))

得到:

a4 = 2652626477
a2 = 3774025685
a3 = 1548802262

 

第一部分

打开sub_400686函数

__int64 __fastcall sub_400686(unsigned int *a1, _DWORD *a2)
{
  __int64 result; // rax
  unsigned int v3; // [rsp+1Ch] [rbp-24h]
  unsigned int v4; // [rsp+20h] [rbp-20h]
  int v5; // [rsp+24h] [rbp-1Ch]
  unsigned int i; // [rsp+28h] [rbp-18h]

  v3 = *a1;
  v4 = a1[1];
  v5 = 0;
  for ( i = 0; i <= 0x3F; ++i )
  {
    v5 += 1166789954;
    v3 += (v4 + v5 + 11) ^ ((v4 << 6) + *a2) ^ ((v4 >> 9) + a2[1]) ^ 0x20;
    v4 += (v3 + v5 + 20) ^ ((v3 << 6) + a2[2]) ^ ((v3 >> 9) + a2[3]) ^ 0x10;
  }
  *a1 = v3;
  result = v4;
  a1[1] = v4;
  return result;
}

这就是一个利用已知数组unk_601060对我们输入的整型数组进行异或操作,因此我们只需要将整个过程逆过来,for循环那段,你将异或过程看成一个整体就行,最后就能得到输入的整型数组。

 

脚本

#include <iostream>

#pragma warning(disable:4996)
using namespace std;

int main()
{
    __int64 a[6] = { 3746099070, 550153460, 3774025685, 1548802262, 2652626477, 2230518816 };
    unsigned int a2[4] = { 2,2,3,4 };
    unsigned int v3, v4;
    int v5;
    for (int j = 0; j <= 4; j += 2) {
        v3 = a[j];
        v4 = a[j + 1];
        v5 = 1166789954*0x40;
        for (int i = 0; i <= 0x3F; ++i) {
            v4 -= (v3 + v5 + 20) ^ ((v3 << 6) + a2[2]) ^ ((v3 >> 9) + a2[3]) ^ 0x10;
            v3 -= (v4 + v5 + 11) ^ ((v4 << 6) + *a2) ^ ((v4 >> 9) + a2[1]) ^ 0x20;
            v5 -= 1166789954;
        }
        a[j] = v3;
        a[j + 1] = v4;
    }

    /*将整型数组作为字符输出,注意计算机小端排序*/
    for (int i = 0; i < 6; ++i) {
        cout << *((char*)&a[i] + 2) << *((char*)&a[i] + 1) <<  * ((char*)&a[i]);
    }

    system("PAUSE");
    return 0;
}

 

get flag!

flag{re_is_great!}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!