본문 바로가기
리버싱/CodeEngn 문제해결

Basic L04

by 멍청이 개발자 2026. 9. 15.
반응형

문제는 다음과 같다.

그림0. 문제화면

프로그램을 실행하면 다음과 같이 뜬다.

그림1. 실행화면

CUI창에서 실행되는 프로그램이고 정상이라는 문자를 약 1초 단위로 출력해주고 있다.

 

이 프로그램을 x32dbg를 이용해서 실행해보면 다음과 같이 뜬다.

그림2. 디버거를 이용해서 실행

그러면 문제에서 말한 것 같이 디버깅을 탐지하는 코드가 있는 것으로 보인다.

 

우선 EP는 다음과 같다.

그림3. EP코드

여기서 바로 예측이 가능한 부분이 있다.

중간에 보면 GetCommandLineA라는 함수가 보인다.

보통 우리가 터미널 기반의 C언어 코드를 짜면 다음과 같이 짠다.

int main(int argc, char* argv[])
{
	...
}

main함수에 들어갈 명령어 인수를 GetCommandLineA로 받아와서 main함수에 매개변수로 넘겨서 실행해 줄 것이다.

그림4. GetCommandLineA실행 이후

GetCommandLineA까지 실행하고 나면 eax에 4번 문제 파일의 경로가 적혀있다.

 

이 후 코드를 F8로 실행하면서 확인해보면 eax값을 push 하는 코드가 보인다.

그림5. eax값을 push하는 코드 직후의 call문 까지 실행

이때 스택 창은 다음과 같다.

그림6. 스택창

아까 메인함수 파라미터를 생각하면 argc에 1, argv*에 파일 경로가 전달되었다고 볼 수 있다.

그렇다면 이후 call문인 0040100F가 우리가 찾던 메인 함수를 호출하는 구문이라고 볼 수 있다.

 

그림7. 메인함수

이렇게 메인함수까지 찾았다. 

여기서 보면 Sleep이라는 함수에 0x3e8이라는 값을 매개변수로 넘기는 걸 볼 수 있다. 3e8은 10진수로 1000이므로 1000ms, 즉 1초를 정지하는 코드이다.

 

그 이후 IsDebuggerPresent라는 함수를 통해서 디버깅을 당했는지 아닌지를 판단하고 je구문으로 분기 되는 것을 확인 할 수 있다.

 

IsDebuggerPresent를 실행후 eax값은 1이다. 이후 test eax, eax를 하면 1 & 1은 1이므로 ZF는 0이다.

ZF가 0이므로 je는 실행되지 않는다. 따라서 그 이후 "디버깅 당함"을 push후 출력을 계속 하는 것이다.

 

문제의 정답은 IsDebuggerPresent이다. 

추가로 여기서 디버깅 시에도 정상이 뜨도록 수정을 해보자.

 

je 40107e문 직전에 ZF가 1로 설정되게 하면 된다.

test eax, eax를 xor eax, eax로 하여 eax가 0이 되도록 하면 ZF가 1로 설정되면서 je문이 실행되어 정상으로 출력된다.

그림8. 분기문이 실행되었다.
그림9. EAX값은 0이고 ZF값은 1이다.
정상으로 출력되었다.

 

이 문제의 핵심은 뭐였을까 고민해보니 IsDebuggerPresent처럼 디버깅을 방해하는 함수도 있다는걸 알려주는 목적인것 같다.

 

반응형

'리버싱 > CodeEngn 문제해결' 카테고리의 다른 글

Basic L06  (0) 2026.09.15
Basic L05  (0) 2026.09.15
Basic L03  (0) 2026.09.15
Basic L02  (0) 2026.09.15
Basic L01  (0) 2026.09.15