히공

hackingcamp22CTF - Opps Enc! 본문

write up/hackingcamp22CTF

hackingcamp22CTF - Opps Enc!

heegong 2021. 3. 20. 19:09
728x90

 

문제

 

 

 

 

 

 

please_analysis_me 파일의 main 함수다.

cypher_code가 굉장히 중요해 보였다.

 

 

 

 

 

 

여기서 get_key가 굉장히 중요해 보였다.

 

 

 

 

 

get_key의 리턴 값이 v7에 들어가는데 v7은 char형이다. 

 

 

그러면 cypher_code에서는 어떠한 부분을 0x1C로 xor 한다고 볼 수 있다.

 

 

 

 

 

 

get_key 함수다.

어차피 char형이 들어가므로 1바이트만 들어간다.

0x1C가 v7에 들어간다. (리틀엔디안)

 

please_analysis_me는 elf 섹션 중 어느 곳을 암호화하는 것 같았다.

 

opps_I_cannot_execute파일을 ida로 열어준다.

 

 

 

 

 

 

 

코드가 이상하다. shift+f7을 눌러 섹션을 본다.

 

 

 

 

 

 

 

 

 

text를 0x1C로 xor 해줄꺼다.

0x1140~0x1AE5 부분 까지 해주면 된다.

 

 

 

 

 

 

 

 

 

shift + f2를 누르면 이 창이 나오는데

scripting language를 idc에서 python으로 바꿔주고

 

 

 

from idc_bc695 import *

xorkey = 0x1c
for i in range(0x1140, 0x1ae6):
   PatchByte(i, Byte(i) ^ xorkey)

이 코드를 입력한 후 Run을 눌러준다.

 

 

 

 

 

뭔가 제대로 바뀌었다.

 

 

 

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rbp
  unsigned int v5; // [rsp-44h] [rbp-44h]
  signed int i; // [rsp-40h] [rbp-40h]
  signed int v7; // [rsp-3Ch] [rbp-3Ch]
  signed int v8; // [rsp-38h] [rbp-38h]
  signed int v9; // [rsp-34h] [rbp-34h]
  signed int v10; // [rsp-30h] [rbp-30h]
  signed int v11; // [rsp-2Ch] [rbp-2Ch]
  signed int v12; // [rsp-28h] [rbp-28h]
  char v13; // [rsp-24h] [rbp-24h]
  signed int j; // [rsp-20h] [rbp-20h]
  __int64 v15; // [rsp-10h] [rbp-10h]
  __int64 v16; // [rsp-8h] [rbp-8h]

  __asm { endbr64 }
  v16 = v3;
  sub_1120(stdin, 0LL, 2LL, 0LL);
  sub_1120(stderr, 0LL, 2LL, 0LL);
  sub_1120(stdout, 0LL, 2LL, 0LL);
  v15 = sub_1110(36LL);
  sub_10F0(v15, 0LL, 36LL);
  sub_1100(1LL, 1LL, "Thank you unpack me !\\n", 22LL);
  sub_1100(1LL, 1LL, "What is password?\\n", 18LL);
  sub_1100(0LL, 0LL, v15, 36LL);
  if ( (unsigned __int64)sub_10D0(v15) > 0x24 )
    sub_1100(1LL, 1LL, "ERR!", 7LL);
  v5 = 15;
  for ( i = 0; i <= 4; ++i )
  {
    if ( (unsigned int)((__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD))round1)(
                         byte_2008[i],
                         *(unsigned __int8 *)(i + v15),
                         v5) != 1 )
      sub_1130(0xFFFFFFFFLL);
    ++v5;
  }
  if ( *(_BYTE *)(v15 + 5) != 123 )
    sub_1130(0xFFFFFFFFLL);
  v7 = 10;
  v8 = 6;
  while ( v8 <= 11 )
  {
    if ( (unsigned int)((__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD))round2)(
                         byte_2008[v8],
                         *(unsigned __int8 *)(v8 + v15),
                         (unsigned int)(v7 + 3)) != 1 )
    {
      sub_10C0("WRONG");
      sub_1130(0xFFFFFFFFLL);
    }
    ++v8;
    ++v7;
  }
  v9 = 30;
  v10 = 12;
  while ( v10 <= 18 )
  {
    if ( (unsigned int)((__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD))round3)(
                         byte_2008[v10],
                         *(unsigned __int8 *)(v10 + v15),
                         (unsigned int)(v9 - 8)) != 1 )
    {
      sub_10C0("WRONG");
      sub_1130(0xFFFFFFFFLL);
    }
    ++v10;
    --v9;
  }
  v11 = -10;
  v12 = 19;
  while ( v12 <= 26 )
  {
    if ( (unsigned int)((__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD))round4)(
                         byte_2008[v12],
                         *(unsigned __int8 *)(v12 + v15),
                         (unsigned int)(v11 + 2)) != 1 )
    {
      sub_10C0("WRONG");
      sub_1130(0xFFFFFFFFLL);
    }
    ++v12;
    ++v11;
  }
  v13 = 50;
  for ( j = 27; j <= 33; ++j )
  {
    if ( (unsigned int)round5(v13 + 1, (__int64)&v16, byte_2008[j], *(_BYTE *)(j + v15)) != 1 )
    {
      sub_10C0("WRONG");
      sub_1130(0xFFFFFFFFLL);
    }
    --v13;
  }
  if ( *(_BYTE *)(v15 + 34) == 125 )
    sub_1100(1LL, 1LL, "GREAT!\\n", 8LL);
  return 0;
}

메인 함수 코드다.

 

 

 

 

 

 

 

round1 함수에 들어가면 이상하게 뜬다.

 

 

 

 

 

 

 

함수 우클릭 후 create function을 누르면 헥스레이 사용이 가능해진다.

round1~5까지 전부 해주자.

 

 

 

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rbp
  unsigned int v5; // [rsp-44h] [rbp-44h]
  signed int i; // [rsp-40h] [rbp-40h]
  signed int v7; // [rsp-3Ch] [rbp-3Ch]
  signed int v8; // [rsp-38h] [rbp-38h]
  signed int v9; // [rsp-34h] [rbp-34h]
  signed int v10; // [rsp-30h] [rbp-30h]
  signed int v11; // [rsp-2Ch] [rbp-2Ch]
  signed int v12; // [rsp-28h] [rbp-28h]
  char v13; // [rsp-24h] [rbp-24h]
  signed int j; // [rsp-20h] [rbp-20h]
  __int64 scanf_value; // [rsp-10h] [rbp-10h]
  __int64 v16; // [rsp-8h] [rbp-8h]

  __asm { endbr64 }
  v16 = v3;
  sub_1120(stdin, 0LL, 2LL, 0LL);
  sub_1120(stderr, 0LL, 2LL, 0LL);
  sub_1120(stdout, 0LL, 2LL, 0LL);
  scanf_value = sub_1110(36LL);
  sub_10F0();
  printf_or_scanf(1LL, 1LL, "Thank you unpack me !\\n", 22LL);
  printf_or_scanf(1LL, 1LL, "What is password?\\n", 18LL);
  printf_or_scanf(0LL, 0LL, scanf_value, 36LL);
  if ( (unsigned __int64)sub_10D0(scanf_value) > 0x24 )
    printf_or_scanf(1LL, 1LL, "ERR!", 7LL);
  v5 = 15;
  for ( i = 0; i <= 4; ++i )
  {
    if ( (unsigned int)round1(byte_2008[i], *(unsigned __int8 *)(i + scanf_value), v5) != 1 )
      sub_1130(0xFFFFFFFFLL);
    ++v5;
  }
  if ( *(_BYTE *)(scanf_value + 5) != 123 )
    sub_1130(0xFFFFFFFFLL);
  v7 = 10;
  v8 = 6;
  while ( v8 <= 11 )
  {
    if ( (unsigned int)round2(byte_2008[v8], *(unsigned __int8 *)(v8 + scanf_value), (unsigned int)(v7 + 3)) != 1 )
    {
      sub_10C0("WRONG");
      sub_1130(0xFFFFFFFFLL);
    }
    ++v8;
    ++v7;
  }
  v9 = 30;
  v10 = 12;
  while ( v10 <= 18 )
  {
    if ( (unsigned int)round3(byte_2008[v10], *(unsigned __int8 *)(v10 + scanf_value), (unsigned int)(v9 - 8)) != 1 )
    {
      sub_10C0("WRONG");
      sub_1130(0xFFFFFFFFLL);
    }
    ++v10;
    --v9;
  }
  v11 = -10;
  v12 = 19;
  while ( v12 <= 26 )
  {
    if ( (unsigned int)round4(byte_2008[v12], *(unsigned __int8 *)(v12 + scanf_value), (unsigned int)(v11 + 2)) != 1 )
    {
      sub_10C0("WRONG");
      sub_1130(0xFFFFFFFFLL);
    }
    ++v12;
    ++v11;
  }
  v13 = 50;
  for ( j = 27; j <= 33; ++j )
  {
    if ( (unsigned int)round5(v13 + 1, (__int64)&v16, byte_2008[j], *(_BYTE *)(j + scanf_value)) != 1 )
    {
      sub_10C0("WRONG");
      sub_1130(0xFFFFFFFFLL);
    }
    --v13;
  }
  if ( *(_BYTE *)(scanf_value + 34) == 125 )
    printf_or_scanf(1LL, 1LL, "GREAT!\\n", 8LL);
  return 0;
}

코드를 예쁘게 정리했다.

 

 

 

 

 

 

 

 

round1부터 round5까진 비슷하다.

&v15-64+n_3977을 해준다.

&v15는 rbp-0x8이고

&v15-64 = rbp-0x48이다.

한 마디로

 

(BYTE *)&v7

 

로 사용한다는 것이다.

 

 

 

byte_2008 = [6, 0x11, 0x13, 0x1B, 2, 0x7B, 0x7E, 0x42, 0x38, 0x6E, 0x6B, 0x15, 0x31, 0x23, \\
    0xA, 0x3F, 0x30, 0xF, 0x18, 0xD3, 0x98, 0xDE, 0xC8, 0xC6, 0xCC, 0xCE, 0xF4, 0x10, 5, 0x17, 0x15, 0x1E, 0x19, 0x26, 0
]

flag = ''

#HCAMP
v5 = [0x41,0x42,0x43,0x44,0x41]
v4 = 15
for i in range(5):
    flag+=chr(v5[i]^byte_2008[i]^v4)
    v4+=1

flag+='{'

#Wow__Y
v5 = [0x24,0x23, 0x40,0x21,0x25, 0x5e]
v6 = 10
for v7 in range(6,0xc):
    flag += chr(v5[v7-6]^byte_2008[v7]^(v6+3))
    v6+=1

#ou_are_
v8 = 30
v9 = 12
v5 = [0x48, 0x43, 0x41, 0x4d, 0x50, 0x7b, 0x57]
for v9 in range(12,18+1):
    flag += chr(v5[v9-12]^byte_2008[v9]^(v8-8))
    v8-=1

#l3arned_
v10 = 0xf6
v5 = [0x47,0x52,0x45,0x41,0x54,0x54,0x54,0x54]
for v11 in range(19,27):
    flag += chr(v5[v11-19]^byte_2008[v11]^(v10+2))
    v10 = (v10+1) & 0xff

#decdec_
v12 = 50
v5 = [0x47,0x52,0x45,0x41,0x54,0x54,0x54] 
for j in range(27,34):
    flag += chr(v5[j-27]^byte_2008[j]^(v12+1))
    v12-=1

flag+='}'

print(flag)
# HCAMP{Wow__You_are_l3arned_decdec_}

 

파이썬으로 복호화 할 수 있다.

 

 

 

 

 

플래그 : HCAMP{Wow__You_are_l3arned_decdec_}

 

'write up > hackingcamp22CTF' 카테고리의 다른 글

hackingcamp22CTF - dvm-rev  (0) 2021.03.20
hackingcamp22CTF - revtine  (0) 2021.03.20
hackingcamp22CTF - Demon Notepad  (0) 2021.03.20
hackingcamp22CTF - Do u know it?  (0) 2021.03.20
Comments