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를 열면 아무런 설정을 안했을 경우 아래와 같이 뜸
> 박스 부분을 살펴보면 현재 ntdll부분에 멈춰있는 것을 알 수 있음
> 이는 x64dbg가 기본적으로 시스템 중단점 설정이 켜져있기 때문
- 설정 - 환경설정으로 들어가서 아래 사진과 같은 창에서 시스템 중단점 설정을 변경해야 함
> 위의 창에서 박스로 표시된 옵션을 해제하면 됨
> 이후 디버깅 프로그램을 재시작하면 시작 지점에서 멈춘 상태로 디버깅이 시작됨
# x64dbg로 main 함수 찾는 법
- 앞에서 설명한대로 설정을 하면 아래와 같이 hello-world.exe의 EntryPoint부분에서 디버깅이 시작됨
- 해당 부분이 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"을 출력한다는 점을 이용함
- 상단 메뉴 아이콘 중 Az라고 써져있는 아이콘을 누르면 현재 창에서 보고있는 모듈(여기서는 hello-world.exe)에 있는 문자열들을 참조하는 어셈블리어를 검색해줌
- 이 창에서는 문자열의 내용, 해당 문자열을 참조하는 어셈블리어의 주소와 내용을 알려줌
- 검색결과를 더블 클릭하면 해당 주소로 이동할 수 있음
- 가장 위에있는 "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가 문자열을 콘솔에 출력한다는 점을 이용
- 상단 메뉴 아이콘 중 옛날 핸드폰 모양으로 생긴 아이콘을 누르면 현재 창에서 보고있는 모듈에 있는 모듈간 함수 호출을 검색해줌
> 이 창에서 호출하는 함수명, 해당 함수를 호출하는 어셈블리 코드의 주소와 내용을 알려줌
- 검색 결과를 더블클릭하면 해당 주소로 이동할 수 있음
> 가장 위에 있는 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
- 분석된 함수들은 상단 아이콘바 fx아이콘을 눌러 확인할 수 있음
# x64dbg 따라가기 기능
- 이 기능을 활용하면 따로 주소를 입력하여 이동할 필요가 없어 편리함
1. call, jmp, jcc와 같은 PC(program counter)를 변경하는 명령어
> <enter>키를 사용해서 이동할 수 있음
2. mov나 lea같은 명령어가 주소를 참조하는 경우
> 아래 그림처럼 해당 주소에서 클릭을 눌러 나오는 메뉴에서 이동이 가능
> 위의 그림의 경우 lea rcx, qword ptr ds: ~를 선택하였고 경우에 따라 덤프창과 디스어셈블창
둘 중 어느 쪽에 주소를 보여줄지 선택할 수 있음(디스어셈블러에서 따라가기, 덤프에서 따라가기)
# 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는 레이블 말고도 주석 달기도 지원
> ; 키를 통해서 주석을 달 수 있음
- 주석은 레이블관느 조금 다름
- 레이블이 해당 주소에 이름을 붙이는 것이라면, 주석은 해당 주소에 설명을 다는 개념
- 주석을 달아도 해당 주소를 참조하는 다른 부분에서는 디스어셈블창에서 주석이 보이지 않음
- 참고로 주석과 레이블이 동시에 달려있는 경우 주석만 보이지만, 실제로는 레이블이 사라지지 않음
'Hacking Tech > Reversing' 카테고리의 다른 글
[Dreamhack] Reversing Engineering - 7. 쉬운 crackme를 통한 디버거 사용법 - 2 (0) | 2021.12.24 |
---|---|
[Dreamhack] Reversing Engineering - 6. 쉬운 crackme를 통한 디버거 사용법 - 1 (0) | 2021.12.21 |
[Dreamhack] Reversing Engineering - 4. x64dbg (0) | 2021.10.03 |
[Dreamhack] Reversing Engineering - 3. puts("hello world!\n") → x86_64 asm (0) | 2021.10.03 |
[Dreamhack] Reversing Engineering - 2. x64 기초 (0) | 2021.09.19 |