- variables
- stack
- arguments
- memory locations
Breakpoints
3가지 breakpoint 가 있다.- soft breakpoints
- one-shot breakpoint : 한 번 쓰이고 breakpoint list 에서 사라지는 것
- persistent breakpoint : breakpoint list 에서 저장되어 있고, 계속해서 쓰이는 것
- hardware breakpoints
- memory breakpoints
soft breakpoints
우리가 debugging 할 때 흔히 쓰는 breakpoint 이다.
1-byte 의 instruction 이다.
process 의 실행을 멈추고 control 을 breakpoint exception handler 에 넘겨준다.
instruction 과 opcode 의 차이
댓글에서 꾸지람을 들어서 ㅜ.ㅜ instruction 과 opcode 에 대해 좀 더 알아봤다.
먼저, 간단한 instuction 에 대한 그림을 하나 보자.
<출처 : wiki, http://en.wikipedia.org/wiki/File:Mips32_addi.svg> |
위에 예제에서 보듯이 instruction 을 구성하는 binary 값들중에 operation(명령)을 나타내는 부분이 opcode 이다. 그래서 operation code 라고 하는 것 아닐까 생각된다.
그리고 우리가 흔히 assembler 라고 하는 것이 밑에 mnemonic 이라고 하는 부분에 있다.
결론은 이렇다. instruction 은 명령어에 대한 가장 추상적인 개념이고, 그 instruction 의 실체(기계어) 중 operation 부분이 opcode 이다. 그리고 이 opcode 와 parameter code 등에 대한 mnemonic 이 바로 우리가 아는 assembler 라고 할 수 있겠다.
INT3
soft breakpoint 를 만들기 위해서는 opcode 를 0xCC 로 바꿔야 한다.
예를 들어, 0x8BC3 (2-byte) 가 있다면 이중에 0x8B 1 byte 를 0xCC, interrupt 3(INT 3) instruction, 로 바꿔야 한다. 이 INT 3 instruction 이 halt CPU 를 하는 명령어 이다.
0x89E5 --> 0xCCE5processor 가 0xCC 를 만나게 되면 execution 을 멈추고 INT3 event 를 발생시키게 된다.
0x89E5 MOV EBP,ESP
라는 명령어가 있다면,
0xCCE5 로 만드는 것이다.
debug-mode run
우리가 debugger에서 breakpoint 를 설정하고 debug mode 로 실행할 때 이런 일이 일어난다.
- breakpoint 를 설정하면, debugger 가 첫byte 를 0xCC 로 바꾸고, 기존에 byte(opcode)는 어딘가에 저장해 놓는다.
- debug mode 로 run 을 해서 CPU 가 0xCC 를 만나서 INT3 event 가 발생되면, debugger 가 그 interrupt 를 받게 된다.
- 그러면, debugger 가 instruction pointer(EIP register) 가 breakpoint list 에 있는 녀석을 가리키고 있는지를 검사한다.
- 그래서 breakpoint list 에 있는 녀석이라면, 아까 저장해 놓은 byte(opcode)를 그 주소(0xCC 가 써져 있는)에 다시 쓰게 된다.(write)
- 그래서 유저가 resume을 했을 때 opcode 는 다시 온전하게 수행이 된다.
soft breakpoint 와 CRC checksum
이런 soft breakpoint 에서 주의할 점 하나는 memory 에서 opcode 를 0xCC로 바꾸게 되면, cyclic redundancy check(CRC) checksum 도 같이 바뀌게 된다. 는 것이다.
CRC checksum 을 이용해 자신의 packet, file, memory 등의 data 가 변경되는가를 감시할 수 있다.
그리고 어떤 악성코드는 이 CRC checksum 이 변동되면 자기 자신을 kill 하는 것을 이용해 soft breakpoint 를 set 하지 못하게 만든다.
Hardware breakpoint
적은 수의 breakpoint 로 충분하다면 hardware breakpoint 가 알맞을 수 있다. 그리고 hardware breakpoint 는 soft breakpoint 와 다르게 software 의 변경을 가하지 않는다.
soft breakpoint 와 다르게 INT1 event 를 사용한다. 이 INT1 event 는 sigle step event(debugger 에서 next step 을 누를 때) 와 hardware breakpoint 를 위해 쓰인다.
hardware breakpoint 는 debug register 라는 것을 이용해 set 하게 된다.
일반적인 CPU 는 debug register(DR) 를 8개 가지고 있다. (DR0~DR7)
8개의 DR중에 DR0~DR3 만 breakpoint 의 address 를 저장하기 때문에, 실제로는 4개의 hardware breakpoint 를 만들 수 있다는 뜻이 된다.
- DR0~DR3 : breakpoint 들의 address 를 저장하기 위해 쓰인다.
- DR4, DR5 는 예약되어 있고,
- DR6는 status register 로 사용된다. 이 status register 는 breakpoint 의 type 을 알려준다.
- DR7 은 on/off switch 역할을 한다. 그리고 다른 breakpoint 의 조건을 저장한다.
DR7
DR7 에 특정 flag 를 설정해서 다음과 같은 조건에 호출되는 breakpoint 를 만들 수 있다.
- 특정주소의 instruction 이 수행됐을 때(0x00)
- data 가 특정 address 에 write 될 때(0x01)
- 실행되지는 않지만, 특정 주소를 read 나 write 를 할 때(0x11)
- Bits 0-7 은 DR0-DR3 의 on/off switch 역할을 하고, L, R field 는 scope를 나타낸다. local 인지, global 인지.
bit1 은 DR0-local,
bit2 는 DR0-global 이런 식으로 switch 역할을 한다.
switch 가 on 이 되면 enable 이 되는 것이다. - Bit 8-15 는 일반적인 debugging 목적으로 쓰이지 않는다.
- Bit (16, 17) - (30, 31) 은 DR0-DR3 에 설정된 breakpoint의 Type과 length 를 나타낸다.
bit16,17 은 DR0의 type
bit18,19는 DR0의 length 이런 식으로 쓰인다.
자세한 사항은 아래 그림을 참고하자.
출처 : Gray Hat Python, Chpater 2. Figure 2-4 |
작동방식
CPU 가 instruction 을 execution 하기 전에 이 instruction address에 hardware breakpoint 가 걸려 있는지 확인한다.
그리고 operator 가 접근하려는 memory 가 hardware breakpoint 에 걸려있는지 확인한다.
제한
hardware breakpoint 의 제한은 4개밖에 없다는 것 이외에, read/write 에 대한 검사가 최대 4-byte 에서만 가능하다는 것이다.
이것을 극복하기 위해 memory breakpoint 가 존재한다.
Memory breakpoint
memory breakpoint 는 실제로 breakpoint 는 아니다. 개인적인 생각에는 우리가 흔히 생각하는 Page Fault 같은 것 같다.
memory 의 가장 작은 단위가 memory page 이다. 이 memory page 가 할당될 때, 이 page 는 특정 permission set 을 갖게 된다. 이런 permission 의 종류에는 아래 4가지가 있다.
- Page execution
- Page read
- Page write
- Guard page
그리고, OS 에서 제공하는 함수를 통해서 이 page 가 어떤 permission 을 가졌는지 query 할 수 있고, permission 을 변경할 수도 있다.
Guard Page
여기서 볼 것은 Guard page 이다.
- heap 을 stack 에서 분리하는 데에 유용하고, 어떤 한계선이상으로 memory 를 쓰지 않게 할 수 있다.
- 특정 메모리 영역을 접근했을 때 process 를 멈추는데 유용하다.
이 breakpoint 가 application 이 수신한 packet 내용을 언제, 어떻게 이용되는지 알아낼 수 있게 해 준다.
그 memory page 에 대한 접근은 CPU 를 멈추고, guard page debugging exception 을 발생시킨다.
buffer memory 에 접근한 instruction 이 무엇인지를 조사할 수 있고, 무엇을 하는지 알아낼 수 있다.
Soft breakpoint 와 Guard Page
이런 방법을 이용하면, software 를 변경해야 하는 soft breakpoint 의 대신에 사용해서 software 를 변경하지 않고 execution 을 멈출 수 있다.
References
- Gray Hat Python, Chapter 2, 2009년
[instruction 과 opcode 의 차이] 에서
답글삭제-> inst는 opcode 및 operand를 포함한 CPU의 최소한의(atomic한) 실행 단위를 뜻하고, opcode는 inst의 일부로서 command 시맨틱을 갖는 부분이라는 표현이 정확한 것 같습니다.
일반적으로 MOV "명령어"라고 하면 물론 뒤에 따라오는 파라미터들도 포함하는 말이기는 하지만,
어셈블리어가 inst.고 기계어가 opcode다..라는 표현은 오해의 소지가 있어보입니다.^^;
감사합니다. ㅜ.ㅜ 글 수정했습니다.
삭제