Fascination
article thumbnail

Reversing Engineering - 5. hello-world로 배우는 x64dbg 사용법


# 프롤로그

- hello-world.cpp

// hello-world.cpp
#include <stdio.h>
void main(){
    puts("hello world!\n");
}

 

 

# x64dbg 기본 설정

- x64dbg로 hello-world.exe를 열면 아무런 설정을 안했을 경우 아래와 같이 뜸

 x64dbg 기본 설정

> 박스 부분을 살펴보면 현재 ntdll부분에 멈춰있는 것을 알 수 있음

> 이는 x64dbg가 기본적으로 시스템 중단점 설정이 켜져있기 때문

- 설정 - 환경설정으로 들어가서 아래 사진과 같은 창에서 시스템 중단점 설정을 변경해야 함

시스템 중단점 설정

> 위의 창에서 박스로 표시된 옵션을 해제하면 됨

> 이후 디버깅 프로그램을 재시작하면 시작 지점에서 멈춘 상태로 디버깅이 시작됨

 

 

# x64dbg로 main 함수 찾는 법

- 앞에서 설명한대로 설정을 하면 아래와 같이 hello-world.exe의 EntryPoint부분에서 디버깅이 시작됨

x64dbg로 main 함수 찾는 법

- 해당 부분이 hello-world.exe의 코드는 맞지만, 분석해보면 hello-world.cpp에서 작성한 main 함수의 내용은 아님

  > 프로그램의 main 함수를 바로 실행하는 것이 아닌 main 함수 실행을 위한 코드를 컴파일러가

     EntryPoint에 넣어놨기 때문

 

 

# x64dbg로 main 함수 찾는 법 - 정해진 패턴

- 이 방법은 Windows에서 Visual Studio 2019로 64비트 릴리즈 모드를 통해 컴파일 된 바이너리에 대해서만 쓸 수 있음

1400012B4 <hello-world.EntryPoint> | sub rsp,28                 |
1400012B8                          | call hello-world.140001694 |
1400012BD                          | add rsp,28                 |
1400012C1                          | jmp hello-world.140001138  |

- 처음 시작 부분에서 4번째 라인에 있는 JMP에서 <enter>키를 통해 이동

  > 이동하게되면 함수가 길게 있는데 해당 부분에서 조금만 내려가면 오른쪽 두번째 부분과 같은 코드가 있음

140001222 | call <JMP.&_get_initial_narrow_environment> |
140001227 | mov rdi,rax                                 |
14000122A | call <JMP.&__p___argv>                      |
14000122F | mov rbx,qword ptr ds:[rax]                  |
140001232 | call <JMP.&__p___argc>                      |
140001237 | mov r8,rdi                                  |
14000123A | mov rdx,rbx                                 |
14000123D | mov ecx,dword ptr ds:[rax]                  |
14000123F | call hello-world.140001000                  |

- 해당 부분은 main함수의 인자인 argc, argv, envp를 Windows API를 통해 설정하는 코드

  > 자세히 확인해보면 함수의 호출결과 값을 함수 인자의 첫번째(ecx), 두번째(rdx), 세번째(r8)에

     넣는 것을 확인할 수 있음

- 이를 통해 그 다음 호출하는 hello-world.14001000가 main함수라는 것을 알 수 있음

- 이 방법은 다른 컴파일러나 다른 옵션을 통해 컴파일된 바이너리에서 그대로 사용할 수 없지만 코드의 형태는 비슷하기에 어렵지 않게 같은 방법으로 main을 찾을 수 있음

 

 

# x64dbg로 main 함수 찾는 법 - 문자열 검색

- main 함수에서 사용할법한 문자열을 검색하여 main함수를 찾는 방법

- 여기서는 hello-world가 "hello world\n"을 출력한다는 점을 이용함

x64dbg 상단 메뉴 아이콘

- 상단 메뉴 아이콘 중 Az라고 써져있는 아이콘을 누르면 현재 창에서 보고있는 모듈(여기서는 hello-world.exe)에 있는 문자열들을 참조하는 어셈블리어를 검색해줌

- 이 창에서는 문자열의 내용, 해당 문자열을 참조하는 어셈블리어의 주소와 내용을 알려줌

Az 누른 결과

- 검색결과를 더블 클릭하면 해당 주소로 이동할 수 있음

- 가장 위에있는 "hello world\n" 문자열을 참조하는 줄을 더블클릭하면 main함수로 이동하는 것을 볼 수 있음

140001000 | sub rsp,28                       |
140001004 | lea rcx,qword ptr ds:[140002220] | 0000000140002220:"hello world!\n"
14000100B | call qword ptr ds:[<&puts>]      |
140001011 | xor eax,eax                      |
140001013 | add rsp,28                       |
140001017 | ret                              |

 

 

# x64dbg로 main 함수 찾는 법 - 임포트한 함수(모듈간 호출 찾기)

- main함수에서 사용할법한 함수를 검색하여 main 함수를 찾는 방법

- 여기서는 hello-world.exe가 문자열을 콘솔에 출력한다는 점을 이용

x64dbg 상단 메뉴 아이콘

- 상단 메뉴 아이콘 중 옛날 핸드폰 모양으로 생긴 아이콘을 누르면 현재 창에서 보고있는 모듈에 있는 모듈간 함수 호출을 검색해줌

  > 이 창에서 호출하는 함수명, 해당 함수를 호출하는 어셈블리 코드의 주소와 내용을 알려줌

- 검색 결과를 더블클릭하면 해당 주소로 이동할 수 있음

  > 가장 위에 있는 puts 함수를 호출하는 줄을 더블클릭하면 main함수로 이동하는 것을 볼 수 있음

140001000 | sub rsp,28                       |
140001004 | lea rcx,qword ptr ds:[140002220] | 0000000140002220:"hello world!\n"
14000100B | call qword ptr ds:[<&puts>]      |
140001011 | xor eax,eax                      |
140001013 | add rsp,28                       |
140001017 | ret                              |

 

 

# x64dbg로 main 함수 찾는 법 - 응용

- 위에서 설명한 방법 중 문자열을 검색하는 방법과 임포트한 함수를 사용하는 방법은 Windows에서 뿐만 아니라 Linux나 Android 등 대부분의 프로그램을 분석할 때 사용할 수 있는 방법

- main 함수 뿐 아니라 원하는 함수를 찾을 때에도 사용할 수 있는 범용적이고 편리한 방법

  > 다만 찾기 원하는 함수의 동작을 알고 있거나 유추할 수 있는 상황에서만 쓸 수 있음

 

 

# x64dbg로 함수 찾는 법 - 1

- x64dbg에는 모듈에 있는 함수의 시작 부분과 끝나는 부분을 자동으로 찾는 기능이 있음

- 해당 기능은 디스어셈블창에서 오른쪽 클릭을 하면 나오는 메뉴에서 분석 - 모듈 분석을 사용해서 이용 가능

- 분석이 완료되면 함수가 인식되고 위의 사진처럼 인식된 함수나 반복문 부분이 진한 막대기로 표시가 됨

- 한 번 분석을 완료하면 분석 대상을 나중에 다시 열었을 때 저장된 분석결과에서 정보를 불러오기 때문에 다시 분석할 필요는 없음

 

 

# x64dbg로 함수 찾는 법 - 2

x64dbg 상단 아이콘바

- 분석된 함수들은 상단 아이콘바 fx아이콘을 눌러 확인할 수 있음

 

 

# x64dbg 따라가기 기능

- 이 기능을 활용하면 따로 주소를 입력하여 이동할 필요가 없어 편리함

1. call, jmp, jcc와 같은 PC(program counter)를 변경하는 명령어

  > <enter>키를 사용해서 이동할 수 있음

2. mov나 lea같은 명령어가 주소를 참조하는 경우

  > 아래 그림처럼 해당 주소에서 클릭을 눌러 나오는 메뉴에서 이동이 가능

> 위의 그림의 경우 lea rcx, qword ptr ds: ~를 선택하였고 경우에 따라 덤프창과 디스어셈블창

둘 중 어느 쪽에 주소를 보여줄지 선택할 수 있음(디스어셈블러에서 따라가기, 덤프에서 따라가기)

 

 

# x64dbg 레이블과 주석

- 리버싱에 있어서 함수에 이름을 붙이거나 변수에 이름을 붙이는 작업은 큰 프로그램을 분석할 때 매우 중요한 작업 중 하나

- x64dbg는 레이블이라는 이름으로 해당 작업을 지원

x64dbg 레이블

- : 키를 통해 레이블을 붙일 수 있음

- 레이블을 붙인다는 것은 곧 해당 주소의 별칭을 지정하는 것과 같다고 생각하면 됨

- 만약 함수의 시작점에 레이블을 붙인다면 함수의 이름이 되는 것이고, 전역 변수의 시작 주소에 레이블을 붙일 경우 변수의 이름이 되는 것

- 위의 그림에서 dreamhack_main이라는 레이블을 붙이고 해당 함수를 호출하는 부분으로 가면 다음과 같음

140001237 | mov r8,rdi                        |
14000123A | mov rdx,rbx                       |
14000123D | mov ecx,dword ptr ds:[rax]        |
14000123F | call <hello-world.dreamhack_main> |

- x64dbg는 레이블 말고도 주석 달기도 지원

  > ; 키를 통해서 주석을 달 수 있음

- 주석은 레이블관느 조금 다름

- 레이블이 해당 주소에 이름을 붙이는 것이라면, 주석은 해당 주소에 설명을 다는 개념

- 주석을 달아도 해당 주소를 참조하는 다른 부분에서는 디스어셈블창에서 주석이 보이지 않음

- 참고로 주석과 레이블이 동시에 달려있는 경우 주석만 보이지만, 실제로는 레이블이 사라지지 않음

 

profile

Fascination

@euna-319

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!