Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
사례로 배우는 디스어셈블리 디버깅
넥슨코리아 데브캣스튜디오 DD1실
이승재
발표자
이승재:프로그래머
카바티나 스토리 2007~2009
데스크탑 히어로즈 2010~2011.9
마비노기2 2011.10~2013
미공개 프로젝트 2014~
이 발표는
마비노기2 개발중에 실제로 발생했던
버그의 원인을 추적하는 과정을
재구성했습니다.
주제
디스어셈블리 디버깅
• 포인터가있는언어로개발하는한피할수없다
• 아무나할수없고,누구도하기싫어하는일
진짜 주제
어렵지 않다
멘붕하지 말자
2013년 9월
상황
여기서 크래시 0x00000010 읽다가 사망
재현조건: 던전을 플레이한다 (;;;)
상황
0x00000010을 왜 읽지????
디버거로 sim을 보면 멀쩡한 값이 들어있다
상황
언제부터 이랬지?
하루? 이틀? 모르겠다
누가 뭘 바꿨지?
프로그래머 20명 이상…
재현조건이 명확하다면…
리비전 이분검색을 쓸 수 있다
리비전 이분검색?
- 버그 없는 리비전과 버그 있는 리비전을 알면
- 가운데 리비전을 받아서 버그가 재현되는지 본다
- 재현되면 앞쪽 절반, 재현안되면 뒤쪽 절반을 반복
두 명이 동시에 재현하면 삼분검색 가능!
그러나…
재현조건이 애매했다
• 보통 20분 정도면 재현되었지만
• 40분 동안 재현이 안 되어도 버그가 없다는 뜻은 아니다
마감 직전이면 인력을 동원해서 해결하겠지만…
무엇보다, 지루한 작업
가설: 다른 스레드가 덮어썼나?
해당 객체를 건드리는 모든 코드를 리뷰함:
값을 덮어쓰는 곳이 없었다. 멀티스레드 문제는 아니다.
디스어셈블리를 보자
나 어셈 볼 줄 모르는데…
인텔 어셈블리에 대해 알고 있던 것:
• 함수 호출할 때 인자를 스택에 푸시한다 (역순)
• 함수 호출할 때 레지스터를 스택에 푸시해서 보관한다
• 가상함수 호출 메커니즘
• mov는 복사, ...
마음가짐
재현만 되면 못 잡을 버그가 없다
어셈블리 그까짓거
어셈블리 그까짓거!!
디스어셈블리를 보자!
이게 다 무슨 뜻인가? eax는 정체가 뭔가?
← 여기에서, eax+0x0c를 읽다가 죽었다.
잠깐 가상함수 호출 절차
실제 멤버변수들
VTable 시작 주소
class X의 객체 가상함수 A 주소
가상함수 B 주소
가상함수 C 주소
가상함수 D 주소
가상함수 E 주소
가상함수 F 주소
class X의 VTabl...
디스어셈블리를 보자
edi에 sim이 저장되어 있다고 가정하는 코드다.
가상함수 테이블을 조회하다가 죽었구나!
↖vtbl 주소를 eax에 저장
← GameContext 함수 주소를 얻어서
←호출
디버거 Watch에 (GameSimulation*)edi 를 입력해보니
실로 멀쩡한 객체를 가리키는 값이 아니었다
edi는 함수 맨 앞에서 설정했고(mov edi,dwordptr[ebp+8])
이후에 edi를 덮어쓰는 ...
구글 검색 <edi push 책임> 해봄
호출되는 쪽에서 edi를 쓰기 전에 저장할 책임이 있다고 한다
edi 저장 책임은 누가 지나?
누가? 어떻게?
레지스터를 깨먹는 함수라니 듣도 보도 못했다
이 함수에는 58건의 call이 있다. 누굴까?
일일이 들여다보는 건 시간 낭비라고 판단
탐침을 박아보자
누군가가 edi를 깨먹고 있다
모든 함수호출 전에 edi를 저장하고
모든 함수호출 후의 edi와 비교해서
달라지면 브레이크포인트
탐침을 박아보자
여러가지 방법을 시도해봄
뭘 추가하면 레지스터 배치가 달라져서
탐침이 동작 않는 경우가 부지기수
“변수 선언 순서 바꾸니까 되는데요”가 바로 이런 경우
탐침을 박고 빌드한 뒤 어셈블리를 봐서
의도한 대로 동작하는지 확인...
재현 ㄱㄱ
걸렸다!
← 여기에 걸렸다
↑이 코드를 수행하던 도중에 edi가 깨진 것이다
딱히 수상한 점이 없다
한 단계 더 들어가 보자
RegionService::PickingRegion
PickingFloor
여기 어딘가 범인이 있다
디스어셈블리를 보자
edi를스택에보관하고리턴전에복구하네!
보관해놓은동안누군가스택을긁었겠다!
레지스터긁는걸찾아내는문제가
스택긁는걸찾아내는문제로바뀌었다
PickingFloor 함수첫머리
함수끝부분
가설: edi가 저장된 위치 주변의 지역변수에
버퍼 오버런한 거 아닐까?
검증: 코드리뷰해 봤는데 딱히 그런 건 안 보임
새로운 가설
스택에 보관해둔 레지스터를 복구하기 전에
그 스택 영역을 변경하는 일은 일어나선 안 된다
데이터 브레이크포인트가 출동!
다시 탐침
데이터 브레이크포인트?
이 경우 스택의 변조를 감지해야 한다
VS에서 수동으로 매번 잡았다 풀었다 할 순 없다;;
코드에서 데이터 브레이크포인트 설정/해제가 가능
참고:http://dual5651.hacktizen.com/tt/entry/Br...
edi가 push된 곳을 어떻게 알지?
구글: intel assembly stack top register → esp
• edi를push한직후에
• 디버그Watch로*(int*)esp를찍어보니…
• edi내용이똑같이저장...
재현 ㄱㄱ
근데 왜??
걸렸다!
ILocationComponent* logComp에
실제로는 다른 타입의 객체가 들어있다?
새로운 가설
locComp의GetHandle()을호출하려 했다
가상함수테이블의첫번째항목인듯(오프셋0)
locComp가실제론PhysXCollisionActor를가리키고있었다면?
Phys…Actor에는가상함수가딱하나있다:소멸자
그렇다고...
ILocationComponent의GetHandle()을부르려는동작이
PhysXCollisionActor의소멸자를불렀다
그과정에서운좋게(?)그자리에서크래시하지않고스택을망쳐놓기만했고
함수를빠져나간이후에스택으로부터복구한레지...
수사 종료
구체적으로 어떤 과정을 거쳐서 edi가 저장된 위치를 망가뜨린 건지는
더 파고들어 보면 알 수 있겠지만
이 정도에서 충분히 원인을 파악했다고 보고 디버깅을 마무리.
크래시 → 멘탈 붕괴 → 디스어셈블리를 보자 →
가상함수 호출하려다 죽었다 → 레지스터 edi가 깨져있네? →
다른 함수가 스택에 저장했던 걸 또다른 누군가 긁은 거다 →
데이터 브레이크포인트로 긁는 순간을 잡아내자 →...
• void* 는 위험하다.
• 어셈블리는 마법이 아니다.
• 디버깅은 가설 수립과 검증의 연속 가설이없을때는시간낭비하기쉬움
• 적절한 도구를 사용하면 도움이 됨 인라인어셈블리,데이터브레이크포인트
정리
마지막으로
디버깅 멘탈을 키워주는 교재
• 모든 디버깅이 사후postmortem디버깅
• 단서는 비행기록과 잔해 조각 뿐
• 재현해볼 수 없다
항공사고수사대: 항공 사고 디버깅
• 기껏해야 MRI, CT, 혈액검사, 요추천자, 조직검사 정도
• 시시각각 상황이 변화하고
• 환자가 죽기 전에 고쳐야 한다
HOUSE M.D.: 인간 디버깅
항공 사고, 인간 디버깅에 비하면
소프트웨어 디버깅 따위 쉽다
끝
NDC14 - 사례로 배우는 디스어셈블리 디버깅
NDC14 - 사례로 배우는 디스어셈블리 디버깅
NDC14 - 사례로 배우는 디스어셈블리 디버깅
Upcoming SlideShare
Loading in …5
×

39

Share

Download to read offline

NDC14 - 사례로 배우는 디스어셈블리 디버깅

Download to read offline

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

NDC14 - 사례로 배우는 디스어셈블리 디버깅

  1. 1. 사례로 배우는 디스어셈블리 디버깅 넥슨코리아 데브캣스튜디오 DD1실 이승재
  2. 2. 발표자 이승재:프로그래머 카바티나 스토리 2007~2009 데스크탑 히어로즈 2010~2011.9 마비노기2 2011.10~2013 미공개 프로젝트 2014~
  3. 3. 이 발표는 마비노기2 개발중에 실제로 발생했던 버그의 원인을 추적하는 과정을 재구성했습니다.
  4. 4. 주제 디스어셈블리 디버깅 • 포인터가있는언어로개발하는한피할수없다 • 아무나할수없고,누구도하기싫어하는일
  5. 5. 진짜 주제 어렵지 않다 멘붕하지 말자
  6. 6. 2013년 9월
  7. 7. 상황 여기서 크래시 0x00000010 읽다가 사망 재현조건: 던전을 플레이한다 (;;;)
  8. 8. 상황 0x00000010을 왜 읽지???? 디버거로 sim을 보면 멀쩡한 값이 들어있다
  9. 9. 상황 언제부터 이랬지? 하루? 이틀? 모르겠다 누가 뭘 바꿨지? 프로그래머 20명 이상…
  10. 10. 재현조건이 명확하다면… 리비전 이분검색을 쓸 수 있다
  11. 11. 리비전 이분검색? - 버그 없는 리비전과 버그 있는 리비전을 알면 - 가운데 리비전을 받아서 버그가 재현되는지 본다 - 재현되면 앞쪽 절반, 재현안되면 뒤쪽 절반을 반복 두 명이 동시에 재현하면 삼분검색 가능!
  12. 12. 그러나… 재현조건이 애매했다 • 보통 20분 정도면 재현되었지만 • 40분 동안 재현이 안 되어도 버그가 없다는 뜻은 아니다 마감 직전이면 인력을 동원해서 해결하겠지만… 무엇보다, 지루한 작업
  13. 13. 가설: 다른 스레드가 덮어썼나? 해당 객체를 건드리는 모든 코드를 리뷰함: 값을 덮어쓰는 곳이 없었다. 멀티스레드 문제는 아니다. 디스어셈블리를 보자
  14. 14. 나 어셈 볼 줄 모르는데… 인텔 어셈블리에 대해 알고 있던 것: • 함수 호출할 때 인자를 스택에 푸시한다 (역순) • 함수 호출할 때 레지스터를 스택에 푸시해서 보관한다 • 가상함수 호출 메커니즘 • mov는 복사, call은 함수호출 자세한 건 몰랐음 • 데이터 브레이크포인트라는 것이 있고, 코드에서 제어할 수 있다
  15. 15. 마음가짐 재현만 되면 못 잡을 버그가 없다 어셈블리 그까짓거 어셈블리 그까짓거!!
  16. 16. 디스어셈블리를 보자! 이게 다 무슨 뜻인가? eax는 정체가 뭔가? ← 여기에서, eax+0x0c를 읽다가 죽었다.
  17. 17. 잠깐 가상함수 호출 절차 실제 멤버변수들 VTable 시작 주소 class X의 객체 가상함수 A 주소 가상함수 B 주소 가상함수 C 주소 가상함수 D 주소 가상함수 E 주소 가상함수 F 주소 class X의 VTable Visual C++에서의 Machine code X::가상함수 C 코드
  18. 18. 디스어셈블리를 보자 edi에 sim이 저장되어 있다고 가정하는 코드다. 가상함수 테이블을 조회하다가 죽었구나! ↖vtbl 주소를 eax에 저장 ← GameContext 함수 주소를 얻어서 ←호출
  19. 19. 디버거 Watch에 (GameSimulation*)edi 를 입력해보니 실로 멀쩡한 객체를 가리키는 값이 아니었다 edi는 함수 맨 앞에서 설정했고(mov edi,dwordptr[ebp+8]) 이후에 edi를 덮어쓰는 곳이 없다 그런데 edi가 이상한 값이 되어 있다…? 디스어셈블리를 보자
  20. 20. 구글 검색 <edi push 책임> 해봄 호출되는 쪽에서 edi를 쓰기 전에 저장할 책임이 있다고 한다 edi 저장 책임은 누가 지나?
  21. 21. 누가? 어떻게? 레지스터를 깨먹는 함수라니 듣도 보도 못했다 이 함수에는 58건의 call이 있다. 누굴까? 일일이 들여다보는 건 시간 낭비라고 판단 탐침을 박아보자 누군가가 edi를 깨먹고 있다
  22. 22. 모든 함수호출 전에 edi를 저장하고 모든 함수호출 후의 edi와 비교해서 달라지면 브레이크포인트 탐침을 박아보자
  23. 23. 여러가지 방법을 시도해봄 뭘 추가하면 레지스터 배치가 달라져서 탐침이 동작 않는 경우가 부지기수 “변수 선언 순서 바꾸니까 되는데요”가 바로 이런 경우 탐침을 박고 빌드한 뒤 어셈블리를 봐서 의도한 대로 동작하는지 확인해봐야 함 탐침을 박아보자
  24. 24. 재현 ㄱㄱ
  25. 25. 걸렸다! ← 여기에 걸렸다 ↑이 코드를 수행하던 도중에 edi가 깨진 것이다
  26. 26. 딱히 수상한 점이 없다 한 단계 더 들어가 보자 RegionService::PickingRegion
  27. 27. PickingFloor 여기 어딘가 범인이 있다 디스어셈블리를 보자
  28. 28. edi를스택에보관하고리턴전에복구하네! 보관해놓은동안누군가스택을긁었겠다! 레지스터긁는걸찾아내는문제가 스택긁는걸찾아내는문제로바뀌었다 PickingFloor 함수첫머리 함수끝부분
  29. 29. 가설: edi가 저장된 위치 주변의 지역변수에 버퍼 오버런한 거 아닐까? 검증: 코드리뷰해 봤는데 딱히 그런 건 안 보임 새로운 가설
  30. 30. 스택에 보관해둔 레지스터를 복구하기 전에 그 스택 영역을 변경하는 일은 일어나선 안 된다 데이터 브레이크포인트가 출동! 다시 탐침
  31. 31. 데이터 브레이크포인트?
  32. 32. 이 경우 스택의 변조를 감지해야 한다 VS에서 수동으로 매번 잡았다 풀었다 할 순 없다;; 코드에서 데이터 브레이크포인트 설정/해제가 가능 참고:http://dual5651.hacktizen.com/tt/entry/BreakBreak-BreakPoint 없어진문서이지만http://web.archive.org/를통해접근가능 데이터 브레이크포인트?
  33. 33. edi가 push된 곳을 어떻게 알지? 구글: intel assembly stack top register → esp • edi를push한직후에 • 디버그Watch로*(int*)esp를찍어보니… • edi내용이똑같이저장되어있다 • 됐다! 메모리 변경을 감지하자
  34. 34. 재현 ㄱㄱ
  35. 35. 근데 왜?? 걸렸다!
  36. 36. ILocationComponent* logComp에 실제로는 다른 타입의 객체가 들어있다? 새로운 가설
  37. 37. locComp의GetHandle()을호출하려 했다 가상함수테이블의첫번째항목인듯(오프셋0) locComp가실제론PhysXCollisionActor를가리키고있었다면? Phys…Actor에는가상함수가딱하나있다:소멸자 그렇다고 치면
  38. 38. ILocationComponent의GetHandle()을부르려는동작이 PhysXCollisionActor의소멸자를불렀다 그과정에서운좋게(?)그자리에서크래시하지않고스택을망쳐놓기만했고 함수를빠져나간이후에스택으로부터복구한레지스터에 쓰레기값이들어있어서크래시한것 문제 발생 경로
  39. 39. 수사 종료 구체적으로 어떤 과정을 거쳐서 edi가 저장된 위치를 망가뜨린 건지는 더 파고들어 보면 알 수 있겠지만 이 정도에서 충분히 원인을 파악했다고 보고 디버깅을 마무리.
  40. 40. 크래시 → 멘탈 붕괴 → 디스어셈블리를 보자 → 가상함수 호출하려다 죽었다 → 레지스터 edi가 깨져있네? → 다른 함수가 스택에 저장했던 걸 또다른 누군가 긁은 거다 → 데이터 브레이크포인트로 긁는 순간을 잡아내자 → 엉뚱한 객체의 함수를 호출했다 → 고기! 고기! 고기! 요약
  41. 41. • void* 는 위험하다. • 어셈블리는 마법이 아니다. • 디버깅은 가설 수립과 검증의 연속 가설이없을때는시간낭비하기쉬움 • 적절한 도구를 사용하면 도움이 됨 인라인어셈블리,데이터브레이크포인트 정리
  42. 42. 마지막으로 디버깅 멘탈을 키워주는 교재
  43. 43. • 모든 디버깅이 사후postmortem디버깅 • 단서는 비행기록과 잔해 조각 뿐 • 재현해볼 수 없다 항공사고수사대: 항공 사고 디버깅
  44. 44. • 기껏해야 MRI, CT, 혈액검사, 요추천자, 조직검사 정도 • 시시각각 상황이 변화하고 • 환자가 죽기 전에 고쳐야 한다 HOUSE M.D.: 인간 디버깅
  45. 45. 항공 사고, 인간 디버깅에 비하면 소프트웨어 디버깅 따위 쉽다 끝
  • wooseokkim161

    Mar. 24, 2017
  • jaejun0201

    Jan. 24, 2017
  • codingbotaga

    Feb. 5, 2016
  • kyohyeonpark

    Feb. 5, 2016
  • atmelk

    Oct. 1, 2015
  • changhyunpark106

    Jul. 13, 2015
  • seungeonkim3

    Jun. 4, 2015
  • ssuser815249

    May. 11, 2015
  • zedu

    Apr. 24, 2015
  • ssuser61bf76

    Apr. 20, 2015
  • gristmiller

    Mar. 29, 2015
  • seao

    Mar. 15, 2015
  • danny2nd

    Feb. 23, 2015
  • locustspecter

    Feb. 22, 2015
  • joobn

    Feb. 15, 2015
  • MarkersLee

    Jan. 18, 2015
  • ssuseracf13a

    Dec. 2, 2014
  • al6uiz

    Nov. 6, 2014
  • wonst719

    Sep. 17, 2014
  • taru00

    Sep. 7, 2014

Views

Total views

6,720

On Slideshare

0

From embeds

0

Number of embeds

1,140

Actions

Downloads

55

Shares

0

Comments

0

Likes

39

×