본문 바로가기
Wargame Write-Up/Reversing.kr

[Reversing.kr] (Reversing) x64 Lotto 풀이

by snwo 2021. 2. 7.

실행해보면, L O T T O 를 출력하고, 숫자를 입력하라한다.

그리고는 화면이 cls 된다.

 

편하게 디컴파일해 정적분석을 해보자.

1
2
3
4
5
do {   
wprintf(L"\n\t\tL O T T O\t\t\n\n");
    wprintf(L"Input the number: ");
    wscanf_s(L"%d %d %d %d %d %d"&v13, &v14, &v15, &v16, &v17, &v18);
    wsystem(L"cls");
    Sleep(0x1F4u);
cs

숫자 6개를 입력받고, cls 한 뒤, 0.5초 쉰다.

1
2
3
    do
      *(&v18 + ++v1) = rand() % 100;
    while ( v1 < 6 );
cs

v19~v25 까지 srand(time(0)) 해서 나온 100이하 rand값 6개를 저장한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   v2 = 1
v3 = 0;
    v4 = 0i64;
    byte_1400035F0 = 1;
    while ( *(&v19 + v4) == *(&v13 + v4) )
    {
      v4 += 4i64;
      ++v3;
      if ( v4 >= 24 )
        goto LABEL_9;
    }
    v2 = 0;
    byte_1400035F0 = 0;
LABEL_9:
    ;
cs

v3 은 0이고, v13~v18(입력한숫자), v19~v25(rand값) 틀릴때까지 비교한다.

6개 다 맞으면 LABEL_9으로 가서 v2가 1인 상태가 유지되고, v3=6 이 되었으니 반복문이 종료된다.

못맞추면 다시입력받는다.

 

1
2
3
4
5
6
7
8
9
10
  v26 = 0x5C;
  v25 = 0xB8;
  v27 = 0x8B;
  v30 = 0xB8;
  v28 = 0x6B;
  v6 = 0i64;
  v29 = 0x42;
~~~~~~~~~~~~~~~
  v49 = 0xF2;
  v50 = 0;
cs

변수를 초기화하고,

 

1
2
3
4
5
6
7
8
9
10
11
  do
  {
    v7 = byte_140003021[v6 - 1];
    v6 += 5i64;
    *(&v22 + v6 + 1) ^= (v7 - 12);
    *(&v23 + v6) ^= (byte_140003021[v6 - 5- 12);
    *(&v23 + v6 + 1) ^= (byte_140003021[v6 - 4- 12);
    *(&v24 + v6) ^= (byte_140003021[v6 - 3- 12);
    *(&v24 + v6 + 1) ^= (byte_140003021[v6 - 2- 12);
  }
  while ( v6 < 25 );
cs

140003021에 있는 값을 가져와 초기화한 변수에 차례대로 xor한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 if ( v2 )
  {
    v8 = 0;
    v9 = &v25;
    do
    {
      v10 = *v9;
      ++v9;
      v11 = v8++ + (v10 ^ 0xF);
      *(v9 - 1= v11;
    }
    while ( v8 < 25 );
    v50 = 0;
    wprintf(L"%s\n"&v25);
  }
cs

v2 가 1이면, 즉 아까 숫자들을 다 맞췄으면 아까 변수들에 0xf 을 xor 해서

출력해준다. 이것이 flag 이다.


이 문제는 아주 쉽다. 우리의 입력값들이 flag 를 만들어내는데 아무런 영향을 주지 않고,

x96 dbg 로 6개 변수값을 확인할 수 있으니, 값들을 맞출 수도있고, 그냥 뛰어넘고 flag 를 generate 할 수 있다.

그리고 v2 를 조작하거나 분기하지 않도록 조작해서 flag 를 출력할 수 있다.

entrypoint 까지 F9 로 실행하고, 현재모듈에서 cls 라는 문자열을 찾았다. 여기가 wmain 인 것같다.

이 부분에 브포를 걸고, F9 를 눌러 아무숫자 6개를 입력한다. 

브포에 도착하면, ZF 을  0으로 만들어 분기를 조작한다.

놀랍게도 v2 는 R8 레지스터였다. R8 을 1로 만든 뒤, F9 를 눌러 실행하면 flag 가 나온다~

 

wprintf 에 브포 안걸고 실행하면 flag 확인 못하고 종료되는거 아시죵?