[CodeEngn]Advance RCE L06

Hunjison·2021년 7월 25일
0

Reverse Engineering

목록 보기
6/9

문제


남은 군생활은 몇일 인가? 정답인증은 MD5 해쉬값(대문자) 변환 후 인증하시오

실행


'확인'을 누르면 다시 창이 생성된다. 작업관리자로 죽여야 죽음..

접근


메시지박스에 숫자가 하나씩 증가하며 출력되는 구조이다. 분명히 그 부분에 대한 반복문이 있을 것이고, 해당 부분을 찾아내보자.

풀이


1. 언패킹


  • pushad 발견

  • upx 로 패킹되어 있음.

  • upx.exe -d 06.exe -o 06_decompressed.exe

2. 안티디버깅 우회


  • 에러 발생

  • 디버거 탐지 함수 발견

    IsDebuggerPresent 함수를 통해 분기문으로 점프함.

  • 우회

    IsDebuggerPresent 함수는 해당 프로세스가 디버깅 당하고 있는지 여부를 PEB 구조체의 디버깅 상태값을 확인하여 탐지한다. 디버깅 당할 때의 리턴값이 1이며, 아닐 경우에는 0을 리턴한다.

    실행 시에 리턴값을 0으로 수정해주면 우회가 가능하다.

  • 추가 설명

    FS 레지스터는 TIB(Win32 Thread Information Block)의 주소를 저장하고 있다. TIB는 Win32의 자료구조로서 현재 실행 중인 스레드에 대한 정보를 저장하고 있다. 이 구조체는 TEB(Thread Environment Block)이라고도 불린다.

    FS 레지스터를 바로 이용하지 않고, FS:[0x18]을 사용하는 이유는 아래와 같다.

    TIB:[0x30]에는 PEB 구조체가 존재한다. PEB[2]에는 BeingDebugged라는 필드가 존재하여, 디버깅 당하고 있는지의 여부를 확인할 수 있다. IsDebuggerPresent 함수는 해당 필드를 확인하여 디버깅 여부를 알아내는 것이다.

3. 메시지박스 추적


int MessageBox(
  HWND    hWnd,
  LPCTSTR lpText,
  LPCTSTR lpCaption,
  UINT    uType
);

lpText가 출력되는 텍스트의 내용이다. 이 값을 어디에서 가져오는지를 확인하면 좋을 듯하다.

lpText를 추적하는 방법을 시도하였으나, 의미없는 분기가 너무 많아서 추적에 실패하였다.

어떤 분기로 MessageBox를 출력하는 흐름에 오게 되었는지, 크로스 레퍼런스 분석을 우선적으로 해보자. 분기가 엄청 많고, 무언가를 값에 계속 비교하는데 무엇을 의미하는지, 어떻게 동작하는지 잘 모르겠다. 분석 실패

4. 코드 변조


MessageBox의 lpText가 어디에서 왔는지 추적하기를 포기하고, MessageBox에서 숫자가 몇까지 count 되는지에 대해서만 확인하기로 계획을 변경하였다.

아래와 같이 MessageBox는 4개의 인자를 받는다.

MessageBox를 한 번 지날 때마다 bp의 hit count 역시 1 증가한다. 즉, MessageBox에 표시되는 숫자와 hit count는 동일한 숫자이다.

MessageBox가 발생했을 때 일일이 '확인'을 눌러주기 귀찮았기 때문에, 아래와 같이 코드를 변조하여 F9만으로 편하게 숫자를 count할 수 있도록 하였다. 4개의 인자를 받는 함수이기 때문에 0x10만큼 스택을 정리해주었다.

정답


수많은 F9 끝에 790을 발견...

사실 노가다로 푼 것과 다름이 없다.

디버거 기능 중에 hit count만 증가하고, breakpoint 동작은 하지 않도록 하는 기능이 있었으면 좋겠다.

추가


Breakpoint에 condition을 추가하는 방법으로, 노가다에서 벗어날 수 있었다.

x64dbg 기준 - https://help.x64dbg.com/en/latest/introduction/ConditionalBreakpoint.html

Break Condition을 0으로 설정하면, 어떤 경우에도 Break하지 않으며, Log Condition을 1로 설정하면 어떤 경우에도 log한다.

문제는 이렇게 했을 경우에, MessageBox 부분을 790번 지나고 프로그램이 종료되어 버린다는 것이었는데, TerminateProcessExitProcess 등의 함수에 Breakpoint를 걸어서 종료 직전의 hit count를 확인할 수 있었다. 해결!

profile
비전공자 출신 화이트햇 해커

0개의 댓글