More Related Content Similar to 덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012 Similar to 덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012 (20) 덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC20121. 덤프 파일을 통한 사후 디버깅
실용 테크닉
김이선
veblush@[nexon|gmail]
2. 버블파이터
BNB 카트라이더 프로토타입 에버플래닛 던전엔파이터 GTR
프로그래머 리드 프로그래머 리드 프로그래머 리드 프로그래머 테크니컬 디렉터 프로그래머
게임 프로그래밍 11년차
7. Exception
System
프로세스 상태 Thread 아니오
Module
Full-
Memory Dump?
…
예
10. Exception System Module Memory
TheadId: 1956 Processor/CPU Modules(0) addr: 0012fedc,
Code: 80000003 Arch: 0 Name: Tests.exe size: 00000124
Flags: 00000000 Level: 6 Base: 00400000 addr: 0040114f,
Record: 00000000 Revision: 5894 Size: 00006000 size: 00000100
Address: 004011cf VendorId: Intel CheckSum: 00006722 addr: 0040114f,
Version: 00010676 Stamp: 4f926cc4 size: 00000100
Feature: bfebfbff CV_GUID: 244b5515- addr: 00501000,
Thread Extended: 6d960e89 CV_AGE: 43 size: 00010000
Thread(id:1956) OS CV_Path: Tests.pdb addr: 00520000,
SCount: 0 Version: 6.1 Modules(1) size: 00021000
PClass: 32 Build: 7601 Name: ntdll.dll …
Priority: 0 Platform: 2 Base: 777e0000
Stack: 1244892 CSD: SP1 Size: 0013c000
EIP: 004011cf CheckSum: 00141016
EBP: 0012ff40 Stamp: 4ec49b60
Thread(id:2910) CV_GUID: 93d2cd7-
… CV_AGE: 2
CV_Path: ntdll.pdb
…
21. EXE
K
컴파일러
소스
링커
PDB
K
27. Symbol K K
Server
M
L L
?
M M
32. 보안 Minidump
EXE EXE DMP
K K !
33. Name: Tests.exe Name: Tests.exe
Base: 00400000 Base: 00400000
Size: 00005000 Size: 00173000
CheckSum: 0000fdf1 CheckSum: 000b1076
Stamp: 4f936fe3 Stamp: 4f936fe3
CV_GUID: 152589ac- CV_GUID:
CV_AGE:
CV_Path:
1
Tests.pdb
보안 Minidump CV_AGE:
CV_Path:
EXE EXE DMP
K K !
37. EXE EXE DMP
K K !
수집
K
DMP dat DMP
K !
39. ?
EXE DMP
K !
수집된 DMP 가 어떤 EXE 랑 연결되는지?
클라이언트 버전 or 빌드 타임을 사용!
42. EXE EXE DMP
T K T K T !
EXE T
T’ L 수집
EXE K
T” M
DMP dat DMP
T K T !
52. 클라이언트의 경우 실행 환경이 통제되지 않는데
H/W 결함 바이러스 악성유저
Driver 결함 악성코드
57. OS 윈도우 9X : OS + 드라이버 불안
OS Heap 차이, ?
CPU CPU 자체 보다는
메인 보드인 경우가 더 많음
GPU 그래픽 카드 드라이버!!!
58. 모듈 외부 프로그램에 의한 영향
메신저, 보안 솔루션 등의 DLL 이
게임 프로세스에 연결됨.
악성 프로그램 DLL 도 마찬가지
61. 2003
덤프,
클레임 재배포
아니요
2003 2008
개발 배포 괜찮나?
2008
예
아싸!
75. 코드 스택
ADDR VALUE DESC
400h int Func(int x, int y) {
104h 10 a
403h int a = x * y;
40Bh return a; 108h 118h EBP
411h } 10Ch 435h EIP
110h 2
420h void Test() { 114h 5
423h Func(2, 5); 118h 12Ch EBP
435h }
11Ch 470h EIP
76. STACK
…
EBP
EIP
…
EBP
EIP
…
EBP
EIP
…
77. ADDR VALUE EIP:010E2E13
0020fa58 0020fa64
EBP:0020FA58
0020fa5c 010e2e29
0020fa60 004b2ff8
0020fa64 0020fa74
0020fa68 010e2e4d
0020fa6c 00000005
0020fa70 004b2ff8
0020fa74 0020fa88
0020fa78 010e2e6d
0020fa7c 00000002
0020fa80 00000005
78. ADDR VALUE EIP:010E2E13
0020fa58 0020fa64
EBP:0020FA58
0020fa5c 010e2e29
0020fa60 004b2ff8
0020fa64 0020fa74
0020fa68 010e2e4d
0020fa6c 00000005
0020fa70 004b2ff8
0020fa74 0020fa88
0020fa78 010e2e6d
0020fa7c 00000002
0020fa80 00000005
80. ADDR VALUE
0020fa58 0020fa64
EBP:0020FA5c
0020fa5c 010e2e29
0020fa60 004b2ff8
0020fa64 0020fa74
0020fa68 010e2e4d
0020fa6c 00000005
0020fa70 004b2ff8
0020fa74 0020fa88
0020fa78 010e2e6d
0020fa7c 00000002
0020fa80 00000005
81. ADDR VALUE
0020fa58 0020fa64
EBP:002BFE64 0020fa5c 010e2e29
0020fa60 004b2ff8
0020fa64 0020fa74
0020fa68 010e2e4d
0020fa6c 00000005
0020fa70 004b2ff8
0020fa74 0020fa88
0020fa78 010e2e6d
0020fa7c 00000002
0020fa80 00000005
82. ADDR VALUE
0020fa58 0020fa64
EBP:002BFE64 0020fa5c 010e2e29
0020fa60 004b2ff8
0020fa64 0020fa74
0020fa68 010e2e4d
0020fa6c 00000005
0020fa70 004b2ff8
0020fa74 0020fa88
0020fa78 010e2e6d
0020fa7c 00000002
0020fa80 00000005
85. ADDR VALUE
0020fa58 0020fa64 Func2
0020fa5c 010e2e29
1. 스택 메모리에서
0020fa60 004b2ff8 코드 주소 추리기
0020fa64 0020fa74 Func1
0020fa68 010e2e4d
0020fa6c 00000005
0020fa70 004b2ff8
0020fa74 0020fa88
0020fa78 010e2e6d
0020fa7c 00000002 Test4
0020fa80 00000005
86. ADDR VALUE
0020fa58 0020fa64
0020fa5c 010e2e29 2. 스택 메모리에서
0020fa60 004b2ff8 스택 주소 영역 추리기
0020fa64 0020fa74
0020fa68 010e2e4d
0020fa6c 00000005
0020fa70 004b2ff8
0020fa74 0020fa88
0020fa78 010e2e6d
0020fa7c 00000002
0020fa80 00000005
87. ADDR VALUE
0020fa58 0020fa64
0020fa5c 010e2e29 +Func2 3. 콜 스택 추정
0020fa60 004b2ff8
0020fa64 0020fa74
0020fa68 010e2e4d +Func1
0020fa6c 00000005
0020fa70 004b2ff8
0020fa74 0020fa88
0020fa78 010e2e6d +Test4
0020fa7c 00000002
0020fa80 00000005
92. struct Item {
int id;
int count;
};
int GetCount(const vector<Item>& items) {
int count = 0;
for (i in items) {
VERIFY(i->count > 0);
count += i->count;
}
return count;
}
94. int GetCount(const vector<Item>& items) {
int count = 0;
for (i in items) {
int item_id = item.id;
int item_count = item.count;
VERIFY(i->count > 0);
count += i->count;
}
return count;
}
96. 그냥 Trace 쓰지 왜?
간단히 덤프 파일로 볼 수 있다면 더 간편해서!
재귀함수 등 콜 스택의 여러 변수를 봐야 한다!
98. int GetCount(const vector<Item>& items) {
DEBUG_VAR(int, item_id);
DEBUG_VAR(int, item_count);
int count = 0;
for (i in items) {
item_id = item.id;
item_count = item.count;
VERIFY(i->count > 0);
count += i->count;
}
return count;
}
100. 스택 할당은 비용이 거의 없으므로
간편하게 써보자!
(다만 스택 오버플로우는 조심)
103. 몬스터
class Monster
: public Object
{
int id;
int ai_state;
int more_over;
virtual ~Monster();
};
105. 일반
< 1MB
힙포함
프로세스
메모리 용량
106. 용량이 크지만 디버깅이 무척 편함
개발버전 클라이언트, 서버, 툴은 적극 사용!
배포 클라이언트의 경우 선택적으로 사용
108. 사용
void OnAttack(Monster* m, Player* p)
{
SetAttackTarget(m, p);
log(“M:%d – P:%d”, m->id, p->id);
verify(p->valid()); 로그
} M:1500 – P:5
M:1901 – P:5
109. 모든 객체에 쉽게 접근할 수 없다.
콜스택 지역 변수에 남았거나,
전역변수 (싱글턴 등) 로부터!
110. 덤프 파일에 힙 메모리 내용이 다 있으니
어떻게 해볼 수 있지 않을까?
111. 1500 이 나오는 메모리 주소를 찾아
Watch 로 살펴보자!
(Monster*)(0x043BD14-4)
119. Object vftbl COL Type
vftbl &LOC signature vftbl
id &::~dtor offset data
ai_state … cdOffset name[0]
more_over pTypeDesc …
… pClassDesc
120. 메모리에서 모든 객체를 찾아 vftbl 이
주소를 출력한다. 있는 객체
Monster 의
vfptr: 0x4102c4 Monster* 타입?
123. 찾은 Monster 객체에 대해 sizeof(T)
안에서
1500 숫자를 가지고 있는 객체만 출력
Monster 의
vfptr: 0x4102c4
124. 메모리의 모든 Monster 객체 중
32bit 1500 을 가지고 있는 것들 출력
>dat o –t Monster –s 16 –f i1500 A.dmp
127. 플레이어
class Player
: public Object
{
string name;
int ip_addr;
int cid;
virtual ~Player();
};
130. 길이가 16 이니 string 이 문자열 포인터를 가리킴.
먼저 문자열 주소를 찾자.
문자열 주소 0x00391840 을 포함하고 있는 Player
객체를 찾자.
131. 길이가 16 이니 string 이 문자열 포인터를 가리킴.
먼저 문자열 주소를 찾자.
문자열 주소 0x00391840 을 포함하고 있는 Player
객체를 찾자.