[CodeEngn] Basic L04 풀이
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이다.