2020. 3. 17. 03:35ㆍ문제연습/CodeEngn (REC)
본 티스토리 블로그는 PC에 최적화되어 있습니다.
모바일 유저분들은 아래 네이버 블로그를 이용해 주세요.
안녕하세요, ICMP입니다.
이번 시간에는 코드 엔진 챌린지인 Basic RCE L04를 풀어 보도록 하겠습니다.
1. 문제 내용
이 프로그램은 디버거 프로그램을 탐지하는 기능을 갖고 있다. 디버거를 탐지하는 함수의 이름은 무엇인가
Author: CodeEngn
File Password: codeengn
2. 문제 해설
일단 압축 해제하여 파일을 실행시키니 다음과 같은 화면이 출력됩니다.
이번에는 디버거를 이용해 디버깅을 시도하니 다음과 같은 화면이 출력됩니다.
프로그램 출력을 보니 디버거를 탐지하는 기능이 있는듯합니다.
그럼 본격적으로 분석을 해보도록 하겠습니다.
일단 모든 텍스트 스트링을 찾아보니 의심되는 문구가 보이지 않습니다
그럼 이번에는 호출되는 API 함수 목록을 확인해 보도록 하겠습니다.
이름만 보았을 때 isDebuggerPresent와 같은 의심되는 함수들이 여럿 보입니다.
일단 체크만 하고 어셈블리 코드를 실행해 가면서 프로그램을 분석해야겠습니다.
문제에서 말한 힌트처럼 디버거를 사용하고 있다는 내용을 확인할 함수를 호출할 필요가 있습니다.
지금부터 우리가 집중해야 할 내용은 특정 주소나 함수를 call 하는 부분입니다. (삽질의 시작...)
KERNEL32.GetVersion를 검색해 보니 GetVersion 함수는 운영체제의 버전을 리턴하는 함수입니다.
자세한 내용은 아래 링크를 참고해 주시고 계속해서 실행해 보도록 하겠습니다.
아래에서 CALL 0040F310가 보입니다.
0040F310 주소로 들어가면 뭔가 복잡한 코드가 나타나므로 004083F3에 F2로 중단점을 설정하고 F9을 실행하여 실행 결과를 확인해 봐야겠습니다.
실행을 해봐도 아무런 현상이 일어나지 않군요. 그럼 그냥 넘어가도록 합니다.
(원래는 코드 안으로 들어가서 어셈블리 코드를 분석해야 하는데, 풀이 흐름상 넘어가도록 하겠습니다.
추후 풀이를 추가하도록 하겠습니다.)
이런, 낭패입니다. 프로그램에서 호출시키는 call 코드가 너무 많습니다.
이때는 call 다음 주소에 중단점을 설정하고 F9을 눌러서 중단점까지 프로그램을 실행시킵니다.
만약 실행 과정에서 특별한 동작이 발견되면 그 부분을 집중적으로 분석합니다.
일단 0x00408425에 중단점을 설정하고 F9을 눌러 실행하니 화면에 창이 나타났습니다.
잠시, GetCommandLineA 함수에 대해 간략히 알아보도록 하겠습니다.
GetCommandLineA function
-현재 프로세스의 명령 줄 문자열을 검색합니다.
(정확한 내용은 아래 링크를 이용해 주세요.)
계속해서 분석을 진행하도록 하겠습니다.
0x00408425 ~ 0x0040842F 모든 부분에 중단점을 설정하고 실행해도 특별하게 눈에 띄는 동작은 보이지 않는듯합니다.
다음 call 주소인 0x00408454에 중단점을 설정하고 실행해 보도록 하겠습니다.
어?? 0x00408454 주소의 명령어 한 개만 실행시키고 다음 주소로 넘어가려는데 아래와 같은 동작이 보입니다.
음..., 0x00408454 주소에 들어가서 뭐가 있는지 확인해봐야겠습니다.
0x00408454를 클릭하고 Enter 버튼을 눌러 주소 안으로 들어가도록 하겠습니다.
(설마 또 call만 수십 개 있는 건 아니겠지...)
음??? 예상과 다르게 어떤 주소로 이동합니다. 계속해서 이동해 보도록 하겠습니다. (Enter 버튼 클릭)
오!!! 드디어 디버깅을 감지, 출력하는 진또배기 코드를 찾은듯합니다.
(비유를 하자면 어셈코드에서 C언어의 main 문을 찾은 느낌???)
call이 많지만 다행히 주석? 을 보고 어느 정도 추측이 가능할 듯합니다.
본격적으로 분석을 진행하도록 하겠습니다.
함수의 프롤로그가 보입니다. 스택 프레임을 설정하고 필요한 레지스터들을 push 하고 있습니다.
함수의 프롤로그는 아래 링크를 활용해 주세요.
함수의 프롤로그 이후 Sleep 함수에 0x3e8을 넣어 호출하고 있습니다.
0x3e8은 10진수로 1000이므로 1초 정도 쉬는 함수를 호출했습니다.
(참고 : sleep 함수는 프로그램에서 일정 시간 동안 작업을 대기(wait) 하고 싶을 때 사용하는 함수입니다.)
이후 00408210주소로 이동하여 어떠한 작업을 처리한 이후IsDebuggerPresent 함수를 호출하였습니다.
아무래도 함수 이름이 IsDebuggerPresent여서 의심이 듭니다. 바로 검색을 해보도록 하겠습니다.
1. IsDebuggerPresent()
PEB 구조체의 디버깅 상태값을 확인하여 디버깅을 당하고 있다면 1을, 아닐경우 0을 리턴.
커널 모드 디버거는 탐지하지 못하며 kernel32.dll에서 export되는 함수이며 보통 프로그램의 보호 차원에서 쓰인다.
출처: https://dakuo.tistory.com/40 [hacker dakuo]
같이 참고하면 좋은 글입니다. (어떤 고수분께서 함수 작동 원리를 아주 자세히 분석해 주셨습니다.)
우리가 찾던 디버깅 탐지 함수가 바로 이 함수인듯합니다.
하지만, 우리는 리버싱을 통한 분석 능력 증진을 위해 계속 분석을 진행하도록 하겠습니다.
흠, 일단 조건문처럼 보입니다.
저번 시간에도 말했듯이 eax 레지스터는 보통 함수의 리턴 값을 처리하는데 사용한다고 했습니다.
IsDebuggerPresent 함수 주소에 들어가서 확인한 결과, 어떤 루틴으로 처리가 되어 나온 값을 eax에 넣고 바로 나오는 모습을 볼 수 있습니다.
이렇게 나온 eax를 test 하여 점프문으로 갑니다.
(비교 구문에 대한 내용은 아래 링크를 이용해 주세요.)
위키 백과에서는 다음과 같이 설명하고 있습니다.
x86 어셈블리어에서 TEST 명령어는 두 피연산자들에 대한 비트 연산인AND를 수행한다. SF, ZF, PF 플래그가 수정되며 AND의 결과는 버려진다. OF와 CF 플래그는 0으로 설정되며 AF 플래그는 정의되지 않는다.
즉, eax = 0이면 test의 결과는 0이 되고 이를 통해 ZF가 0으로 설정됩니다.
test 연산 이후 점프문이 나오는데, 공통점이 모두 어떤 주소를 push 한다는 점입니다.
push 하는 주소00431024, 0043101C에 들어가서 뭐 하는지 확인해야겠습니다.
주소로 이동해 보니 아까 실행했을 때 보았던 문자열이 저장되어 있습니다.
조건 분기를 마치고 결과를 화면에 출력해 주는 printf와 같은 함수가 출력되는 것을 알 수 있습니다. //직접 주소에 들어가 보세요!!! (00401083.E8 08710000 CALL 04.00408190 ; \04.00408190)
설명이 너무 지저분하니 간단하게 정리하도록 하겠습니다.
1. sleep 함수를 호출하여 1초 대기
2. call 408210 실행 (정확히 어떤 루틴인지는 모르겠음.)
3.IsDebuggerPresent를 호출하여 디버깅 모드 판별 후 결과 리턴
4. 리턴 결과에 따라 "정상" or "디버깅 당함"문자열을 받아옴
5. CALL 00408190 (결과를 화면에 출력)
6. JMP 00401048 (위 과정을 무한 반복)
C언어로 다시 코딩한다면 아마 아래와 같은 형태가 되지 않을까 생각합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#define _WIN32_WINNT 0x0500
#include <stdio.h>
#include <Windows.h>
int main() {
while (1) {
Sleep(1000);
if (IsDebuggerPresent() == 1) {
printf("디버깅 당함 \n");
}
else {
printf("정상\n");
}
}
return 0;
}
|
따라서 Basic RCE L04 최종적인 답은 IsDebuggerPresent입니다.
리버싱은 정말 삽질의 정석인 듯합니다.
( 노오력이 부족하다!!! )
오늘은 여기까지입니다. 다음 시간에는 Basic RCE L05를 풀어보도록 하겠습니다.
이상, ICMP였습니다!!!
'문제연습 > CodeEngn (REC)' 카테고리의 다른 글
Basic RCE L07 - 코드 엔진 (0) | 2020.11.17 |
---|---|
Basic RCE L06 - 코드 엔진 (0) | 2020.03.19 |
Basic RCE L05 - 코드 엔진 (0) | 2020.03.18 |
Basic RCE L01 해설 - 코드 엔진 (0) | 2020.03.13 |
codeengn.com 준비 (0) | 2020.03.13 |