BUUCTF--[V&N2020 公开赛]strangeCpp

Posted mayfly-nymph

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BUUCTF--[V&N2020 公开赛]strangeCpp相关的知识,希望对你有一定的参考价值。

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

 

代码分析

先找到程序运行显示处的代码

 1 // 个数,数组,环境变量
 2 __int64 __fastcall sub_140013AA0(__int64 a1, __int64 a2, __int64 *a3)
 3 {
 4   char *v3; // rdi
 5   signed __int64 i; // rcx
 6   __int64 v5; // rax
 7   __int64 v6; // rax
 8   __int64 v7; // rax
 9   __int64 v8; // rax
10   char v10; // [rsp+0h] [rbp-20h]
11   struct _SYSTEM_INFO SystemInfo; // [rsp+28h] [rbp+8h]
12   __int64 *j; // [rsp+78h] [rbp+58h]
13   __int64 v13; // [rsp+98h] [rbp+78h]
14   __int64 *v14; // [rsp+1A0h] [rbp+180h]
15 
16   v14 = a3;
17   v3 = &v10;
18   for ( i = 94i64; i; --i )
19   {
20     *(_DWORD *)v3 = 3435973836;
21     v3 += 4;
22   }
23   sub_1400110AA((__int64)&unk_140027033);
24   GetSystemInfo(&SystemInfo);
25   putchar(byte_140021004);                      // w
26   putchar(byte_140021005);                      // e
27   putchar(byte_140021006);                      // l
28   putchar(byte_140021007);                      // c
29   putchar(byte_140021019);                      // o
30   putchar(byte_14002101A);                      // m
31   putchar(byte_140021005);                      // e
32   putchar(10);
33   puts("Let me have a look at your computer...");
34   for ( j = v14; *j; ++j )                      // 循环输出环境变量
35   {
36     v13 = *j;
37     sub_140011226("%s
", v13);
38   }
39   std::basic_ostream<char,std::char_traits<char>>::operator<<(std::cout, sub_140011127);
40   dword_140021190 = SystemInfo.dwNumberOfProcessors;// CPU数量
41   sub_140011226("now system cpu num is %d
", SystemInfo.dwNumberOfProcessors);
42   if ( dword_140021190 < 8 )
43   {
44     puts("Are you in VM?");
45     _exit(0);
46   }
47   if ( GetUserNameA(Str1, &pcbBuffer) )         // 获取用户名
48   {
49     v5 = sub_140011172(std::cout, (__int64)"this is useful");
50     std::basic_ostream<char,std::char_traits<char>>::operator<<(v5, sub_140011127);
51   }
52   v6 = std::basic_ostream<char,std::char_traits<char>>::operator<<(std::cout, sub_140011127);
53   v7 = sub_140011172(v6, (__int64)"ok,I am checking...");
54   std::basic_ostream<char,std::char_traits<char>>::operator<<(v7, sub_140011127);
55   if ( !j_strcmp(Str1, "cxx") )
56   {
57     v8 = sub_140011172(std::cout, (__int64)"flag{where_is_my_true_flag?}");
58     std::basic_ostream<char,std::char_traits<char>>::operator<<(v8, sub_140011127);
59     _exit(0);
60   }
61   system("pause");
62   sub_1400113E3((__int64)&v10, (__int64)&unk_14001DE50);
63   return 0i64;
64 }

在我查看第21~25行代码,输出字符串处时

技术图片

中间插了一个byte_140021008变量,找到引用处

 1 __int64 sub_140013580()
 2 {
 3   __int64 *v0; // rdi
 4   signed __int64 i; // rcx
 5   __int64 result; // rax
 6   __int64 v3; // [rsp+0h] [rbp-20h]
 7   int v4; // [rsp+24h] [rbp+4h]
 8   int j; // [rsp+44h] [rbp+24h]
 9   __int64 v6; // [rsp+128h] [rbp+108h]
10 
11   v0 = &v3;
12   for ( i = 82i64; i; --i )
13   {
14     *(_DWORD *)v0 = -858993460;
15     v0 = (__int64 *)((char *)v0 + 4);
16   }
17   v6 = -2i64;
18   sub_1400110AA((__int64)&unk_140027033);
19   result = sub_140011384((unsigned int)dword_140021190);
20   v4 = result;
21   if ( (_DWORD)result == 607052314 && dword_140021190 <= 14549743 )
22   {
23     for ( j = 0; j < 17; ++j )
24     {
25       putchar((unsigned __int8)(dword_140021190 ^ byte_140021008[j]));
26       result = (unsigned int)(j + 1);
27     }
28   }
29   return result;
30 }

我们首先需要看到第19行代码,进入sub_140011384函数(dword_140021190实际就是我们第一处代码的CPU数量,变量的值可以通过下面if条件,暴力解出值)

 1 signed __int64 __fastcall sub_140013890(int a1)
 2 {
 3   __int64 *v1; // rdi
 4   signed __int64 i; // rcx
 5   signed __int64 result; // rax
 6   __int64 v4; // [rsp+0h] [rbp-20h]
 7   int v5; // [rsp+24h] [rbp+4h]
 8   int v6; // [rsp+44h] [rbp+24h]
 9   unsigned int v7; // [rsp+64h] [rbp+44h]
10   int v8; // [rsp+160h] [rbp+140h]
11 
12   v8 = a1;
13   v1 = &v4;
14   for ( i = 82i64; i; --i )
15   {
16     *(_DWORD *)v1 = -858993460;
17     v1 = (__int64 *)((char *)v1 + 4);
18   }
19   sub_1400110AA((__int64)&unk_140027033);
20   v5 = v8 >> 12;
21   v6 = v8 << 8;
22   v7 = (v8 << 8) ^ (v8 >> 12);
23   v7 *= 291;
24   if ( v7 )
25     result = v7;
26   else
27     result = 987i64;
28   return result;
29 }

通过这段代码的第22,23行和上段代码的第25行,我们可以解出flag

 

脚本

# -*- coding:utf-8 -*-
import hashlib

result = 0
for v8 in range(14549743):
    v7 = (((v8 << 8) ^ (v8 >> 12))*291)&0xFFFFFFFF # 原文是unsigned int--0~0xFFFFFFFF,输出的值需要截断
    if (v7 == 607052314):
        result = v8
        break

enc = [0x26, 0x2C, 0x21, 0x27, 0x3B, 0x0D, 4, 0x75, 0x68, 0x34, 0x28,
       0x25, 0x0E, 0x35, 0x2D, 0x69, 0x3D]

flag = ""
for i in enc:
    flag += chr((result ^ i)&0xFF) # unsigned __int8--0~0xFF
print (flag)
md = hashlib.md5()
md.update(str(result).encode(utf-8))
print ("flag{"+md.hexdigest()+"}")

技术图片

 

get flag!

flag{e10adc3949ba59abbe56e057f20f883e}

以上是关于BUUCTF--[V&N2020 公开赛]strangeCpp的主要内容,如果未能解决你的问题,请参考以下文章

BUUCTF--[V&N2020 公开赛]strangeCpp

[V&N2020 公开赛]CHECKIN

[V&N2020 公开赛]CHECKIN

[V&N2020 公开赛]CHECKIN

[V&N2020 公开赛] Web misc部分题解

BUUCTF V&N-misc内存取证