Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- shellcode
- picoCTF
- Leak
- pwnable
- TUCTF
- Bug
- Toddler's Bottle
- Rookiss
- writeup
- pwnable.kr
- ASM
- reversing
- Read
- toddler
- pwn
- rev
- CTF
- Reverse
- practicalmalwareanalysis
- 2018
- shellcraft
- CANARY
- format
- FSB
- BOF
- pico
- string
- Bottle
- anti
- PMA
Archives
- Today
- Total
제리의 블로그
pwnable.kr input 본문
input - 4 pt
Mom? how can I pass my input to a computer program?
ssh input2@pwnable.kr -p2222 (pw:guest)
뭔가 입력할 것이 많아보이는 문제입니다.
input2@ubuntu:~$ ls -l
total 24
-r--r----- 1 input2_pwn root 55 Jun 30 2014 flag
-r-sr-x--- 1 input2_pwn input2 13250 Jun 30 2014 input
-rw-r--r-- 1 root root 1754 Jun 30 2014 input.c
이번 문제도 소스코드가 주어졌습니다.
Stage 1
// 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");
인자 100개인데
argv 의 'A' 번째와 'B' 번째의 데이터가 지정되어 있습니다.
'A' 번째란 ascii code 로 변환했을 때의 값으로 0x41 이고
'B' 번째란 ascii code 로 변환했을 때의 값으로 0x42 입니다.
$ ./input `python -c 'print "1 "*0x40+"\x00 "+"\x20\x0a\x0d "+"2 "*(99-0x42)'`
그러나 위와같이 해보니
쉘에서 "\x00" 은 EOF이므로 페이로드가 끊깁니다.
그렇기 때문에 스크립트를 실행하는 방식으로 하게 되는데요
from pwn import *
p = ['/home/input2/input'] + ['\0'] * 0x41 + ['\x20\x0a\x0d'] + ['1'] * (99 - 0x42)
p = process(p)
p.interactive()
$ python a.py
[+] Starting local process '/home/input2/input': Done
[*] Switching to interactive mode
Welcome to pwnable.kr
Let's see if you know how to give input to program
Just give me correct inputs then you will get the flag :)
Stage 1 clear!
stage 2
// 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");
file descriptor 에는 stdin - 0, stdout - 1, stderr - 2 가 있습니다.
pipe() 를 통해서 입력했습니다.
# Stage 2
fd1 = os.pipe()
fd2 = os.pipe()
os.write(fd1[1], "\x00\x0a\x00\xff")
os.write(fd2[1], "\x00\x0a\x02\xff")
p = process(p, stdin=fd1[0], stderr=fd2[0])
for i in range(2):
os.close(fd1[i])
os.close(fd2[i])
print p.recvuntil('Stage 2 clear!')
stdin 은 p.send('\x00\x0a\x00\xff') 로 대체 가능합니다.
Stage 3
// env
if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;
printf("Stage 3 clear!\n");
변수명 "\xde\xad\xbe\xef" 의 데이터는 "\xca\xfe\xba\xbe" 여야 한다.
$ export `echo -e "\xde\xad\xbe\xef=\xca\xfe\xba\xbe"`
bash: export: `ޭ��=����': not a valid identifier
export 하는 법을 모르겠다.
그래서 python 코드에 넣어보았다.
e = {"\xde\xad\xbe\xef":"\xca\xfe\xba\xbe"}
p = process(p, stdin=fd1[0], stderr=fd2[0], env=e)
$ python a.py
[+] Starting local process './input': pid 1026
[*] Process './input' stopped with exit code 0 (pid 1026)
[*] Switching to interactive mode
Stage 3 clear!
Exception in thread Thread-2:
...
Stage 4
// 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");
이번엔 파일 "\x0a" 를 읽어는데 내용이 "\x00\x00\x00\x00" 이어야 한다.
# Stage 4
with open('\x0a', 'w') as f:
f.write("\x00\x00\x00\x00")
$ python a.py
[+] Starting local process './input': pid 1096
[*] Switching to interactive mode
Stage 4 clear!
$
Stage 5
// 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");
Stage 5 는 socket 을 열어서 4 bytes 의 데이터를 받습니다.
48번째 줄에 의하면 argv[67] 이 포트 번호가 됩니다.
그리고 입력되는 데이터는 "\xde\xad\xbe\xef" 입니다.
# Stage 5
r = remote('localhost', int(arg[67]))
r.send("\xde\xad\xbe\xef")
r.close()
$ python a.py
[+] Starting local process './input': pid 1323
[+] Opening connection to localhost on port 7000: Done
[*] Closed connection to localhost port 7000
[*] Switching to interactive mode
[*] Process './input' stopped with exit code 0 (pid 1323)
Stage 5 clear!
Exception in thread Thread-3:
...
AttributeError: 'NoneType' object has no attribute 'closed'
$
Hiden Stage?
// here's your flag
system("/bin/cat flag");
return 0;
fopen("","w") 파일 작성하는것도 있고 해서
작업하는 디렉토리가 /tmp/*/ 입니다.
그런데 flag 파일이 상대주소입니다.
그래서 심볼릭 링크를 사용합니다.
$ ln -s /home/input2/flag flag
input2@ubuntu:/tmp/1710201420$ python a.py
[+] Starting local process '/home/input2/input': Done
[+] Opening connection to localhost on port 7000: Done
[*] Closed connection to localhost port 7000
Stage 5 clear!
[*] Switching to interactive mode
Mommy! I learned how to pass various input in Linux :)
...
$
'Wargame > pwnable.kr' 카테고리의 다른 글
pwnable.kr syscall (0) | 2018.09.04 |
---|---|
pwnable.kr fix (0) | 2018.09.03 |
pwnable.kr random (0) | 2018.08.30 |
pwnable.kr passcode (0) | 2018.08.29 |
pwnable.kr flag (0) | 2018.08.29 |
Comments