NX bit
- NX bit 가 걸려있다면, 스택에 실행권한이 존재하지 않는 것 →
rwx 권한 중 x 권한 없는 것.
- 실행 권한이 존재하지 않으면 Shellcode를 넣고 프로그램 흐름을 변조하더라도 shellcode 실행이 되지 않음 → Return to Shellcode 기법 사용 어려움
- 다만 NX bit 걸려 있는 바이너리에서 shellcode를 실행시키려면 mprotect와 같은 함수를 불러 원하는 메모리 공간에 rwx 권한을 준 후 shellcode를 실행시키는 여러 chaining 과정이 필요함 → ROP 기법에서 다룸
ASLR
- 힙, 스택, 라이브러리 영역의 base 주소를 바이너리를 실행할 때마다 Randomization 시켜 고정된 주소로 메모리에 직접 접근하는 행위를 할 수 없게끔 함
- 스택 base 주소가 매번 바뀌니 shellcode가 들어간 스택 주소까지 알아내기 어렵게 됨
- 각 메모리 영역의 base 주소만 Radomization 시키는 것이기 때문에 base 주소만 알아낸다면 해당 메모리 영역에서 원하는 주소에 base + offset 으로 맘대로 접근하는 게 가능해짐
- 특정 영역에 해당하는 메모리 주소를 하나라도 가지고 있다면 offset을 빼서 base주소를 알아내는 게 가능해지고 알아낸 메모리 영역 내에서 원하는 공간에 마음대로 접근할 수 있게 됨.
- 프로그램에 취약점이 존재해서 메모리에 존재하는 스택 주소나 라이브러리 주소를 그대로 화면에 출력할 수 있게 된다면 ASLR을 우회할 수 있게 됨 → memory leak (ROP 기법에서 다룸)
SSP
- SSP(Stack Smashing Protector) 는 BOF가 터지더라도 exploit으로 연계되는 것을 방어하기 위해서 sfp 위에 랜덤한 값을 넣어서 함수 에필로그 과정에서 해당 값을 변조 여부를 체크하는 보호 기법
- 랜덤한 값을 Canary라고 부름, sfp나 ret을 덮기 위해선 canary 값을 덮을 수 있어야 함
- canary 값이 변조될 경우 __stack_chk_fail 함수를 호출하여 프로그램을 강제 종료 시키게 됨
pwndbg> disass main
Dump of assembler code for function main:
0x00000000004006f7 <+0>: push rbp
0x00000000004006f8 <+1>: mov rbp,rsp
0x00000000004006fb <+4>: sub rsp,0x40
**
**0x00000000004006ff <+8>: mov rax,QWORD PTR fs:0x28
0x0000000000400708 <+17>: mov QWORD PTR [rbp-0x8],rax**
0x000000000040070c <+21>: xor eax,eax
0x00000000004007d2 <+219>: mov rcx,QWORD PTR [rbp-0x8]
0x00000000004007d6 <+223>: xor rcx,QWORD PTR fs:0x28
0x00000000004007df <+232>: je 0x4007e6 <main+239>
0x00000000004007e1 <+234>: call 0x4005c0 <__stack_chk_fail@plt>
0x00000000004007e6 <+239>: leave
0x00000000004007e7 <+240>: ret
End of assembler dump.
- memory leak을 내어 카나리값을 알아내거나 master canary(fs:0x28)을 원하는 값으로 덮거나 자식 프로세스를 사용할 때 1byte씩 brute force하여 카나리 값 알아낼 수 있음
RELRO
- 프로세스의 섹션을 보호하는 기술
- 3가지 모드가 있음
- Full relro : data, bss를 제외한 모든 섹션에서 쓰기 권한을 없앰. → GOT Overwrite가 불가함
- Pertial relro : GOT 섹션에 쓰기 권한이 존재함. → Lazy binding 과정을 거쳐서 함수 주소를 가져오고 GOT Overwrite 진행 가능
- No relro : ELF 기본 헤더와 code영역을 제외하고는 거의 모든 섹션에 쓰기 권한 존재. .init, .fini와 같은 섹션 또한 덮어쓸 수 있음.
PIE
- PIE (Position Independent Execution) ; 위치 독립 실행
- binary base 주소를 Randomization 시킴. 동작 원리는 ASLR과 유사함
- ASLR이 binary에 적용된 것과 유사. → PIE가 적용된 바이너리는 code, data, bss 등 섹션들의 주소를 알 수 없게 됨
- binary base 자체가 계속 바뀌어 code 영역의 가젯(코드 조각)에 의존적인 ROP 공격을 어렵게 만드는 보호 기법 → memory leak 을 내는 게 확실한 방법
⇒ 프로그램이 실행 중에 있을 때 PIE base를 leak할 수 있다면, 이를 기반으로 함수들에 대한 offset을 구하여 exploit을 진행해주면 됨.