어셈블리 핸드레이
어셈블리어를 c언어로 복원시키는 것을 의미한다.
일반적으로 바이너리(0,1로 이루어진 이진법)를 디버거(프로그래밍 과정 중에 발생하는 오류나 비정상적인 연산을 찾아 수정하는 것)로 보게 되면 바이너리에 대한 어셈블리 코드가 나오게 된다. 이 어셈블리 코드는 명시적으로 알아보기 힘든데 그래서 사용자에게 익숙한 c언어로 변환하게 된다. 보통 IDA를 사용하면 IDA의 기능 중 하나인 헥스레이 기능을 이용해서 이 작업을 수행할 수 있게 된다. IDA 역시 완벽한 변환이 아니고 수작업을 통해 변환된 코드를 수정할 일이 필요하므로 어셈블리 핸드레이에 익숙해져야 한다.
그래서 기본적인 어셈블리 명령어들을 알아야한다. (게시글로 정리)
스택 프레임
함수가 실행되기 위해 스택에 데이터를 올리게 되는데, 각 함수가 사용하는 스택의 영역을 스택 프레임이라고 한다.
즉, 함수 호출 시 할당되는 메모리 블록(지역변수 선언으로 할당됨), 함수 종료 시 호출 전에 저장해둔 주소로 복귀한다.
아래는 스택 프레임을 어셈블리어로 보았을 때의 구조이다.
PUSH EBP: 함수시작(EBP를 사용하기 전에 초기 값을 스택에 저장) MOV EBP, ESP: 현재의 ESP를 EBP에 저장 ; 함수의 본체 ; 여기서 ESP가 변경되더라도 EBP가 변경되지 않으므로 ; 안전하게 로컬변수와 파라미터를 엑세스할 수 있음 MOV ESP, EBP: ESP를 정리(함수가 시작했을 때의 초기값으로 복원) POP EBP: 리턴되기 전에 저장해 놓았떤 원래 EBP 값으로 복원 RETN: 함수 종료 |
이런 식으로 스택 프레임을 이용해 관리하면 아무리 함수 호풀이 복잡해져도 관리하기 쉽다.
함수 프롤로그
함수가 호출될 때, 스택 프레임을 설정하는 과정
베이스포인터(ebp)를 스택에 저장하고 / 현재 스택포인터(esp)를 베이스포인터(ebp)에다가 저장한다.
push ebp // ebp를 스택에 저장하고(ebp에 esp를 넣기 전 값을 저장)
mov ebp, esp // esp에 ebp를 저장한다. 어셈블리어를 이용해 스택 프레임을 설정한다.
함수 에필로그
스택 프레임을 소멸시키는 과정
leave 명령어와 ret 명령어를 사용
현재 스택 포인터(esp)를 베이스포인터(ebp)로 복구한 후, 베이스 포인터(ebp)를 복구해주고 ret를 통해 다음에 가야될 adress로 점프한다.
mov esp, ebp // esp 원래 값으로 변경한다.
pop ebp // 원래의 ebp 값으로 바꾼다. 어셈블리어를 이용해 스택을 복원한다.
함수 프롤로그와 에필로그
PUSH ebp //함수 시작 MOV ebp, esp // 현재의 esp를 ebp에 저장 -(body부분)- MOV esp, ebp //저장해둔 ebp를 esp에 옮김 & esp정리 POP ebp //ebp반환, 함수 호출 전에 저장해둔 ebp 값으로 복원됨 RETN //함수 종료 |
(body부분)을 기준으로 앞부분을 함수의 프롤로그, 뒷부분을 함수의 에필로그라고 한다.
3. 핸드레이 & 기본 어셈블리 명령어 (tistory.com)
'System & Reversing 필기' 카테고리의 다른 글
gcc 컴파일러( + .so, .a, .o, .c) (0) | 2023.03.12 |
---|---|
DLL (0) | 2023.03.12 |
컴퓨터 메모리 구조 (0) | 2023.03.11 |
어셈블리어 (0) | 2023.03.11 |
아키텍쳐 (0) | 2023.03.10 |