SSCTF 2016 : Re1

CTF/Writeup 2019. 3. 13. 16:53

안드로이드 리버싱 문제다.


앱을 실행해보면 유저명,비밀번호를 입력받아 중국어로된 문구를 띄어준다.


앱을 까서보면 인풋을 네이티브 함수의 인자로 사용하는데 해당 함수 리턴값이 True이면 된다.


ida로 jni 함수를 확인해보면 아래와 같이 상당히 복잡해보이는 코드가 나온다.


bool __fastcall getpl(const char *a1, const char *a2)

{

  int v2; // r7

  int v3; // r0

  const char *i; // r3

  int j; // r7

  int k; // r4

  int v7; // r0

  signed int v8; // r4

  int v9; // r0

  int l; // r6

  int v11; // r0

  _BOOL4 v12; // r3

  const char *v14; // [sp+0h] [bp-B90h]

  signed int v15; // [sp+0h] [bp-B90h]

  const char *v16; // [sp+4h] [bp-B8Ch]

  char v17[12]; // [sp+14h] [bp-B7Ch]

  int v18; // [sp+20h] [bp-B70h]

  int v19; // [sp+2Ch] [bp-B64h]

  int v20; // [sp+30h] [bp-B60h]

  const char *v21; // [sp+50h] [bp-B40h]

  const char *v22; // [sp+54h] [bp-B3Ch]

  const char *v23; // [sp+58h] [bp-B38h]

  const char *v24; // [sp+5Ch] [bp-B34h]

  const char *v25; // [sp+60h] [bp-B30h]

  const char *v26; // [sp+64h] [bp-B2Ch]

  const char *v27; // [sp+68h] [bp-B28h]

  const char *v28; // [sp+6Ch] [bp-B24h]

  const char *v29; // [sp+70h] [bp-B20h]

  const char *v30; // [sp+74h] [bp-B1Ch]

  const char *v31; // [sp+78h] [bp-B18h]

  const char *v32; // [sp+7Ch] [bp-B14h]

  const char *v33; // [sp+80h] [bp-B10h]

  const char *v34; // [sp+84h] [bp-B0Ch]

  const char *v35; // [sp+88h] [bp-B08h]

  const char *v36; // [sp+8Ch] [bp-B04h]

  const char *v37; // [sp+90h] [bp-B00h]

  const char *v38; // [sp+94h] [bp-AFCh]

  const char *v39; // [sp+98h] [bp-AF8h]

  const char *v40; // [sp+9Ch] [bp-AF4h]

  const char *v41; // [sp+A0h] [bp-AF0h]

  const char *v42; // [sp+A4h] [bp-AECh]

  const char *v43; // [sp+A8h] [bp-AE8h]

  const char *v44; // [sp+ACh] [bp-AE4h]

  char v45; // [sp+118h] [bp-A78h]

  int v46; // [sp+ADCh] [bp-B4h]

  int v47; // [sp+AE8h] [bp-A8h]

  int v48; // [sp+AF4h] [bp-9Ch]

  int v49; // [sp+B34h] [bp-5Ch]


  v16 = a2;

  v14 = a1;

  j_memset(&v21, 0, 200);

  v21 = "103066";

  v22 = "78yn";

  v2 = 0;

  v23 = "91";

  v24 = "jk@O";

  v25 = "w0%3";

  v26 = "okJni";

  v27 = "32tP";

  v28 = "pYn";

  v29 = "oty3e";

  v30 = "ss";

  v31 = "whw3";

  v32 = "Gh$";

  v33 = "ju3t";

  v34 = "g986";

  v35 = "rTp0";

  v36 = "J)g";

  v37 = "a";

  v38 = "pLoKm7";

  v39 = "0o7";

  v40 = "******";

  v41 = "plokm7";

  v42 = "SSCFlg2016";

  v43 = "aP$";

  v44 = "kEy";

  j_memcpy(v17, off_B309F004, 60);

  j_memset(&v48, 0, 64);

  j_memset(&v46, 0, 10);

  j_memset(&v47, 0, 10);

  j_memset(&v49, 0, 64);

  byte_B309F109 = 0;

  v3 = j_strlen(v14);

  for ( i = v14; i - v14 < v3; ++i )

  {

    if ( (unsigned int)*(unsigned __int8 *)i - 33 <= 0x5D )

      *((_BYTE *)&v47 + v2++) = *i;

  }

  for ( j = 0; *(&v21)[j] != 42; ++j )

    ;

  j_qsort(&v21, j, 4, cmp_string);

  for ( k = 0; k < j; ++k )

  {

    j_strcpy(&v45 + 50 * k, (&v21)[k]);

    v7 = j_strlen(&v45 + 50 * k);

    j_qsort(&v45 + 50 * k, v7, 1, cmp_char);

  }

  v8 = 0;

  do

  {

    while ( 1 )

    {

      j_strcpy(&v46, *(_DWORD *)&v17[4 * v8]);

      v9 = j_strlen(&v46);

      j_qsort(&v46, v9, 1, cmp_char);

      v15 = 0;

      for ( l = 0; l < j; ++l )

      {

        if ( !j_strcmp(&v45 + 50 * l, &v46) )

        {

          j_strcat(&v48, (&v21)[l]);

          v15 = 1;

        }

      }

      if ( v15 )

        break;

      switch ( v8 )

      {

        case 3:

          v8 = 4;

          j_strcat(&v48, v43);

          break;

        case 6:

          j_sprintf(&v49, "%c", 105);

          v8 = 7;

          j_strcat(&v48, &v49);

          break;

        case 11:

          v8 = 12;

          j_strcat(&v48, v20);

          break;

        default:

          goto LABEL_25;

      }

    }

LABEL_25:

    ++v8;

  }

  while ( v8 != 15 );

  j_strcat(&v48, &v47);

  j_sprintf(&v49, "%c", 125);

  j_strcat(&v48, &v49);

  j_sprintf(&v49, "%c", 123);

  j_strcat(&v49, &v48);

  j_strcat(&pl, v19);

  j_strcat(&pl, v18);

  j_strcat(&pl, &v49);

  if ( !v16 )

    return 0;

  v11 = j_strlen(v16);

  v12 = 0;

  if ( v11 == 0x27 )

    v12 = (unsigned int)j_strncmp(&pl, v16) <= 0;

  return v12;

}


근데 코드를 쭉 분석해보면 사실 인풋으로 들어온 유저명, 패스워드를 코드 내에서 전혀 사용하지 않고 있다가 마지막에 패스워드 길이 구하고 특정 값이랑 비교할때만 사용하고 있다.


즉, 저위의 복잡해보이는 코드를 분석할 필요가 없다는 거고 그냥 마지막에 strncmp에서 들어온 값만 확인해주면 된다.


디버깅을 통해 해당 값을 확인해봤고 플래그가 있었다.



FLAG = SSCTF{oty3eaP$g986iwhw32j%OJ)g0o7J.CG:}

'CTF > Writeup' 카테고리의 다른 글

Tokyo-Westerns-3rd-2017 CTF Rev Rev Rev  (0) 2019.03.15
0CTF 2016 Quals : boomshakalaka  (0) 2019.03.14
Sharif University CTF 2016 : Serial  (0) 2019.03.11
35C3 CTF 2018 COREBOT  (0) 2019.02.26
Evlz CTF 2019 Smol-Big  (0) 2019.02.20
블로그 이미지

JeonYoungSin

메모 기록용 공간

,