zoukankan      html  css  js  c++  java
  • day2

    pwnable

    input2

     本题要求对目标文件进行正确的输入。查看源代码,该程序需要5次不同的输入,只有全部输入正确才能得到flag。

    第一次是命令行参数,源代码如下:

    if(argc != 100) return 0;
    if(strcmp(argv['A'],"x00")) return 0;
    if(strcmp(argv['B'],"x20x0ax0d")) return 0;
    printf("Stage 1 clear! ");

    可以看到,命令行参数个数必须为100,'A'的ascii码为67,'B'为68,这两个位置的命令行参数必须为"x00"和"x20x0ax0d",这里我先试着用python直接打印参数的方式输入,结果由于x00的存在执行不成功。还是得写一个程序来运行,且后面其余输入也一并写进去。我们可以用execv()函数来执行input,并以命令行参数作为其参数

    char *argv[101] = {"~/input", [1 ... 99] = "a", NULL};
    argv['A'] = "x00";
    argv['B'] = "x20x0ax0d";

    然后使用execve("/home/input2/input", argv, NULL);

    执行这个程序即可完成第一阶段的输入

    第二阶段要求从标准输入流和标准错误流读取数据

    char buf[4];
    read(0, buf, 4);
    if(memcmp(buf, "x00x0ax00xff", 4)) return 0;
    read(2, buf, 4);
    if(memcmp(buf, "x00x0ax02xff", 4)) return 0;
    printf("Stage 2 clear! ");

    正常情况下我们是不能直接向标准错误流输入数据的,可以通过管道来实现对标准输入流与标准错误流的输入。

    使用pipe可以将一个二元整形数组通过系统调用变为输入/输出文件标识符,[0]为输入,[1]为输出。所谓管道是用来给父进程与子进程通信的,若子进程要向父进程传输数据时,关闭[0]并将数据写入[1]中,然后父进程关闭[1]即可从[0]读取数据。我们要做的就是创建一个子进程,将需要的数据传入子进程的[1]中,然后父进程关闭[1],将[0]转换位标准输入流或标准错误流,这样标准输入流与标准错误流中就有我们需要的数据了,代码如下:

    int stdout_pipe[2] = {-1, -1};
    int stderr_pipe[2] = {-1, -1};
    pid_t child_pid;
    pipe(stdout_pipe);
    pipe(stderr_pipe);
    
    child_pid = fork(); 
    
    if (child_pid == 0) 
    { 
    close(stdout_pipe[0]); 
    close(stderr_pipe[0]); 
    write(stdout_pipe[1], "x00x0ax00xff", 4); 
    write(stderr_pipe[1], "x00x0ax02xff", 4); 
    } 
    else 
    { 
    close(stdout_pipe[1]); 
    close(stderr_pipe[1]); 
    dup2(stdout_pipe[0], 0); 
    dup2(stderr_pipe[0], 2); 
    close(stdout_pipe[0]); 
    close(stderr_pipe[0]); 
    char* env[2] = {"xdexadxbexef=xcaxfexbaxbe", NULL};
    execve("/home/input2/input", argv, NULL); 
    }

    第三阶段和第四阶段分别是环境变量读取和文件读取,环境变量可直接作为execv函数的参数直接传入,而文件直接创建并写入数据即可

    FILE* fp = fopen("x0a", "w");
    fwrite("x00x00x00x00", 4, 1, fp);
    fclose(fp);

    char* env[2] = {"xdexadxbexef=xcaxfexbaxbe", NULL};
    execve("/home/input2/input", argv, env);

    第五阶段是网络的通信,input程序会将命令行参数的第67个作为侦听端口,从中接收要求的数据,所以第五阶段的本质就是网络编程,先设置好端口,再向该端口传输要求的数据即可,代码如下

    argv['C'] = "666666";

    int csock;
    struct sockaddr_in server;
    csock = socket(AF_INET, SOCK_STREAM, 0);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_port = htons(666666);
    connect(csock, (struct sockaddr*)&server, sizeof(server));
    char buf[4] = "xdexadxbexef";
    write(csock, buf, 4);
    close(csock);

    输入全部正确后flag就被打印出来了。

  • 相关阅读:
    LINUX的SSH下FTP到远程服务器Entering Passive Mode失败解决
    LINUX的SSH下FTP到远程服务器Entering Passive Mode失败解决
    LINUX的SSH下FTP到远程服务器Entering Passive Mode失败解决
    git rm简介
    git rm简介
    git rm简介
    linux rz -e
    新版住院电子病历首页 (2012年修订说明)
    DateEdit和TimeEdit用法
    ORA-22868: 具有 LOB 的表包含有位于不同表空间的段
  • 原文地址:https://www.cnblogs.com/amlkhlwd33/p/9404429.html
Copyright © 2011-2022 走看看