pwn 공부가 필요하다..
졸라 갓모듈이다 진짜루;;
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
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
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;
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd == -1){
printf("socket error, tell admin\n");
return 0;
}
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons( atoi(argv['C']) );
if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){
printf("bind error, use another port\n");
return 1;
}
listen(sd, 1);
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;
}
각각의 스테이지들을 깨고나면 플래그를 먹을 수 있는 구조이다.
문제풀이는 사실상 pwn모듈 설명이 전부다
차근차근 한 스테이지씩 풀이해보겠다.
++ 홈디렉터리 말고 /tmp에 자기 소유의 폴더를 하나 파고 거기서 스크립트를 짜야 권한 문제가 발생하지 않는다.
[Stage 1]
from pwn import *
p = [str(i) for i in range(100)]
p[65] = '\x00'
p[66] = '\x20\x0a\x0d'
s = process(executable = '/home/input2/input', argv = p)
print s.recvuntil('Stage 1 clear!')
첫 스테이지는 쉽다. ( 근데 펄로 하면 안되더라 )
인자 100개에 65, 66번째 인자를 특정값으로 바꿔주면 된다.
[Stage 2]
from pwn import *
p = [str(i) for i in range(100)]
p[65] = '\x00'
p[66] = '\x20\x0a\0d'
fi = open('./in', 'a')
fi.write('\x00\x0a\x00\xff')
fe = open('./err', 'a')
fe.write('\x00\x0a\x02\xff')
s = process(executable = '/home/input2/input', argv = p, stderr = open('./err'), stdin = open('./in'))
print s.recvuntil('Stage 2 clear!')
표준 입출력 관련 입력이다.
파일에 쓰고 해당 파일의 서술자를 넘겨줘야한다. (솔찍히 좀 불편함 걍 문자열로 받으면 안되남 ㅇㅅㅇ)
[Stage 3]
from pwn import *
p = [str(i) for i in range(100)]
p[65] = '\x00'
p[66] = '\x20\x0a\x0d'
fi = open('./in', 'a')
fi.write('\x00\x0a\x00\xff')
fe = open('./err', 'a')
fe.write('\x00\x0a\x02\xff')
e = {"\xde\xad\xbe\xef" : "\xca\xfe\xba\xbe"}
s = process(executable = '/home/input2/input', argv = p, stderr = open('./err'), stdin = open('./in'), env = e)
print s.recvuntil('Stage 3 clear!')
[Stage 4]
from pwn import *
p = [str(i) for i in range(100)]
p[65] = '\x00'
p[66] = '\x20\x0a\x0d'
fi = open('./in', 'a')
fi.write('\x00\x0a\x00\xff')
fe = open('./err', 'a')
fe.write('\x00\x0a\x02\xff')
ff = open('./\x0a', 'a')
ff.write("\x00\x00\x00\x00")
e = {"\xde\xad\xbe\xef" : "\xca\xfe\xba\xbe"}
s = process(executable = '/home/input2/input', argv = p, stderr = open('./err'), stdin = open('./in'), env = e)
print s.recvuntil('Stage 4 clear!')
16진수 이름의 파일 만들고 내용 입력하기
[Stage 5]
from pwn import *
p = [str(i) for i in range(100)]
p[65] = '\x00'
p[66] = '\x20\x0a\x0d'
p[67] = '21212'
fi = open('./in', 'a')
fi.write('\x00\x0a\x00\xff')
fe = open('./err', 'a')
fe.write('\x00\x0a\x02\xff')
ff = open('./\x0a', 'a')
ff.write("\x00\x00\x00\x00")
e = {"\xde\xad\xbe\xef" : "\xca\xfe\xba\xbe"}
s = process(executable = '/home/input2/input', argv = p, stderr = open('./err'), stdin = open('./in'), env = e)
r = remote('127.0.0.1', 21212)
r.sendline("\xde\xad\xbe\xef")
print s.recvuntil('Stage 5 clear!')
s.interactive();
소켓 입출력
여기까지 하고나서 interactive()썼을 때 깔끔하게 나오면 좋겠지만 우리가 현재 작업하는 경로는 /tmp폴더이고 flag파일은 /home/input2에 있기 때문에 플래그를 출력하지 못하는 문제가 발생한다.
그냥 tmp폴더에 심볼릭 링크 하나 만들면 된다.
ln -s /home/input2/flag ./flag
하고 실행시키면 플래그 잘 나온다.
'write-up > pwnable.kr' 카테고리의 다른 글
[toddler's bottle] cmd2 (0) | 2018.12.03 |
---|---|
[toddler's bottle] cmd1 풀이 (0) | 2018.12.03 |
[toddler's bottle] mistake (0) | 2018.11.30 |
[toddler's bottle] random (0) | 2018.11.30 |
[toddler's bottle] passcode (0) | 2018.11.30 |