버퍼 오버플로우
1. 메모리 구조와 어셈블리어의 기본
- 여기서는 리눅스 6.2로 실습 ( 최신 OS에서는 버퍼 오버플로우에 대한 대비책이 존재)
메모리의 기본 구조
상위 메모리 주소(0xffff)
Env/Argv Strings : 환경 변수와 명령 창의 데이터가 저장 |
Env/Argv Pointers : 위와 비슷;; |
Args |
스택영역 : 가장 낮은 부분에 스택 포인터 위치 |
|
힙 영역 : 동적으로 할당된 데이터가 저장 |
데이터(.bss) : 초기화되지 않은 변수 |
데이터(.data) : 초기화된 변수 |
코드(.text) |
하위 메모리 주소(0x0000)
** 스택 영역은 아래로 자라고, 힙 영역은 위쪽으로 자란다.
Intel 8086 registers
19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 | (bit position) |
Main registers |
||||||||||||||||||||
AH | AL | AX (primary accumulator) | ||||||||||||||||||
BH | BL | BX (base, accumulator) | ||||||||||||||||||
CH | CL | CX (counter, accumulator) | ||||||||||||||||||
DH | DL | DX (accumulator, other functions) | ||||||||||||||||||
Index registers |
||||||||||||||||||||
0 0 0 0 | SI | Source Index | ||||||||||||||||||
0 0 0 0 | DI | Destination Index | ||||||||||||||||||
0 0 0 0 | BP | Base Pointer | ||||||||||||||||||
0 0 0 0 | SP | Stack Pointer | ||||||||||||||||||
Program counter |
||||||||||||||||||||
0 0 0 0 | IP | Instruction Pointer | ||||||||||||||||||
Segment registers |
||||||||||||||||||||
CS | 0 0 0 0 | Code Segment | ||||||||||||||||||
DS | 0 0 0 0 | Data Segment | ||||||||||||||||||
ES | 0 0 0 0 | ExtraSegment | ||||||||||||||||||
SS | 0 0 0 0 | Stack Segment | ||||||||||||||||||
Status register | ||||||||||||||||||||
- | - | - | - | O | D | I | T | S | Z | - | A | - | P | - | C | Flags |
GENERAL PURPOSE
REGISTERS
8086 CPU has 8 general purpose registers, each
register has its own name:
- AX - the accumulator register (divided into AH / AL):
- Generates shortest machine code
- Arithmetic, logic and data transfer
- One number must be in AL or AX
- Multiplication & Division
- Input & Output
- BX - the base address register (divided into BH / BL).
- CX - the count register (divided into CH / CL):
- Iterative code segments using the LOOP instruction
- Repetitive operations on strings with the REP command
- Count (in CL) of bits to shift and rotate
- DX - the data register (divided into DH / DL):
- DX:AX concatenated into 32-bit register for some MUL and DIV operations
- Specifying ports in some IN and OUT operations
- SI - source index register:
- Can be used for pointer addressing of data
- Used as source in some string processing instructions
- Offset address relative to DS
- DI - destination index register:
- Can be used for pointer addressing of data
- Used as destination in some string processing instructions
- Offset address relative to ES
- BP - base pointer:
- Primarily used to access parameters passed via the stack
- Offset address relative to SS
- SS 레지스터와 함께 사용되어 스택 내의 변수 값을 읽는 데 사용
- SP - stack pointer:
- Always points to top item on the stack
- Offset address relative to SS
- Always points to word (byte at even address)
- An empty stack will had SP = FFFEh
SEGMENT REGISTERS
- CS - points at the segment containing the current program.
- DS - generally points at segment where variables are defined.
- ES - extra segment register, it's up to a coder to define its usage.
- SS - points at the segment containing the stack.
메모리와 어셈블리어를 테스트해 볼 sample.c 코드
[sample.c]
int function (int a, int b) {
char buffer[10];
a = a + B;
return a;
}
void main() {
int c;
c = function( 1, 2);
}
***
gcc -S -o sample.a sample.c
vi sample.a
- or use gedit etc
실행 결과
.file "sample.c"
.text
.globl function
.type function, @function
function:
.LFB0:
.cfi_startproc
pushl %ebp // 7
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp // 8
.cfi_def_cfa_register 5
subl $16, %esp // 9
movl 12(%ebp), %eax // 10
addl %eax, 8(%ebp) // 11
movl 8(%ebp), %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size function, .-function
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushl %ebp // 1
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp // 2
.cfi_def_cfa_register 5
subl $16, %esp // 3
pushl $2 // 4
pushl $1 // 5
call function // 6
addl $8, %esp // 17
movl %eax, -4(%ebp) //
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Debian 4.9.2-10) 4.9.2"
.section .note.GNU-stack,"",@progbits
*****
숫자를 붙여둔 순서대로 실행
** 위 내용과 밑에서 설명하는 내용이 약간 다를 수 있다.
1. pushl %ebp // push long
- 최초의 프레임 포인터(ebp)가 할당될 값을 스택에 저장
2. movel %esp, %ebp
- 현재의 SP(Stack Pointer) 값을 EBP 레지스트리에 저장
실습 : 셀 코드 생성하기
OS : 와우 리눅스 6.2
필요 요소 : gcc, gdb
실습 내용 : 셀 코드를 기계어로 생성
[shell.c]
#include <stdio.h>
#include <unistd.h>
int main() {
char * name [2];
name [0] = "/bin/sh";
name [1] = 0;
execve( name [0], name, NULL);
}
컴파일 및 gdb를 이용하여 셀 분석
gcc -0 shell shell.c
gdb shell
disass main