원하는 코드를 빨리 찾아내는 4가지 방법

자신이 원하는 코드를 빨리 찾아내기 위해서는 여러가지 자신만의 노하우가 있습니다.
여기서는 가장 기본이 되면서 가장 유용한 4가지 방법을 소개합니다.

  • 코드 실행 방법
  • 문자열 검색 방법
  • API 검색 방법 (1) - 호출 코드에 BP
  • API 검색 방법 (2) - API 코드에 직접 BP


0) 이미 아는 사실

4가지 방법을 소개하기 전에 먼저 한번 생각을 해봅시다.

우리는 HelloWorld.exe 프로그램이 "Hello World!" 메시지 박스를 출력한다는 것을 이미 알고 있습니다.
물론 우리가 코드를 만들었기 때문이지만, 이 경우에는 그냥 실행만 해봐도 누구나 알 수 있는 것입니다.

C 언어 개발자들이라면 MessageBox 계열 함수가 머릿속에 떠오를 것입니다.

이렇게 프로그램의 기능이 명확한 경우는 그냥 실행만 해봐도 내부 구조를 대략적으로 추측할 수 있습니다.
(물론 개발/분석 경험이 요구됩니다.)



1) 코드 실행 방법

우리가 원하는 코드main() 함수내의 MessageBox() 함수 호출 코드 입니다.
OllyDbg 디버거로 HelloWorld.exe 를 디버깅하면 어느 순간 자동으로 메시지 박스를 띄워 주는데요,
디버깅을 해나가다 보면 언젠가 main() 함수내의 MessageBox() 함수가 실행되어 "Hello World!"  메시지박스가 출력되겠지요?

이것이 코드 실행 방법의 원리입니다.
기능이 명확한 경우에 소스 코드를 실행해 가면서 찾아가는 것입니다.
코드 크기가 작고 기능이 명확한 경우에 사용할 수 있습니다.
코드 크기가 크고 복잡한 경우에는 적절하지 않습니다.

OllyDbg 와 콘솔 윈도우를 적절한 크기로 조정하여 동시에 살펴 볼 수 있도록 하세요.

베이스 캠프(40104F)에서부터 명령어를 한줄한줄 실행[F8]해 봅니다.
어느 순간 "Hello World!" 메시지 박스가 출력 되어 있을 것입니다.
몇 번 반복해 보시면 특정 함수를 호출 한 이후에 메시지 박스가 나타나는 것을 파악할 수 있습니다.

바로 그 함수가 main() 함수입니다.


<Fig. 7>

즉 <Fig. 7> 의 401145 주소에 있는 CALL 명령어가 호출하는 주소 401000 로 가보면 [F7]
그곳이 바로 우리가 찾는 main() 함수 코드 영역입니다.


<Fig. 8>

"Hello World!" 문자열과 MessageBoxW() 함수 호출 코드가 보이시죠?
정확히 찾아왔습니다.

* VC++ 2008 Express Edition 을 사용하면 기본 문자열은 UNICODE 가 되고,
   문자열 처리 API 함수들도 전부 W(ide) character 계열의 함수로 변경됩니다.




2) 문자열 검색 방법

All referenced text strings : 마우스 우측 메뉴 -> Search for -> All referenced text strings

C 언어를 처음 배울때 문자열은 코드와 다른 영역에 저장된다라고 배웠습니다.
즉, 어딘가에 "Hello World!" 문자열이 저장되어 있을꺼란 얘기입니다.

프로그램내의 문자열을 확인할 수 있는 여러가지 방법이 있습니다만 여기서는 OllyDbg 기능을 설명드리겠습니다.

OllyDbg 가 디버깅할 프로그램을 로딩할 때 나름대로 분석과정을 거치게 되는데요,
코드를 좍~ 훑어서 참조되는 문자열호출되는 API 들을 뽑아내서 따로 목록으로 정리를 해놓습니다.

'All referenced text strings' 명령을 사용하면 아래와 같은 윈도우가 뜨면서 코드에서 참조되는 문자열들을 보여줍니다.


<Fig. 9>

OllyDbg 는 "401007 주소의 PUSH 004092A4 명령이 있는데, 이 명령에서 참조되는 4092A4 주소에는 'Hello World!' 문자열이 존재합니다." 라고 말하고 있는 것이죠.

문자열을 더블 클릭하면 main() 함수의 MessageBoxW() 호출 코드로 갈 수 있습니다.

참고로 메모리상에 있는 문자열의 확인을 위하여 OllyDbg 덤프 윈도우에서 Go to[Ctrl+G] 명령을 써보겠습니다.
(포커스를 덤프 윈도우에 놓고 단축키 명령 [Ctrl+G] 을 내려주세요.)


<Fig. 10>

"Hello World!\n" 문자열과 그 뒤의 NULL 들이 보이시죠?
(VC++ 2008 에서는 static 문자열을 UNICODE 로 저장한다고 아까 설명하였습니다.)
 
"Hello World!" 문자열 대신 "Reversing!" 문자열을 쓸 수 있는 공간이 충분히 존재하는군요.
(우리의 목표를 기억하시죠? 문자열을 패치시킬 것입니다.)

또 한가지 중요한 내용은 4092A4 라는 주소입니다.
지금까지 본 코드의 주소 401XXX 와는 다른 영역입니다.
HelloWorld.exe 프로세스에서 409XXX 주소는 프로그램에서 사용되는 데이타가 저장되는 영역입니다.

코드와 데이타가 파일에서 어떻게 저장되고 메모리에 어떻게 올라가는지
원리를 자세히 배우려면 PE header 를 공부해야 합니다.
(PE header 는 처음에 설명할 내용이 너무 많아서 나중에 따로 정리하여 올리도록 하겠습니다.)



3) API 검색 방법 (1) - 호출 코드에 BP

All intermodular calls : 마우스 우측 메뉴 -> Search for -> All intermodular calls

Windows 프로그래밍에서 모니터 화면(hardware)에 뭔가를 출력하려면
어쩔 수 없이 Win32 API 를 사용하여 OS 에게 화면출력을 요청해야 합니다.

즉, 프로그램이 화면에 뭔가를 출력했다는 얘기는 프로그램 내부에서 Win32 API 를 사용하였다는 뜻입니다.

그렇다면 프로그램의 기능을 보고 사용되었을법한 Win32 API 호출을 예상하고,
그 부분을 찾을 수 있다면 디버깅이 매우 간편해 질 것입니다.

OllyDbg 에는 디버깅 시작전에 미리 코드를 분석하여 사용되는 API 함수 목록을 뽑아내는 기능이 있습니다.

코드에서 사용된 API 호출 목록만 보고 싶을때는 'All intermodular calls' 명령을 사용하면 됩니다.
아래와 같이 프로그램에서 사용되는 API 함수 호출 목록이 나타납니다.
(OllyDbg 옵션에 따라서 표시되는 모양이 약간 틀려질 수 있습니다.)


<Fig. 11>

<Fig. 11> 에 MessageBoxW 호출 코드가 보이시죠?
역시 더블클릭으로 해당 주소(40100E) 로 갈 수 있습니다.

이런 식으로 코드에서 사용된 API 를 예상할 수 있을때 이 방법을 사용하면 쉽게 원하는 부분을 찾아낼 수 있습니다.

* OllyDbg 가 어떻게 호출되는 API의 이름을 정확히 뽑아올 수 있을까요?
  소스코드를 보고 있는것도 아닌데요.
  이 원리를 이해하기 위해서는 역시 PE header 의 IAT(Import Address Table) 구조를 이해해야 합니다.
  (나중에 따로 설명 하겠습니다.)



4) API 검색 방법 (2) - API 코드에 직접 BP

Name in all modules : 마우스 우측 메뉴 -> Search for -> Name in all modules

모든 실행 파일에 대해서 OllyDbg 가 API 함수 호출 목록을 추출할 수 있는것은 아닙니다.
Packer/Protector 를 사용하여 실행파일을 압축 또는 보호해 버리면,
IAT 구조가 변경되거나 OllyDbg 에서 보이지 않게 됩니다. (심지어는 디버깅 자체가 매우 어려워 집니다.)
* Packer(Run Time Packer)
  실행압축 유틸리티. 실행파일의 코드, 데이타, 리소스 등을 압축시켜 버립니다.
  일반 압축 파일과 다른 점은 실행 압축된 파일 그 자체도 실행파일 이라는 것입니다.
  (나중에 대표적인 packer 를 분석해 보도록 하겠습니다.)

* Protector 
  실행압축 기능외에 파일과 그 프로세스를 보호하려는 목적으로
  anti-debugging, anti-emulating, anti-dump 등의 기능을 추가한 유틸리티 입니다.
  Protector 를 상세 분석하려면 높은 분석 지식이 요구됩니다.
  (굉장히 고급 주제이고 너무 재밌는 내용입니다. 나중에 상세히 분석 해보겠습니다.)


이런 경우에는 프로세스 메모리에 로딩된 DLL 코드에 직접 BP 를 걸어 보는 겁니다.

API 라는 것은 OS 에서 제공한 함수이고, 실제로 API 코드는 %system32% 폴더에 *.dll 파일 내부에 구현되어 있습니다.
(kernel32.dll, user32.dll, gdi32.dll, advapi32.dll, ws2_32.dll 등입니다.)

간단히 말해서 우리가 만든 프로그램이 어떤 의미 있는 일(각종 I/O)을 하려면
반드시 OS 에서 제공된 API 를 사용해서 OS 에게 요청해야 하고,
그 API 가 실제 구현된 시스템 DLL 파일들은 우리 프로그램의 프로세스 메모리에 로딩(정확히는 매핑)되어야 합니다.

OllyDbg 에서 확인해 볼까요. View – Memory 메뉴를 선택해 주세요. (단축키 [Alt+M])


<Fig. 12>

<Fig. 12> 는 HelloWorld.exe 프로세스 메모리의 일부분을 보여주고 있습니다.
빨간색으로 표시된 부분이 바로 시스템 DLL 들이 로딩된 메모리 영역입니다.

* 참고로 MessageBoxW() API 는 USER32.DLL 에 속해 있습니다.

OllyDbg 의 또 다른 기본 해석 기능은 프로세스 실행을 위해서
같이 로딩된 시스템 DLL 파일이 제공하는 모든 API 목록을 보여주는 것입니다.

'Name in all modules' 명령을 사용해 보겠습니다.
나타나는 윈도우에서 'Name' 정렬시키고, MessageBoxW 를 타이핑 하면 자동 검색됩니다.


<Fig. 13>

USER32 모듈에서 Export type 의 MessageBoxW 함수를 선택하세요.
(시스템 환경에 따라 버전이 틀려질 수 있습니다.)

더블 클릭 하시면 아래와 같이 USER32.dll 에 구현된 실제 MessageBoxW 함수가 나타납니다.


<Fig. 14>

주소를 보시면 HelloWorld.exe 에서 사용되는 주소와 확연히 틀리다는걸 아실 수 있습니다.

이곳에 BP 를 설치[F2]하고 실행[F9]해 보겠습니다.

만약 HelloWorld.exe 프로그램에서 MessageBoxW 함수를 호출한다면 결국 이곳에서 실행이 멈추게 될 것입니다.
(간단한 원리 입니다.)


<Fig. 15>


예상대로 MessageBoxW 코드 시작에 설치한 BP 에서 실행이 멈췄습니다.

레지스터(Register) 윈도우의 ESP 값이 12FF68 인데, 이것은 프로세스 스택(Stack)의 주소입니다.

스택 윈도우에서 빨간색으로 표시된 부분을 아래에 자세히 표시했습니다.

Stack
address     Value       Comment
-----------------------------------------------------------------------
0012FF68    00401014    CALL to MessageBoxW from HelloWor.0040100E
                        => MessageBoxW 는 40100E주소에서 호출되었으며,
                                             함수 실행이 종료되면 복귀주소는 401014 이다.

0012FF6C    00000000    hOwner = NULL
0012FF70    004092A4    Text = "Hello World!"
0012FF74    0040927C    Title = "www.reversecore.com"
0012FF78    00000000    Style = MB_OK|MB_APPLMODAL


* 함수 호출과 스택의 동작 원리등은 나중에 "Stack Frame" 설명할 때 더 자세히 보도록 하겠습니다.

ESP 의 값 12FF68 에 있는 복귀 주소 401014 는
HelloWorld.exe 의 main 함수내의 MessageBoxW 함수 호출 바로 다음의 코드입니다.

간단히 MessageBoxW 함수의 RETN 명령까지 실행[Ctrl+F9]한 다음,
RETN 명령도 실행[F7]하면 복귀주소 401014 로 갈 수 있습니다.

바로 위에 MessageBoxW  함수 호출 코드가 있는 것을 확인할 수 있습니다. (<Fig. 8> 참고)

(continue)

  1. 베리굿 2009.11.07 22:49 신고 댓글주소 | 수정 | 삭제 | 댓글

    감사합니다.

  2. 아르가페 2011.03.02 17:33 신고 댓글주소 | 수정 | 삭제 | 댓글

    잘보고 갑니다.

  3. 2011.04.20 19:19 댓글주소 | 수정 | 삭제 | 댓글

    비밀댓글입니다

    • reversecore 2011.04.28 21:01 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      OllyDbg 의 분석이라고 하시면...

      올리로 파일을 열었을때 진행되는 간단 분석작업을 말씀하시는 것이지요? 그 작업은 코드의 구조를 살피는 것이기 때문에 데이터 메모리 영역은 해당되지 않습니다.

      감사합니다.

  4. 겸이 2012.04.03 20:53 신고 댓글주소 | 수정 | 삭제 | 댓글

    C언어에서도 messagebox()가 있엇나요???

  5. taso 2012.07.05 08:04 신고 댓글주소 | 수정 | 삭제 | 댓글

    호출되는 API함수이름을 olydbg가 알아내는 건, IID의 INT를 참조하는 거겠네요 ㅇ..

  6. 2012.08.19 17:54 댓글주소 | 수정 | 삭제 | 댓글

    비밀댓글입니다

  7. HackPlum 2012.10.17 00:28 신고 댓글주소 | 수정 | 삭제 | 댓글

    아.. ㅠㅠ 너무 어렵네요 ㅠㅠ
    책을 보면서 하고있는데
    블로그에 나와있는 내용이랑은 약간 다른 부분도 있군요.

    • reversecore 2012.10.17 01:11 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      블로그 내용과는 약간 다릅니다.

      공부에 어려움을 느끼시는 것 같은데요.
      제가 도와드릴 수 있는게 있을 지도 모르니, 주저 마시고 질문 해주세요~

      감사합니다.

  8. HackPlum 2012.10.18 10:08 신고 댓글주소 | 수정 | 삭제 | 댓글

    위에서 한대로 Name 을 정렬시키고 MessageBoxW 를 검색했더니
    이상한 다른게 뜨더라구요.. 그래서 결국 그림보고 직접 주소(77D46534)를 찾아가서 USER32.dll 에 구현된 함수를 보았습니다... ㅠㅜ

    • reversecore 2012.10.19 00:42 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      그림 11을 말씀하시는 거라면 마우스 우측 버튼 메뉴의 "Search for - All intermodular callls" 항목을 선택하시면 코드에서 MessageBoxW() API 가 사용되는 코드 주소를 얻을 수 있고요.

      만약 그림 13을 말씀하시는 거라면 마우스 우측 버튼 메뉴의 "Search for - All intermodular callls" 항목을 선택하시면 코드에서 "Name in all modules" 항목을 선택합니다. 그리고 나타나는 다이알로그에서 Name 항목으로 정렬 시킨후 MessageBoxW 를 한글자씩 타이핑합니다. 이때 Type 항목에 Export 라고 표시된 항목이 바로 찾으시는 API 코드 시작 주소입니다. (Type 이 Import 인 경우를 선택하시면 다른 주소가 나타날 수 있습니다.)

      감사합니다.

  9. 2012.11.12 18:11 댓글주소 | 수정 | 삭제 | 댓글

    비밀댓글입니다

    • reversecore 2012.11.12 23:03 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      블로그 내용(그림, 표, 소스, 글)을 퍼가시는건 자제해 주시고요.
      링크만 허용합니다~ ^^

      책의 내용을 스스로 정리/요약하는 정도는 괜찮습니다.
      그대로 옮기지만 않으시면 됩니다.

      감사합니다.

  10. 궁금이 2012.12.12 13:41 신고 댓글주소 | 수정 | 삭제 | 댓글

    그림 15에서 보이는 것 처럼
    ESP값이 12FF68인 부분까지는 진행이 되었습니다.
    그런데 맨 마지막에 "간단히 MessageBoxW함수의 RETN 명령까지 실행한 다음
    RETN 명령도 실행하면 복귀주소 401014로 갈 수 있다"고 나오는데
    그림 15상태에서 아무리 ctrl+f9, f7을 실행해도 엄한데가 나오고
    401014가 안나오는데 어떻게 해야되는지 잘 모르겠어요...

    그리고 책에서는 ESP값이 12FF68가 아니고 조금 다르던데
    책보고 따라할때는 여기 블로그 그림처럼 12FF68가 나오는데
    상관 없는거겠죠???

    좋은책 출간해 주셔서 감사합니다.. (__)

    • reversecore 2012.12.12 23:46 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      지금 보니 그 설명에 문제가 있습니다. ㅡㅡ;;;

      MessageBoxW() 는 내부적으로 MessageBoxExW() 를 호출하는데 일단 MessageBoxExW() 가 호출되면 화면에 메시지박스가 나타나면서 디버깅이 일시 정지 됩니다.

      정확한 설명은 이렇습니다.

      "MessageBoxW() 함수의 RETN 명령어에 BP 를 설치[F2]한 후 실행[F9]합니다. 도중에 메시지박스가 나타나면 [확인]을 선택합니다. 그리고 RETN 명령어에서 디버깅이 멈추면 StepInto[F7]/StepOut[F8] 명령으로 리턴 주소 401014로 갈 수 있습니다."

      좋은 지적 감사합니다.

      스택 주소가 다른 이유는 블로그와 책의 실행파일이 약간 다르고, 책의 실행 환경이 Windows 7 이어서 그런것입니다. 디버깅에는 지장이 없습니다.

      감사합니다.

  11. hj0779 2014.05.24 19:22 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.. 리버싱 공부하고있는 학생인데요 책을보고 할떄 f7로 따라가고 하는걸 몇일쨰 하고있습니다.
    처음에 시작할떄 004011A0 주소도 다르고 여러가지가 달라서 f7로 따라가는걸 잠시 멈춰둔뒤 이번 강좌를보고 했습니다 근데또 문제가 발생햇습니다.
    search for>All referenced text strings
    햇을떄 사진처럼
    00401002 PUSH Hellowor.0040927C UNICODE"www.reversecore.com"
    00401007 PUSH Hellowor.004092A4 UNICODE"Hello World!"
    처럼나와야하는데
    Disassembly 부분이
    PUSH OFFSET HelloWor.??_C@_1CI@BENPCJB.....이런식으로뜹니다..
    Text string 부분은 정상으로 나오고요..
    Disassembly 부분이 정상적으로나와서 제대로된 주소가 써있어야 문자열패치를 할수있을꺼같습니다..
    뭐가 문제일까요? 저희컴은 윈7 64비트고
    ollydbg 1.1 버전에 advancedolly.dll 플러그인까지 넣어서 문제없이되는걸로 압니다.
    ㅠㅠ 책이랑 블로그랑 겸해서 보고있는중인데 이게안뜨면 더이상못나갈꺼같아요ㅠㅠ

    • reversecore 2014.05.26 01:25 신고 댓글주소 | 수정 | 삭제

      안녕하세요. ReverseCore 입니다.

      PUSH OFFSET HelloWor.??_C@_1CI@BENPCJB 이런식이라면...
      마치 C++ 빌드후 Name Decoration 코드 같습니다.

      혹시 소스 코드를 직접 빌드 하셔서 테스트 하셨나요?
      빌드 환경과 컴파일 옵션에 따라 결과물이 달라지기 때문에,
      책과 동일한 디버깅을 하시려면 제공된 실습 예제 파일을 사용하시면 됩니다.

      www.reversecore.com/104

      * 혹시 이걸로 해결되지 않는다면 다시 질문 올려주시기 바랍니다.

      감사합니다.

  12. hj0779 2014.06.07 16:35 신고 댓글주소 | 수정 | 삭제 | 댓글

    실습 예제 파일로 하니까 됩니다 ..
    하지만 ctrl+e 해서 수정을하려고하니 글씨가 꺠저서 나오는데 어떻게 해결할수없을까요 ..
    그리고 올리디버거 시작할때 영어로you do not have administrative rights on this computer
    As a result,some debugging features may fail.
    To enable all OllyDbg features,
    please log in as administrator.
    Note:you can permanently disable this warning in options
    security긴문장으로 에러? 비슷한게 뜹니다 이거랑 연관있나여?
    필요없는거면 옵션가서 안뜨게 해도되나여 ?

    • reversecore 2014.06.08 00:08 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      문자열 에디트 할 때 글씨가 깨져서 나온다구요?
      혹시 캡쳐해서 보내주실 수 있으실까요?
      reversecore@gmail.com

      그리고 그 경고창은 아마 Win 7 의 관리자 권한 실행을 안해주셔서 나타나는것 같습니다. 문자열 깨지는 거랑은 별 연관성은 없어보입니다. 디버깅 하실 때는 관리자로 로그인 하신 후 올리디버거 아이콘에서 마우스 우측 메뉴의 '관리자 실행' 으로 해보시기 바랍니다. (디버깅 할 때만 UAC 기능을 꺼두셔도 됩니다.)

      감사합니다.

  13. hj0779 2014.06.08 13:39 신고 댓글주소 | 수정 | 삭제 | 댓글

    글자가 꺠졋던 이유가 덤프윈도우에서 컨트롤 e 를눌럿기때문이엿습니다...
    감사합니다. 열심히공부하겟습니다!





티스토리 툴바