Wargame

[CodeEngn] Basic L04 풀이

배이즈 2025. 4. 4. 22:30

04.exe 실행

 

1초 간격으로 '정상' 이라는 문자가 띄워진다.

xdbg로 열어보자

entrypoint에 종단점을 걸고 한번에 실행해 보았다.

F9를 두 번 누르니까 ‘디버깅 당함’ 이라는 문자가 계속 뜬다.

디버거로 실행하면 이 프로그램을 탐지하고 저런 문자열을 띄우는 것 같다.

1차 코드 분석

한 줄 씩 실행해 보겠다.

 

call 04.40100F 에서 함수 내부를 건너뛰고 실행(F8)하면 ‘디버깅 당함’ 이 연속적으로 뜬다.

이 함수 안으로 들어가 봐야겠다.

04.40100F (디버깅당함 출력 함수) 내부 분석

 

내부 전체 코드는 이렇게 생겼다. 

 

F7을 이용해 진행해보니 rep stosd 라는 줄에서 디버깅이 일시중지가 된다. 이게 무엇인지 구글링 해보았다.

 

REP : ECX을 카운터로 사용해서 문자열 관련 명령을 그 값만큼 반복하겠다는 명령어다.

한 번 수행할 때마다 ECX는 감소한다.

 

STOS : EAX 값을 EDI가 가리키는 주소에 저장 (STOSD는 DOUBLE WORD(4)단위로 반복)

 

REP STOS : ECX에 있는 값만큼 STOS 실행

→ 그냥 문자열 명령을 계속 반복한다는 것 같다.

 

rep stosd 부분을 F8로 그냥 진행시켜 보았다.

 

ECX 값을 눈여겨 보았는데 10 → 1 → 0 이었다가 <Sleep> 을 call하고 나서는 DBADE818와 같은 매우 큰 수로 바뀌었다. jmp로 repeat할때마다 ECX값은 계속 Sleep 구간에서 DBADE818로 바뀐다.

그래서 ECX를 카운터값으로 보기에는 유의미하지 않은 것 같다.

 

그냥 이 함수 내부에서는 계속 rep stosd 하위 코드를 진행하는 것 같다.

 

rep stosd을 실행하면 ECX가 0이 된다.

 

<IsDebuggerPresent>함수를 콜하면 EAX가 1 증가한다. (혹시 EAX값이 1이면 디버깅 당했다는 의미인가?)

그리고 cmp esi, esp 구간에서 두 레지스터 값이 모두 같다. (mov esi, esp때문)

 

EAX가 1로 변하고 난 뒤, test eax, eax로 두 오퍼랜드를 AND연산 시킨다.

이는 Zero Flag를 1로 만든다. (위에 cmp esi, esp에서 ZF는 0이었다)

ZF의 값과 JE 조건과는 무슨 관련이 있는지 찾아보았다.

 

Zero Flag

  • 연산 결과가 0이면 1
  • 연산 결과가 0이 아니면 0

 

JE

  • ZF=1일 때 점프한다.
  • 즉, 두 값이 같아서 뺄셈 결과가 0이면 ZF가 1이 되므로 점프가 발생한다.

즉, 이 코드는 je 구간에서 점프를 하지 않고 그대로 진행하면 ‘디버깅 당함’을 띄우는 코드가 진행된다.

즉 je에서 점프를 해야 ‘정상’을 띄우는 것이다.

 

call 04.408190에서 ‘디버깅 당함’을 띄우고 jmp로 다시 rep stosd 밑으로 이동하여 이 출력과정을 반복한다.

‘정상’ 띄워보기

 

그렇다면 EAX를 0으로 바꿔보면 ‘정상’이라고 뜰까?

 

그렇다! ZF가 1이어서 je 조건을 만족해 ‘정상’이라는 문자열을 push하는 구간으로 점프한다.

그럼 문제에서 물어본 ‘디버거 탐지 함수’는 <IsDebuggerPresent>이다.

 

이 함수를 지나니까 EAX가 1로 바뀌면서 디버깅을 탐지한 효과를 낸 것이다.

만약 디버거가 아닌 그냥 실행파일을 실행했다면 이 함수는 EAX를 1로 만들지 않으므로 ‘정상’을 출력하는 것

 

IsDebuggerPresent란?

호출 프로세스가 사용자 모드 디버거에 의해 디버그되고 있는지 여부를 확인하는 win32 API이다.

  • 현재 프로세스가 디버거의 컨텍스트에서 실행 중인 경우 반환 값은 1이다.
  • 현재 프로세스가 디버거의 컨텍스트에서 실행되고 있지 않으면 반환 값은 0이다.