zoukankan      html  css  js  c++  java
  • pwnable.kr input解题记录

    pwnable input解题记录

    给了源码如下:

    #include "stdio.h"
    #include "unistd.h"
    #include "stdlib.h"
    #include "arpa/inet.h"
    
    int main(){
    
    	//stage argv
    	char *argv[101] = {"/home/input2/input", [1 ... 99] = "A", NULL};
    	argv['A'] = "x00";
    	argv['B'] = "x20x0ax0d";
    	argv['C'] = "55555";
    
    	//stage stdio
    	int pipe2stdin[2] = {-1, -1};
    	int pipe2stderr[2] = {-1, -1};
    	pid_t childpid;
    
    	//stage file
    	FILE* fp = fopen("x0a", "w");
    	fwrite("x00x00x00x00", 4, 1, fp);
    	fclose(fp);
    
    	if(pipe(pipe2stdin) < 0 || pipe(pipe2stderr) < 0)
    	{
    		perror("Cannot create the pipe!");
    		exit(1);
    	}
    	if((childpid = fork()) < 0)
    	{
    		perror("Cannot fork!");
    		exit(1);
    	}
    	if(childpid == 0)
    	{
    		close(pipe2stdin[0]);  //close pipes of read
    		close(pipe2stderr[0]);
    		
    		write(pipe2stdin[1], "x00x0ax00xff", 4);
    		write(pipe2stderr[1], "x00x0ax02xff", 4);
    	}
    	else{
    		close(pipe2stdin[1]); close(pipe2stderr[1]);   //close pipes of write
    		dup2(pipe2stdin[0], 0); dup2(pipe2stderr[0], 2);
    		close(pipe2stdin[0]); close(pipe2stderr[0]);
    		
    		//stage env
    		char *envp[2] = {"xdexadxbexef=xcaxfexbaxbe", NULL};
    	
    		execve("/home/input2/input", argv, envp);
    	}
    	sleep(2);
    	int sockfd;
    	struct sockaddr_in server;
    	sockfd = socket(AF_INET, SOCK_STREAM, 0);
    	if(sockfd < 0){
    		perror("Socket build error!");
    		exit(1);
    	}
    	server.sin_family = AF_INET;
    	server.sin_addr.s_addr = inet_addr("127.0.0.1");
    	server.sin_port = htons(55555);
    	if(connect(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0){
    		perror("Connect error!");
    		exit(1);
    	}
    	char buf[4] = "xdexadxbexef";
    	write(sockfd, buf, 4);
    	close(sockfd);
    	
    	return 0;
    }
    

    是为了让解题者满足代码中所需要满足的条件,总共5个,分别包括:参数传递、标准输入输出、环境变量、文件读写以及网络通信方面。

    1.argv

      参数第'A''B'位分别为"x00"和"x20x0ax0d",也就是第65位和第66位(第0位为可执行文件的路径),但是'x00'会截断。
      于是使用execve运行input文件,execve函数在unistd(unix standard)头文件中:

    int execve(const char *path, char *const argv[], char *const envp[]);

    以argv参数进行传递相应参数。

    2.stdio

    ssize_t read(int fildes, void *buf, size_t nbytes);

    摘自 http://codewiki.wikidot.com/c:system-calls:read

    Field Description
    int fildes The file descriptor of where to read the input. You can either use a file descriptor obtained from the open system call, or you can use 0, 1, or 2, to refer to standard input, standard output, or standard error, respectively.
    const void *buf A character array where the read content will be stored.
    size_t nbytes The number of bytes to read before truncating the data. If the data to be read is smaller than nbytes, all data is saved in the buffer.
    return value Returns the number of bytes that were read. If value is negative, then the system call returned an error.

      可以看到分别需要从stdinstderr读取相关的数据,但是stderr没法写,于是需要用到c中的叫做管道(pipe)的东西可用于子进程与父进程之间的通讯使用;于是子进程向缓冲区写数据,而父进程先将定义的相应缓冲区分别替换stdin和stderr,之后则可以从缓冲区进行读取。

    3.env

      getenv函数获取系统中环境变量,这个同样以execve进行处理,其中的envp参数进行传递。

    4.file

      常规操作,自己创建一个文件,然后写"x00x00x00x00"进去然后再读即可。

    5.network

      是以传递的第C个参数作为监听端口,以及socket通信获取传来的消息,采用本地通信。socket网络编程网上一搜就出来的,其实百度百科说的还挺清楚的...中间需要sleep几秒等待接收信息的服务开启,然后传递信息。


      最后在/tmp目录下面可以创建一个文件xxx,但是由于后面还得创建一个与/home/input2/flag的软链接(因为在/tmp目录下仍然没有权限cat flag),因为在运行input2文件时路径还是相对路径:

    ln -s /home/input2/flag flag

    之后创建一个c文件编译运行即可。
    代码整理:

    #include "stdio.h"
    #include "unistd.h"
    #include "stdlib.h"
    #include "arpa/inet.h"
    
    int main(){
    
    	//stage argv
    	char *argv[101] = {"/home/input2/input", [1 ... 99] = "A", NULL};
    	argv['A'] = "x00";
    	argv['B'] = "x20x0ax0d";
    	argv['C'] = "55555";
    
    	//stage stdio
    	int pipe2stdin[2] = {-1, -1};
    	int pipe2stderr[2] = {-1, -1};
    	pid_t childpid;
    
    	//stage file
    	FILE* fp = fopen("x0a", "w");
    	fwrite("x00x00x00x00", 4, 1, fp);
    	fclose(fp);
    
    	if(pipe(pipe2stdin) < 0 || pipe(pipe2stderr) < 0)
    	{
    		perror("Cannot create the pipe!");
    		exit(1);
    	}
    	if((childpid = fork()) < 0)
    	{
    		perror("Cannot fork!");
    		exit(1);
    	}
    	if(childpid == 0) //child process 
    	{
    		close(pipe2stdin[0]);  //close pipes of read
    		close(pipe2stderr[0]);
    		
    		write(pipe2stdin[1], "x00x0ax00xff", 4);
    		write(pipe2stderr[1], "x00x0ax02xff", 4);
    	}
    	else{            //parent process
    		close(pipe2stdin[1]); close(pipe2stderr[1]);   //close pipes of write
    		dup2(pipe2stdin[0], 0); dup2(pipe2stderr[0], 2);    //change stdin and stderr 
    		close(pipe2stdin[0]); close(pipe2stderr[0]);
    		
    		//stage env
    		char *envp[2] = {"xdexadxbexef=xcaxfexbaxbe", NULL};
    	
    		execve("/home/input2/input", argv, envp);
    	}
    	sleep(2);
    	int sockfd;
    	struct sockaddr_in server;
    	sockfd = socket(AF_INET, SOCK_STREAM, 0);
    	if(sockfd < 0){
    		perror("Socket build error!");
    		exit(1);
    	}
    	server.sin_family = AF_INET;
    	server.sin_addr.s_addr = inet_addr("127.0.0.1");
    	server.sin_port = htons(55555);
    	if(connect(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0){
    		perror("Connect error!");
    		exit(1);
    	}
    	char buf[4] = "xdexadxbexef";
    	write(sockfd, buf, 4);
    	close(sockfd);
    	
    	return 0;
    }
    

    参考链接:https://werewblog.wordpress.com/2016/01/11/pwnable-kr-input/

  • 相关阅读:
    sql左外连接、右外连接、group by、distinct(区别)、intersect(交叉)、通配符、having
    nvarchar,varchar 区别
    链家笔试链家——找寻最小消费获取最大平均分java
    利用SpringAOP 实现 日志输出
    AOP 学习笔记
    Spring AOP中pointcut expression表达式解析
    基于@Aspect的AOP配置
    URI 中特殊字符处理
    给电脑设置视力保护色
    Spring不支持依赖注入static静态变量
  • 原文地址:https://www.cnblogs.com/zUotTe0/p/10125533.html
Copyright © 2011-2022 走看看