0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

claustra01's Daily CTFAdvent Calendar 2024

Day 5

[rev] nimrev (CakeCTF 2022) writeup

Last updated at Posted at 2024-12-04


Nim言語のバイナリが与えられる。

Ghidraに投げてmain関数から順に処理を追っていくと、NimMainModuleという関数が見つかる。

void NimMainModule(void)

{
  char cVar1;
  undefined8 uVar2;
  undefined8 *puVar3;
  undefined8 uVar4;
  long in_FS_OFFSET;
  code *local_28;
  undefined8 local_20;
  undefined8 local_18;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  nimZeroMem(&local_18,8);
  uVar2 = readLine_systemZio_271(stdin);
  puVar3 = (undefined8 *)newSeq(NTIseqLcharT__lBgZ7a89beZGYPl8PiANMTA_,0x18);
  *(undefined *)(puVar3 + 2) = 0xbc;
  *(undefined *)((long)puVar3 + 0x11) = 0x9e;
  *(undefined *)((long)puVar3 + 0x12) = 0x94;
  *(undefined *)((long)puVar3 + 0x13) = 0x9a;
  *(undefined *)((long)puVar3 + 0x14) = 0xbc;
  *(undefined *)((long)puVar3 + 0x15) = 0xab;
  *(undefined *)((long)puVar3 + 0x16) = 0xb9;
  *(undefined *)((long)puVar3 + 0x17) = 0x84;
  *(undefined *)(puVar3 + 3) = 0x8c;
  *(undefined *)((long)puVar3 + 0x19) = 0xcf;
  *(undefined *)((long)puVar3 + 0x1a) = 0x92;
  *(undefined *)((long)puVar3 + 0x1b) = 0xcc;
  *(undefined *)((long)puVar3 + 0x1c) = 0x8b;
  *(undefined *)((long)puVar3 + 0x1d) = 0xce;
  *(undefined *)((long)puVar3 + 0x1e) = 0x92;
  *(undefined *)((long)puVar3 + 0x1f) = 0xcc;
  *(undefined *)(puVar3 + 4) = 0x8c;
  *(undefined *)((long)puVar3 + 0x21) = 0xa0;
  *(undefined *)((long)puVar3 + 0x22) = 0x91;
  *(undefined *)((long)puVar3 + 0x23) = 0xcf;
  *(undefined *)((long)puVar3 + 0x24) = 0x8b;
  *(undefined *)((long)puVar3 + 0x25) = 0xa0;
  *(undefined *)((long)puVar3 + 0x26) = 0xbc;
  *(undefined *)((long)puVar3 + 0x27) = 0x82;
  nimZeroMem(&local_28,0x10);
  local_28 = colonanonymous__main_7;
  local_20 = 0;
  if (puVar3 == (undefined8 *)0x0) {
    uVar4 = 0;
  }
  else {
    uVar4 = *puVar3;
  }
  puVar3 = (undefined8 *)map_main_11(puVar3 + 2,uVar4,colonanonymous__main_7,0);
  if (puVar3 == (undefined8 *)0x0) {
    uVar4 = 0;
  }
  else {
    uVar4 = *puVar3;
  }
  uVar4 = join_main_42(puVar3 + 2,uVar4,0);
  cVar1 = eqStrings(uVar2,uVar4);
  if (cVar1 == '\x01') {
    local_18 = copyString(&TM__V45tF8B8NBcxFcjfe7lhBw_4);
  }
  else {
    local_18 = copyString(&TM__V45tF8B8NBcxFcjfe7lhBw_5);
  }
  echoBinSafe(&local_18,1);
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

puVar3に何らかの値を格納し、map_main_11join_main_42で何らかの処理を行い、標準入力と比較しているように見える。

map_main_11を見てみる。

long map_main_11(long param_1,long param_2,code *param_3,long param_4)

{
  undefined uVar1;
  long lVar2;
  long local_28;
  
  lVar2 = newSeq(NTIseqLcharT__lBgZ7a89beZGYPl8PiANMTA_,param_2);
  for (local_28 = 0; local_28 < param_2; local_28 = local_28 + 1) {
    if (param_4 == 0) {
      uVar1 = (*param_3)((int)*(char *)(param_1 + local_28));
    }
    else {
      uVar1 = (*param_3)((int)*(char *)(param_1 + local_28),param_4);
    }
    *(undefined *)(local_28 + lVar2 + 0x10) = uVar1;
  }
  return lVar2;
}

param_4が0なので、関数ポインタparam_3の処理を配列全てに対して行っているだけっぽい。NimMainModuleに戻ってparam_3の値を確認すると、colonanonymous__main_7という関数が渡されていた。

colonanonymous__main_7の中身はこれ。NOTを取っているだけ。

byte colonanonymous__main_7(byte param_1)

{
  return ~param_1;
}

一応join_main_42も見る。配列を結合して文字列に変換しているだけのような雰囲気。

undefined8 join_main_42(long param_1,long param_2,undefined8 *param_3)

{
  char cVar1;
  undefined8 *puVar2;
  undefined8 uVar3;
  undefined8 local_28;
  undefined8 local_20;
  
  local_28 = 0;
  for (local_20 = 0; local_20 < param_2; local_20 = local_20 + 1) {
    cVar1 = *(char *)(param_1 + local_20);
    if (0 < local_20) {
      if (param_3 == (undefined8 *)0x0) {
        uVar3 = 0;
      }
      else {
        uVar3 = *param_3;
      }
      local_28 = resizeString(local_28,uVar3);
      appendString(local_28,param_3);
    }
    puVar2 = (undefined8 *)nimCharToStr((int)cVar1);
    if (puVar2 == (undefined8 *)0x0) {
      uVar3 = 0;
    }
    else {
      uVar3 = *puVar2;
    }
    local_28 = resizeString(local_28,uVar3);
    appendString(local_28,puVar2);
  }
  return local_28;
}

よって、puVar3のNOTを求めてやれば良さそう。

solverを書く。
単に~で演算すると負数になってしまうので0xffとの積を取る必要がある。

raw = [
  0xbc, 0x9e, 0x94, 0x9a, 0xbc, 0xab, 0xb9, 0x84,
  0x8c, 0xcf, 0x92, 0xcc, 0x8b, 0xce, 0x92, 0xcc,
  0x8c, 0xa0, 0x91, 0xcf, 0x8b, 0xa0, 0xbc, 0x82
]

data = []
for i in range(len(raw)):
    data.append(~raw[i] & 0xff)

print(''.join([chr(x) for x in data]))

flagが得られた。
CakeCTF{s0m3t1m3s_n0t_C}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?