FooBar CTF 2022 Writeup

この大会は2022/3/4 23:30(JST)~2022/3/5 23:30(JST)に開催されました。
今回もチームで参戦。結果は301点で372チーム中116位でした。
自分で解けた問題をWriteupとして書いておきます。

Sanity Check (Welcome)

Discordに入り、#announcementsチャネルのメッセージを見ると、フラグが書いてあった。

GLUG{W3lc0m3_7o_F00b4r!!}

Baby Rev (Rev)

Ghidraでデコンパイルする。

undefined8 main(int param_1,long param_2)

{
  char *__s;
  undefined8 uVar1;
  size_t sVar2;
  bool bVar3;
  bool bVar4;
  bool bVar5;
  bool bVar6;
  bool bVar7;
  bool bVar8;
  bool bVar9;
  bool bVar10;
  bool bVar11;
  bool bVar12;
  bool bVar13;
  bool bVar14;
  bool bVar15;
  bool bVar16;
  bool bVar17;
  bool bVar18;
  bool bVar19;
  bool bVar20;
  bool bVar21;
  bool bVar22;
  bool bVar23;
  bool bVar24;
  bool bVar25;
  bool bVar26;
  bool bVar27;
  bool bVar28;
  bool bVar29;
  bool bVar30;
  bool bVar31;
  bool bVar32;
  bool bVar33;
  bool bVar34;
  bool bVar35;
  bool bVar36;
  bool bVar37;
  bool bVar38;
  bool bVar39;
  bool bVar40;
  bool bVar41;
  bool bVar42;
  bool bVar43;
  bool bVar44;
  bool bVar45;
  bool bVar46;
  bool bVar47;
  bool bVar48;
  bool bVar49;
  bool bVar50;
  bool bVar51;
  bool bVar52;
  bool bVar53;
  bool bVar54;
  bool bVar55;
  bool bVar56;
  bool bVar57;
  bool bVar58;
  bool bVar59;
  bool bVar60;
  bool bVar61;
  bool bVar62;
  bool bVar63;
  bool bVar64;
  bool bVar65;
  bool bVar66;
  bool bVar67;
  bool bVar68;
  bool bVar69;
  bool bVar70;
  bool bVar71;
  bool bVar72;
  bool bVar73;
  bool bVar74;
  bool bVar75;
  bool bVar76;
  bool bVar77;
  bool bVar78;
  bool bVar79;
  bool bVar80;
  bool bVar81;
  bool bVar82;
  bool bVar83;
  bool bVar84;
  bool bVar85;
  
  if (param_1 == 2) {
    __s = *(char **)(param_2 + 8);
    sVar2 = strlen(__s);
    if ((int)sVar2 == 0x2a) {
      bVar3 = (int)__s[8] + (int)__s[0xd] + (int)__s[7] == 0x10d;
      bVar4 = (int)*__s + ((int)*__s - (int)__s[1]) + (int)__s[0xe] == 0xa5;
      bVar5 = (int)__s[0x26] + (int)__s[0x15] * (int)__s[0x10] + (int)__s[0x22] == 0x250a;
      bVar6 = (int)__s[0x17] + (int)__s[0x29] + (int)__s[6] * (int)__s[8] == 0x157c;
      bVar7 = -(int)__s[0x15] - (int)__s[0x29] == -0xdf;
      bVar8 = (int)__s[0x13] + (int)__s[0x12] * (int)__s[4] * (int)__s[0xb] == 0x9c2de;
      bVar9 = (int)__s[0x22] * (int)__s[0x21] + (int)__s[0x17] == 0x1903;
      bVar10 = (int)__s[0xe] * (int)__s[0x12] - (int)__s[0x21] == 0x13d0;
      bVar11 = (((int)__s[0x18] - (int)__s[0x27]) - (int)__s[0x1e]) - (int)__s[0x16] == -0x6e;
      bVar12 = (int)__s[1] + (((int)__s[0x1e] + (int)__s[10]) - (int)__s[0x13]) == 0x6e;
      bVar13 = ((int)__s[0xf] - (int)__s[0x14]) - (int)__s[0x29] == -0xa9;
      bVar14 = (int)__s[0x23] * (int)__s[0xf] - (int)__s[8] * (int)__s[0x29] == -0x27f7;
      bVar15 = ((int)__s[0xb] * (int)__s[0x1f] + (int)__s[0x24]) - (int)__s[0x20] == 0x20ec;
      bVar16 = (int)__s[0x28] + (int)__s[0x19] + (int)__s[0x1d] == 0x121;
      bVar17 = (int)__s[0x18] + ((int)__s[7] - (int)__s[0xc]) == 100;
      bVar18 = (int)__s[0x1e] * (int)__s[0x15] - (int)__s[6] == 0x242e;
      bVar19 = (int)__s[3] * (int)__s[0x21] * (int)__s[0x26] == 0x753f4;
      bVar20 = ((int)__s[0x14] - (int)*__s * (int)__s[0x1f]) - (int)__s[2] == -0x1742;
      bVar21 = (int)__s[0x15] * (int)__s[0xc] + (int)__s[0x1b] == 0x13e7;
      bVar22 = ((int)__s[6] + (int)__s[8] * (int)__s[0xb]) - (int)__s[8] == 0x2aba;
      bVar23 = (int)__s[0x18] * (int)__s[7] + ((int)__s[0x22] - (int)__s[5]) == 0x1396;
      bVar24 = ((int)__s[0x28] - (int)__s[0x12]) - (int)__s[2] == -0x53;
      bVar25 = (int)__s[0x18] * (int)__s[9] + ((int)__s[0xb] - (int)__s[0x1f]) == 0x2782;
      bVar26 = ((int)__s[0x1c] + (int)__s[0x1e]) - (int)__s[0x10] * (int)__s[3] == -0x198f;
      bVar27 = (int)__s[0x19] * (int)__s[0x12] - (int)__s[0xb] == 0x16c4;
      bVar28 = (int)__s[0xb] * (int)__s[9] * (int)__s[8] == 0x109de8;
      bVar29 = (int)__s[0x19] * (int)__s[3] - (int)__s[6] * (int)__s[0x1d] == 0x8ee;
      bVar30 = (int)__s[0x24] - (int)__s[0x21] * (int)__s[7] == -0xe3a;
      bVar31 = (int)__s[0x14] + ((int)__s[0x20] - (int)__s[1]) == 0x49;
      bVar32 = (int)__s[4] * (int)__s[5] + (int)__s[0x27] == 0x2073;
      bVar33 = (int)__s[8] * (int)__s[0x27] * (int)*__s == 0x7dd84;
      bVar34 = (int)__s[0x1f] + ((int)__s[0xc] - (int)__s[0xd]) == 0x19;
      bVar35 = (int)__s[0x29] + (int)__s[0x29] + (int)__s[10] + (int)__s[0x12] == 0x15f;
      bVar36 = (int)__s[0x16] + (int)__s[1] * (int)__s[0xe] + (int)__s[7] == 0x1dc8;
      bVar37 = (int)__s[0xe] + (int)__s[0x12] * (int)__s[0x18] + (int)__s[0x1b] == 0x157c;
      bVar38 = (int)__s[0x12] + ((int)__s[0x14] - (int)__s[6] * (int)__s[0x29]) == -0x16dd;
      bVar39 = ((int)__s[0x21] - (int)__s[2]) - (int)__s[0x1f] * (int)__s[0x19] == -0x2571;
      bVar40 = (int)__s[0x25] * (int)__s[0xb] * (int)__s[0x12] == 0x56540;
      bVar41 = ((int)__s[7] + (int)__s[8] + (int)__s[0x11]) - (int)__s[0x27] == 0xc0;
      bVar42 = ((int)__s[0xb] - (int)__s[0x23]) - (int)__s[0x1f] * (int)__s[9] == -0x205d;
      bVar43 = (int)__s[0x27] + ((int)__s[0x17] - (int)__s[0x1d]) == 0x28;
      bVar44 = (int)__s[0x14] * (int)__s[0x19] * (int)__s[10] + (int)__s[0x1c] == 0x81959;
      bVar45 = (int)__s[3] * (int)__s[0x1d] * (int)__s[0x20] == 0x7142a;
      bVar46 = (int)__s[0x1e] + ((int)__s[0x20] - (int)__s[0x16]) == 0x62;
      bVar47 = (((int)*__s - (int)__s[0xd]) + (int)__s[0x28]) - (int)__s[0x26] == -0x4a;
      bVar48 = ((int)__s[0x15] + (int)__s[0x11]) - (int)__s[0x26] == 0x6c;
      bVar49 = (int)*__s - (int)__s[0x17] * (int)__s[0x29] == -0x2e1c;
      bVar50 = (int)__s[0x1b] * (int)__s[0x1d] * (int)__s[2] == 0xf390d;
      bVar51 = (int)__s[0x19] - (int)__s[0x23] * (int)__s[0x13] == -0x1d34;
      bVar52 = (int)__s[0x10] - (int)__s[7] * (int)__s[0x13] == -0x14af;
      bVar53 = (int)__s[0x16] + (int)__s[0x21] + (int)__s[0x1a] * (int)__s[0xc] == 0xaa8;
      bVar54 = (int)__s[0x20] + (int)__s[0x18] + (int)__s[0x29] == 0x119;
      bVar55 = (int)__s[0xe] * (int)__s[0x1f] * (int)__s[0x17] == 0xc0e04;
      bVar56 = ((int)__s[0x23] - (int)__s[6] * (int)__s[0x23]) - (int)__s[0xe] == -0xd0e;
      bVar57 = ((int)__s[0x1f] + (int)__s[0x28]) - (int)__s[0x19] * (int)__s[0x11] == -0x2b8c;
      bVar58 = (int)__s[0x13] * (int)__s[0xd] + (int)__s[0x12] * (int)__s[0x24] == 0x3fec;
      bVar59 = (int)__s[0x12] * (int)__s[2] + ((int)__s[0x28] - (int)__s[5]) == 0x1137;
      bVar60 = (int)__s[3] + ((int)__s[0x15] - (int)__s[0x19]) == 0x37;
      bVar61 = ((int)__s[0xd] + (int)__s[0xe] + (int)__s[0xe]) - (int)__s[2] == 0xdf;
      bVar62 = (int)__s[0x23] * (int)__s[0x24] - (int)__s[0x1d] * (int)__s[5] == -0x991;
      bVar63 = (int)__s[1] + ((int)__s[0x29] - (int)__s[0x27]) == 0x87;
      bVar64 = (int)*__s + ((int)__s[0x23] - (int)__s[0x23] * (int)*__s) == -0x1297;
      bVar65 = ((int)__s[8] - (int)__s[0x15] * (int)__s[10]) - (int)__s[0x1f] == -0x12a8;
      bVar66 = (int)__s[0x1c] + ((int)__s[0x1d] - (int)__s[0x18]) == 0x7e;
      bVar67 = ((int)__s[10] * (int)*__s - (int)__s[0x20]) - (int)__s[8] == 0xcf3;
      bVar68 = (int)__s[0x29] + (int)__s[0x20] * (int)__s[0x1c] == 0x170f;
      bVar69 = (int)__s[0x20] + ((int)__s[0x25] - (int)__s[0x18]) == 0x14;
      bVar70 = (int)__s[0x1f] + ((int)__s[10] * (int)__s[0x14] - (int)__s[0xf]) == 0x1250;
      bVar71 = ((int)__s[0x24] - (int)__s[9]) - (int)__s[0x12] * (int)__s[0x12] == -0xaa1;
      bVar72 = (int)__s[0x1e] * (int)__s[0x10] + (int)__s[7] * (int)__s[9] == 0x3634;
      bVar73 = ((int)__s[0x18] + (int)__s[0x22] + (int)__s[0x12]) - (int)__s[7] == 0xbc;
      bVar74 = (int)__s[0x14] + (int)__s[0x1b] * (int)__s[0x10] == 0x245e;
      bVar75 = (((int)__s[0x16] - (int)__s[0x1e]) - (int)__s[0x25]) - (int)__s[9] == -0xd3;
      bVar76 = (int)__s[0x1b] * (int)__s[0x29] * (int)__s[4] - (int)__s[0x26] == 0x16c156;
      bVar77 = (int)__s[0xd] + ((int)__s[0x23] - (int)__s[8] * (int)__s[0x1d]) == -0x334b;
      bVar78 = (((int)__s[0x17] - (int)__s[7]) - (int)__s[0x18]) - (int)__s[0x16] == -0x6b;
      bVar79 = (int)__s[5] * (int)__s[4] * (int)__s[0x25] == 0x88d04;
      bVar80 = (int)__s[0x20] * (int)__s[0x11] - (int)__s[0xf] == 0x14af;
      bVar81 = ((int)__s[0x20] + (int)__s[0x12] * (int)__s[0x17]) - (int)__s[5] == 0x133f;
      bVar82 = (int)__s[0x27] + (int)__s[3] + (int)__s[0x27] * (int)__s[8] == 0x1ce5;
      bVar83 = (int)__s[0x24] + ((int)__s[0x19] * (int)__s[7] - (int)__s[3]) == 0x15dd;
      bVar84 = ((int)__s[9] - (int)__s[0x18]) - (int)__s[0x21] == -0x4f;
      bVar85 = (int)__s[0x24] * (int)__s[0xe] + (int)__s[0x1e] == 0x2015;
      if (bVar85 && (bVar84 &&
                    (bVar83 &&
                    (bVar82 &&
                    (bVar81 &&
                    (bVar80 &&
                    (bVar79 &&
                    (bVar78 &&
                    (bVar77 &&
                    (bVar76 &&
                    (bVar75 &&
                    (bVar74 &&
                    (bVar73 &&
                    (bVar72 &&
                    (bVar71 &&
                    (bVar70 &&
                    (bVar69 &&
                    (bVar68 &&
                    (bVar67 &&
                    (bVar66 &&
                    (bVar65 &&
                    (bVar64 &&
                    (bVar63 &&
                    (bVar62 &&
                    (bVar61 &&
                    (bVar60 &&
                    (bVar59 &&
                    (bVar58 &&
                    (bVar57 &&
                    (bVar56 &&
                    (bVar55 &&
                    (bVar54 &&
                    (bVar53 &&
                    (bVar52 &&
                    (bVar51 &&
                    (bVar50 &&
                    (bVar49 &&
                    (bVar48 &&
                    (bVar47 &&
                    (bVar46 &&
                    (bVar45 &&
                    (bVar44 &&
                    (bVar43 &&
                    (bVar42 &&
                    (bVar41 &&
                    (bVar40 &&
                    (bVar39 &&
                    (bVar38 &&
                    (bVar37 &&
                    (bVar36 &&
                    (bVar35 &&
                    (bVar34 &&
                    (bVar33 &&
                    (bVar32 &&
                    (bVar31 &&
                    (bVar30 &&
                    (bVar29 &&
                    (bVar28 &&
                    (bVar27 &&
                    (bVar26 &&
                    (__s[0x29] == '}' &&
                    (bVar25 &&
                    (bVar24 &&
                    (bVar23 &&
                    (bVar22 &&
                    (bVar21 &&
                    (bVar20 &&
                    (bVar19 &&
                    (bVar18 &&
                    (bVar17 &&
                    (bVar16 &&
                    (bVar15 &&
                    (bVar14 &&
                    (bVar13 &&
                    (bVar12 &&
                    (bVar11 &&
                    (bVar10 &&
                    (bVar9 && (bVar8 && (bVar7 && (bVar6 && (bVar5 && (bVar4 && bVar3)))))))))))))))
                    )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) {
        puts(":) CORRECT!");
        uVar1 = 0;
      }
      else if (bVar85 && (bVar84 &&
                         (bVar83 &&
                         (bVar82 &&
                         (bVar81 &&
                         (bVar80 &&
                         (bVar79 &&
                         (bVar78 &&
                         (bVar77 &&
                         (bVar76 &&
                         (bVar75 &&
                         (bVar74 &&
                         (bVar73 &&
                         (bVar72 &&
                         (bVar71 &&
                         (bVar70 &&
                         (bVar69 &&
                         (bVar68 &&
                         (bVar67 &&
                         (bVar66 &&
                         (bVar65 &&
                         (bVar64 &&
                         (bVar63 &&
                         (bVar62 &&
                         (bVar61 &&
                         (bVar60 &&
                         (bVar59 &&
                         (bVar58 &&
                         (bVar57 &&
                         (bVar56 &&
                         (bVar55 &&
                         (bVar54 &&
                         (bVar53 &&
                         (bVar52 &&
                         (bVar51 &&
                         (bVar50 &&
                         (bVar49 &&
                         (bVar48 &&
                         (bVar47 &&
                         (bVar46 &&
                         (bVar45 &&
                         (bVar44 &&
                         (bVar43 &&
                         (bVar42 &&
                         (bVar41 &&
                         (bVar40 &&
                         (bVar39 &&
                         (bVar38 &&
                         (bVar37 &&
                         (bVar36 &&
                         (bVar35 &&
                         (bVar34 &&
                         (bVar33 &&
                         (bVar32 &&
                         (bVar31 &&
                         (bVar30 &&
                         (bVar29 &&
                         (bVar28 &&
                         (bVar27 &&
                         (bVar26 &&
                         (__s[0x29] == '}' &&
                         (bVar25 &&
                         (bVar24 &&
                         (bVar23 &&
                         (bVar22 &&
                         (bVar21 &&
                         (bVar20 &&
                         (bVar19 &&
                         (bVar18 &&
                         (bVar17 &&
                         (bVar16 &&
                         (bVar15 &&
                         (bVar14 &&
                         (bVar13 &&
                         (bVar12 &&
                         (bVar11 &&
                         (bVar10 &&
                         (bVar9 && (bVar8 && (bVar7 && (bVar6 && (bVar5 && (bVar4 && bVar3))))))))))
                         ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) {
        uVar1 = 0;
      }
      else {
        puts(";( INCORRECT");
        uVar1 = 0;
      }
    }
    else {
      puts(";( INCORRECT");
      uVar1 = 0xffffffff;
    }
  }
  else {
    puts("Usage: ./binary <key>");
    uVar1 = 0xffffffff;
  }
  return uVar1;
}

":) CORRECT!"になる条件を使って、z3で解く。

from z3 import *

x = [BitVec('x%d' % i, 8) for i in range(42)]
s = Solver()

s.add(x[8] + x[0xd] + x[7] == 0x10d)
s.add(x[0] + (x[0] - x[1]) + x[0xe] == 0xa5)
s.add(x[0x26] + x[0x15] * x[0x10] + x[0x22] == 0x250a)
s.add(x[0x17] + x[0x29] + x[6] * x[8] == 0x157c)
s.add(-x[0x15] - x[0x29] == -0xdf)
s.add(x[0x13] + x[0x12] * x[4] * x[0xb] == 0x9c2de)
s.add(x[0x22] * x[0x21] + x[0x17] == 0x1903)
s.add(x[0xe] * x[0x12] - x[0x21] == 0x13d0)
s.add(((x[0x18] - x[0x27]) - x[0x1e]) - x[0x16] == -0x6e)
s.add(x[1] + ((x[0x1e] + x[10]) - x[0x13]) == 0x6e)
s.add((x[0xf] - x[0x14]) - x[0x29] == -0xa9)
s.add(x[0x23] * x[0xf] - x[8] * x[0x29] == -0x27f7)
s.add((x[0xb] * x[0x1f] + x[0x24]) - x[0x20] == 0x20ec)
s.add(x[0x28] + x[0x19] + x[0x1d] == 0x121)
s.add(x[0x18] + (x[7] - x[0xc]) == 100)
s.add(x[0x1e] * x[0x15] - x[6] == 0x242e)
s.add(x[3] * x[0x21] * x[0x26] == 0x753f4)
s.add((x[0x14] - x[0] * x[0x1f]) - x[2] == -0x1742)
s.add(x[0x15] * x[0xc] + x[0x1b] == 0x13e7)
s.add((x[6] + x[8] * x[0xb]) - x[8] == 0x2aba)
s.add(x[0x18] * x[7] + (x[0x22] - x[5]) == 0x1396)
s.add((x[0x28] - x[0x12]) - x[2] == -0x53)
s.add(x[0x18] * x[9] + (x[0xb] - x[0x1f]) == 0x2782)
s.add((x[0x1c] + x[0x1e]) - x[0x10] * x[3] == -0x198f)
s.add(x[0x19] * x[0x12] - x[0xb] == 0x16c4)
s.add(x[0xb] * x[9] * x[8] == 0x109de8)
s.add(x[0x19] * x[3] - x[6] * x[0x1d] == 0x8ee)
s.add(x[0x24] - x[0x21] * x[7] == -0xe3a)
s.add(x[0x14] + (x[0x20] - x[1]) == 0x49)
s.add(x[4] * x[5] + x[0x27] == 0x2073)
s.add(x[8] * x[0x27] * x[0] == 0x7dd84)
s.add(x[0x1f] + (x[0xc] - x[0xd]) == 0x19)
s.add(x[0x29] + x[0x29] + x[10] + x[0x12] == 0x15f)
s.add(x[0x16] + x[1] * x[0xe] + x[7] == 0x1dc8)
s.add(x[0xe] + x[0x12] * x[0x18] + x[0x1b] == 0x157c)
s.add(x[0x12] + (x[0x14] - x[6] * x[0x29]) == -0x16dd)
s.add((x[0x21] - x[2]) - x[0x1f] * x[0x19] == -0x2571)
s.add(x[0x25] * x[0xb] * x[0x12] == 0x56540)
s.add((x[7] + x[8] + x[0x11]) - x[0x27] == 0xc0)
s.add((x[0xb] - x[0x23]) - x[0x1f] * x[9] == -0x205d)
s.add(x[0x27] + (x[0x17] - x[0x1d]) == 0x28)
s.add(x[0x14] * x[0x19] * x[10] + x[0x1c] == 0x81959)
s.add(x[3] * x[0x1d] * x[0x20] == 0x7142a)
s.add(x[0x1e] + (x[0x20] - x[0x16]) == 0x62)
s.add(((x[0] - x[0xd]) + x[0x28]) - x[0x26] == -0x4a)
s.add((x[0x15] + x[0x11]) - x[0x26] == 0x6c)
s.add(x[0] - x[0x17] * x[0x29] == -0x2e1c)
s.add(x[0x1b] * x[0x1d] * x[2] == 0xf390d)
s.add(x[0x19] - x[0x23] * x[0x13] == -0x1d34)
s.add(x[0x10] - x[7] * x[0x13] == -0x14af)
s.add(x[0x16] + x[0x21] + x[0x1a] * x[0xc] == 0xaa8)
s.add(x[0x20] + x[0x18] + x[0x29] == 0x119)
s.add(x[0xe] * x[0x1f] * x[0x17] == 0xc0e04)
s.add((x[0x23] - x[6] * x[0x23]) - x[0xe] == -0xd0e)
s.add((x[0x1f] + x[0x28]) - x[0x19] * x[0x11] == -0x2b8c)
s.add(x[0x13] * x[0xd] + x[0x12] * x[0x24] == 0x3fec)
s.add(x[0x12] * x[2] + (x[0x28] - x[5]) == 0x1137)
s.add(x[3] + (x[0x15] - x[0x19]) == 0x37)
s.add((x[0xd] + x[0xe] + x[0xe]) - x[2] == 0xdf)
s.add(x[0x23] * x[0x24] - x[0x1d] * x[5] == -0x991)
s.add(x[1] + (x[0x29] - x[0x27]) == 0x87)
s.add(x[0] + (x[0x23] - x[0x23] * x[0]) == -0x1297)
s.add((x[8] - x[0x15] * x[10]) - x[0x1f] == -0x12a8)
s.add(x[0x1c] + (x[0x1d] - x[0x18]) == 0x7e)
s.add((x[10] * x[0] - x[0x20]) - x[8] == 0xcf3)
s.add(x[0x29] + x[0x20] * x[0x1c] == 0x170f)
s.add(x[0x20] + (x[0x25] - x[0x18]) == 0x14)
s.add(x[0x1f] + (x[10] * x[0x14] - x[0xf]) == 0x1250)
s.add((x[0x24] - x[9]) - x[0x12] * x[0x12] == -0xaa1)
s.add(x[0x1e] * x[0x10] + x[7] * x[9] == 0x3634)
s.add((x[0x18] + x[0x22] + x[0x12]) - x[7] == 0xbc)
s.add(x[0x14] + x[0x1b] * x[0x10] == 0x245e)
s.add(((x[0x16] - x[0x1e]) - x[0x25]) - x[9] == -0xd3)
s.add(x[0x1b] * x[0x29] * x[4] - x[0x26] == 0x16c156)
s.add(x[0xd] + (x[0x23] - x[8] * x[0x1d]) == -0x334b)
s.add(((x[0x17] - x[7]) - x[0x18]) - x[0x16] == -0x6b)
s.add(x[5] * x[4] * x[0x25] == 0x88d04)
s.add(x[0x20] * x[0x11] - x[0xf] == 0x14af)
s.add((x[0x20] + x[0x12] * x[0x17]) - x[5] == 0x133f)
s.add(x[0x27] + x[3] + x[0x27] * x[8] == 0x1ce5)
s.add(x[0x24] + (x[0x19] * x[7] - x[3]) == 0x15dd)
s.add((x[9] - x[0x18]) - x[0x21] == -0x4f)
s.add(x[0x24] * x[0xe] + x[0x1e] == 0x2015)
s.add(x[0x29] == ord('}'))

r = s.check()
assert r == sat
m = s.model()
flag = ''
for i in range(42):
    flag += chr(m[x[i]].as_long())
print flag
GLUG{C01nc1d3nc3_c4n_b3_fr3aky_T6LSERDYB6}

bijective (Rev)

pycをデコンパイルする。

$ uncompyle6 chall.pyc
# uncompyle6 version 3.8.0
# Python bytecode 3.8.0 (3413)
# Decompiled from: Python 3.6.9 (default, Dec  8 2021, 21:08:43) 
# [GCC 8.4.0]
# Embedded file name: /home/error/Desktop/Question/chall.py
# Compiled at: 2022-03-04 21:59:24
# Size of source mod 2**32: 357 bytes
from secret import flag
s = 'aabacadaeafagaha'
characters = 'abcdefghijklmnopqrstuvwxyz1234567890{}_'

def encode(ch):
    i = characters.index(ch)
    return s[i // 3:i // 3 + i % 3 + 2]


enc = ''
for ch in flag:
    enc += encode(ch)
else:
    print(enc)
# okay decompiling chall.pyc

1文字ずつ暗号化しているので、ブルートフォースで復号する。ただし複数候補があるので、全リストを出し、手動で復号していく。

#!/usr/bin/env python3
s = 'aabacadaeafagaha'
characters = 'abcdefghijklmnopqrstuvwxyz1234567890{}_'

def encode(ch):
    i = characters.index(ch)
    return s[i // 3:i // 3 + i % 3 + 2]

with open('output.txt', 'r') as f:
    enc = f.read()

for ch in characters:
    print(ch, '->', encode(ch))

実行結果は以下の通り。

a -> aa
b -> aab
c -> aaba
d -> ab
e -> aba
f -> abac
g -> ba
h -> bac
i -> baca
j -> ac
k -> aca
l -> acad
m -> ca
n -> cad
o -> cada
p -> ad
q -> ada
r -> adae
s -> da
t -> dae
u -> daea
v -> ae
w -> aea
x -> aeaf
y -> ea
z -> eaf
1 -> eafa
2 -> af
3 -> afa
4 -> afag
5 -> fa
6 -> fag
7 -> faga
8 -> ag
9 -> aga
0 -> agah
{ -> ga
} -> gah
_ -> gaha

以上を元に復号する。

baacaddaeabagacaafagcadeagahadaeagahgahaagahcadabagah
g l   u   g { m 4   n  y _   t  0   _   0   n  e  }
glug{m4ny_t0_0ne}

Daredevil's server (Crypto)

$ nc chall.nitdgplug.org 30093
WELCOME TO DAREDEVIL'S SIGNING SERVER...

AVAILABLE OPTIONS !

[E]ncryption function
[P]ublic key 
[S]ign msg (hex)! 
[V]erify signature (hex)! 
[Q]uit 

> E
TOKEN = b'd4r3d3v!l'
def chall():
    s = Sign()
    while True:
        choice = input("> ").rstrip()
        if choice == 'P':
            print("\nN : {}".format(hex(s.n)))
            print("\ne : {}".format(hex(s.e)))
        elif choice == 'S':
            try:
                msg = bytes.fromhex(input('msg to sign : '))
                if TOKEN in msg:
                    print('[!] NOT ALLOWED')
                else:
                    m = bytes_to_long(msg)
                    print("\nsignature : {}".format(hex(s.sign(m))))      #pow(msg,d,n)
                    print('\n')
            except:
                print('\n[!] ERROR (invalid input)')
                
        elif choice == 'V':
            try:

                msg = bytes.fromhex(input("msg : "))
                m = bytes_to_long(msg)
                signature = int(input("signature : "),16)
                if m < 0 or m > s.n:
                    print('[!] ERROR')
                
                if s.verify(m, signature):                           #pow(sign, e, n) == msg
                    if long_to_bytes(m) == TOKEN:
                        print(SECRET)
                
                    else:
                        print('\n[+] Valid signature')
                       
                else:
                    print('\n[!]Invalid signature')
   
            except:
                print('\n[!] ERROR(invalid input)')


        elif choice == 'Q':
            print('OK BYE :)')
            exit(0)
        else:
            print('\n[*] SEE OPTIONS')


> P

N : 0xb56c516e9ba02ad85161943475f451736d7c6669ea368631f965ed02d1a55051b06226104489296a65317b7e6b3fe0988f5f83d128d0932731dc37fd362360614165a01ceebdab72094135928429bb0f79265ae74a7528b06fe7f912f68bc8d27966fcbdc427fd672ec2d6386490a570010de71510cd0d552c9ab47d20bc1d4f

e : 0x10001


> S
msg to sign : 1234

signature : 0xac3af3667f9ddb5638012dc80cc2c230efd402729f204960cf6bdb45a5d0e1152d714914355e7f53a66ac823925d57d654d6c03140f71382b645a26ea3a87357bb668449f6b72b1c19d88380323462f8127790c14f80d7ad492daa54f7f0a5dd432c8faed85bbc0d74e411d3c4f10485ba4b83ad01bc37a6a7ed23724622d5d


> V
msg : 1234
signature : 0xac3af3667f9ddb5638012dc80cc2c230efd402729f204960cf6bdb45a5d0e1152d714914355e7f53a66ac823925d57d654d6c03140f71382b645a26ea3a87357bb668449f6b72b1c19d88380323462f8127790c14f80d7ad492daa54f7f0a5dd432c8faed85bbc0d74e411d3c4f10485ba4b83ad01bc37a6a7ed23724622d5d

[+] Valid signature


> 

以下が指定できれば、フラグが表示される。

msg: "d4r3d3v!l"の16進数
signature: d4r3d3v!lを数値化したものの復号データ(pow(bytes_to_long("d4r3d3v!l"), d, N))

bytes_to_long("d4r3d3v!l")は偶数なので、2*Aと表せる。

pow(bytes_to_long("d4r3d3v!l"), d, N) = (pow(2, d, N) * pow(A, d, N)) % N

以上のことを使って、条件を満たす情報を指定し、フラグを取得する。

import socket
from Crypto.Util.number import *

def recvuntil(s, tail):
    data = b''
    while True:
        if tail in data:
            return data.decode()
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chall.nitdgplug.org', 30093))

data = recvuntil(s, b'\n> ')
print(data + 'E')
s.sendall(b'E\n')

data = recvuntil(s, b'\n> ')
print(data + 'P')
s.sendall(b'P\n')

data = recvuntil(s, b'\n> ')
print(data + 'S')
s.sendall(b'S\n')

N = int(data.split('\n')[1].split(' ')[-1], 16)
e = int(data.split('\n')[3].split(' ')[-1], 16)

TOKEN = b'd4r3d3v!l'
c = bytes_to_long(TOKEN)
assert c % 2 == 0
c1 = long_to_bytes(2).hex()
c2 = long_to_bytes(c // 2).hex()

data = recvuntil(s, b': ')
print(data + c1)
s.sendall(c1.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)
sig1 = int(data.split(' ')[-1], 16)

data = recvuntil(s, b'\n> ')
print(data + 'S')
s.sendall(b'S\n')
data = recvuntil(s, b': ')
print(data + c2)
s.sendall(c2.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)
sig2 = int(data.split(' ')[-1], 16)

sig = (sig1 * sig2) % N

data = recvuntil(s, b'\n> ')
print(data + 'V')
s.sendall(b'V\n')
data = recvuntil(s, b': ')
print(data + TOKEN.hex())
s.sendall(TOKEN.hex().encode() + b'\n')
data = recvuntil(s, b': ')
print(data + hex(sig))
s.sendall(hex(sig).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

実行結果は以下の通り。

WELCOME TO DAREDEVIL'S SIGNING SERVER...

AVAILABLE OPTIONS !

[E]ncryption function
[P]ublic key 
[S]ign msg (hex)! 
[V]erify signature (hex)! 
[Q]uit 

> E
TOKEN = b'd4r3d3v!l'
def chall():
    s = Sign()
    while True:
        choice = input("> ").rstrip()
        if choice == 'P':
            print("\nN : {}".format(hex(s.n)))
            print("\ne : {}".format(hex(s.e)))
        elif choice == 'S':
            try:
                msg = bytes.fromhex(input('msg to sign : '))
                if TOKEN in msg:
                    print('[!] NOT ALLOWED')
                else:
                    m = bytes_to_long(msg)
                    print("\nsignature : {}".format(hex(s.sign(m))))      #pow(msg,d,n)
                    print('\n')
            except:
                print('\n[!] ERROR (invalid input)')
                
        elif choice == 'V':
            try:

                msg = bytes.fromhex(input("msg : "))
                m = bytes_to_long(msg)
                signature = int(input("signature : "),16)
                if m < 0 or m > s.n:
                    print('[!] ERROR')
                
                if s.verify(m, signature):                           #pow(sign, e, n) == msg
                    if long_to_bytes(m) == TOKEN:
                        print(SECRET)
                
                    else:
                        print('\n[+] Valid signature')
                       
                else:
                    print('\n[!]Invalid signature')
   
            except:
                print('\n[!] ERROR(invalid input)')


        elif choice == 'Q':
            print('OK BYE :)')
            exit(0)
        else:
            print('\n[*] SEE OPTIONS')


> P

N : 0x86dfe4de8bd59d225a26a72eae28e79e8b43f7db623ed0095f22171ce5ba1fd4817e42d8f1cf1cd39e6f96d56ff6db276aff83fa6f5d8299b64b3d51bba61775a98d0c371c7b919ca6528492cfa10bbfb3ed1a173f562ecc6736bae32d8da5345aa68290d0a120985471d184301a38f64cd11a6c102f2cd0d81a57781cfb76e3

e : 0x10001


> S
msg to sign : 02

signature : 0x79e13f957788cc876473d71d6804c330bf38046b216ed1b9468134be341feee03a3881b64292d2877f83ae9e85b4dfeb0f16efbdd32ee365d531ebf3069d5d352b6ded7269b57a7c2bcef8cbc7a932c56f4d9d522262d214b22351a2c9e92a1bd79e7770b61bd4debc35905dbabc648a60a115fa18d5409f73bbaad8591bdecd


> S
msg to sign : 321a3919b219bb10b6

signature : 0x12e7f43bdabb9f82c9401dd76c101d32504cb487988ebbee742f6c4e3880c284263a57158fdd927e9fa114b6270d9d5c41abc1ee19a214ace503ee43d791d1ea889e6ba86e39978508857c82b8f10b8559033ba8a774185d1afee632d74bb025e6544f00493d4152b6d5c3a7cea3cf28352fe2bd59cd6c4c0ecda731968e550b


> V
msg : 64347233643376216c
signature : 0x23a7526933625deb7ef10f119a23ea077dfb91a1e7af5e52eda2fd678a755fbbae93b1cbab6adaa3b0524aa1104b4fc597426daed70b387ffe0999b82881ef59b98dc30b1803b6867f425befb5030f2648e497b8fbd71c5197003195b946624f1214f4b719132706ef0cefaedd2e2e90946faa131c8e4f1fcdd372a2dffa89a4
GLUG{fl4g_15_53rv3d_xD_E9644V2GG0}
GLUG{fl4g_15_53rv3d_xD_E9644V2GG0}