[Dreamhack] secret message

chrmqgozj·2025년 2월 13일

DreamHack

목록 보기
29/39
  1. main
__int64 __fastcall main(int a1, char **a2, char **a3)
{
  FILE *v4; // [rsp+0h] [rbp-10h]
  FILE *stream; // [rsp+8h] [rbp-8h]

  v4 = fopen("secretMessage.raw", "rb");
  stream = fopen("secretMessage.enc", "wb");
  encode(v4, stream);
  remove("secretMessage.raw");
  puts("done!");
  fclose(stream);
  fclose(v4);
  return 0LL;
}

encode 함수를 역연산하여 raw를 얻어야 한다.

  1. encode
__int64 __fastcall encode(FILE *a1, FILE *a2)
{
  unsigned __int8 v3; // [rsp+17h] [rbp-9h]
  int c; // [rsp+18h] [rbp-8h]
  int v5; // [rsp+1Ch] [rbp-4h]

  if ( a1 && a2 )
  {
    v5 = -1;
    v3 = 0;
    while ( 1 )
    {
      c = fgetc(a1);
      if ( c == -1 )
        return 0LL;
      fputc(c, a2);
      if ( c == v5 )
      {
        v3 = 0;
        while ( 1 )
        {
          c = fgetc(a1);
          if ( c == -1 )
            break;
          if ( c != v5 )
          {
            fputc(v3, a2);
            fputc(c, a2);
            v5 = c;
            break;
          }
          if ( ++v3 == 0xFF )
          {
            fputc(255, a2);
            v5 = -1;
            break;
          }
        }
      }
      else
      {
        v5 = c;
      }
      if ( c == -1 )
      {
        fputc(v3, a2);
        return 0LL;
      }
    }
  }
  else
  {
    *__errno_location() = 2;
    return 0xFFFFFFFFLL;
  }
}

여기서 핵심은

	v5 = -1;
    v3 = 0;
    while ( 1 )
    {
      c = fgetc(a1);
      if ( c == -1 )
        return 0LL;
      fputc(c, a2);
      if ( c == v5 )
      {
        v3 = 0;
        while ( 1 )
        {
          c = fgetc(a1);
          if ( c == -1 )
            break;
          if ( c != v5 )
          {
            fputc(v3, a2);
            fputc(c, a2);
            v5 = c;
            break;
          }
          if ( ++v3 == 0xFF )
          {
            fputc(255, a2);
            v5 = -1;
            break;
          }
        }
      }
      else
      {
        v5 = c;
      }
      if ( c == -1 )
      {
        fputc(v3, a2);
        return 0LL;
      }
    }

일단 raw에서 읽은 값을 enc에 저장하고 이전의 값과 동일하다면 동일한 갯수를 쓰고 해당 값을 한 번 더 써서 마무리한다. 이때 갯수의 최대값은 255다. 그리고 255의 경우에는 문자를 한 번 더 쓰지 않는다.

A B B 10 C -> B가 12개 연속함
A B B 255 B B 2 C -> B가 261개 연속함

  1. exploit.py
with open('D:\\code\\dh\\rev\\secretmsg\\secretMessage.enc', 'rb') as f:
    raw = open('D:\\code\\dh\\rev\\secretmsg\\secretMessage.raw', 'wb')
    
    data = f.read()
    idx = 0
    
    while idx < len(data):
        c = data[idx]
        
        if ((idx + 1) < len(data)) and c == data[idx+1]:
            for i in range(data[idx+2]+2):
                raw.write(bytes([c]))
            idx += 3

        else:
            raw.write(bytes([c]))
            idx += 1

    raw.close()

0개의 댓글