debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

72
Debugging with VisualStudio Debugging theory and real life exercises. 2017-06-13 Kiyoung Moon

Upload: kiyoung-moon

Post on 21-Jan-2018

281 views

Category:

Software


10 download

TRANSCRIPT

Page 1: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Debugging with VisualStudio

Debugging theory and real life exercises.

2017-06-13 Kiyoung Moon

Page 2: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Bug, Debugging

• 버그(Bug)• 프로그래머가 작성한 Logic이 의도한 대로 동작하지 않는 상태 또는 결

과.

• 디버깅(Debugging)• 버그가 발생한 이유를 찾고 해결하는 과정

Page 3: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

버그는 왜 발생하는가?

• 컴퓨터의 기본 원리• 입력, 처리, 출력

• 프로그래머가 작성한 처리 Logic이 원활하게 동작하기 위한 입력 데이터가 올바르게 입력되지 않았을 때

• 프로그래머가 작성한 처리 Logic이 잘못 작성되었을 때

• 프로그래머가 출력을 제대로 정의하지 않았을 때

Page 4: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

다른 형태의 버그도 발생할 수 있는가?

• 하드웨어의 오류로 인해 로직이 제대로 처리되지 않을 수 있다.• 가령 하드웨어의 온도가 낮아져 처리 속도가 낮아 짐으로서 원래의 역

할을 못할 수도 있다.

• 예> 급속 냉각을 의도적으로 적용해 데이터를 해킹 할 수 있다.• 암호 데이터가 담겨 있는 메모리가 있고 전원이 날아간 상태에서 급속

냉각하여 데이터를 중간에 취득하거나 소멸되지 않게 할 수 있다.

Page 5: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

컴퓨터 소프트웨어 디버깅

• 이 PT에서는 소프트웨어 디버깅. 비주얼 스튜디오를 사용한 디버깅에 대한 이야기만 할 예정.

Page 6: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

디버거의 원리, 컴퓨터의 동작 원리

• 컴퓨터는 순서대로 명령어를 실행• 순서는 누가 기억하는가? IP(Instruction Pointer)

• EIP(Extended Instruction Pointer)• 다음에 실행될 명령어의 주소를 보관하고 있다.

• 만일 EIP가 올바른 명령어 주소를 보관하고 있지

않다면 CPU가 뭔짓을 할지 모른다!

• 흔히 버퍼오버플로우(Buffer Overflow)라는

해킹 기법은 EIP 조작을 주로 한다.

명령어1

명령어2

명령어3

명령어n

Page 7: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

중단점(Breakpoint,브레이크포인트)

• 중단점, 브레이크포인트라고 부른다.

• 멈추고 싶은 컴퓨터 명령어의 주소에 중단점을 걸어 놓으면 프로그램의 실행이 해당 명령어에서 멈춘다.

Page 8: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 두 개의 정수 값을 더하는 sum이라는 함수가 정상 동작하지 않고 있다. 입력 값 각각 10, 20을주었을 때 30이 c에 들어가야 하지만 의도치 않게 200이 설정된다.

• 중단점을 사용해 프로그램의 명령어 실행을 중단 시키고 디버깅해보도록 하자.

Page 9: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 중단시킬 명령어에서 F9를

누르거나 마우스 왼쪽 버튼을

클릭해서 중단점을 설정한다.

Page 10: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

프로그램의 실행

• 비주얼 스튜디오에서 프로그램을 실행하는 방법은 F5 또는 Ctrl + F5가 있다.

• Ctrl+F5는 디버거를 붙이지 않은 상태로 실행하고 F5는 디버거를 붙여서 실행한다. 우리는 디버깅을 해야하므로 F5번을 눌러프로그램을 실행시킨다.

Page 11: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 프로그램이 해당 명령어에서 멈춘 모습. 중단점이 걸리면 프로그램의 실행은 잠시 멈추게 된다. (종료 되는 것은 아니다)

Page 12: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

디버깅 단축키

• 비주얼 스튜디오의 디버깅 명령어의

단축키들은 외울 필요가 있다.

Page 13: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Watch Window

• 다음 명령어를 실행하기 위해 (EIP를 다음으로 진행) F10을 누르면 프로시저 단위로 실행이 된다. 즉, 프로시저가 있다면(지금은sum함수) sum함수의 내부로 들어가지 않고 sum을 실행한 이후에 다음 명령어에서 멈춘다.

• F10을 눌러서 다음 명령어를 실행한다.

Page 14: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 그림을 보면 왼쪽에 노란색 화살표가 int c = sum(a, b); 아래로 내려간 것을 확인할 수 있다. 즉 명령어가 실행되었고 다음에실행될 명령어가 return 1;이라는 뜻이다.

• 이 시점에서 int c의 값은 sum의 결과로 할당(Assign)되어 있다.

• 이제 이 값을 확인해 보도록 하자.

Page 15: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Watch Window

• 변수 c를 선택한 상태에서Shift+F9키를 누르거나 디버그-> 간략한 조사식 메뉴 아이템을 선택하여 조자식을 표시한다.

Page 16: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 간략한 조사식을 보면 현재 c의값이 200으로 설정된 것을 볼 수있다. 엄연히 잘못된 값이 할당되어 있음을 알 수 있다.

Page 17: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

디버깅은 왜 버그가 발생했는지 알아내는 과정

• 이제 sum이 어떤 일을 하길래 200을 결과값으로 내뱉는지 알아보도록 하자.

• 프로그램을 다시 F5키로 실행하여 디버거를 붙인후 진행한다.

• 프로그램이 중단점에서 멈추면 F10이 아니라 F11을 눌러 ‘한 단계 코드 실행’을 실행한다.

Page 18: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 이전의 상황과 다르게 노란색화살표(IP)가 return 1;로 가지않고 sum 함수의 내부로 들어간다. 왜냐면 프로시저 단위로 실행된 것이 아니라 코드 하나씩실행했기 때문에 내부로 들어간다. IP를 더 진행하기 위해 F10을 눌러 보자.

Page 19: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 이제 노란색 화살표가 return a* b;를 지시하고 있다. 기억할 것은 현재 a * b라는 코드가 실행되기 전이다. 그렇다면 해당 코드가 실제로 우리가 원하는 결과를 나타내는 코드인지 조사식을 통해서 보도록 하자.

• Shift+F9키를 눌러서 조사식을띄운다.

Page 20: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 조사식에서 a*b를 입력하면 계산이 실행되며 값이 200이 나온다. 이것은 엄연히 sum이 아니라mul(곱)이다.

• 이제 a+b를 식에 넣고 실행해 보자.

Page 21: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 값이 30이 되었고 이것이 우리가 원하는 a + b가 되는 sum의정의다. 즉, 코드는 a*b가 아니라 a+b이어야 한다. 이제 프로그램 실행을 멈추고 해당 코드를 return a+b;로 수정하면 버그가 해결된다.

Page 22: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Options for watch window

• 조사식은 표현식을 실행 할 수 있으며 값을 표현하는 방법을 설정할 수 있다. 예를 들어 아래와 같이 char buffer[]가 있을 때

Page 23: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 조사식으로 보면 다음과 같다.

Page 24: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

배열 형태로 보기

• 배열 형태로 보려면 buffer, 12라고 하면 된다.

• 12는 원소의 개수다.

Page 25: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

데이터 타입에 따라 값을 편하게 보기

• 데이터 타입에 따라 비주얼스튜디오는 값을 편하게 보기 위해Visualizer를 제공하는데 고급 주제이므로 이것은 다음 링크를참고 하길 바란다.

• https://msdn.microsoft.com/en-us/library/esta7c62.aspx

Page 26: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

EIP 조작

• 컴퓨터는 EIP를 이용해 다음에 실행될 명령어를 알아낸다. 이제EIP를 어떻게 조작하며 어떠한 디버깅을 할 수 있는지 알아 보자.

Page 27: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

현재 EIP 체크

Page 28: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• Ctrl + Alt + G를 누르거나 해당 디버그 -> 창 -> 레지스터를 선택해 레지스터의 현재 값들을 볼 수 있다.

• x86 architecture, 컴퓨터 구조, Compiler를 공부하면 이러한 레지스터의 용도를 알 수 있다.)

Page 29: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 현재 EIP는 009E16AE의 값을 가지고 있다. 여기에 다음 실행될명령어의 주소가 담겨 있다.

Page 30: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 다음에 실행될 명령어 mov eax, dword ptr [a]의 주소는009E16AE임을 디스어셈블리 윈도우에서 확인할 수 있다.

Page 31: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

EIP 조작 방법

• 다시 왼쪽 그림과 같이 프로그램의 명령어가 return 1;에 있고sum이라는 함수는 입력 값들을계산하고 끝이 났다. 이 상황에서 다시 프로그램을 실행한 후중단점에서 디버깅을 다시 해도되지만 sum이라는 함수가stateful하지 않은 stateless 로직이라면 eip를 조작해 다시 구문을 실행할 수 있다.

Page 32: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 왼쪽 노란색 화살표를 마우스 왼쪽 버튼으로 클릭한 후 드래그 하여 int c = sum(a, b);로 움직여서드랍하면 EIP를 int c = sum(a, b);로 설정할 수 있다. 즉, 이미 실행된 로직을 eip를 조작함으로서 해당 구문을 다시 실행할 수 있게 해준다.

• 이렇게 하면 프로그램을 종료했다가 다시 실행할 필요가 없다.• 물론 이것이 가능 하려면 지금 예

(sum함수)에서 함수가 stateful하지않고 stateless해야 한다.

Page 33: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 이제 F11을 누르면 sum 함수의 내부 로직으로 들어가며 다시디버깅 가능하다.

Page 34: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Stateful vs Stateless

• 쉽게 말해서 어떠한 로직이 실행되면서 내부 상태를 바꾸어 상태에 따라 다른 결과를 내놓는다면 ‘stateful하다.’라고 말할 수있고 그렇지 않고 로직이 단순 계산 로직이고 내부 상태를 바꾸지 않는다면 ‘stateless하다’라고 말할 수 있다.

• EIP 조작에서 Stateful한 경우는 조작할 수 없다는 의미는 내부상태의 값에 따라 이전과 같은 초기 상태를 보장할 수 없으므로좋은 디버깅 조건이 아니기 때문에 EIP 조작을 권하지 않는다.

Page 35: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

함수의 결과값 디버깅

• 변수의 경우 메모리 조사를 통해서 알 수 있지만 함수의 결과물은 보통 메모리가 아닌 레지스터에 저장된다. 앞서 sum의 결과값이 어디에 저장되는지 알아 보는 방법은 다음과 같다.

Page 36: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 왼쪽 그림처럼 int c = sum(a, b);가 실행된 후 결과값은 c라는변수에 저장되어 있다. 물론 c값을 조사해서 함수의 결과값을볼 수 있지만 c라는 값을 쉽게볼 수 없는 경우도 이럴 때는 레지스터 EAX를 보면 함수의 결과값을 볼 수 있다.

Page 37: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• EAX의 값은 현재 0xC8이고 이 값은 10진수 값으로 200이다.

• 조사식에서 0xC8을 입력해서 값을 확인할 수도 있다.

Page 38: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

계산기 사용 팁

• 계산기를 이용해 16진수 C8을 입력하고

10진수 (DEC)로 컨버팅해서 결과값을 확인할 수도 있다.

Page 39: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

데이터 브레이크 포인트

• 까먹고 안넣은거 설명은 실시간으로!

Page 40: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

옛날 이야기 : 듀얼 모니터를 썼던 이유

• 디버깅의 용이함

• 전면 버퍼의 소실로 인해 디버깅하고 있던 게임 내 화면 데이터를 잃어 버리는 경우가 많았음.

Page 41: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

메모리 윈도우(Memory Window)

• 조사식을 통해서 변수의 값을 확인할 수 있지만 경우에 따라 조사식으로 충분하지 않은 경우도 있다. 이럴 때는 메모리 윈도우를 통해 메모리 값을 볼 수 있다.

Page 42: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅
Page 43: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 메모리 윈도우를 사용해서 현재 메모리 값을 모두 볼 수 있다.

Page 44: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

메모리 윈도우를 통해 변수 c의 값 확인하기

• 조사식에서 &c를 입력하면 c변수의 주소값을 확인할 수 있다.

• C의 주소값은 0x00dbfda0이고 (이 값은 다를 수 있다.)

• 메모리 윈도우에서 0x00dbfda0을 찾아가 보도록 하자.

Page 45: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 0x00DBFDA0을 보면 값이 c8 00 00 00으로 되어 있는 것을 확인할 수 있다.

Page 46: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

메모리 윈도우에서 값 변조하기

• 메모리 윈도우에서 값을 볼 수도 있지만 변경도 가능하다. 16진수 값 c8을 다른 값으로 변경해 보도록 하자. 예를 들어 FF와 같이 수정하자.

Page 47: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 이제 c값을 조사식에서 보면 값이 200이 아닌 255로 되어 있는것을 볼 수 있다.

Page 48: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

컴퓨터의 데이터 표현은 결국 메모리 메모리 메모리 메모리!• 메모리를 조작하면 프로그램을 원하는 방식으로 바꿀 수 있다.

Page 49: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

0xCDCDCDCD?

• 매직 넘버(Magic Number)

• 디버깅할 때 프로그래머가 의미를 알아보기 쉽게 하기 위한 미리 정의된 값들.

• https://en.wikipedia.org/wiki/Magic_number_(programming)

CDCDCDCDUsed by Microsoft's C/C++ debug malloc() function to mark uninitialized heap memory, usually returned from HeapAlloc()[19]

Page 50: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅
Page 51: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅
Page 52: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 16진수로 초기화되지 않은 값을 보면 0xcccccccc으로 되어 있다. 0xcccccccc은 무슨 뜻인가?• Used by Microsoft's C++ debugging runtime library and many DOS

environments to mark uninitialized stack memory.

• 초기화되지 않은 스택 메모리를 의미한다.

Page 53: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

콜스택, 스택프레임

• 프로그램은 차례대로 명령어를 수행하며 함수의 구현을 위해스택 프레임(StackFrame)이라는 것을 사용한다.

• 앞서 설명한 sum 함수는 대표적인 값을 반환하는 함수이며 이것의 내부 구현이 스택 프레임 기반으로 작동된다.

• 함수를 호출하는 것을 콜(Call)한다고 하며 이 콜이 내부적으로중첩되면서 콜스택으로 표현된다.

Page 54: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅
Page 55: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

콜스택에서 호출 순서

• 호출 순서는 아래에서 위로

• mainCRTStartup()에서

• __scrt_common_main()을 호출하고

• 다음에 __scrt_common_main_she를 호출한다.

• 다음으로 invoke_main()을 호출하고

• 다음에 main()이 호출된다. 그리고 이 main에서

• Sum을 호출한다.

• 현재 그림에서 노란색 화살표가 sum을 지시하고 있으므로 현재 명령어는

Sum함수에서 멈춰 있다는 것을 알 수 있다.

Page 56: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

콜스택이 왜 중요한가?

• 콜스택을 분석하면 어떤 함수가 어떤 경로를 통해서 호출되었는지 알 수 있다.

• 버그의 재구현에 아주 큰 역할을 한다. 즉, 버그가 발견되었을때 최소한 콜스택만 알아도 수백만의 코드에서 어느 부분이 문제가 되는 것인지 알 수 있다.

Page 57: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Dump(덤프)를 뜬다라는 말.

• 보통 ‘Dump를 뜬다.’라는 말은 현재 프로세스의 메모리 상태와명령어의 콜스택을 프로그래머가 알 수 있는 형태로 저장하는것을 말한다.

Page 58: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

다양한 디버거들

• ollydbg

• Softice

• IDA Pro

• WinDbg

• Debug.com

Page 59: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Advanced topics

• Real life cases.• memory overflow

• Displacement memory allocation

• gcc compiler bug• Wrong compiler optimization

• desync on online play

• Hidden watch window expression(legacy case)

Page 60: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Memory Overflow

• 메모리는 데이터(Data), 자료

• 데이터에는 범위, 크기가 있다.• 예를 들어 int, float, double, dword, etc…

• 자료의 크기가 곧 범위. 데이터의 값이 데이터의 표현 범위를 넘어가는 것이 곧 메모리 오버플로우.

Page 61: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 데이터의 크기를 결정하는 것이 매우 중요하다.

• 데이터의 크기는 성능에 큰 영향을 끼친다.

• 가령 나이를 저장하는 데이터의 범위는 몇 바이트(Byte)를 사용하는 것이 좋은가?

Page 62: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

• 보통 나이는 255살 넘어가는 경우가 없으므로 1Byte면 충분하다.

• 이러한 나이를 4Byte에 저장할 경우에는?• 아무런 문제가 없다. 다만 더 많은 메모리를 사용할 뿐이다.

• 진짜?

Page 63: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

축구 선수 데이터라면?

• 축구 선수를 표현하기 위한 데이터는?• 이름• 나이• 키• 몸무게• 스킬• 포지션• 볼 컨트롤• 드리블• 마킹• 슬라이드 태클• 스탠딩 태클• 크로싱• 짧은 패스• 긴 패스• 등등…

Page 64: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

단순한 산수

• 구조체 필드 데이터가 하나 당 무조건 1바이트라면 4바이트로사용했을 때 무조건 4배.

• 경우에 따라 꽤 큰 비용(?)이 될 수 있음.• 성능, 네트워크 트래픽 등등

Page 65: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

그래서?

• 용량을 줄여서 최대한 데이터의 값이 딱 맞게 데이터의 범위를설정해야 한다. (좋은 프로그래머가 되고 싶다면!)

• 하지만 처리 로직을 잘못 작성하거나 본의 아니게 이러한 범위를 넘어가는 경우 메모리 오버플로우가 생길 수 있다.

Page 66: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

어떻게 잡나?

• Concept, 컨셉, 개념

Page 67: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Memory manager using Displacement Memory Allocation.• Create a custom memory manager.

• There are bunch of benefits of using displacement memory allocation. Such as…• Find a memory overflow

• Memory leaks

• Speed optimization

• Avoid memory defragmentation.

• Memory Viewer

• And so on…

Page 68: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

GCC Compiler Bug

• Compiler is a software and could be exist a bug which is critical and hard to find.• Stuffs related with hardware such as optimization of vector operation.

• Xbox360 and ps3 are different platform and compiler couldn’t handle it somehow.

• How did I fix it?• Try to fix it.

• Can’t? Report it to sony.

• Wait

• If we don’t have enough time? Then turn off the optimization.

Page 69: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Desync online play.

Page 70: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

Hidden watch window expression(Legacy)• When I attached a debugger somehow logic is totally *uckedup.

Page 71: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅

읽어보면 좋은 책들

Page 72: Debugging with visual studio. 비주얼 스튜디오를 활용한 디버깅