'2013/11'에 해당되는 글 2건

  1. 2013.11.22 [WinDbg 분석] 메모리 손상 디버깅 6
  2. 2013.11.03 초난감 기업의 조건 - 릭 채프먼 2
WinDbg 디버깅2013. 11. 22. 21:46
반응형

커널 메모리가 손상되면 분석하기 매우 곤란한 경우가 많은데요.

그중에서 분석이 가능한 한 가지 상황에 대해 분석을 진행해 보겠습니다.


이번 분석의 초식은 "깨진 메모리 앞쪽 메모리를 의심하라" 입니다.


MyDrv.sys가 사용중인 메모리가 손상돼 발생한 덤프입니다.


0: kd> !analyze -v

*******************************************************************************

*                                                                             *

*                        Bugcheck Analysis                                    *

*                                                                             *

*******************************************************************************


DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)

An attempt was made to access a pageable (or completely invalid) address at an

interrupt request level (IRQL) that is too high.  This is usually

caused by drivers using improper addresses.

If kernel debugger is available get stack backtrace.

Arguments:

Arg1: 00000008, memory referenced

Arg2: 00000002, IRQL

Arg3: 00000000, value 0 = read operation, 1 = write operation

Arg4: 8c032fa5, address which referenced memory


Debugging Details:

------------------

READ_ADDRESS:  00000008 

CURRENT_IRQL:  2


FAULTING_IP: 

MyDrv!GetListEntry+85 

8c032fa5 3b5108          cmp     edx,dword ptr [ecx+8]


DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT

BUGCHECK_STR:  0xD1

PROCESS_NAME:  SomeProcess.exe


TRAP_FRAME:  bdf939b4 -- (.trap 0xffffffffbdf939b4)

ErrCode = 00000000

eax=00000000 ebx=8c0344b0 ecx=00000000 edx=c339fdc0 esi=0101ed94 edi=bdf93b60

eip=8c032fa5 esp=bdf93a28 ebp=bdf93a4c iopl=0         nv up ei pl nz na pe cy

cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010207

MyDrv!GetListEntry+0x85:

8c032fa5 3b5108          cmp     edx,dword ptr [ecx+8] ds:0023:00000008=????????

Resetting default scope


LAST_CONTROL_TRANSFER:  from 8c032fa5 to 83248b7f


STACK_TEXT:  

bdf939b4 8c032fa5 badb0d00 c339fdc0 00000000 nt!KiTrap0E+0x1b3

bdf93a4c 8c03331d c339fdc0 a0fa8b08 bdf93a68 MyDrv!GetListEntry+0x85 

bdf93a5c 8c0325fc c339fdc0 bdf93a7c 8c0364e5 MyDrv!GetEntryTable+0xd 

...

bdf93c10 76e270f4 0101f08c 00020019 0101eda0 nt!KiSystemServicePostCall

WARNING: Frame IP not in any known module. Following frames may be wrong.

0101ef94 00000000 00000000 00000000 00000000 0x76e270f4


STACK_COMMAND:  kb


FOLLOWUP_IP: 

MyDrv!GetListEntry+85 

8c032fa5 3b5108          cmp     edx,dword ptr [ecx+8]


SYMBOL_STACK_INDEX:  1

SYMBOL_NAME:  MyDrv!GetListEntry+85

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: MyDrv

IMAGE_NAME:  MyDrv.sys


DEBUG_FLR_IMAGE_TIMESTAMP:  5099ff75

FAILURE_BUCKET_ID:  0xD1_MyDrv!GetListEntry+85

BUCKET_ID:  0xD1_MyDrv!GetListEntry+85

Followup: MachineOwner

---------




.trap 명령으로 죽은 시점을 복원합니다.


0: kd> .trap 0xffffffffbdf939b4

ErrCode = 00000000

eax=00000000 ebx=8c0344b0 ecx=00000000 edx=c339fdc0 esi=0101ed94 edi=bdf93b60

eip=8c032fa5 esp=bdf93a28 ebp=bdf93a4c iopl=0         nv up ei pl nz na pe cy

cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010207

MyDrv!GetListEntry+0x85:

8c032fa5 3b5108          cmp     edx,dword ptr [ecx+8] ds:0023:00000008=????????



GetListEntry 함수에서 죽었는데 변수를 살펴보면 pListEntry 가 NULL이어서 문제가 발생했습니다.


0: kd> dv

     pListHead = 0x8c038d00 [ 0x89e95988 - 0x864f3ea8 ]

     pListEntry = 0x00000000



pListEntry는 pListHead에서 연결되는 리스트이므로 pListHead를 살펴봅니다.


0: kd> dl 0x8c038d00 

8c038d00  89e95988 864f3ea8 8c038d08 8c038d08

89e95988  00000000 00000000 00000000 00000000



pListHead가 가리키는 89e95988의 내용은 더블 링크드 리스트라서 00000000이면 안되고 어떤 포인터가 들어 있어야 하는데 00000000 이 들어 있습니다.


기존에 있던 포인터 값이 0으로 덮어써진 것으로 추정됩니다.


0: kd> db 89e95988

89e95988  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

89e95998  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

89e959a8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

89e959b8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

89e959c8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

89e959d8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

89e959e8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

89e959f8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................



어떤 모듈이 이 영역을 덮어쓰는지 추적합니다.

일단 메모리 정보를 확인합니다.


0: kd> !pool 89e95988  

Pool page 89e95988 region is Nonpaged pool


89e95808 doesn't look like a valid small pool allocation, checking to see

if the entire page is actually part of a large page allocation...


89e95808 is freed (or corrupt) pool

Bad previous allocation size @89e95808, last size was 0


...


Pool page [ 89e95000 ] is __inVALID.


Analyzing linked list...

[ 89e95000 ]: invalid previous size [ 0x43 ] should be [ 0x0 ]

[ 89e95000 --> 89e95c10 (size = 0xc10 bytes)]: Corrupt region


Scanning for single bit errors...

None found



메모리 헤더까지 손상되어 정보가 나오지 않습니다.


바로 앞 페이지의 정보를 확인합니다. 

보통은 앞의 메모리를 사용하는 모듈이 뒤 부분의 메모리를 손상시키기 때문입니다.


0: kd> !pool 89e94378 

Pool page 89e94378 region is Nonpaged pool

*89e89000 : large page allocation, Tag is Ddk , size is 0xc808 bytes

Pooltag Ddk  : Default for driver allocated memory (user's of ntddk.h)



Ddk 태그를 가진 메모리가 확인됩니다. 이 부분은 손상되지 않았습니다.

이 메모리를 사용하는 모듈이 메모리를 손상했을 가능성이 높습니다.


89e89000 메모리를 들여다보면 특정한 패턴을 가지고 있고 이 패턴이 0xc808 길이를 넘어서 이어집니다.

따라서 이 메모리를 사용하던 모듈이 메모리 경계를 넘어서 메모리를 손상시켰다고 가정할 수 있습니다.


Ddk는 디폴트 태그라서 태그로는 어떤 모듈이 사용중인지 알 수 없으니...

시스템에 로드된 모듈중에서 89e89000 라는 메모리 포인터를 가지고 있는 모듈을 검색합니다.


0: kd> !for_each_module s @#Base @#End 00 90 e8 89

Page 69a9 not present in the dump file. Type ".hh dbgerr004" for details

Page 6414d not present in the dump file. Type ".hh dbgerr004" for details

Page 63b60 not present in the dump file. Type ".hh dbgerr004" for details

bebb5424  00 90 e8 89 21 00 00 00-00 00 00 00 01 00 00 00  ....!...........



다행히 bebb5424 하나만 찾아지네요.

bebb5424 위치에서 89e89000 포인터를 보관하고 있습니다.


bebb5424 은 어떤 모듈인지 확인합니다.


0: kd> u bebb5424

NotMyDrv+0x6424:

bebb5424 0090e8892100    add     byte ptr [eax+2189E8h],dl

bebb542a 0000            add     byte ptr [eax],al

bebb542c 0000            add     byte ptr [eax],al

bebb542e 0000            add     byte ptr [eax],al

bebb5430 0100            add     dword ptr [eax],eax

bebb5432 0000            add     byte ptr [eax],al

bebb5434 0800            or      byte ptr [eax],al

bebb5436 0000            add     byte ptr [eax],al



NotMyDrv.sys 모듈의 내부로 나옵니다.

NotMyDrv.sys 내부의 어떤 위치인지 확인합니다.


0: kd> lmvm NotMyDrv

start    end        module name

bebaf000 bebbe780   NotMyDrv     (no symbols)           

    Loaded symbol image file: NotMyDrv.sys

    Image path: \??\C:\Windows\system32\Drivers\NotMyDrv.sys

    Image name: NotMyDrv.sys


0: kd> !dh bebaf000


File Type: EXECUTABLE IMAGE

FILE HEADER VALUES

     14C machine (i386)

       5 number of sections

4D880A01 time date stamp Tue Mar 22 11:31:29 2011


       0 file pointer to symbol table

       0 number of symbols

      E0 size of optional header

     10E characteristics

            Executable

            Line numbers stripped

            Symbols stripped

            32 bit word machine


OPTIONAL HEADER VALUES

     10B magic #

    6.00 linker version

    6300 size of code

    9200 size of initialized data

       0 size of uninitialized data

    50D3 address of entry point

     280 base of code

         ----- new -----

00010000 image base

      80 section alignment

      80 file alignment

       1 subsystem (Native)

    5.00 operating system version

    5.00 image version

    1.10 subsystem version

    F780 size of image

     280 size of headers

   16350 checksum

00040000 size of stack reserve

00001000 size of stack commit

00100000 size of heap reserve

00001000 size of heap commit

       0  DLL characteristics

       0 [       0] address [size] of Export Directory

    E680 [      3C] address [size] of Import Directory

    EC00 [     4A8] address [size] of Resource Directory

       0 [       0] address [size] of Exception Directory

       0 [       0] address [size] of Security Directory

    F100 [     4F8] address [size] of Base Relocation Directory

     370 [      1C] address [size] of Debug Directory

       0 [       0] address [size] of Description Directory

       0 [       0] address [size] of Special Directory

       0 [       0] address [size] of Thread Storage Directory

       0 [       0] address [size] of Load Configuration Directory

       0 [       0] address [size] of Bound Import Directory

     280 [      F0] address [size] of Import Address Table Directory

       0 [       0] address [size] of Delay Import Directory

       0 [       0] address [size] of COR20 Header Directory

       0 [       0] address [size] of Reserved Directory



SECTION HEADER #1

   .text name

    5D18 virtual size

     280 virtual address

    5D80 size of raw data

     280 file pointer to raw data

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

68000020 flags

         Code

         Not Paged

         (no align specified)

         Execute Read



Debug Directories(1)

     Type       Size     Address  Pointer

     cv           8d           0     f780 [Debug data not mapped]



SECTION HEADER #2

   .data name

    8680 virtual size

    6000 virtual address

    8680 size of raw data

    6000 file pointer to raw data

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

C8000040 flags

         Initialized Data

         Not Paged

         (no align specified)

         Read Write


SECTION HEADER #3

    INIT name

     556 virtual size

    E680 virtual address

     580 size of raw data

    E680 file pointer to raw data

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

E2000020 flags

         Code

         Discardable

         (no align specified)

         Execute Read Write


SECTION HEADER #4

   .rsrc name

     4A8 virtual size

    EC00 virtual address

     500 size of raw data

    EC00 file pointer to raw data

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

42000040 flags

         Initialized Data

         Discardable

         (no align specified)

         Read Only


SECTION HEADER #5

  .reloc name

     61E virtual size

    F100 virtual address

     680 size of raw data

    F100 file pointer to raw data

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

42000040 flags

         Initialized Data

         Discardable

         (no align specified)

         Read Only




bebb5424은 bebaf000 + 6000 에서 시작하는 data SECTION에 위치하는 메모리입니다.

NotMyDrv.sys의 데이터 영역에 있으므로 이 드라이버에서 사용하는 전역변수로 추정됩니다.


결국 NotMyDrv.sys라는 드라이버가 MyDrv.sys가 사용하는 메모리를 overwrite해서 발생하는 문제로 볼 수 있습니다.



반응형
Posted by GreeMate
책좀읽자2013. 11. 3. 01:32
반응형




나의 평점 : 4.0 / 5.0


여기서 초난감 기업이란 성장과정에서 엉뚱한 마케팅이나 제품 전략을 취했던 미국 IT업체를 말한다.

하지만 모두 망한 회사를 말하는 것은 아니다. 

저자가 거쳐온 회사들에서 겪었던 다양한 사례를 말해 주는 것 뿐이다.

Microsoft, IBM은 아직도 건재한 회사이니 말이다.


저자의 이야기를 듣고 있노라면 1980년대 미국 IT 업계의 별들의 전쟁을 보고 있는 듯한 느낌이 든다.

마이크로소프트, 애플 등은 그 때부터 수 많은 업체들과 생존을 위한 치열한 싸움을 벌여 왔으며 그러는 동안 떴다가 져버린 회사들이 수없이 많았다는 점을 알게 됐다.


개인용 컴퓨터의 시초라 할 수 있는 알테어, 애플II, 코모도어 등의 출현과 발전사, 이들과 함께 성장했던 소프트웨어들의 흥망성쇠가 다채롭게 언급된다. 비지캘크라는 스프레드 시트의 원조(비지캘크 - 로터스 123 - 엑셀로 이어지는 스프레드 시트 역사의 흐름도 느껴볼 수 있다), CP/M이라는 당시 대세 운영체제, 또 다른 운영제제들인 애플 도스, Q 도스, 데이터베이스의 대작인 애시톤테이트의 디베이스, 워드 프로세서를 장악했던 마이크로프로의 워드스타, 터보 파스칼로 시작해서 종합 소프트웨어 회사가 된 볼랜드 등의 재미있는 정보가 많이 있었다. 


IBM PC의 탄생 비화도 재미있다. 

IBM은 이미 당시에도 기업용 컴퓨터를 만드는 대기업이었기 때문에 굳이 개인용 컴퓨터 시장에 관심이 없었단다. 하지만 애플 등의 출현으로 점차 개인용 컴퓨터 시장이 커지고 있었기 때문에 무시할 수 만은 없었고... 결국 주력 사업처럼은 하지 않되 일단 투자는 해보자는 식의 결정을 했다.


IBM은 원래부터 필요한 하드웨어를 모두 만들고 컴파일러, 운영체제, 구동 소프트웨어 모든 것을 스스로 만들어 완전한 컴퓨터를 생산하는 엄청난 회사였다. 이런 회사가 개인용 컴퓨터 시장에 간을 보기 위해 했던 일이 어찌보면 코미디다. 주력 사업이 아니므로 약간의 돈으로 시범 사업을 해보려고 했었기 때문에 자금도 부족했고 본사의 훌륭한 자원을 이용하지 못했다. 그래서 취한 방법이 외주 정책이었다. CPU는 인텔(당시에는 모토롤라보다 못했던), 소프트웨어는 마이크로소프트 베이직, 운영체제는 CP/M을 추진하다가 거절당하는 바람에 우려곡절 끝에 마이크로소프트 DOS(이것도 IBM과 MS가 운영체제를 계약할 당시에는 MS에 존재하지 않았었고 이 후에 인수했다고 한다) 등을 채택하며 저렴한 외부 자원을 최대한 활용했고 애플II의 개방형 모델처럼 개방형으로 설계했다. (현재의 애플은 폐쇄형이 아니던가? 매킨토시부터 폐쇄형 정책이 적용됐고 이 때부터 시장 점유율이 줄어들지 않았나 싶다.) 더 재미있는 것은 개방형 모델에 힘입어 IBM PC 호환 기종과 함께 PC 시대 진입에는 성공했으나 결국 IBM PC 호환 기종들에 밀려 정작 IBM PC는 그닥 재미를 보지 못했다는 것이다. 그 다음 삽질은 배가 아팠는지 PS/2라는 폐쇄형 모델을 만들어 독식하려다가 인기를 끌지 못하고 저물어 버린 것이고...



사실 책의 전반적인 내용은 초난감함을 찾아서 정리한 내용이라기 보다는 저자가 두루 거쳐갔던 굵직한 IT업체들의 일화와 저자의 개인적인 비판이 주를 이룬다. 저자의 입담 때문에 재미있게 그냥 읽혀지는 책이지 초난감함에 대한 깔끔한 정리를 해주는 내용은 아니다.


굳이 IT 업체들이 하지 말아야 할 초난감함을 정리하자면 가장 큰 것이 중복 라인업인 것 같다.

마이크로 프로도 망할 때 했던 일이 서로 호환이 되지 않은 2가지 워드 제품(워드스타, 워드스타 2000)을 내 놨다는 것이고, 볼랜드도 파라독스라는 데이터베이스 제품이 있는 상태에서 디베이스를 인수해 비슷한 상황을 만들어 냈고, 마이크로소프트도 윈도우 95와 윈도우 NT를 동시에 팔면서 고개들에게 "도대체 어떤 것을 사야 하나요?"라는 질문을 하게 했다. 물론 회사들은 모두 다음과 같이 말했다. "둘 다 좋은 제품입니다." (여전히 어떤 것을 사야하는지 알려주지 않는다. 아니 알려줄 수가 없지 않겠는가? 모두 팔아야 하는데... ㅋㅋ)


윈도우 95, 윈도우 NT 얘기가 나오니 IBM OS/2가 생각난다. 저자의 의견으로는 1990년대에 이미 윈도우 2000의 수준이었다던데 시대를 너무 앞서가서 느리기도 했고 역시 IBM의 잘못된 여러 정책으로 인해 사라져버린 안타까운 예가 되겠다.


또 다른 초난감은 기능을 줄이면서 가격을 낮춰서 어떻게든 팔아보겠다고 하는 것과 아예 제품 자체가 엉망인 경우다. 여기서 갑자기 아이폰 5C가 생각나면 어쩌자는 것인가? 확실히 요즘의 애플은 예전의 애플답지 않은 전략을 구사하고 있다. 애플의 애플답지 않음은 애플이 계속 애플일 수 없음을 예견하는 것인데... 곧 화면이 큰 아이폰이 나올 것 같은 이 불길한 예감은 또 무엇이란 말인가? ㅋㅋㅋ



반응형
Posted by GreeMate