Wargame/CTF

IOLI crackme 0x00 ~ 0x05

마띠(쥔장) 2020. 4. 19. 15:26
crackme0x00

패스워드를 찾는 문제. 

일단 포함된 문자열을 찾아봤다.

"Password: " 다음 누가봐도 비밀번호일 것 같은 숫자가 있었다.

crackme0x01

비슷한 문제다. 바로 전 문제처럼 문자열을 찾아봤지만 그렇다할 단서는 찾지 못했다.

심볼 트리 탭에서 _main 함수를 선택하니 디컴파일 탭에서 비밀번호를 찾았다.

13번째 라인에서 0x149a와 local_8 변수를 비교하는데 맞으면 OK!

어셈블 코드는 이랬다..

5274를 넣어보자ㅏ

crackme0x02

0x01과 같은 문제다.

0x52b24 = 338724

crackme0x03

디컴파일러는 참 좋은 도구이다..

0x52b24 = 338724

crackme0x04

 

?.. 의도치 않게 풀어버렸다

일단 디컴파일된 코드를 보자

디컴파일된 코드를 좀 더 알기 쉽게 변수 명을 임의로 바꾸어 봤다.

int __cdecl _main(int _Argc,char **_Argv,char **_Env){
  size_t a0; //a0 = local_a0
  char s[120]; //s = local_7c
  
  __alloca(a0);
  ___main();
  _printf("IOLI Crackme Level 0x04\n");
  _printf("Password: ");
  _scanf("%s",s);
  _check(s);
  return 0;
}

s를 패스워드 인자로 받아 check 함수를 실행한다. check()는 아래와 같다.

void __cdecl _check(char *s){ //s = param_1
  size_t var; //var = sVar1
  char str; //str = local_11
  uint a; //a = local_10
  int m; //m = local_c
  int n; //n = local_8
  
  m = 0;
  a = 0;
  while(1) {
    var = _strlen(s); //var은 인자로 받은 s의 길이
    if (var <= a) {
      _printf("Password Incorrect!\n");
      return;
    }
    str = s[a]; //str은 입력값의 첫 글자(첫 루프)
    _sscanf(&str,"%d",&n);
    m = m + n; 
    if (m == 15) break; /m과 15가 같으면 OK
    a = a + 1; //a에 1 더함 = 입력값의 다음 글자를 str에 저장
  }
  _printf("Password OK!\n");
                    /* WARNING: Subroutine does not return */
  _exit(0);
}

 결국 check()는 인자로 받은 숫자의 각 자리수 합이 15면 되는 거다

12345의 각 자리 합이 15라서 ok가 떴던 것..

그럼 555도 되겠져?

crackme0x05

역시 디컴파일된 main 함수, check 함수를 보자.

변수명이 보기 어려우니까 쉽게~

int __cdecl _main(int _Argc,char **_Argv,char **_Env){
  size_t a0; //a0 = local_a0
  char 7c[120]; //7c = local_7c
  
  __alloca(a0);
  ___main();
  _printf("IOLI Crackme Level 0x05\n");
  _printf("Password: ");
  _scanf("%s",7c);
  _check(7c);
  return 0;
}

0x04처럼 7c를 인자로 받아 check() 함수를 실행한다.

void __cdecl _check(char 7c){ //7c = *param_1
  size_t var; //var = sVar1
  char s; //s = local_11
  uint a; //a = local_10
  int m; //m = local_c
  int n; //n = local_8
  
  m = 0;
  a = 0;
  while(1){
    var = _strlen(7c); 
    if (var <= a) 
    	break;
    s = 7c[a];
    _sscanf(&s,"%d",&n);
    m = m + n;
    if (m == 16) {
      _parell(7c);
    }
    a = a + 1;
  }
  _printf("Password Incorrect!\n");
  return;
}

앞선 0X04랑 같은 알고리즘인 것 같다. 그대신 각 자리 수 합이 15가 아니라 16이어야 한다.

잘 보면 OK 프린트 문이 없는데 _parell() 함수에서 실행되는 것 같다.

그럼 각 자리 수 합이 16이 되게 79를 입력해보자

이미 알다시피 비밀은 _parell()에 있다.

디컴파일된 코드를 보면 아주 간단하다.

if문을 봐야하는데 입력값과 1을 AND 연산하여 결과값이 0일 때 OK가 뜬다.

1과 AND 연산한다는 뜻은 마지막 비트가 1인지 판단하는 것, 간단히 말해서 짝수를 입력해야 한다는 뜻이다.

앞서 입력한 79는 각 자리 수 합이 16이지만 홀수였다.

따라서 790, 862, 952 등 짝수이면서 각 자리 수 합이 16인 수를 입력하면 될 듯 하다.

728x90

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

InCTF 2020 Forensics_Investigation  (0) 2020.08.02
RACTF 2020: Dimensionless Loading, Disk Forensics Fun  (0) 2020.06.13
2020 AUCTF  (2) 2020.04.11
Codegate 2020  (1) 2020.04.02
UTCTF 2020 Chatt with Bratt: Write-Up  (0) 2020.03.11