Mom? how can I pass my input to a computer program?
ssh input2@pwnable.kr -p2222 (pw:guest)
input2@pwnable:~$ 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
input2@pwnable:~$ cat input.c
#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
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;
}
STAGE1,STAGE5に従ってargvを入力します。
argv['A'] = '\x00' (STAGE1)
argv['B'] = '\x20\x0a\x0d'
argv['C'] = 4444 (STAGE5,接続するポート番号を指定する。)
STAGE2では標準入力と標準エラー出力に入力を渡す必要があるため、パイプを別々に作ってprocess()に渡します。ちなみにこれをssh接続からしようとするとpty等を意識する必要が出てきて一気に面倒になります。
STAGE3に従って環境変数をprocess()に渡し、STAGE5に従って先にファイルに'\x00\x00\x00\x00'を書き込んでおきます。
from pwn import *
import os
args = ['A']*100
args[65] = '\x00'
args[66] = '\x20\x0a\x0d'
args[67] = '4444'
r1, w1 = os.pipe()
r2, w2 = os.pipe()
os.write(w1, '\x00\x0a\x00\xff')
os.write(w2, '\x00\x0a\x02\xff')
with open('\x0a', 'w') as f:
f.write('\x00\x00\x00\x00')
p = process(executable='/home/input2/input',
argv=args,
stdin=r1, stderr=r2,
env={'\xde\xad\xbe\xef' :'\xca\xfe\xba\xbe'})
net = remote('localhost', 4444)
net.sendline('\xde\xad\xbe\xef')
p.interactive()
[*] Closed connection to localhost port 4444
input2@pwnable:/tmp/input212$ ln -s /home/input2/flag flag
input2@pwnable:/tmp/input212$ python input212.py
[+] Starting local process '/home/input2/input': pid 108561
[+] Opening connection to localhost on port 4444: 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 clear!
Stage 3 clear!
Stage 4 clear!
Stage 5 clear!
Mommy! I learned how to pass various input in Linux :)
[*] Process '/home/input2/input' stopped with exit code 0 (