BUU [GKCTF 2021]Crash

7 篇文章 0 订阅
4 篇文章 0 订阅

[GKCTF 2021]Crash

首先查壳,64bit,elf文件

刚解压完发现只有一个文件,大小足足有2M,我感觉不太简单,ida64, 定位到main函数

main_main()关键部分

我看到fmt_Fprintln这个的时候就反应过来了,这是道go的题。

头一次做go的题,没有基础,就试着一点一点分析了:(很多地方都参考了wp)

首先分析main函数关键部分

 if ( flag[1] == 43 && *(_DWORD *)v0 == 'TCKG' && *(_WORD *)(v0 + 4) == '{F' && *(_BYTE *)(v0 + 42) == '}' )
  {
    main_check(*flag, 0x2BuLL);
    if ( v1 )
    {
      v6[0] = &unk_523A20;
      v6[1] = &off_5724B0;
      fmt_Fprintln((__int64)&off_574420, qword_625B28, (__int64)v6, 1LL, 1LL);
    }

满足if条件后执行main_check函数

main_check()

void __golang main_check(__int64 a1, unsigned __int64 a2)
{
  __int64 v2; // [rsp+10h] [rbp-68h]
  __int64 v3; // [rsp+10h] [rbp-68h]
  __int64 v4; // [rsp+18h] [rbp-60h]
  char v5; // [rsp+18h] [rbp-60h]
  __int64 v6; // [rsp+18h] [rbp-60h]
  char v7; // [rsp+18h] [rbp-60h]
  __int64 v8; // [rsp+18h] [rbp-60h]
  __int64 v9; // [rsp+20h] [rbp-58h]
  __int64 v10; // [rsp+20h] [rbp-58h]
  char v11[32]; // [rsp+30h] [rbp-48h] BYREF
  char v12[32]; // [rsp+50h] [rbp-28h] BYREF
​
  if ( a2 < 0x1E )
    runtime_panicSliceAlen();
  v2 = main_encrypto(a1 + 6, 24LL);
  if ( v4 == 44 )
  {
    v9 = runtime_memequal(v2, (__int64)"o/aWPjNNxMPZDnJlNp0zK5+NLPC4Tv6kqdJqjkL0XkA=", 44LL, 44);
    if ( v5 )
    {
      if ( a2 < 0x22 )
        runtime_panicSliceAlen();
      v6 = runtime_stringtoslicebyte((__int64)v11, a1 + 30, 4LL);
      Encrypt_HashHex2(v6, v9);
      if ( v9 == 64 )
      {
        v10 = runtime_memequal(
                v6,
                (__int64)"6e2b55c78937d63490b4b26ab3ac3cb54df4c5ca7d60012c13d2d1234a732b74",
                64LL,
                v6);
        if ( v7 )
        {
          if ( a2 < 0x26 )
            runtime_panicSliceAlen();
          v8 = runtime_stringtoslicebyte((__int64)v12, a1 + 34, 4LL);
          Encrypt_HashHex5(v8, v10);
          if ( v10 == 128 )
          {
            runtime_memequal(
              v8,
              (__int64)"6500fe72abcab63d87f213d2218b0ee086a1828188439ca485a1a40968fd272865d5ca4d5ef5a651270a52ff952d955c9"
                       "b757caae1ecce804582ae78f87fa3c9",
              128LL,
              v8);
            if ( (_BYTE)v8 )
            {
              if ( a2 < 0x2A )
                runtime_panicSliceAlen();
              main_hash(a1 + 38, 4LL);
              if ( v8 == 32 )
                runtime_memequal(v3, (__int64)"ff6e2fd78aca4736037258f0ede4ecf0", 32LL, 32);
            }
          }
        }
      }
    }
  }
}

里面的逻辑就是把flag分为四部分,然后分别进行了不同的加密

第一部分

v2 = main_encrypto(a1 + 6, 24LL);
  if ( v4 == 44 )
  {
    v9 = runtime_memequal(v2, (__int64)"o/aWPjNNxMPZDnJlNp0zK5+NLPC4Tv6kqdJqjkL0XkA=", 44LL, 44);

main_encrypto()

__int64 __usercall main_encrypto@<rax>(__int64 a1, __int64 a2)
{
  __int64 v3; // [rsp+18h] [rbp-100h]
  __int64 v4; // [rsp+20h] [rbp-F8h]
  __int64 v5; // [rsp+20h] [rbp-F8h]
  __int64 v6; // [rsp+28h] [rbp-F0h]
  __int64 v7; // [rsp+48h] [rbp-D0h]
  __int64 v8; // [rsp+60h] [rbp-B8h]
  __int64 v9; // [rsp+68h] [rbp-B0h]
  __int64 v10; // [rsp+70h] [rbp-A8h]
  __int64 v11; // [rsp+78h] [rbp-A0h]
  char v12[32]; // [rsp+B0h] [rbp-68h] BYREF
  __int64 v13; // [rsp+D0h] [rbp-48h]
  __int64 v14; // [rsp+D8h] [rbp-40h]
  __int64 v15; // [rsp+E0h] [rbp-38h]
  __int64 v16; // [rsp+E8h] [rbp-30h]
  __int64 v17; // [rsp+F0h] [rbp-28h]
  __int64 *v18; // [rsp+F8h] [rbp-20h]
  _QWORD v19[2]; // [rsp+100h] [rbp-18h] BYREF

  v18 = (__int64 *)runtime_newobject((__int64)" ");
  v6 = encoding_json_Unmarshal((__int64)off_61E540, qword_61E548, qword_61E550, (__int64)"\b", (__int64)v18);
  v13 = *v18;
  v10 = v18[1];
  v14 = v18[2];
  v11 = v18[3];
  v15 = runtime_stringtoslicebyte(0LL, a1, a2);
  v16 = runtime_stringtoslicebyte((__int64)v12, v13, v10);
  v3 = runtime_stringtoslicebyte(0LL, v14, v11);
  Encrypt_DesEncrypt(v15, v4, v6, v16, v4, v6, v3, v4);
  v17 = v7;
  if ( v8 )
  {
    v19[0] = *(_QWORD *)(v8 + 8);
    v19[1] = v9;
    fmt_Fprintln((__int64)&off_574420, qword_625B28, (__int64)v19, 1LL, 1LL);
  }
  encoding_base64___ptr_Encoding__EncodeToString(qword_625AD0, v17);
  return v5;
}

在其中代码里找到了Encrypt_DesEncrypt()函数,由于是以encrypt命名的,所以猜测代码的加密在这个函数里,继续查看该函数内部,该函数内部第一个crypto_des_NewTripleDESCipher函数引起了注意,其内部是这样的

__int64 __usercall crypto_des_NewTripleDESCipher@<rax>(__int64 a1, __int64 a2)
{
  __int64 v3; // [rsp+20h] [rbp-10h]
​
  if ( a2 != 24 )
    return runtime_convT64(a2);
  v3 = runtime_newobject((__int64)&unk_534820);
  crypto_des___ptr_desCipher__generateSubkeys(v3, a1, 8LL);
  crypto_des___ptr_desCipher__generateSubkeys(v3 + 128, a1 + 8, 8LL);
  crypto_des___ptr_desCipher__generateSubkeys(v3 + 256, a1 + 16, 8LL);
  return v3;
}

去查看了一下wp,发现这是3des加密算法,然后搜集了一些3des加密算法的信息,要解密的话需要得到密钥,一般的题目好像都会有welcome这样的话,我就直接搜素了一下,然后直接找到了key 和 iv,然后要加密的字符串是"o/aWPjNNxMPZDnJlNp0zK5+NLPC4Tv6kqdJqjkL0XkA="

然后就模仿wp放在在线解密工具中,得到了第一部分

87f645e9-b628-412f-9d7a-

第二部分加密

Encrypt_HashHex2(44LL, v4);
    if ( v4 == 64 )
    {
      runtime_memequal(44LL,(__int64)"6e2b55c78937d63490b4b26ab3ac3cb54df4c5ca7d60012c13d2d1234a732b74");
    }

Encrypt_HashHex2()

__int64 __usercall Encrypt_HashHex2@<rax>(__int64 a1, __int64 a2, __int64 a3)
{
  __int128 v4; // [rsp+18h] [rbp-50h]
  __int64 v5; // [rsp+18h] [rbp-50h]
  __int64 v6; // [rsp+20h] [rbp-48h]
  __int64 v7; // [rsp+48h] [rbp-20h]
  __int64 v8; // [rsp+50h] [rbp-18h]
  __int64 v9; // [rsp+58h] [rbp-10h]
​
  v8 = Encrypt_Sha256(a1, a2, a3);
  v7 = 2 * v6;
  v9 = runtime_makeslice((__int64)&unk_523B60, 2 * v6, 2 * v6);
  *((_QWORD *)&v4 + 1) = encoding_hex_Encode(v9, v7, v7, v8);
  runtime_slicebytetostring(0LL, v9, v7, v4);
  return v5;
}

可知这个是sha256加密

直接上python爆破

import hashlib
hash="6e2b55c78937d63490b4b26ab3ac3cb54df4c5ca7d60012c13d2d1234a732b74"
for i in range(90000000):
    pwd1=hex(i)
    pwd1=pwd1[2:]
    h1=hashlib.sha256(pwd1.encode('utf-8')).hexdigest()
    #print(h1)
    if h1==hash:
        print(hex(i))
        break
#0xe402

第三部分加密

Encrypt_HashHex5(v8, v10);
          if ( v10 == 128 )
          {
              runtime_memequal(v8,(__int64)"6500fe72abcab63d87f213d2218b0ee086a1828188439ca485a1a40968fd272865d5ca4d5ef5a651270a52ff952d955c9b757caae1ecce804582ae78f87fa3c9", 128LL,v8);

Encrypt_HashHex5()

__int64 __usercall Encrypt_HashHex5@<rax>(__int64 a1, __int64 a2, __int64 a3)
{
  __int64 v4; // [rsp+18h] [rbp-50h]
  __int128 v5; // [rsp+18h] [rbp-50h]
  __int64 v6; // [rsp+18h] [rbp-50h]
  __int64 v7; // [rsp+20h] [rbp-48h]
  __int64 v8; // [rsp+48h] [rbp-20h]
  __int64 v9; // [rsp+50h] [rbp-18h]
  __int64 v10; // [rsp+58h] [rbp-10h]
​
  v9 = Encrypt_Sha512(a1, a2, a3);
  v8 = 2 * v7;
  runtime_makeslice((__int64)&unk_523B60, 2 * v7, 2 * v7, v9);
  v10 = v4;
  *((_QWORD *)&v5 + 1) = encoding_hex_Encode(v4, v8, v8, v9);
  runtime_slicebytetostring(0LL, v10, v8, v5);
  return v6;
}

可知是sha512加密,上python

import hashlib
hash="6500fe72abcab63d87f213d2218b0ee086a1828188439ca485a1a40968fd272865d5ca4d5ef5a651270a52ff952d955c9b757caae1ecce804582ae78f87fa3c9"
for i in range(90000000):
    pwd1=hex(i)
    pwd1=pwd1[2:]
    h1=hashlib.sha512(pwd1.encode('utf-8')).hexdigest()
    if h1==hash:
        print(hex(i))
        break
#0xf20a

第四部分加密

main_hash(a1 + 38, 4LL);
              if ( v8 == 32 )
                runtime_memequal(v3, (__int64)"ff6e2fd78aca4736037258f0ede4ecf0", 32LL, 32);

main_hash()函数

__int64 __usercall main_hash@<rax>(__int64 a1, __int64 a2)
{
  const char *v2; // rdi
  __int128 v4; // [rsp+18h] [rbp-78h]
  __int64 v5; // [rsp+28h] [rbp-68h]
  __int128 v6; // [rsp+48h] [rbp-48h] BYREF
  char v7[32]; // [rsp+58h] [rbp-38h] BYREF
  __int128 v8; // [rsp+78h] [rbp-18h]
​
  *(_QWORD *)&v4 = runtime_stringtoslicebyte((__int64)v7, a1, a2);
  crypto_md5_Sum(v4);
  v6 = v4;
  v8 = 0LL;
  *(_QWORD *)&v8 = runtime_convT2Enoptr((__int64)&unk_524360, (__int64)&v6);
  *((_QWORD *)&v8 + 1) = v4;
  fmt_Sprintf(v2);
  return v5;
}

可知是md5加密

网上找md5在线解密,但是没有找到一个可以正确解密出来的,直接用python写了(自己写不出来,还是wp里面的)

解密

import itertools
import string
import hashlib
​
def md5crash(sha256enc):
    code = ''
    strlist = itertools.product(string.ascii_letters + string.digits, repeat=4)
​
    for i in strlist:
        code = i[0] + i[1] + i[2] + i[3]
        encinfo = hashlib.md5(code.encode()).hexdigest()
        if encinfo == sha256enc:
            return code
​
flag = md5crash("ff6e2fd78aca4736037258f0ede4ecf0")
print(flag)
#f940

最后的flag是

GKCTF{87f645e9-b628-412f-9d7a-e402f20af940}

这绝对是我做过最难的题目了

还发现一个奇怪的事情,第一次ida64打开该文件时,main_check函数里面四个runtime_memequal()函数都没有参数,但是第二次再打开,它又突然显示出来了所有的参数。

参考wp:

GKCTF 2021 Re复现_Pvr1sC的博客-CSDN博客

2021GKCTF re wp_yaoxixixi的博客-CSDN博客

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值