Level
초급
Content
"Hello World!" 프로그램을 디버깅 해보고 간단한 패치를 해보도록 하겠습니다.
이를 통하여 디버깅에 대한 감을 잡으실 수 있습니다.
Goal
- 기본적인 디버거 사용방법의 이해
- 간단한 Disassembly code 이해
- 간단한 프로그램 패치(patch)
Tool
Visual C++ 2008 Express Edition
OllyDbg 1.10
Hello World!
모든 C 프로그래머가 최초로 만들어 본 프로그램 Hello World! 를 최초의 디버깅 프로그램으로 결정하였습니다. SW 업계에서의 차지하는 Hello World! 의 의미, 처음 C 를 배울때의 두근거림 그리고 소스 코드의 간결함까지... 이 모든 것이 최초의 디버깅 프로그램으로써 더 할 나위 없이 딱 들어맞는군요.
자신에게 익숙한 C/C++ 개발툴을 이용하여 Hello World! 를 만들어 봅니다.
(Release 모드로 빌드하면 코드가 좀 더 간결해져서 디버깅하기 편합니다.)
<Fig. 1>
디버깅 목표
위에서 만든 HelloWorld.exe 를 실행해보면 당.연.히. "Hello World!" 메시지 박스가 출력될 것입니다. 그냥 디버깅만 하면 재미없으니까 이 문자열을 "Hello Reversing!" 으로 바꾸는걸 목표로 하겠습니다.
그러기 위해서는 먼저 HelloWorld.exe 를 디버깅하여 main() 함수내의 MessageBox() 함수 호출 코드를 찾아야 합니다.
그리고 적절히 해당 문자열 위치를 알아내어 변경시키면 되겠지요.
디버깅 시작
첨부된 HelloWorld.exe 파일을 OllyDbg.exe 로 열어보겠습니다.
* VC++ 도 소스가 있을때 어셈블리 수준의 디버깅이 가능합니다만, 일반적으로는 분석할때 소스가 없으므로 OllyDbg 같은 Win32 전문 디버거를 사용하게 됩니다.
<Fig. 2>
디버깅을 시작하기 전에 간단히 <Fig. 2> 에 보이는 OllyDbg 의 메인 화면 구성에 대해 설명드리겠습니다.
- code : 기본적으로 disassembly code 를 표시하고 각종 comment, label 을 보여주며 코드를 분석하여 loop, jump 위치 등의 정보를 표시한다.
- register : CPU register 값을 실시간으로 표시하며 특정 register 들은 수정도 가능함.
- dump : 프로세스내의 원하는 memory 주소 위치를 hex 와 ASCII 값으로 표시하고 수정도 가능함.
- stack : ESP register 가 가리키는 프로세스 stack memory 를 실시간으로 표시하고 수정도 가능함.
디버거가 멈춘 곳은 EntryPoint(EP) 코드로써 HelloWorld.exe 의 실행 시작 위치(4011A1)입니다. 일단 EP 코드에서 눈에 띄는건 CALL 명령과 그 밑의 JMP 명령입니다.
Address OP code Disassembly comment
----------------------------------------------------------------------------
004011A1 EB A6160000 CALL 0040284C ; 0040284C (40284C 주소의 함수를 호출)
004011A6 E9 A4FEFFFF JMP 0040104F ; 0040104F (40104F 주소로 점프)
- Address : 프로세스의 가상메모리(Virtual Address:VA) 내의 주소 위치
- OP code : OPeration code 의 줄임말로써 IA32(또는 x86) CPU 명령어
- Disassembly : OP code 를 보기쉽게 디스어셈 해준 코드
- comment : 디버거에서 추가한 주석 (옵션에 따라 약간씩 다르게 보임)
디스어셈 코드를 처음 보신 분들이라도 위 두줄의 코드는 그 의미가 명확합니다.
"40284C 주소의 함수를 호출(CALL)한 후 40104F 주소로 점프(JMP) 하라"
계속 디버깅을 진행해 보겠습니다.
목표는 우리가 작성한 main() 함수내의 MessageBox() 함수 호출을 확인하는 것입니다.
40284C 함수 따라가기
- Step Into [F7] : 하나의 OP code 실행 (CALL 명령을 만나면, 그 함수 코드 내부로 따라 들어감.)
- Step Over [F8] : 하나의 OP code 실행 (CALL 명령을 만나면, 따라 들어가지 않고 그냥 함수자체를 실행함.)
- Execute till Return [Ctrl+F9] : 함수 코드 내에서 RETN 명령어 까지 실행 (함수 탈출 목적)
F7 단축키로 함수 안으로 따라갈 수 있습니다.
<Fig. 3>
위 코드를 얼핏 보아도 Hello World! 에서는 사용된 적 없는 API 들이 호출되고 있습니다.
이곳은 분명 우리가 찾는 main() 함수가 아니겠군요.
이곳은 VC++ 에서 프로그램 실행을 위해서 추가시킨 (우리 소스코드에는 없지만) VC++ stub code 입니다. (각 컴파일러 종류/버전별로 stub code 는 틀려집니다.)
지금은 신경쓰지 말고 우리의 목표 main() 을 찾아 계속 진행해 보겠습니다.
* 주의사항 : 처음에는 Win32 API 함수들(OllyDbg 의 comment 상에서 빨간색 API 함수 호출 부분)은 따라가지 마세요. 너무 헤멜 수 있습니다. Step over[F8] 로 넘어가세요.
4028E1 주소에 RETN 명령어가 있습니다.
(RETN 은 함수의 끝을 나타내며 함수가 호출된 명령어 바로 다음 명령어로 되돌아 갑니다.)
그곳까지 Step over [F8] 하시거나 또는 Execute till Return [Ctrl+F9]로 한방에 가봅니다.
그리고 RETN 명령어를 실행하면[F7/F8] <Fig. 2> 에서 봤던 4011A6 주소로 오게됩니다.
(C 언어에서 함수를 호출하고 리턴하면 그 다음 명령어로 오는 것을 생각하시면 됩니다.)
40104F 따라가기
4011A6 주소의 JMP 0040104F 명령을 실행해서 40104F 로 갑니다.
<Fig. 4>
<Fig. 5>
<Fig. 6>
'analysis' 카테고리의 다른 글
HxD.exe 프로세스에 새로운 기능 추가 (2) (17) | 2012.07.14 |
---|---|
HxD.exe 프로세스에 새로운 기능 추가 (1) (2) | 2012.06.23 |
"Hello World!" - 내 생애 첫 디버깅 (3) (42) | 2009.02.28 |
"Hello World!" - 내 생애 첫 디버깅 (2) (21) | 2009.02.28 |
"Hello World!" - 내 생애 첫 디버깅 (1) (68) | 2009.02.26 |
- 이전 댓글 더보기
-
-
-
reversecore 2011.02.28 15:44 신고
안녕하세요.
GDB 코드를 보면 스택 프레임도 생성되어 있는데,
디스어셈 표현 방식이 OllyDbg 와는 좀 틀려 보입니다.
push 로 stack 에 넣어도 되지만 [ESP+X] 형식으로 넣어도 함수 입장에서 보면 파라미터 입니다.
보통 VC++ 에서는 PUSH 로 파라미터를 전달합니다.
혹시 어떤 컴파일러를 쓰셨는지요?
감사합니다.
-
-
TeamKhan 2011.03.02 16:53
안녕하세요 질문이잇어서 이렇게 댓글을 남기게되는데요
베이스캠프부터 시작해서 코드를 분석하라고하시는데
어떻게분석을하라는거죠??그냥 막막하기만한데요...;
이부분을 분석해보라고하시는의도를 잘모르겟내요...
글에서는 stub code를 눈에 익혀두면 다음에 디버깅할떄 뛰어넘을수잇다고
하시는데 왜 뛰어넘는건지??그리고 어떻게 눈에 익혀야되는지 잘모르겟내요...-
reversecore 2011.03.10 10:53 신고
안녕하세요.
Stares 님, 답변 감사드려요~ 너무 잘 설명해 주셨네요~ ^^
그리고 눈에 익히는 법은요... 간단합니다...
눈에 익을 때까지 계속 보는 겁니다.
누구도 예외 없죠. 지름길은 없어요.
꾸준히 계속 디버깅을 하다보면 실력이 쌓이는 겁니다.
그런면에서 리버싱은 시간 투자한 만큼 실력이 늘어나는 참 정직한 분야인것 같아요.
감사합니다.
-
수미르 2011.03.10 15:10
리버싱 제대로 공부 해 볼려고 합니다.
시중에 책도 나와 있지만, 여기 설명이 저한테는 더 와 닿네요.
감사한 마음으로 강의 잘 보겠습니다. -
reverse 2011.03.10 21:02
디버깅 모드로 생성된 파일을 열면 ollydbg로 열게되면
Module 'HelloWorld' has entry point outside the code (as specified in the PE header). Maybe this file is self-extracting or self-modifying. Please keep it in mind when setting breakpoints!
이러한 오류가 나는데,, 뭐 때문에 그러는건가요??
릴리스 모드로 생성된 실행파일은 아무 에러 없이 되네요..-
reversecore 2011.03.16 23:11 신고
안녕하세요.
OllyDbg 는 파일을 로딩하고 자체적으로 스캔을 쭉~ 합니다. 그때 EP(EntryPoint) 가 첫번째 코드섹션(".text" 또는 ".CODE")의 바깥쪽에 있다면 저런 에러메시지를 출력합니다.
하지만 디버그 모드라고 해서 EP 가 코드섹션을 벗어나지는 않을 텐데요~ PEView 나 OllyDbg 에서 직접 확인 해보시기 바랍니다.
감사합니다.
-
-
reversing 2011.04.20 19:10
올리디버그의 dump window 칸엔 원하는 메모리에 있는 아스키값이나 유니코드값으로 나타나 있다고 하셨는데,저기엔 코드영역메모리와 데이터영역메모리(문자열 같은것)모두 들어있나요?
/아니면 저곳에 모든 섹션영역의 메모리주소가 다 들어있고 ctrl+G 로 원하는 메모리로 간다는 뜻??? -
처음인데... 2011.11.09 09:39
처음이라서 하나도 모르겠는데 뭘 공부해야 이걸 이해할 수 있죠?
영어로 적어 논게 무슨 말인지 하나도 모르겠네요... -
tjdrua74 2012.04.03 15:06
좋은강좌 잘 봣습니당
이제 막 리버싱배우는데
리버싱책보면서 같이보면 이해가 더 잘 되겠네여
아 그리고 보면서 질문이 생겼어요
전 집에서 visual c++2010 쓰는데 주소값출력되는게 다른가요??-
reversecore 2012.06.14 01:27 신고
안녕하세요.
빌드/실행 환경에 따라서 주소값이 약간씩 변할 수 있습니다.
본문에 첨부된 실행 파일을 사용하시면 보시기 편하실 것입니다.
감사합니다.
-
-
-
wlfanswk 2013.02.03 21:32
베이스캠프의 선정 기준은 뭔가요?
책보면서 무작정 따라서 해보고 있는데 나중에 다른 프로그램들도 분석할 때 베이스캠프를 정해서 해야할 텐데 어떠한 기준으로 베이스캠프를 지정해야 할지 잘 모르겠습니다.-
reversecore 2013.02.08 17:19 신고
안녕하세요.
좋은 질문입니다. ^^
약간 개인마다 차이가 있고 각자의 노하우가 필요한데요...
그 부분을 통과하지 못하면 더 이상 진행할 수 없고...
그곳까지 가는길이 단순 반복적이라면...
그런 곳이 바로 베이스 캠프를 차리기에 적합한 곳이라 할 수 있습니다.
제 경우에는 주로 디코딩 루프 전/후, 안티디버깅 코드 전/후, 동적으로 어떤 값이 변경되는 코드 등에 베이스 캠프를 차립니다.
주로 PE Protector 같이 곳곳에 안티디버깅으로 함정을 파놓은 경우에 베이스 캠프를 차린답니다.
감사합니다.
-
-
-
reversecore 2013.02.08 17:16 신고
안녕하세요.
혹시 직접 빌드해서 디버깅 하셨나요?
Windows Vista/7 에서 Visual C++ 2008/2010/2012 등으로 빌드하면 그런 증상이 나타납니다.
첨부된 실습 예제로 다시 해보시기 바랍니다.
감사합니다.
-
-
wnrnrxla 2013.03.23 13:59
제 경우에 address부분이 4011A1 이런식으로 나오지않고
013D284E 이렇게 나오는데 왜이런건가요?
현재 윈도우 7 64bit 사용중입니다
예제를 다운받아서 했습니다-
reversecore 2013.04.01 22:16 신고
아, 문제를 해결 하셨군요.
Vista/7/8 OS 의 ASLR 기능 때문인데요.
XP 에서 테스트하시거나 ASLR 기능을 제거하고 테스트 하시면 됩니다.
감사합니다.