System Hacking - Pwnable
1. 포너블 개념
-포너블 : 공격을 위해 관리자 권한을 강탈해오는 것! -> shell을 탈취해야 함(shell = 사용자와 커널을 연결해주는 매개체) -> shell을 통해 공격 가능
2. 레지스터
-레지스터 : CPU에서 요청을 처리하는 데 필요한 데이터를 일시적으로 저장하는 기억장치. CPU 옆에 붙어있고 CPU는 연산을 할 때 레지스터를 반드시 거쳐감
-x86 vs x64 : 한번에 처리할 수 있는 bit 수 -> 메모리 인식률, 레지스터에 적용시키면 x86-저장 가능한 공간 크기가 4기가
3. 리눅스 메모리 구조(유저 영역 - 프로세스 메모리 구조)
-스택 : 함수, 지역변수 정보 포함 -> 취약점 존재, 버퍼오버플로우 많이 발생, @주의@ 스택은 높은 주소에서 낮은 주소로 쌓임! 거꾸로 쌓인다고 보면 됨.
-heap : 동적 할당 malloc()
-bss : 변수들이 실제 위치하는 곳(초기화되지 않은 상태)
-data : 초기화된 변수가 위치하는 곳
-text(code) : 실제 우리가 작성한 소스 코드가 들어가있는 공간
4. cdecl
-stack frame : 스택 영역에 차례대로 저장되는 함수의 호출 정보 -> 스택 프레임 덕분에 함수의 모든 호출이 끝난 뒤, 해당 함수가 호출되기 이전 상태로 돌아갈 수 있음.
x86(32bit) | x64(64bit) | |
함수 호출 규약 | cdecl | sysv |
-cdecl : x86에서 사용되는 함수 호출 규약, c에서도 기본적으로 사용됨.
int sum(int a, int b) {
return a + b;
}
void main(void) {
sum(1,2);
}
- 위 코드에서 sum 함수를 부르는 main 함수가 caller, 호출 당하는 sum 함수는 callee
- 인자는
- 인자 전달 방법 : stack을 통해 전달(오른쪽 -> 왼쪽 ), 리턴 값은 eax를 통해 전달 받음. 인자 정리는 callee가 아닌 caller가 함.
- 처리 순서
- caller가 전달할 argument를 stack에 push
- callee prolog
- callee epilog
- caller가 call과정에서 사용한 stack 정리
-push할 때마다 esp 4씩 증가
5. sysv
-sysv : x64에서 사용되는 함수 호출 규약
- 6개의 인자를 RDI, RSI, RDX, RCX, R8, R9에 순서대로 저장하여 전달.
더 많은 인자를 사용해야 할 때는 스택을 추가로 이용 - callee prolog
- callee epilog
- caller가 call과정에서 사용한 stack 정리
- 함수의 반환 값은 RAX로 전달
6. Stack frame 변화 과정
-stack frame : 어떤 함수가 실행될 때, 스택 안에서 그 함수의 영역을 구분하기 위해 생성되는 공간, 함수 프롤로그(Prolog)와 에필로그(Epilog)를 수행하여 영역 표현을 함.
-함수 프롤로그(Prolog) : push %ebp, mov %ebp, %esp -> ebp를 스택에 저장한 후, esp를 ebp에 복사함. ebp를 기준으로 함수 위치 정보를 파악할 수 있음
-함수 에필로그(Epilog) : leave, ret
1) leave : move esp, ebp, pop ebp로 나눠짐
2) ret : pop eip, jmp eip로 나눠짐
[gate@localhost /tmp]$ gdb -q stack
(gdb) set dis int
(gdb) disas main
Dump of assembler code for function main:
0x80483e8 <main>: push ebp
0x80483e9 <main+1>: mov ebp,esp
0x80483eb <main+3>: sub esp,20
0x80483ee <main+6>: push 0x804846f
0x80483f3 <main+11>: call 0x8048308 <printf>
0x80483f8 <main+16>: add esp,4
0x80483fb <main+19>: call 0x80483d0 <func>
0x8048400 <main+24>: xor eax,eax
0x8048402 <main+26>: jmp 0x8048404 <main+28>
0x8048404 <main+28>: leave
0x8048405 <main+29>: ret
End of assembler dump.
위 코드에서
프롤로그
에필로그
-함수 호출 call fun
<프롤로그>
push rip, jmp fcn -> 스택에 다음 함수 실행 위치가 저장됨 (push rip),
move rbp, rsp -> rbp에 rsp값 저장
sub rsp -> callee의 각종 지역 변수들이 쌓임
<에필로그>
move rsp, rbp -> rbp값이 rsp에 저장
pop rbp