[QCTF2018]ollvm

...
用的mpz库
前面的代码:

if ( argc == 2 )
  {
    if ( strlen(INPUT[1]) == 38 )
    {
      i = 0;
      j = 0;
      oo2::MemsetQuantum_Test((oo2 *)v119, (const unsigned __int8 *)1);
      __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::__gmp_expr((__int64)v118);
      v22 = v116;
      do
      {
        __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::__gmp_expr((__int64)v22);
        v22 += 16;
      }
      while ( v22 != v117 );                    // v22->&v117
      v115 = 0;
      for ( i = 0; ; ++i )
      {
        v21 = i;
        if ( v21 >= strlen(INPUT[1]) )
          break;
        __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::operator=(v119, 1LL);
        __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::operator=(v118, (unsigned int)(INPUT[1][i] - v115));
        for ( j = 0; j < 5; ++j )               // 也就是5次方...
        {
          v114[0] = operator*<__mpz_struct [1],__mpz_struct [1],__mpz_struct [1],__mpz_struct [1]>(v119, (size_t)v118);// mul
          v114[1] = v3;
          rcs::analytics::Event::operator=(v119, v114);
        }                                       // v119 = ord(flag[i])**5
        v113[0] = operator%<__mpz_struct [1],__mpz_struct [1]>(v119, 323LL);
        v113[1] = v4;
        __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::operator=<__mpz_struct [1],__gmp_binary_expr<__gmp_expr<__mpz_struct [1],__mpz_struct [1]>,long,__gmp_binary_modulus>>(
          &v116[i],
          v113);                                // v116[i]=ord(flag[i])**5 % 323
      }
      v20 = (__int64 *)v111;
      do
      {
        __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::__gmp_expr((__int64)v20);
        v20 += 2;
      }
      while ( v20 != &v112 );
      v109[0] = operator-<__mpz_struct [1],__mpz_struct [1]>((__int64)v116, 0);
      v109[1] = v5;
      v6 = strlen(INPUT[1]);
      v110[0] = operator+<__mpz_struct [1],__gmp_binary_expr<__gmp_expr<__mpz_struct [1],__mpz_struct [1]>,long,__gmp_binary_minus>>(
                  v109,
                  v6);
      v110[1] = v7;
      __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::operator=<__mpz_struct [1],__gmp_binary_expr<__gmp_expr<__mpz_struct [1],__gmp_binary_expr<__gmp_expr<__mpz_struct [1],__mpz_struct [1]>,long,__gmp_binary_minus>>,unsigned long,__gmp_binary_plus>>(
        v111,
        v110);
      for ( i = 1; ; ++i )
      {
        v19 = i;
        if ( v19 >= strlen(INPUT[1]) )
          break;
        v108[0] = operator+<__mpz_struct [1],__mpz_struct [1],__mpz_struct [1],__mpz_struct [1]>(&v116[i], &v116[i - 1]);
        v108[1] = v8;
        __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::operator=<__mpz_struct [1],__gmp_binary_expr<__gmp_expr<__mpz_struct [1],__mpz_struct [1]>,__gmp_expr<__mpz_struct [1],__mpz_struct [1]>,__gmp_binary_plus>>(
          &v111[i],
          v108);
      }
      v18 = (__int64 *)v107;

后面都是重复的赋值
最后的check:

for ( i = 0; ; ++i )
      {
        v16 = i;
        if ( v16 >= strlen(INPUT[1]) )
          break;
        encrypt((__int64)v23, (__int64)&v111[i], (__int64)v101, (__int64)v102);// v23=&v111[i]**v101 % v102
        __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::operator=(&v107[i], v23);
        __gmp_expr<__mpz_struct [1],__mpz_struct [1]>::~__gmp_expr(v23);
        if ( operator!=<__mpz_struct [1],__mpz_struct [1],__mpz_struct [1],__mpz_struct [1]>(
               (__int64)&v107[i],
               (__int64)&v63[16 * i]) )
        {
          v15 = std::operator<<<std::char_traits<char>>(&_bss_start, (unsigned int)"wrong flag.");
          std::ostream::operator<<(v15, (unsigned int)&std::endl<char,std::char_traits<char>>);
          v124 = 0;
          goto LABEL_31;
        }
      }

主要是开始前面那个5次方硬是没反应过来...
整个流程大概就是

v116[i]=ord(flag[i])**5 % 323
for i in range(1,38):
    v111[i] = v116[i]+v116[i-1]
    assert pow(v111[i],41609,n) == enc[i]

但问题是 39(1+38)个大数... 累不累啊...

由于它是单字符check 单字符! 而且check时经过了RSA运算(需要一定的运算量) 所以可以考虑pintool
测试了一下: inscount0.so
0000...:5500870
Q000...:6743637
QC00...:7987243
每次的运行次数不一定一模一样 但是正确一个后会增加显著的1000000+
可以利用这个来侧信道爆破
这里不知道flag字符范围 只能0-9a-zA-Z慢慢跑了

import subprocess
import time

st_time = time.time()
l = 38
table="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
now = 5
flag = "QCTF{"+"*"*33
prev_cnt = 11718047
while(1):
    if(now>=37):
        break
    for x in table:
        cmd = '../../../pin -t obj-intel64/inscount0.so -o ollvm.log -- ./ollvm '+\
            flag[:now]+x+flag[now+1:]+\
                '; cat ./ollvm.log'
        output = subprocess.check_output(cmd,shell=True,stderr=subprocess.PIPE) 
        now_cnt = int(output.split(b'\n')[1].split()[1].decode())
        # print(now_cnt)
        if(now_cnt-prev_cnt>=1000000):
            print(f"[+] RIGHT!        {x}")
            flag = flag[:now]+x+flag[now+1:]
            now += 1
            prev_cnt = now_cnt
            break
    else:
        print("[+] ERROR !")

print(f'[+] Done!\ntime: {time.time()-st_time}')
print(f'\n[+]{flag}\n')

28min左右爆出来...
image

QCTF{5Ym4aOEww2NcZcvUPOWKYMnPaqPywR2m}
但是buu交不对... 嘛 无妨~

posted @ 2024-02-10 16:37  N0zoM1z0  阅读(13)  评论(0编辑  收藏  举报