2018. 1. 11. 10:18ㆍ0x04 pwnable/윈도우즈 어플리케이션 취약점 분석
DEP : Data Execution Prevention
힙 이나 스택과 같은 데이터 영역에서 실행을 금지하는 기법
소프트웨어 기반 : safeSEH
하드웨어 기반 : NX/XD
NX : AMD에 있는 실행 방지 페이지 보호
XD : INTEL에 있는 실행 불가능 비트
인텔 보호 정책 설정 레벨은 4가지다.
-----------------------------------------------------------------------------
AlwaysOn : 모든 프로세스를 DEP에 의해 보호 => VISTA는 이것땜에 망했다.
OptOut : 예외 설정 외 프로세스는 DEP에 의해 보호 (화이트리스트기반인듯)
예외설정에 포함되지 않는 착한애들(OutBoundary)만 DEP에 의해 보호
OptIn : 예외 설정 외에 프로세스는 DEP에 의해 보호되지 않음
-> 너가 따로 요청한다면 그때 DEP에 의해 보호해 주겠다. (중간자 역할)
즉, 원하는 프로세스만 DEP 적용 허용하겠다.
AlwaysOff : 어떤 프로세스를 DEP에 의해 보호하지 않음
-----------------------------------------------------------------------------
아.. 프로세스 작업관리자에서 DEP를 확인가능 하구나.
프로세스 익스플로러에서도 DEP 확인 가능 (아는 만큼 보이구나)
<DEP 우회 기법 일부> - 나머지는 구글링으로 찾아보기.
1. ret2libc (no shell code)
: 쉘코드로 직접 점프하는 것이 아니라 기존에 존재하는 라이브러리 또는 함수를 호출하는 방법을 이용.
결국 라이브러리/함수 내의 코드가 실행되고, 공격자가 의도한 코드가 실행되게 된다.
2. ZwProtectVirtualMemory
: ret2libc를 기반으로 하며, 다수의 ret2libc 함수를 체인으로 연결해 메모리 특정 부분의 실행 가능
여부를 재정의 한다.
프로세스별로도 가능하지만, 메모리별로도 가능하다는 것이 증명된 ZwProtectVirtualMemory.
3. Disable DEP for the process (NtSetInformationProcess)
: DEP가 여러 모드를 가지고 있기 때문에 OS는 기본적으로 각 프로세스에 대해 DEP를 해제할 수 있다.
NX 활성화 유무를 담당하는 코드를 가지는 핸들러나 API를 이용한다.
DEP 우회는 이렇게 한다 ! (Hardware DEP bypass)
1. Stack Pivot을 활용하여 ESP의 위치를 내린다.
2. ret2libc 기법을 활용하여 ESP로 점프한다.
3. ROP(Return-Oriented Programming)로 ZwProtectVirtualMemory를 구성하여
ShellCode 메모리 재 정의
4. ShellCode 실행
<TIP>
ESP+0x490을 하면 0x490오프셋만큼 "ESP 위치가 내려간다"
ROP 시 리턴을 해야하는데 중요한 사항에 대해 알아봄
RETN 8 : WINDOWS API함수는 Standard call 방식을 사용한다.
Windows API함수는 8바이트의 인자가 필요한데, 하나는 문자열, 하나는 주소 (각 4바이트씩)
WinExec는 4바이트 push 2번
call WinExec 실행
쭉 작업하고 RETN 8 하게 되면 위에서 4바이트 push한 값이 정리 되는 것
여기서도 pop pop ret를 사용하네. (가젯)
ex)
3000h *WinExec
3004h RET
3008h &("calc.exe") <- 실행할 어플리케이션의 주소 (4바이트)
300ch 0x0000 0005 <- SW_HIDE (4바이트)
ROP Weapon 중 VirtuallProtect를 사용할 것임
우선 VirtualProtect함수를 뜯어봐야함
4개의 인자가 필요하다.
BOOL WINAPI VirtualProtect
{
_In_ LPVOID lpAddress, // input
_In_ SIZE_T dwSize,
_In_ DWORD flNewProtect,
_Out_ PWORD lpflOldProtect // output
};
dwSize : 페이지 용량 재정의 -> 팁 : 스택 영역에 맞게 사이즈 조정을 해야함
flNewProtect : 어떤 속성을 정의할 것인지 판단 (Read Write Excute)
lpflOldProtect : NULL이 나올 수 없음. lpflOldProtect가 잘못되면 VirtualProtect 자체가 안됨
(즉, 쓰기 권한이 없으면 오류) -> VirtualProtect 못 씀
팁 : Immunity Debugger로 보면 정확히 RWE에 대해 알 수 있음
ROP Weapon :: VirtualProtect() design
3000h &VirtualProtect()
3004h &JMP ESP (중요)
3008h Auto(Shellcode addr)
300Ch 쉘 코드 크기
3010h RWE 속성 값 (0x40)
3014h 쓰기 가능한 주소
Register를 이용해서도 ROP를 디자인 할 수 있다.
하지만, 중요한건 esp를 하드코딩하면 문제가 생긴다.
ESP를 하드코딩하면 안되는 이유?
=>현 스택의 TOP을 찾을 수 없기 때문임.
ESP를 건들리지 않으면 생기는 장점
쉘코드를 리턴된 값에서 사용할 수 있다?
calc.exe - PUSHAD 후 스택 모습을 디자인 하면 이렇다
EDI RET
ESI *WinExec
EBP RET
ESP &("calc.exe")
EBX 0x0000 0005
EDX ...
ECX ...
EAX ...
*ESP calc.exe --> 그럼 현재 esp는 calc.exe의 주소가 되는 것
이제 드디어 ROP를 수집하는 것을 배워본다.
타겟 : 1.4.1 wireshark
mona.py는 실행 중인 바이너리의 가젯을 수집할 수 있다. 완전 개 쩔지 않음? ㅋㅋ
!mona rop -o # 운영체제 모드를 쓰지 않는 옵션 : -o
운영체제의 버전이 바뀔 수 있기 때문에 운영체제의 모듈은 수집하지 않는 것
(똑똑이)
ROP 검색방법 : Kali linux
니가 제일 편한걸로 해
[] : space
ROP 검색 방법 1
cat rop.txt | grep ":[][]# POP EAX #[]RETN[][][]**"
ROP 검색 방법 2 -E: 정규표현식
cat rop.txt | grep -E":[][]# POP .A. #[]RETN[][][]**" # .A. 하면 EAX가 검색 됨
ROP 검색 방법 3
cat rop.txt | grep ":[][]# MOV EAX, DWORD PTR ...:\[EAX\][]#[]RETN"
# 역슬래쉬 안쓰면 오류 발생 ~
EXAMPLE ) calc.exe PUSHAD 후 스택 모습
그림 1
EDI RET
ESI *WinExec
EBP RET
ESP &("calc.exe")
EBX 0x0000 0005
EDX ...
ECX ...
EAX ...
*ESP calc.exe --> 그럼 현재 esp는 calc.exe의 주소가 되는 것
그림 2
구성 가이드 실제 값
For EDI # POP EDI # RETN 0x64fa 0bc4
# RETN 0x64fa 0bc5
For ESI # POP ESI # RETN 0x0051 99e2
&WinExec 0X7c86 23ad
For EBX # POP EBX # RETN 0x64fa 09e6
0x0000 0005 0x0000 0005
For PUSHAD #PUSH AD #RETN 0x0046 0d9b
calc.exe 0x6361 6c63
\0 0x00
반드시 알아야 하는건, ret 하게 되면 esp는 내려간다.
자 우선 For EDI 부터 할 건데, For EDI라는 것을 EDI 레지스터안에 있는 값을 사용하겠다는 의미
지금 그림에선 EDI에 RET가 있으니 RET에 대한 실제 주소를 찾음(0x64fa 0bc5)
POP EDI 하는 순간 RETN의 실제 값 0x64fa 0bc5은 #RETN으로 들어감
RET 했으니 ESP가 내려가게 되고 지금 ESP가 내려가면 ESI가 실행 됨
POP ESI가 될 때 &WinExec를 꺼내어서 ESI에 넣음
그다음 또 RETN을 하게 되면 이제 ESP는 한 단계 더 내려가서 EBX를 가리킬 것이고
EBX에서 POP EBX가 될 때 0x0000 0005를 꺼내어 EBX에 넣을 것이고
마찬가지로 ret 하게 되면 또 다시 ESP가 내려가서 이번엔 PUSHAD를 가리킨다.
PUSHAD하면 EAX~EDI까지 쌓이게 됨
뭔소린가...... 했더니 이거네
PUSHAD는 EDI, ESI, EBX 순으로 스택에 쌓는 명령어지.
그렇다면 PUSHAD 딱 하는 순간
ESP-> [EBX]
[ESI]
[EDI] 가 스택에 쫜 올라가 있는데
스택은 LIFO니까 가장 마지막에 쌓인 EBX부터 POP EBX 하면서 ESP를 내려 가는거네
[EBX] (사라짐)
ESP-> [ESI]
[EDI]
[EBX] (사라짐)
[ESI] (사라짐)
ESP-> [EDI]
Windows XP dep 설정
우선 숨김해제 다 풀고
C드라이브의 boot.ini -> dep : alwayson
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=alwayson /fastdetect
Windows 7 이상
bcdedit.exe /set nx alwayson
ROP 실습 두둥... 존나 어려워보인다 ㅋㅋㅋㅋ
A-PDF All to MP3 Converter 내에 가젯을 사용하여 Stack으로부터 직접 어셈블리어로 계산기를
실행하는 ROP를 디자인해보자.
WinExec() 사용하여 계산기 실행 후 ExitProcess()로 프로그램을 정상 종료하도록 설계하자.
이 코드를 구성하는 ROP를 레지스터를 활용하여 그림으로 그려보자.. 와우...
'0x04 pwnable > 윈도우즈 어플리케이션 취약점 분석' 카테고리의 다른 글
ROP3 (0) | 2018.01.17 |
---|---|
ROP2 (0) | 2018.01.17 |
SEH Handler 우회 공부 (0) | 2018.01.09 |
SEH Handler 공부 (0) | 2018.01.09 |
SEH 기초공부 1 (0) | 2018.01.09 |