[모각코] #10 드림핵강의 리버스 엔지니어링(4~5강)
x64dbg
- x64dbg: 오픈소스로, 32비트와 64비트 둘 다 지원하는 윈도우 디버거
x64dbg의 시작화면
x64dbg의 사용법
기본적인 UI
- 상단바
- 분석할 프로그램을 엽니다.
- 프로그램을 재시작합니다.
- 프로그램을 완전히 정지합니다.
- 프로그램을 실행(재개)합니다.
- 프로그램을 일시정지 시킵니다. 실행중인 상태에서 임의로 중단시키고 싶을 때 사용합니다.
- 어셈블리 코드를 한 줄 실행합니다. 만약
call
을 실행하려 하면call
한 함수 내부로 진입합니다. (Step Into) - 어셈블리 코드를 한 줄 실행합니다. 만약
call
을 실행하려 하면call
한 함수가ret
명령어를 실행할 때까지(리턴할 때까지) 실행한 다음 멈춥니다. (Step Over)
-
CPU 탭 구성
-
주소와 어셈블리 코드와
x64dbg
나 사용자가 단 주석이 여기에 표시됨 왼쪽서부터- 주소
- 옵코드
- 기계어 코드
- 주석
의 순서로 표시됨 => 주소 부분에는 함수명을 알고 있을경우 함수명이 표시 이곳에서
jmp
나call
같은 실행 흐름을 바꾸는 어셈블리 코드를 선택하고enter
키를 누르면 해당 부분으로 이동합니다. 되돌아올땐-
키를 사용함 -
현재 CPU의 레지스터 상태 표시 아래로 스크롤하면
xmm
과 같은 부동소수점 관련 레지스터의 상태도 볼 수 있습니다. -
1번창에서 선택한 부분에 대한 정보가 여기에 표시
-
현재 레지스터 상태중
rcx
,rdx
,r8
,r9
값을 보여줌 2번창과 별도로 보여주는 이유는 해당 레지스터 순서가 Windows 64비트 운영체제에서 기본적으로 사용하는 함수 호출 규약(Calling Convention)의 인자 순서이기 때문=> 이를 통해
call
명령어에서 쉽게 인자로 어떤값들이 넘어가는지 확인함 -
핵스값을 보여줌
-
스택값을 보여줌 => 기본적으로
rsp
값을 따라서 보여줌
-
브레이크 포인트
-
브레이크 포인트:
리버싱에 있어서 필수적인 도구 중 하나로, 프로그램 실행 중 원하는 지점이나 특정 조건을 만족할 경우 프로그램을 멈추게 할 수 있는 기능
-
용도:
이를 통해 리버서는 프로그램의 시작지점부터가 아닌 분석을 원하는 특정 지점부터 분석을 하는게 가능
-
종류:
- 소프트웨어 브레이크 포인트,
- 하드웨어 브레이크 포인트,
- 메모리 브레이크 포인트
필수 단축키
- F2
- 소프트웨어 브레이크 포인트를 걸 때 사용하는 단축키입니다. 이미 브레이크 포인트가 걸려있는 주소에서 누를 경우 브레이크 포인트를 삭제합니다.
- F7
- 어셈블리 코드를 한 줄 실행합니다. 만약
call
을 실행하려 하면call
한 함수 내부로 진입합니다.
- 어셈블리 코드를 한 줄 실행합니다. 만약
- F8
- 어셈블리 코드를 한 줄 실행합니다. 만약
call
을 실행하려 하면call
한 함수가ret
명령어를 실행할 때까지(리턴할 때까지) 실행한 다음 멈춥니다.
- 어셈블리 코드를 한 줄 실행합니다. 만약
- F9
- 프로그램의 실행을 재개합니다.
- ctrl + g
- 현재 창이 보여주는 주소를 바꿉니다. 디스어셈블 창에서 사용하면 디스어셈블 창이 해당 주소로 가고, 헥스덤프 창에서 사용하면 헥스덤프 창이 해당 주소로 가는 식입니다. 주소값 말고도 간단한 사칙 연산이나 함수명도 인식합니다.
- -, +
- 이전 또는 다음 주소로 이동합니다.
call
이나jmp
명령어의 주소로 이동했을 때, 이전 주소로 돌아가거나 다시 이동할 때 자주 쓰입니다.
- 이전 또는 다음 주소로 이동합니다.
-
키 - call
이나
jcc와 같은 PC(
program counter)를 변경시키는 명령어를 선택한 상태에서 누르면 해당되는 주소로 이동합니다. ex)
call 0x11223344` → 0x11223344로 이동
- call
-
키 - 선택한 어셈블리어를 수정합니다.
잔존 바이트를 NOP로 채우기
를 선택하면 수정된 코드 길이가 기존 코드의 길이보다 작을 때 남는 공간을NOP
으로 자동으로 채워줍니다.
- 선택한 어셈블리어를 수정합니다.
x64dbg 사용법
x64dbg로 main함수 찾는법
// hello-world.cpp
#include <stdio.h>
void main(){
puts("hello world!\n");
}
정해진 패턴
-> Windows에서 Visual Studio 2019로 64비트 릴리즈 모드를 통해 컴파일 된 바이너리에 대해서만 쓸 수 있는 방법
main
함수의 인자인argc
,argv
,envp
를 Windows API를 통해 설정하는 코드
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 |
함수의 호출결과 값을 함수 인자의 첫번째(
ecx
), 두번째(rdx
), 세번째(r8
)에 넣는 것을 확인할 수 있음 이를 통해 그 다음 호출하는hello-world.140001000
가main
함수라는것을 알 수 있음
문자열 검색
-> main
함수에서 사용할법한 문자열을 검색하여 main
함수를 찾는 방법
-
Az
라 써져있는 아이콘을 누르면 현재 창에서 보고있는 모듈(여기서는hello-world.exe
)에 있는 문자열들을 참조하는 어셈블리어를 검색=>
hello world\n
문자열을 참조하는 줄을 더블클릭하면main
함수로 이동
임포트한 함수(모듈간 호출 찾기)
-> main
함수에서 사용할법한 함수를 검색하여 main
함수를 찾는 방법
-
상단 메뉴 아이콘중 옛날 핸드폰 모양으로 생긴 아이콘을 누르면 현재 창에서 보고 있는 모듈(여기서는
hello-world.exe
)에 있는 모듈간 함수 호출을 검색=>
puts
함수를 호출하는 줄을 더블클릭하면main
함수로 이동출처: https://dreamhack.io/lecture/curriculums/3