CPU 레지스터 어셈블리어 표기법 정리
새로운 공격 루트를 확보하기 위한 공격에 대한 원리를 캐는 섹션에 앞서 gdb(GNU 디버거) 명령을 통해 확인할 수 있었던 어셈블리 언어 표기법에 대해 정리하는 시간을 가지겠다.
gdb$ 명령단에서 x 명령을 통해 메모리 내용을 확인할 수 있었다.
gdb$ x/ (명령 수) i (선두 주소)
gdb에서는 기본적으로 AT&T 표기법이 사용된다. 인텔 표기법/AT&T 표기법은 다음과 같이 변경할 수 있다.
인텔 표기법
mov eax, 5
AT&T 표기법
mov $5, %eax
인텔 명령은 두 번째 오퍼랜드(피연산자)의 값을 첫 번째 오퍼랜드에 저장하지만 AT&T 표기법에서는 첫 번째 오퍼랜드를 두 번째 오퍼랜드에 저장한다. 그리고 위의 예에서도 알 수 있듯이 접두사 또한 다르다. 인텔 표기법에서는 레지스터 이름이나 정수에 접두사가 붙지 않지만 AT&T 표기법에서는 레지스터 이름에는 %를, 정수에는 $를 붙이는 것을 알 수 있다(이걸 구글링 해서도 못 찾았는데).
어느 서적에서는 AT&T 표기법을 이용하고 다른 서적에서는 인텔 표기법이 이용되어 어셈블리 명령에서 오퍼랜드(Operand, 피연산자)의 순서가 뒤바뀌기기도 하는데, gdb 명령단에서 'set disassembly-flavor intel' 명령어로 변경하여 인텔 표기법으로 통일시킬 수 있다.
앞서 우분투 리눅스를 통해 버퍼오버플로우 공격을 실습한 섹션들에서는 AT&T 표기법이었다. 레지스터 값과 관련하여 gdb 단에서의 명령어이다.
1) 레지스터 값을 로딩하려면 p 명령을 사용함.
gdb$ p (레지스터명)
2) i 명령을 통해 일부 레지스터를 제외한 모든 레지스터의 값을 표시할 수도 있다.
gdb$ i r
원래 명령어: info registers
[메모리 덤프 관련]
b: BYTE(1 byte)
h: HALFWORD(2 bytes)
w: WORD(4 bytes)
g: GIANTWORD(8 bytes)
표시 형식은 다음과 같은 것이 있다.
s: 문자열
i: 명령
x: 16진수
만약 x/100wx *0x4010000이라고 쓴다면 메모리 주소 0x4010000부터 4 바이트 단위로 100개분의 메모리값을 16진수로 읽어온다.
gdb$ x/(읽어오고 싶은 크기)(메모리 크기)(표시 형식)(읽어올 메모리의 시작 주소)
참조
우스이 토시노리 외 7인. 양현 역. (2016). CTF 정보보안 콘테스트 챌린저 북: Capture The Flag 문제 풀이로 배우는 해킹 테크닉, 서울: 위키북스.