34번째 문제 가보자구!
ghidra로 이용해서 디컴파일했다
undefined8 main(void)
{
int iVar1;
long in_FS_OFFSET;
undefined8 *local_48;
undefined8 local_40;
char local_38 [40];
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
proc_init();
iVar1 = open("/dev/urandom",0);
read(iVar1,password,8);
close(iVar1);
puts("can u guess me?");
sleep(0);
read_input(local_38,0x20);
iVar1 = strncmp(password,local_38,8);
if (iVar1 == 0) {
system("cat flag");
}
else {
puts("wrong... :p");
puts("can you try another path? maybe impossible");
printf("> ");
read_input(&local_48,8);
printf("> ");
read_input(&local_40,8);
*local_48 = local_40;
puts("wish your happy sleep");
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 0;
}
지피티야 지피티야!
이 코드는 C로 작성된 프로그램의 일부분으로, 특정 기능을 수행하는 구조를 가지고 있습니다. 코드를 단계별로 분석하여 설명하겠습니다.
### 코드 분석
1. **함수 시그니처**:
```c
undefined8 main(void)
```
- `main` 함수가 정의되어 있으며, 반환형은 `undefined8`로 나타나 있습니다. 이는 `unsigned long` 또는 8바이트 정수를 반환하는 것으로 볼 수 있습니다.
2. **변수 선언**:
```c
int iVar1;
long in_FS_OFFSET;
undefined8 *local_48;
undefined8 local_40;
char local_38 [40];
long local_10;
```
- `iVar1`: 반환 값을 저장할 변수입니다.
- `in_FS_OFFSET`: 스택 보호를 위한 값입니다.
- `local_48`: 포인터로 사용될 변수를 저장합니다.
- `local_40`: 8바이트 정수로 사용될 변수입니다.
- `local_38`: 입력을 저장하기 위한 문자 배열입니다.
- `local_10`: 스택 보호를 위한 값을 저장하는 변수입니다.
3. **스택 보호 초기화**:
```c
local_10 = *(long *)(in_FS_OFFSET + 0x28);
```
- 스택 보호를 위한 초기값을 설정합니다. 이는 나중에 스택 오버플로우가 발생했는지 확인하는 데 사용됩니다.
4. **초기화 및 난수 읽기**:
```c
proc_init();
iVar1 = open("/dev/urandom",0);
read(iVar1,password,8);
close(iVar1);
```
- `proc_init()` 함수가 호출되어 초기화를 수행합니다.
- `/dev/urandom` 파일을 열어 8바이트의 랜덤 값을 읽어 `password` 변수에 저장합니다.
5. **사용자 입력 요청**:
```c
puts("can u guess me?");
sleep(0);
read_input(local_38,0x20);
```
- 사용자에게 "can u guess me?"라는 메시지를 출력합니다.
- `sleep(0)`는 즉시 반환되어 아무런 효과가 없습니다.
- `read_input(local_38, 0x20)`는 사용자로부터 입력을 받고 최대 32바이트(`0x20`)를 `local_38`에 저장합니다.
6. **비밀번호 비교**:
```c
iVar1 = strncmp(password, local_38, 8);
if (iVar1 == 0) {
system("cat flag");
}
```
- `password`와 `local_38`의 처음 8바이트를 비교합니다. 두 값이 같으면 `system("cat flag")`가 실행되어 플래그 파일의 내용을 출력합니다.
7. **잘못된 비밀번호 처리**:
```c
else {
puts("wrong... :p");
puts("can you try another path? maybe impossible");
printf("> ");
read_input(&local_48, 8);
printf("> ");
read_input(&local_40, 8);
*local_48 = local_40;
puts("wish your happy sleep");
}
```
- 비밀번호가 틀린 경우, "wrong... :p"라는 메시지를 출력하고 다른 입력을 요청합니다.
- 사용자로부터 두 개의 추가 입력을 받아서 `local_48` 포인터가 가리키는 메모리 주소에 `local_40`의 값을 저장합니다. 이는 버퍼 오버플로우 공격을 수행할 수 있는 기회를 제공합니다.
8. **스택 보호 검사**:
```c
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
__stack_chk_fail();
}
```
- 스택 보호 변수가 변경되었는지 확인하여, 만약 변경되었다면 프로그램이 비정상적으로 종료됩니다.
9. **종료**:
```c
return 0;
```
- 프로그램이 정상적으로 종료됩니다.
### 요약
이 프로그램은 사용자가 8바이트 길이의 비밀번호를 입력하도록 요구하고, 입력한 비밀번호가 랜덤으로 생성된 비밀번호와 일치하는지 확인합니다. 일치하면 플래그를 출력하고, 일치하지 않으면 추가 입력을 받아 그 값을 다른 메모리 주소에 저장하는데, 이는 버퍼 오버플로우 공격을 수행할 수 있는 기회를 제공합니다. 스택 보호 메커니즘이 도입되어 있어, 스택이 변경되면 프로그램이 종료됩니다.
### 플래그를 획득하는 방법
- **비밀번호 맞추기**: `/dev/urandom`에서 생성된 비밀번호를 맞추면 플래그를 얻을 수 있습니다. 하지만 이를 맞추는 것은 난이도가 높습니다.
- **버퍼 오버플로우**: 추가 입력을 통해 메모리 주소를 조작하여 공격을 시도할 수 있습니다.
이 프로그램의 취약점을 이용해 플래그를 확보하는 방법에 대한 질문이 있으시면 더 도와드리겠습니다!
랜덤으로 생성되는 나수를 어떻게 맞추죠
살려줘
버퍼 오버플로우 공격인건가..
하지만 질문글에서 흰트를 봤을때는
`strncmp` 함수의 허점을 이용하여 취약한 프로그램을 공격하는 방법은 버퍼 오버플로우 또는 비밀번호 유추 공격과 관련이 있습니다. 아래에서는 `strncmp`를 이용한 공격 방법에 대한 설명을 드리겠습니다.
### `strncmp`의 기능
`strncmp` 함수는 두 문자열을 지정된 길이만큼 비교합니다. 두 문자열이 같으면 0을 반환하고, 다르면 다른 값을 반환합니다. 주의할 점은 `strncmp`가 문자열의 길이를 제한하여 비교를 수행하기 때문에, 길이가 짧은 문자열과 길이가 긴 문자열의 비교에서 정확하게 일치하지 않을 수 있습니다.
### 공격 방법
1. **비밀번호 유추**:
- 프로그램이 `/dev/urandom`에서 생성한 비밀번호의 첫 8바이트와 사용자가 입력한 값만 비교합니다.
- 사용자가 비밀번호를 입력할 때, 랜덤 값의 길이가 8바이트로 제한되기 때문에, 사용자가 입력하는 문자열이 8바이트 이상인 경우 여전히 비교는 첫 8바이트만 수행됩니다.
2. **시간적 측면에서의 공격**:
- `strncmp`는 두 문자열을 비교할 때, 일치하지 않는 첫 번째 문자까지의 모든 문자를 비교하기 때문에, 비밀번호와 입력값의 일치 여부에 따라 함수가 반환되는 시간이 다를 수 있습니다.
- 예를 들어, 비밀번호의 첫 문자와 입력한 문자열의 첫 문자가 다르다면, `strncmp`는 즉시 반환되지만, 두 문자열의 첫 문자가 일치한다면 계속해서 다음 문자를 비교하게 됩니다. 이렇게 되면, 올바른 비밀번호를 찾기 위한 브루트 포스 공격을 시도할 수 있습니다.
### 공격 절차
1. **패턴 분석**:
- 비밀번호의 첫 문자부터 차례대로 유추해 나가는 방식입니다. 예를 들어, 비밀번호가 `abcd1234`라면, 먼저 `a`, 그 다음 `b`를 유추해 나갑니다.
2. **비교 과정**:
- 각 문자를 추측하여 입력하고, 프로그램의 응답 시간을 측정합니다. 입력한 문자가 올바르면 다음 문자로 진행하고, 틀리면 다른 문자를 시도합니다.
3. **자동화**:
- 위의 과정을 자동화할 수 있습니다. 스크립트를 작성하여 가능한 모든 문자를 시도하고, 그 결과를 기록하여 올바른 비밀번호를 찾아낼 수 있습니다.
### 예시 코드
아래는 위에서 설명한 방식을 자동화하는 간단한 예시 코드입니다. 이 코드는 비밀번호 길이가 8자라고 가정합니다.
```python
import time
import string
import subprocess
# 비밀번호의 길이
password_length = 8
# 가능한 모든 문자 집합 (예: 소문자, 대문자, 숫자)
charset = string.ascii_lowercase + string.ascii_uppercase + string.digits
def guess_password():
guess = ['a'] * password_length # 초기값으로 'aaaaaaa' 설정
for i in range(password_length):
for char in charset:
guess[i] = char # 현재 자리의 문자를 변경
start_time = time.time() # 시간 측정 시작
# 입력값을 프로그램에 전달
process = subprocess.Popen(['./chal'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output, error = process.communicate(input=''.join(guess).encode())
elapsed_time = time.time() - start_time # 경과 시간 계산
# 반환된 출력이나 시간에 따라 결과를 분석
if "wrong..." not in output.decode(): # 잘못된 입력이 없을 경우
print("Found password: ", ''.join(guess))
return
print(f'Trying {"".join(guess)} - Time: {elapsed_time:.5f}s')
# 비밀번호 추측 함수 호출
guess_password()
```
https://supervingo.tistory.com/152
Dreamhack - Broken Password
처음에는 포인트 조작인가 했는데, strncmp로 password(/dev/urandom)값이랑 비교한다.입력으로 null을 주면 0이랑 비교하는데, stnrcmp는 null이후는 비교하지 않으니까 그냥 null로 브포하면 된다...
supervingo.tistory.com
https://hyungin0505.tistory.com/90
[DreamHack] Broken Password #634
int __fastcall main(int argc, const char **argv, const char **envp){ int fd; // [rsp+Ch] [rbp-44h] _QWORD *v5; // [rsp+10h] [rbp-40h] BYREF __int64 v6; // [rsp+18h] [rbp-38h] BYREF char s2[40]; // [rsp+20h] [rbp-30h] BYREF unsigned __int64 v8; // [rsp+48h]
hyungin0505.tistory.com
gpt가 준 소스코드로 python3파일 만들어서 브포하는데 오류뜬다
하
살려줘..
2024-10-22
다시 문제 풀러왔다
드림핵 qna를 보면 strncmp() 허점을 이용하면 된다했다
난수인 password가 \x00으로 시작하는 경우, input으로 null을 넣으면
그냥 바로 같은 문자열로 인식하는?...그런 거라고 함.
그래서 확률적으로 256번 null을 쏘는 코드를 만들면 그 중에 한 번은 플래그를 얻을 수 있다...
출처: https://hxxxxng.tistory.com/52
입력으로 null을 주면 0이랑 비교하는데, stnrcmp는 null이후는 비교하지않으니까 그냥 null로 브포하면 된다
출처 ㅣ https://supervingo.tistory.com/152
gpt:
이 코드는 **DreamHack**의 문제를 풀기 위한 Python 스크립트로, **pwntools** 라이브러리를 사용하여 원격 서버와 통신하는 프로그램입니다. `pwntools`는 주로 **취약점 탐색 및 익스플로잇**을 자동화하는 데 사용됩니다. 아래에서 이 코드를 단계별로 설명하겠습니다.
### 주요 목적:
- 서버에 반복적으로 연결을 시도하며, 서버가 맞추기를 요구하는 값을 보내서 **특정 응답**을 찾는 작업을 합니다.
- 서버에서 'DH' 문자열이 포함된 응답을 받을 때까지 반복합니다.
### 코드 설명:
1. **`from pwn import *`**:
- `pwntools` 라이브러리에서 모든 기능을 임포트합니다. 이 라이브러리는 **원격 연결**, **패킷 송수신**, **익스플로잇** 등을 쉽게 할 수 있게 도와줍니다.
2. **`while True:`**:
- **무한 루프**를 사용하여, 조건을 만족할 때까지 계속 서버에 연결하고 데이터를 보내는 과정을 반복합니다.
3. **`r = remote("host3.dreamhack.games", 12955)`**:
- DreamHack 서버 `host3.dreamhack.games`의 **포트 12955**에 연결합니다. 이 포트는 서버가 데이터를 받을 준비가 되어 있는 특정 서비스나 프로그램을 의미합니다.
4. **`r.recvuntil(b'can u guess me?\n')`**:
- 서버로부터 **"can u guess me?"**라는 메시지를 받을 때까지 데이터를 기다립니다. `recvuntil()` 함수는 주어진 문자열이 수신될 때까지 데이터를 읽습니다.
- `b'can u guess me?\n'`는 **바이트 문자열**로, 서버에서 보내는 메시지를 그대로 받는 형식입니다.
5. **`r.send(b'\0')`**:
- 서버에 **null 바이트** (`\0`)를 전송합니다. 이 메시지는 사용자가 서버가 요청한 값을 "맞추기" 위해 보낸 값입니다. 여기서 `\0`은 **null 바이트**로, 정수로는 0을 의미합니다.
6. **`res = r.recv(100)`**:
- 서버로부터 **최대 100바이트**의 응답을 받습니다. 이 응답은 서버가 클라이언트(이 코드)를 처리한 결과로 보내는 데이터입니다.
- 이 데이터를 **`res`**라는 변수에 저장합니다.
7. **`r.close()`**:
- 서버와의 연결을 종료합니다. 이를 통해 메모리 누수를 방지하고 불필요한 연결을 차단합니다.
8. **`if b'DH' in res:`**:
- 서버로부터 받은 응답(`res`)에 **`'DH'`라는 문자열이 포함되어 있는지** 확인합니다. DreamHack과 관련된 문제에서는 주로 `DH`로 시작하는 플래그를 사용하므로, 이 문자열을 찾습니다.
9. **`print(res)`**:
- `res`에 `'DH'` 문자열이 포함되어 있을 경우, **응답을 출력**합니다. 주로 이 응답에는 **플래그**나 문제 해결의 중요한 정보가 들어 있습니다.
10. **`break`**:
- `while True` 무한 루프를 종료합니다. 즉, `'DH'`가 포함된 응답을 받으면 루프가 끝나고 프로그램이 종료됩니다.
### 동작 요약:
1. **DreamHack 서버**에 계속 연결합니다.
2. 서버에서 **"can u guess me?"** 메시지를 받을 때까지 대기합니다.
3. 서버가 값을 맞추라고 요청하면 **null 바이트 (`\0`)**를 서버에 전송합니다.
4. 서버가 반환한 응답에서 **'DH'** 문자열을 찾습니다.
5. **'DH'** 문자열이 포함된 응답을 받으면, 응답을 출력하고 프로그램을 종료합니다.
### 목적:
이 코드는 DreamHack 서버에서 **특정 문자열 ('DH')**을 포함하는 응답을 받을 때까지 계속해서 시도하는 작업입니다. 일반적으로 이런 코드는 **플래그**를 찾거나 **취약점**을 탐지하기 위해 사용됩니다.
야무지다 야무져..
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[36] IT 비전공자 [dreamhack]xss-1문제 풀기 (0) | 2024.10.15 |
---|---|
[35] IT 비전공자 [dreamhack]session-basic문제 풀기 (0) | 2024.10.14 |
[33] IT 비전공자 [dreamhack]Path Finder문제 풀기 (0) | 2024.10.12 |
[32] IT 비전공자 [dreamhack] whatsdifferent문제 풀기 (0) | 2024.10.11 |
[31] IT 비전공자 [dreamhack] addition-quiz문제 풀기 (0) | 2024.10.10 |