pwnable input2 之 write up
首先看源代码:
1 input2@ubuntu:~$ cat input.c 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <sys/socket.h> 6 #include <arpa/inet.h> 7 8 int main(int argc, char* argv[], char* envp[]){ 9 printf("Welcome to pwnable.kr\n"); 10 printf("Let's see if you know how to give input to program\n"); 11 printf("Just give me correct inputs then you will get the flag :)\n"); 12 13 // argv 14 if(argc != 100) return 0; 15 if(strcmp(argv['A'],"\x00")) return 0; 16 if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0; 17 printf("Stage 1 clear!\n"); 18 19 // stdio 20 char buf[4]; 21 read(0, buf, 4); 22 if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0; 23 read(2, buf, 4); 24 if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0; 25 printf("Stage 2 clear!\n"); 26 27 // env 28 if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0; 29 printf("Stage 3 clear!\n"); 30 31 // file 32 FILE* fp = fopen("\x0a", "r"); 33 if(!fp) return 0; 34 if( fread(buf, 4, 1, fp)!=1 ) return 0; 35 if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0; 36 fclose(fp); 37 printf("Stage 4 clear!\n"); 38 39 // network 40 int sd, cd; 41 struct sockaddr_in saddr, caddr; 42 sd = socket(AF_INET, SOCK_STREAM, 0); 43 if(sd == -1){ 44 printf("socket error, tell admin\n"); 45 return 0; 46 } 47 saddr.sin_family = AF_INET; 48 saddr.sin_addr.s_addr = INADDR_ANY; 49 saddr.sin_port = htons( atoi(argv['C']) ); 50 if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){ 51 printf("bind error, use another port\n"); 52 return 1; 53 } 54 listen(sd, 1); 55 int c = sizeof(struct sockaddr_in); 56 cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c); 57 if(cd < 0){ 58 printf("accept error, tell admin\n"); 59 return 0; 60 } 61 if( recv(cd, buf, 4, 0) != 4 ) return 0; 62 if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0; 63 printf("Stage 5 clear!\n"); 64 65 // here's your flag 66 system("/bin/cat flag"); 67 return 0; 68 }
1 argv['A'] = "\x00";
argv['B'] = "\x20\x0a\x0d";
argv['C'] ="55555";
这里可以用’A’作为参数的索引,这是原来没有见过的,默认把字符转换成ASCII码了。
2 execve函数
execve(执行文件)在父进程中fork一个子进程,在子进程中调用exec函数启动新的程序。exec函数一共有六个,其中execve为内核级系统调用,其他(execl,execle,execlp,execv,execvp)都是调用execve的库函数。
int execve(const char * filename,char *const argv[ ],char * const envp[ ]);
execve()用来执行参数filename字符串所代表的文件路径
第二个参数是利用指针数组来传递给执行文件,并且需要以空指针(NULL)结束
最后一个参数则为传递给执行文件的新环境变量数组
3 进程间通信(以后再补上)
4 socket编程
一般的模式:
(1)建立套接字:sockfd = socket(AF_INET,SOCK_STREAM,0)
AF_INET:IPV4
SOCK_STREAM:TCP
最后一个参数一般为0
(2)设置socket_in结构中的参数(套接字地址),包括Ip、端口和IPV4or6
http://www.cnblogs.com/hnrainll/archive/2011/04/24/2026432.html
(3)bind监听函数
http://blog.chinaunix.net/uid-24954950-id-2956469.html
(4)listen函数
http://blog.chinaunix.net/uid-25749806-id-348681.html
(5)accpet函数
http://blog.chinaunix.net/uid-25749806-id-348689.html
(6)recv/send函数
http://www.cnblogs.com/blankqdb/archive/2012/08/30/2663859.html
还是不太明白,这题在搞什么