Post

[Reversing] 리버싱을 위한 도구(IDA)와 기초 알아보기!

내 아이다

리버싱(Reverse Engineering)이란?

리버싱(Reverse Engineering), 또는 역공학은 이미 완성된 프로그램이나 시스템을 분석하여 내부 구조, 동작 원리, 로직 등을 파악하는 과정을 말합니다. 말 그대로 거꾸로(Reverse) 코드를 추적하고 해석하는 작업이죠.

일반적으로 우리는 소스 코드를 작성한 뒤, 이를 컴파일하여 실행 파일을 생성합니다. 이 실행 파일은 Windows의 .exe와 같이 사용자에게 익숙한 형태로 제공되기도 하죠. 리버싱은 이 과정을 거꾸로 따라가며, 실행 파일로부터 원래의 코드 구조를 유추해내는 작업입니다.

왜 리버싱을 배워야 할까?

리버싱은 단순히 해킹 기술이 아니라, 실제로 다양한 분야에서 유용하게 사용됩니다:

  • 보안 분석 악성코드(Malware) 분석, 취약점 탐지 등에서 핵심적인 기술입니다.

  • CTF 문제 풀이 해킹 대회에서는 Reversing이라는 이름으로 별도의 카테고리가 존재할 정도로 중요하죠.

  • 프로그램 패치 및 수정 특정 프로그램의 동작을 바꾸거나, 디버깅을 통해 오류를 고치는 데 활용됩니다.

리버싱을 위한 기본 도구

리버싱을 수행하기 위해서는 실행 파일의 내부 구조를 분석할 수 있는 전문 도구들이 필요합니다. 가장 널리 사용되는 리버싱 도구들은 아래와 같습니다:

  • IDA (Interactive Disassembler)

    가장 유명한 상용 디스어셈블러 중 하나로, 정적 분석에 매우 강력한 기능을 제공합니다. 바이너리 파일을 어셈블리 코드로 변환하고 함수 흐름을 시각화할 수 있으며, IDA Pro와 무료 버전인 IDA Free가 있습니다. 초보가 사용하기에는 Free 버전 기능을 다 쓰지도 않는다는 사실.

  • Ghidra

    미국 NSA가 개발한 강력한 오픈소스 리버싱 프레임워크입니다. 디스어셈블 뿐 아니라 C 수준의 디컴파일 기능도 제공하며, 다양한 플랫폼을 지원합니다. 무료로 사용할 수 있으면서도 상용 도구에 버금가는 기능을 갖추고 있어 많은 보안 연구자들이 애용합니다.

    Ghidra에 대한 설명 추가적인 설명

  • Binary Ninja

    비교적 최근에 주목받고 있는 상용 리버싱 도구로, 직관적인 인터페이스와 빠른 분석 속도가 특징입니다. 스크립팅(특히 Python) 기능이 뛰어나며, 정적 분석과 디컴파일을 효율적으로 지원합니다. 커뮤니티 에디션도 제공됩니다. 이것도 오픈소스.

  • x64dbg

    Windows 환경에서 널리 사용되는 디버깅 도구입니다. 실행 중인 프로그램을 동적으로 분석하면서 레지스터, 메모리, 스택 등의 상태를 실시간으로 확인할 수 있어 CrackMe나 바이너리 패치 실습 등에 많이 활용됩니다.

그리고 이 중에 IDA의 사용 방법을 설명해 볼까 합니다.

IDA Free 기본 사용법

  • IDA 설치 및 실행
  • 간단한 프로그램 로드하기
  • 함수 분석 (Function window, Graph view vs Text view)
  • 문자열(Shift+F12), Imports, Exports 분석
  • 코드 흐름 따라가기 (XREF, Call, Jump 등)

IDA 설치 (신버전)

라고 하지만 처음에 들어가보면

Image

라이선스 키를 입력하는 부분이 있다. 어? 나는 이런거 없었는데?

Image

필요한 시스템 사항은 위와 같고 일단 나도 라이선스 넣어야 하는건 처음이라 하나씩 해보도록 하자.

Image

이렇게 라이센스에 이메일을 넣고 나면 라이센스 준비가 되었으니 로그인 해서 다운하란다… 아니 이런거 없었잖아요?

Image

으엑 진짜로 로그인 해야하나보다.. 바~로 귀찮으니 구글로 로그인해 들어가자.

Image

들어가면 바로 이렇게 라이선스 키가 뜨는걸 보니 잘 되었나보다.

Image

이제 설치를 위해 Download Center로 들어가면 여러 버전이 있고 뭐.. 당연히 가장 최신버전으로 설치해주자.

Image

설치 후에 이렇게 찾을 수 있으면 끝!

IDA 실행 전 여담

Image

참고로 이 프로그램의 로고는 희안하게도 사람의 초상화가 들어있는데 이 사람은 맹트농 후작부인(Françoise d’Aubigné)으로 직접 찾아보니 hey-rays 뉴스에서 그 전말을 찾을 수 있었다.

Image

말하길 원래는 컴퓨터의 작동 원리를 처음으로 설명한 사람인 에이다 러브레이스(Ada Lovelace) 의 초상화를 넣고자 했으나 마땅한 이미지를 찾지 못해 대타로 들어갔다고 한다. 그리고 좀 더 아래로 내려보면 IDA 9.0에서는 안티얼라이징 기술로 좀 더 사진을 젊게 만들었다나? 하는 이야기가 있다.


근데 가만 생각해보니 이상하네? 내 버전은 8.4.24인데 9.0버전이라니?

이거 버전이 업데이트 되면서 뭔가 바뀌었나보다 바로 확인하러 가야겠네.

Image

아이다가 두배지요


IDA 실행

Image

오 처음 실행을 하게 되면 최근에 새로운 단축키를 설정하고 있는데 새로운거 쓸래? 하고 묻는 문장이 나오네요.

뭐 한번 써보죠.

Image

익숙하고 중요하지만 읽어본 적 없는 동의서는 당연히도 I Agree를 눌러야 할 것이고.

Image

드디어! 프로그램을 시작할 수 있었습니다!

어.. 음.. 아래 몇가지 실행해본 것들은 테스트 할게 있어서 열어본 것들이라죠. 솔직히 궁금하잖어…

간단한 프로그램 구현하기

IDA에서 분석할 바이너리가 필요하니, 우리가 직접 간단한 프로그램을 하나 만들어보겠습니다. C 언어로 작성하고 컴파일한 뒤 .exe를 열어 분석해보도록 하겠습니다.

여기서 잠깐! 굳이 직접 코딩하는 이유는?

리버싱을 처음 배울 때는, 내가 어떤 코드를 짰는지 알고 있는 상태에서 그 바이너리를 분석하는 게 가장 좋습니다. 무작정 남이 만든 실행 파일을 열어보는 것보다, 내가 만든 코드가 어떤 식으로 어셈블리로 바뀌고, 함수나 문자열이 어떤 식으로 표시되는지를 확인하는 게 큰 도움이 되기 때문이죠.

예제 코드: Hello, Reversing!

1
2
3
4
5
6
#include <stdio.h>

int main() {
      printf("Hello, Reversing!\n");
      return 0;
}

이 코드를 메모장이나 VSCode 등 원하는 편집기에서 hello.c라는 이름으로 저장한 다음, 다음 명령어로 컴파일해줍니다.

윈도우에서 Visual Studio Code를 이용해 컴파일하는 방법 (MinGW, tdm-gcc 설치 기준)

gcc가 없으면 MinGW 혹은 tdm-gcc를 설치하거나 WSL/Ubuntu 환경에서 gcc를 설치해서 사용하세요.

아니면 아예 아래 나오는 Visual Studio를 사용하여도 좋습니다! 하지만 저는 vsc가 가벼워서 추천 드려요.

1
gcc hello.c -o hello.exe

Image

컴파일 후 생성된 hello.exe 파일을 IDA에 로드하여 분석해보면 됩니다!

윈도우에서 Visual Studio를 이용해 컴파일하는 방법

Visual Studio는 Microsoft에서 제공하는 강력한 통합 개발 환경(IDE)으로, C/C++ 개발에 최적화된 환경을 제공합니다. Visual Studio를 이용하면 편리하게 C 프로그램을 작성하고 디버깅할 수 있어 리버싱 학습에도 도움이 됩니다.

  1. Visual Studio 2022 설치

    Visual Studio는 공식 다운로드 페이지에서 받을 수 있습니다.

    설치 시 “C++를 사용한 데스크톱 개발” 워크로드를 꼭 선택해주세요. 그래야 C 프로젝트를 만들 수 있습니다.

  2. 프로젝트 생성

    • Visual Studio를 실행한 뒤, 새 프로젝트 만들기빈 프로젝트(Empty Project)를 선택합니다.
    • 프로젝트 이름은 HelloReversing 같은 걸로 해도 좋습니다.
    • 생성 후, 솔루션 탐색기에서 소스 파일(Source Files) 항목을 마우스 우클릭 → 추가새 항목을 클릭하여 hello.c 파일을 추가합니다.
  3. 코드 작성

    1
    2
    3
    4
    5
    6
    
    #include <stdio.h>
    
    int main() {
       printf("Hello, Reversing!\n");
       return 0;
    }
    

    위 코드를 작성한 뒤 저장합니다.

  4. 컴파일 및 실행 파일(.exe) 생성

    • 상단 메뉴에서 디버그디버깅 없이 시작(Ctrl+F5)을 눌러 실행해보세요.
    • 빌드가 정상적으로 완료되면, 프로젝트의 Debug 혹은 Release 폴더 안에 HelloReversing.exe 파일이 생성됩니다.
    • 이 파일을 IDA로 불러와 분석해볼 수 있습니다!

참고: .exe 파일의 경로는 보통 프로젝트 폴더\Debug\HelloReversing.exe 혹은 Release 폴더에 위치합니다.

Image

이렇게 만들고 실행을 한 번 한 후에 우측 프로젝트(여기서는 HelloReversingVS)를 우클릭 하여 파일 탐색기에서 폴더 열기(x)를 누르면

Image

이렇게 프로젝트 폴더에 들어오게 될 텐데 여기서 생각해야하는것!

우리가 만든 프로젝트는 지금 이 폴더가 아니라 그 상위 폴더의 이름이 같지만 그곳에 위치한다는 사실!

Image

이 위치(HelloReversingVS/HelloReversingVS)에서 .exe를 찾아가보면 찾을 수 없다.

Image

바로 이렇게 저장한 폴더/프로젝트명/x64폴더 안에 있기 때문이다.

Image

찾았다!

VSC + GCC vs Visual Studio: 어떤 차이가 있을까?

같은 C 코드를 작성하더라도, 어떤 컴파일러를 사용하느냐에 따라 결과물인 .exe 파일은 꽤 다른 모습을 보이게 됩니다. 보기에는 완전 같은 모습으로 작동하는 것 처럼 보이지만 실제로는 용량도 내용도 다르답니다. 리버싱을 할 때 이 차이를 이해하고 있는 건 정말 중요합니다. 그리고 솔직히 처음 배우는데 복잡하면 좀 그렇잖아요?

1. 사용하는 컴파일러의 종류

  • VSC + GCC

    • 여기서 사용하는 gcc는 GNU 컴파일러입니다.
    • 보통 MinGWtdm-gcc를 설치해서 사용하며, 리눅스에서 쓰이는 gcc와 거의 동일한 결과를 내놓습니다.
    • 출력물은 간결하고, 리눅스 환경과 유사한 바이너리를 만들어 줍니다.
  • Visual Studio

    • Microsoft에서 만든 MSVC(Microsoft Visual C++) 컴파일러를 사용합니다.
    • Windows에 최적화된 실행 파일을 생성하며, 자체 런타임 라이브러리를 연동합니다.
    • 컴파일 옵션이나 디버깅 정보도 더 풍부하게 붙는 경우가 많습니다.

2. 실행 파일 내부 구조의 차이

  • gcc로 컴파일한 hello.exe

    • 구조가 상대적으로 단순하며, 불필요한 부가 정보가 적습니다.
    • 함수명이나 문자열이 비교적 명확하게 보일 수 있습니다.
    • 리버싱 연습을 처음 시작할 때 추천되는 형태입니다.
  • vs로 컴파일한 hello.exe

    • MSVC 런타임 관련 코드가 포함되어 있어 실행 파일 크기가 크고, 내부 구조가 더 복잡해 보입니다.
    • 시작점(main)으로 진입하기까지 다양한 초기화 함수들이 호출되며, 초보자에게는 다소 혼란스러울 수 있습니다.
    • 함수 호출 규약, 명명 방식 등이 gcc와는 다릅니다.

3. 리버싱 관점에서의 고려사항

항목GCC (MinGW 등)Visual Studio (MSVC)
파일 크기작음상대적으로 큼
실행 흐름단순복잡 (CRT 초기화 등)
디버깅 심플함비교적 쉬움초기에는 어렵게 느껴질 수 있음
함수명/심볼제한적디버그 빌드 시 풍부하게 남기도 함
시작 주소main 바로 근처_mainCRTStartup 등 다양한 함수들 거쳐야 함

어라? 그런데 크기 차이가 위에서 말한거랑 다른데요?

Image

엇 그런데 위를 따라서 코드를 만들어 보니까 이상하게도 오히려 Visual Studio로 만든 실행파일이 더 작은 상황을 볼 수 있다. 이 아래 나올 내용은 어쩌면 조금 이른 내용일 수도 있으므로 잘 이해가 안된다면 넘기고 나중에 찾아와도 문제 없다.

그..래도.. 언젠가는 마주해야하는 내용이니 한번 눈으로만 쓱 읽어보는것도?

1. 링크 방식 (Static vs Dynamic Linking)

  • GCC (기본 설정) 기본적으로 libgcc, libc, 기타 런타임을 정적으로 링크합니다. → 필요한 라이브러리 코드가 바이너리에 통째로 포함됨. → 그래서 파일 크기가 크게 나옴.

  • MSVC (Visual Studio) 기본 설정은 동적 링크(DLL) 사용. → msvcrt.dll 같은 시스템(윈도우) DLL을 참조만 하고, 실제 코드 포함 X → 바이너리 크기 작게 나옴.


2. 기본 설정의 차이 (Debug Info 포함 여부)

  • GCC는 디버그 정보 (-g)가 자동 포함되거나, 별도로 제거하지 않으면 들어가는 경우가 많음.
  • MSVC는 릴리스 모드일 경우 디버그 정보 없이, 최적화된 코드를 내보냄.

만약 GCC로 -s 옵션(심볼 제거)이나 -O2(기본 최적화) -s 같이 최적화하고 심볼 제거하면 파일 크기가 줄어듭니다.

3. 런타임 라이브러리 포함 여부

  • GCC는 MinGW나 TDM-GCC의 런타임 라이브러리를 바이너리에 붙이는 경향이 강함.
  • MSVC는 Visual C++ Redistributable을 깔아놓은 시스템이 많기 때문에 DLL 링크로 처리하는 게 일반적.

비교 예시

환경예상 크기설명
GCC 기본 컴파일수백 KB정적 링크 + 디버그 심볼 포함
GCC -s -O2수십 KB최적화 + 디버깅 정보 제거
Visual Studio 릴리즈수십 KB동적 링크 + 최적화
Visual Studio 디버그 모드수백 KB디버그 심볼 포함됨

Image

직접 비교를 해보기 위해 위와같이 종류별로 다 컴파일을 해봤습니다!

이렇게 보니 어째서 같은 코드인데 용량 차이가 나는지 어느정도 이해가 되죠?

이제 여기서 디버깅 정보는 또 무엇이고 디버그 심볼은 뭐지? 싶을 수 있습니다.

솔직히 저도 이거 찾아보면서 차이를 알았거든요..

용어설명
디버그 심볼 (Debug Symbols)변수 이름, 함수 이름, 소스 코드 라인 정보 등 소스 코드와 바이너리를 연결해주는 심볼.
디버깅 정보 (Debugging Information)디버그 심볼을 포함해 디버깅에 필요한 모든 메타데이터. 예: 심볼, 스택 정보, 최적화 무효화 등.

조금 더 풀어서 이야기 해보자면 다음과 같습니다.

  • 디버그 심볼은 책의 목차페이지 번호 같은 역할:

    “함수 main은 0x401000에 있음”, “변수 x는 이 위치에 있음”

  • 디버깅 정보는 그에 더해 읽기 편하게 메모가 달린 책 전체

    어떤 줄에서 예외가 발생했는지, 최적화가 꺼졌는지 등 더 풍부한 정보 포함

즉! 디버그 심볼은 디버깅 정보의 일부라는 의미인거죠.

이제 실제로 IDA에서 컴파일한 PE(Portable Executable) 또는 .exe를 직접 열어 정말로 우리가 짠 코드가 잘 들어있는지 디버그 심볼이 리버싱을 할 때 어떤 역할을 해줄지 눈으로 확인하러 갑시다!

IDA에서 열어보기

Image

이렇게 IDA를 실행시키고 New 혹은 Go를 눌러 IDA에 들어갈 수 있다.

New는 들어가서 바로 파일탐색기가 열리기에 Go를 눌러 들어간 후에 뜯어볼 PE파일을 드래그하여 여는 것을 선호한다.

Image

필자는 아무래도 컴퓨터를 다크모드로 사용하다보니 IDA의 화면도 그를 따라가는데 기본적으로는 밝은 화면이 반겨줄 것이다.

Image

바로 이렇게

Image

다시 돌아와 프로그램을 드래그 하여 넣으면 위와 같이 수많은 옵션이 뜨는 창을 만나게 될 것이다.

Image

좀 더 크게 보면 이런 느낌인데 위에서 부터 알아보자.

1. Load file … as

  • Portable executable for AMD64 (PE) [pe.dll]

이건 IDA가 자동으로 감지한 파일 포맷입니다. 여기서:

  • Portable executable (PE) → 윈도우 실행 파일 포맷
  • AMD64 → 64비트 아키텍처 (x86-64 기반)
  • [pe.dll] → PE 파일 로딩에 사용하는 IDA 내부 모듈 이름

즉, 이건 “64비트 윈도우 실행 파일로 감지됨“을 의미합니다.


2. Processor type

  • 선택된 값: MetaPC (disassemble all opcodes)metapc

이건 IDA가 어떤 CPU 명령어 세트를 기준으로 해석할지 고르는 부분입니다. metapcx86 및 x64 아키텍처 전용 디스어셈블러로, 거의 모든 일반적인 PE 파일은 이걸로 분석합니다.


3. Loading segment / Loading offset

  • 일반적으로 기본값 0x0000000000000000을 둡니다.
  • 특별한 경우가 아니면 수정할 필요 없습니다. 이건 바이너리를 어느 메모리 주소에 매핑할지 결정하는데, IDA가 PE 헤더 기반으로 자동 설정합니다.

요건 좀 어려운 말이라 넘겨도 무방하다. 하지만 리버싱을 공부하며 책을 한권이라도 살짝 읽어본 사람이라면 바로 이해 가능!


4. Analysis

  • ✔ Enabled

    • IDA가 자동으로 코드 분석 및 함수 추출을 수행합니다. 필수!
  • ✔ Indicator enabled

    • 분석 진행 상태를 보여주는 상단 진행 표시줄(초록색 줄)을 켭니다. 가시성이 좋아서 보통 체크합니다.

5. Options

아래 체크박스들은 분석 결과에 영향을 줍니다:

옵션설명
✔ Create segmentsPE 헤더의 세그먼트(.text, .data 등)를 IDA 세그먼트로 생성
✔ Create imports segmentimport table을 분리된 영역으로 보여줌
✔ Load resourcesPE 내부 리소스 (아이콘, 문자열 등)을 불러옴
✔ Rename DLL entriesAPI 호출 함수 이름을 자동으로 이름 붙임 (예: MessageBoxA)
✔ Create FLAT group세그먼트를 그룹으로 묶어 보여주는 IDA 내부 설정
☐ Manual load직접 수동으로 로드 주소/세그먼트를 지정할 수 있게 함 (고급자용)
☐ Load as code segment바이너리를 무조건 코드로 해석 (보통 체크 안함)
☐ Fill segment gaps세그먼트 간 빈 공간을 채움 (보통 체크 안함)

이 화면은 “이 파일을 어떤 구조로, 어떤 CPU 아키텍처로 해석할지”를 IDA에 알려주는 매우 중요한 단계입니다.

그리고 보통의 경우에는 딱히 건드릴게 없이 진행하면 됩니다.

Image

OK를 누르고 진행하면 이번에도 또 뭔가 뜬다.

이 창은 IDA가 DWARF 디버깅 정보를 감지했을 때 나오는 옵션 창으로 DWARF란 디버깅 정보를 위한 표준 포맷으로, 변수 이름, 타입, 함수 위치, 소스 코드 라인 정보 등을 포함한다.

라고 한다만.. 요 부분은 내가 아는 부분이 없기도 하고 딱히 다들 바꾸거나 하지는 않아서 초보자에게는 그냥 넘어가는 부분인걸로!

그리고 위의 디버깅 정보관련 글을 읽고 내려왔다면 어느정도 예상을 할 수 있겠지만 디버깅 정보를 제외한 PE(.exe)파일은 이 창이 뜨지 않는다!

Image

모두 OK를 누르고 더이상 창이 뜨지 않으며 프로그램을 로드 했을 때에는 위와 같은 알 수 없는 것들이 많이 보인다.

음… 이거 색을 다시 밝은걸로 바꾸는게 보기에는 더 편해 보이네..

Image

Image

아닌가? 일단 여기 글을 쓸 때는 밝은 버전으로 쓰고 내가 쓸 때는 어두운 버전으로 사용해야겠다.

IDA 기본 화면

Image

지금 보이는 이 화면이 우리가 만든 helloReversing.exe의 실제 .exe속 내용물인 것이다.

정말 간단한 5~6줄밖에 되지 않는 코드였는데, 왼쪽의 Functions 창에는 뭔가 엄청 많은 함수가 포함되어 있다.

왜 이렇게 많은 함수가 있을까?

이는 우리가 작성한 코드 외에도, 컴파일러(GCC나 MSVC 등)가 자동으로 삽입한 라이브러리 코드나 런타임 초기화 코드들이 함께 포함되어 있기 때문이다.

예를 들어:

  • __security_init_cookie
  • __scrt_common_main
  • msvcrt.dll의 함수들
  • 내부적으로 필요한 초기화 함수들 등등…

이런 함수들은 우리가 직접 작성하지 않았더라도, 프로그램을 실행할 수 있게 만드는 최소한의 준비 작업을 위해 포함된다.

예를 들어 printf("Hello"); 한 줄만 써도, 이 코드가 작동하려면 printf 함수 자체와, 그 함수가 내부적으로 호출하는 여러 함수들까지 함께 필요하다. 그래서 실제 컴파일된 .exe 안에는 우리가 쓰지 않은 것처럼 보이는 함수들까지 같이 들어가는 것이다.

화면 구성 간단 요약

영역설명
왼쪽 상단 (Functions)디스어셈블된 함수 목록. 우리가 작성한 코드뿐만 아니라 컴파일러가 추가한 라이브러리 함수도 포함됨.
중앙 (IDA View / Disassembly)선택한 함수의 기계어(어셈블리) 코드가 분석되어 보이는 영역. 기본적으로 Pseudocode(C코드) 대신 어셈블리 기준.
하단 (Output, Log, Problems 등)분석 과정 중 로그, 경고 메시지, 분석 힌트 등을 볼 수 있는 창들.

여기부터 아직 작성하는 중

작성중././././//./. 일단 오늘은 여기까지

실습: 간단한 CrackMe 분석 (작성중)

This post is licensed under CC BY 4.0 by the author.