[ctf.show.reverse] 月饼杯 re1_西北望乡、re2_归心、re3_若无月

re1_西北望乡

主程序很容易看明白,格式是flag{....}长45,然后把3,6,13,36拿出来作为系数,这些字符每5个一组分别乘系数后的和给定了。然后就是怎么解了。

  if ( strlen(flag) == 45 )
  {
    v21[0] = flag[3];
    v21[1] = flag[6];
    v21[2] = flag[13];
    v21[3] = flag[36];
    v21[4] = 13;
    for ( i = 0; i < 5; ++i )
    {
      v19 = 1LL;
      for ( j = 0; j < 5 - i; ++j )
        v19 *= v21[4 - i];
      v9 = (_QWORD *)i;
      *((_QWORD *)b + i) = v19;
    }
    for ( k = 0; k < 9; ++k )
    {
      v16 = 0LL;
      for ( l = 0; l < 5; ++l )
        v16 += flag[5 * k + l] * *((_QWORD *)b + l);
      v9 = arr;
      if ( v16 != arr[k] )
      {
        v11 = std::operator<<<std::char_traits<char>>(&std::cout, "哎呀,错了呢~~", arr);
        std::ostream::operator<<(v11, std::endl<char,std::char_traits<char>>);
        return 0;
      }
    }
    v12 = std::operator<<<std::char_traits<char>>(&std::cout, "哎呦,不错呦,去提交下试试吧。", v9);
    std::ostream::operator<<(v12, std::endl<char,std::char_traits<char>>);
  }
  else
  {
    v14 = std::operator<<<std::char_traits<char>>(&std::cout, "flag长度为49字符。", v9);
    v10 = strlen(flag);
    std::ostream::operator<<(v14, v10);
  }

因为第1组5个flag{已经知道了,可以先爆破出这3个值,然后再解。坑点是它说是小写字母和_但里边出了数字。


from z3 import *

arr = [0x2A6274623, 0x2A1032DAD, 0x27BD29EFD, 0x2D186CDC5, 0x2CB93A140, 0x286EB174E, 0x2CB9611A2, 0x27AE20336, 0x141D07333, 0x0ACEEBB]

#先求系数
i, j, k = Ints("i j k")
s = Solver()
s.add(arr[0] == ord('f')*13**5 + ord('l')*i**4 + ord('a')*j**3 + ord('g')*k**2 + ord('{')*ord('g'))
s.add(And(i>=95, i<=122))
s.add(And(j>=95, j<=122))
s.add(And(k>=95, k<=122))
if s.check():
    m= s.model()
    b1 = int(f'{m[i]}')**4
    b2 = int(f'{m[j]}')**3
    b3 = int(f'{m[k]}')**2

b0 = 13**5
b4 = ord('g')
    
print(b0,b1,b2,b3,b4)

#再爆破
flag = [Int(f'f[{i}]') for i in range(45)]
s=Solver()

#已知部分
for i,v in enumerate(b'flag{'):
    s.add(flag[i] == v)
s.add(flag[44] == ord('}'))

for i in range(45):
    s.add(And(flag[i]>=0x20, flag[i]<0x7f))

for i in range(9):
    data = f"flag[{i*5}]*{b0} + flag[{i*5+1}]*{b1} + flag[{i*5+2}]*{b2} + flag[{i*5+3}]*{b3} + flag[{i*5+4}]*{b4} == {arr[i]}"
    print(data)
    s.add(eval(data))

if s.check() == sat:
    m = s.model()
    print(m)
    for i in range(45):
        print(chr(int("%s" % (m[flag[i]]))), end='')

#flag{okok_here_is_your_flag_where_are_my_36d}

re2_归心

提示是说用啥打的包,用ida打开看是java的应该是jar文件,搜了下是exe4j运行一下,在临时目录里找到释放出来的jar文件,打开就看到flag

C:\Users\XXXXXXXX\AppData\Local\Temp\e4jCA19.tmp_dir1650439000\readme.jar
flag{You_Win_0nce_You_C_Me}

re3_若无月

有提示是RC4,先把一个序列作64轮轮换,然后每再按序号每轮换一次与明文作异或。如果提前生成足够多的码表,然后依次与密文异或就能得到明文。

windows程序里,事件1进行初始化密钥

    case 1u:
      w = GetSystemMetrics(0);
      cy = GetSystemMetrics(1);
      SetTimer(hWnd, 1u, 0xAu, 0);
      v8 = FindResourceA(0, (LPCSTR)0x78, (LPCSTR)8);
      v9 = SizeofResource(0, v8);
      v10 = LoadResource(0, v8);
      v11 = LockResource(v10);
      pNumFonts = 0;
      AddFontMemResourceEx(v11, v9, 0, &pNumFonts);
      v12 = 0;
      v13 = strlen(aTriglavian);
      do
      {
        byte_405418[v12] = v12;
        v14 = 0;
        while ( aTriglavian[v12 % v13] != byte_403370[v14] )// base64 A-a-0-+/
        {
          if ( ++v14 >= 64 )
          {
            LOBYTE(v14) = -1;
            break;
          }
        }
        byte_4053D8[v12++] = v14;
      }
      while ( v12 < 64 );
      v15 = 0;
      for ( i = 0; i < 64; ++i )
      {
        v17 = byte_405418[i];
        v15 = (v17 + byte_4053D8[i] + v15) % 64;
        byte_405418[i] = byte_405418[v15];
        byte_405418[v15] = v17;
      }
      v18 = time64(0);
      srand(v18);
      v19 = GetDC(hWnd);
      hdcSrc = CreateCompatibleDC(v19);
      ho = CreateCompatibleBitmap(v19, w, cy);
      SelectObject(hdcSrc, ho);
      ReleaseDC(hWnd, v19);
      v20 = CreateFontA(32, 27, 0, 0, 700, 0, 0, 0, 1u, 0, 0, 1u, 0x21u, "Triglavian - Complete");
      SelectObject(hdcSrc, v20);
      DeleteObject(v20);
      SetBkMode(hdcSrc, 1);
      dword_405474 = w / 48;
      v21 = 0;
      Block = calloc(w / 48, 0x20u);
      if ( dword_405474 > 0 )
      {
        v22 = 0;
        v23 = 0;
        do
        {
          sub_401270(v23);
          ++v21;
          v22 += 32;
          v23 += 48;
        }
        while ( v21 < dword_405474 );
      }
      return 0;

然后加密,每运行1次加密1字符。

char sub_401160()
{
  char v0; // bl
  int v1; // edi
  char v2; // dl
  int v3; // ecx
  char v4; // al
  int v5; // eax

  if ( dword_40545C > *(_DWORD *)(*(_DWORD *)NtCurrentTeb()->ThreadLocalStoragePointer + 4) )
  {
    _Init_thread_header(&dword_40545C);
    if ( dword_40545C == -1 )
    {
      dword_405460 = rand();
      _Init_thread_footer(&dword_40545C);
    }
  }
  dword_405460 = (dword_405460 + 1) % 192;
  v0 = byte_4032A8[dword_405460];
  v1 = (dword_4053D4 + 1) % 64;
  v2 = byte_405418[v1];
  dword_4053D4 = v1;
  v3 = (v2 + dword_4053D0) % 64;
  v4 = byte_405418[v3];
  dword_4053D0 = v3;
  byte_405418[v1] = v4;
  byte_405418[v3] = v2;
  v5 = 0;
  while ( v0 != byte_403370[v5] )
  {
    if ( ++v5 >= 64 )
    {
      LOBYTE(v5) = -1;
      return byte_403370[(char)v5 ^ byte_405418[(v2 + byte_405418[v1]) % 64]];
    }
  }
  return byte_403370[(char)v5 ^ byte_405418[(v2 + byte_405418[v1]) % 64]];
}

前边已经有好几个RC4的题了,思路都一样

code = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
key = (b'Triglavian'*10)[:64]
key = [code.index(i) for i in key]

#生成key
S = list(range(64))
j = 0
for i in range(64):
    j = (j + S[i] + key[i])%64
    S[i],S[j] = S[j],S[i]

#生成足够长的码表
i,j = 0,0
tab = [0]*200
for k in range(200):
    i = (i + 1)%64
    j = (j + S[i])%64
    S[i],S[j] = S[j],S[i]
    tab[k] = S[(S[i]+S[j])%64]

print(tab, len(tab))

c = b'20c1LOP2FnBOCMhPbCdtXTHmpgoK7g1sPN0KCcaBs3sWx/5Bob1t6IJaahW6SUGpTW11DmhJGeTj3UCSPCOZYaLw9qmg80kN56XF+dNhBYlfKbWqwSKJl+zTBvH0yBLDy7nwJ1W/SeBW+LaUV1Dq4FRnogzD5FOHNknyfyMerA3o5lgRq03f2M5C7ixuJ6WK'
print( bytes( [code[code.index(v) ^ tab[i]] for i,v in enumerate(c) ] ) )
#b'flag/SECRETTriglavianModifiyM1n1RC4StreamCipher/flag/SECRETTriglavianModifiyM1n1RC4StreamCipher/flag/SECRETTriglavianModifiyM1n1RC4StreamCipher/flag/SECRETTriglavianModifiyM1n1RC4StreamCipher/'
#flag/SECRETTriglavianModifiyM1n1RC4StreamCipher/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值