Solution of the task with pwnable.kr 07 - input. Understanding pwntools

    image

    In this article, we will analyze the solution of a multi-level task using the pwntools library .

    Organizational Information
    Especially for those who want to learn something new and develop in any of the areas of information and computer security, I will write and talk about the following categories:

    • PWN;
    • cryptography (Crypto);
    • network technologies (Network);
    • reverse (Reverse Engineering);
    • steganography (Stegano);
    • search and exploitation of WEB vulnerabilities.

    In addition to this, I will share my experience in computer forensics, analysis of malware and firmware, attacks on wireless networks and local area networks, conducting pentests and writing exploits.

    So that you can find out about new articles, software and other information, I created a channel in Telegram and a group to discuss any issues in the field of ICD. Also, I will personally consider your personal requests, questions, suggestions and recommendations personally and will answer everyone .

    All information is provided for educational purposes only. The author of this document does not bear any responsibility for any damage caused to someone as a result of using knowledge and methods obtained as a result of studying this document.

    Input job solution


    We click on the icon with the signature input, and we are told that we need to connect via SSH with the password guest.

    image

    When connected, we see the corresponding banner.

    image

    Let's find out what files are on the server, as well as what rights we have.

    ls -l

    image

    Thus, we can read the source code of the program, since there is a right to read for everyone, and execute the input program with the rights of the owner (the sticky bit is set). Let's see the outcome of the code.

    Source Code input.c
    #include 
    #include 
    #include 
    #include 
    #include 
    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;
    }


    From the code it follows that we need to go through five levels. We will take them in turn.

    image

    At the first level, it is checked that the number of program arguments is 100. In this case, the 65th element should be the string “\ x00”, and the 66th element should be “\ x20 \ x0a \ x0d”. Create your own directory in the directory / tmp / and create a Python script there.

    image

    To solve the first level, we will create an array of one hundred lines of 'A'. And assign the necessary arguments to the desired values. We can start the process with these arguments as follows:

    from pwn import *
    a = ['A']*100
    a[0] = '/home/input2/input'
    a[ord('A')] = '\x00'
    a[ord('B')] = '\x20\x0a\x0d'
    ex = process(argv=a)
    ex.interactive()

    image

    We passed the first level. Take a look at the second.

    image

    At this level, two lines are read, one of the standard input stdin, and the other from stderr. We need to create two files that will contain these lines.

    image

    Open streams to these files and specify the descriptor for the stream of one file as the descriptor stdin, and another file as the descriptor stderr.

    from pwn import *
    a = ['A']*100
    a[0] = '/home/input2/input'
    a[ord('A')] = '\x00'
    a[ord('B')] = '\x20\x0a\x0d'
    fin = open('/tmp/ex/in.txt', 'r')
    ferr = open('/tmp/ex/err.txt', 'r')
    ex = process(argv=a, stdin=fin, stderr=ferr)
    fin.close()
    ferr.close()
    ex.interactive()

    image

    We proceed to the decision of the third level.

    image

    The getenv () function returns the value of an environment variable, which should be equal to the reference value. Thus, you need to create an environment variable with a specific value.

    from pwn import *
    a = ['A']*100
    a[0] = '/home/input2/input'
    a[ord('A')] = '\x00'
    a[ord('B')] = '\x20\x0a\x0d'
    fin = open('/tmp/ex/in.txt', 'r')
    ferr = open('/tmp/ex/err.txt', 'r')
    e={'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'}
    ex = process(argv=a, stdin=fin, stderr=ferr, env=e)
    fin.close()
    ferr.close()
    ex.interactive()

    image

    We managed the environment variable, now let's start from the fourth level.

    image

    According to the code, we can say that the program opens a file with the name “\ x0a” and reads 4 characters from it, after which it compares them with bytes “\ x00”. Since both the characters themselves and the file name consist of non-printable characters, we use python.

    image

    image

    The last level remains. Let's get started.

    image

    The program opens the socket on the port specified in the 66th argument. Then it receives 4 bytes over the network and compares it with the reference string. We need to add another argument to the program - the port number, establish a connection and send the necessary 4 bytes.

    from pwn import *
    a = ['A']*100
    a[0] = '/home/input2/input'
    a[ord('A')] = '\x00'
    a[ord('B')] = '\x20\x0a\x0d'
    a[ord('C')] = '1234'
    fin = open('/tmp/ex/in.txt', 'r')
    ferr = open('/tmp/ex/err.txt', 'r')
    e={'\xde\xad\xbe\xef':'\xca\xfe\xba\xbe'}
    ex = process(argv=a, stdin=fin, stderr=ferr, env=e)
    fin.close()
    ferr.close()
    ex.interactive()

    image

    image

    That's all, get your points.

    image

    See you in the following articles!

    We are in a telegram channel: a channel in Telegram .

    Also popular now: