write-up(rev)/reversing.kr

[reversing.kr] Music Player write-up

ssongk 2024. 5. 31. 13:10

리버싱 능력의 필요성을 느껴서 공부를 다시 해보려 한다..

이번 문제는 라업 참고해 가면서 분석했다.

 


 

GUI 기반의 mp3 player exe파일이 주어진다.

 

문제 설명은 다음과 같다.

1분 체크 루틴을 우회하면 플래그를 얻을 수 있다고 한다.

This MP3 Player is limited to 1 minutes.
You have to play more than one minute.

There are exist several 1-minute-check-routine.
After bypassing every check routine, you will see the perfect flag.

 

1분이 되면 이렇게 메시지 박스가 뜬다.

디버거로 어디서 이 메시지 박스를 띄우는지 확인해봐야 한다.

 

xdbg에서 alt+k를 누르면 콜스택을 볼 수 있다.

거기서 주 스레드를 확인해보면 다음과 같다.

 

여기서 music_player와 관련된 주소들을 확인해보자.

중앙을 살펴보니

music_player.004045DE와 문제 파일에 있던 dll인 msvbvm60의 rtcMsgBox가 있음을 확인할 수 있다.

아이다로 004045DE을 확인해보니 정확히 찾은 것 같다.

(rtcMsgBox도 있다)

  else
  {
    v4 = *v55;
    v47 = v55;
    v5 = (*(int (**)(void))(v4 + 0x708))();
    if ( v5 < 0 )
      _vbaHresultCheckObj(v5, v55, dword_4025C0, 0x708);
    v37 = 0x80020004;
    v40 = 0x80020004;
    v43 = 0x80020004;
    v36[0] = 0xA;
    v39[0] = 0xA;
    v42[0] = 0xA;
    v34 = (int *)L"1분 미리듣기만 가능합니다.";
    v33[0] = 8;
    _vbaVarDup(&v45, v33, v47, v48);
    v48 = v36;
    v47 = v39;
    v46 = v42;
    v45 = 0x40;
    ((void (__stdcall *)(int *))rtcMsgBox)(&v45);
    v48 = v36;
    v47 = v39;
    v46 = v42;
    v45 = (int)&v45;
    ((void (__cdecl *)(int))_vbaFreeVarList)(4);
  }
  v54 = 0;
  v48 = (int *)&loc_4047CF;
  (*(void (__stdcall **)(int *))(*v55 + 8))(v55);
  return v54;
}

 

코드에서 볼 수 있듯이 else로 가야지 이 부분이 실행된다.

if문은 다음과 같다.

if ( v29[0] < 0xEA60 )

 

문제 풀 땐 몰랐는데

0xEA60을 10진수로 바꿔보니 60000라서 ms단위의 1분을 의미한 것 같다.

아무튼 값을 0xEA60에서 0xFFFFF으로 바꿔줬다.

 

그러고나서 실행해보면 런타임 에러를 만날 수 있다.

 

다시 호출 스택은 보면

도움이 안 되는 정보들만 있다.

(라업 보니까 다들 잘 나오던데 ㅋㅋ..)

 

어쩔 수 없이 하나씩 실행해보는 수 밖에 없었다.

실행될 부분은 다음과 같다.

 if ( v30[0] < 0xFFFFF )
  {
    if ( v30[0] != 0xFFFFFFFF )
    {
      (*(void (__stdcall **)(int *, int, int *))(*v56 + 0x6F8))(v56, v30[0], v49);
      v25 = (double)v52;
      v6 = v25;
      if ( dword_407000 )
        adj_fdiv_m64(0, 0x40590000);
      else
        v6 = v25 / 100.0;
      if ( (v7 & 0xD) != 0 )
        _vbaFPException(v56);
      v11 = _vbaFpI4(v50, v51, v6);
      if ( v11 > 0x258 )
        _vbaStrCopy(v56 + 0xE, L"LI");
      if ( !v11 )
        v11 = 1;
      v12 = (*(int (__cdecl **)(int *))(*v56 + 0x31C))(v56);
      v13 = (int *)_vbaObjSet(&v50, v12);
      v24 = *v13;
      v14 = _vbaI2I4(v11);
      v15 = (*(int (__stdcall **)(int *, int))(v24 + 0xBC))(v13, v14);
      __asm { fnclex }
      if ( v15 < 0 )
        _vbaHresultCheckObj(v15, v13, dword_402B58, 0xBC);
      _vbaFreeObj(&v50);
    }
    if ( !v56[0xD] )
      _vbaNew2(dword_40186C, v56 + 0xD);
    v16 = v56[0xD];
    v17 = (*(int (__stdcall **)(int, int *, int *))(*(_DWORD *)v16 + 0x44))(v16, v30, v49);
    __asm { fnclex }
    if ( v17 < 0 )
      _vbaHresultCheckObj(v17, v16, dword_40276C, 0x44);
    if ( v30[0] > 0xEA6A )
    {
      v35 = dword_402BDC;
      v34[0] = 8;
      rtcVarBstrFromAnsi(&v46, 0x72);
      v31[0] = 8;
      v32 = dword_402BE4;
      v18 = _vbaVarCat(v43, &v46, v34);
      v19 = _vbaVarCat(v40, v31, v18);
      v20 = _vbaStrVarMove(v19);
      v21 = _vbaStrMove(&v51, v20);
      _vbaStrCopy(v56 + 0x10, v21);
      _vbaFreeStr(&v51);
      v49 = v40;
      v48 = v43;
      v47 = &v46;
      ((void (__cdecl *)(int))_vbaFreeVarList)(3);
    }
  }

 

step-over로 실행하다보면 

이 부분이 문제라는 것을 알 수 있다.

__vbaHresultCheckObj 함수를 실행하면서 런타임 에러가 발생한다.

      if ( v15 < 0 )
        _vbaHresultCheckObj(v15, v13, dword_402B58, 0xBC);

 

어셈으로 보면 다음과 같다.

.text:004046AB 7D 12                                   jge     short loc_4046BF
.text:004046AD 68 BC 00 00 00                          push    0BCh
.text:004046B2 68 58 2B 40 00                          push    offset dword_402B58
.text:004046B7 57                                      push    edi
.text:004046B8 50                                      push    eax
.text:004046B9 FF 15 3C 10 40 00                       call    ds:__vbaHresultCheckObj

 

__vbaHresultCheckObj를 호출하지 않도록 jge를 jmp로 바꿔준다.

.text:004046AB EB 12                                   jmp     short loc_4046BF

 

이제 1분을 넘길 수 있고

창 상단에 플래그가 등장한다.

 


 

https://snwo.tistory.com/42

 

[Reversing.kr] (Reversing) Music Player 풀이

문제를 다운받고, 압축을 풀면 다음과 같이 나온다. 뮤직플레이어는 1분미리듣기가있다는데, 1분을 체크하는 루틴을 뚫으라한다. 노래를 듣고있었는데, 진짜 1분밖에 못듣는다. 역시 EXE32 파일이

snwo.tistory.com

 

댓글수0