ブログ未満のなにか

ブログなのか誰にも分からない

セキュリティキャンプ2016 選択問題(※一部)

追記(2016/6/14)

選考通ってました。
全国大会2016行きます!講師・参加者各位よろしくお願いします!
(あとで選択問題の解答を全部晒す記事書きます)

去年落ちたセキュキャン。
リベンジでありラストチャンスとして臨んだセキュキャン。
余裕を持って応募用紙を埋めていこうと思っていたセキュキャン。

結局、徹夜で仕上げました。
ちゃんと計画しておけばよかった。

今回挑んだ選択問題は、1,3,4,5。
文章量を書けそうな問題ばかり選んだら、似たようなものばかりに。

特に面白そうだと思ったのが、RHプロトコル
コーディングしてる途中で、心がぴょんぴょんしてた。
設問の本質は、C/C++での文字列処理だった。
とりあえず動けばいいという思考なので、セキュリティは全く考慮していない。(セキュキャンへの応募なのにそれでいいのか...)

以下が、今回書いたCでのRHプロトコルアナライザー。一応ちゃんと判定できてるはず。


大文字小文字を区別せずにマッチングする処理が面倒だったので、ネット拾ってきた関数そのまま使ってます。
勝手に使ってすみませんでした。
www.c-tipsref.com

ソースコード

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#define BUF_SIZE 2048

#define MAGIC_SIZE  2
#define SOURCE_SIZE 20
#define DEST_SIZE   20
#define LENGTH_SIZE 4
#define HEADER_SIZE MAGIC_SIZE + SOURCE_SIZE + DEST_SIZE + LENGTH_SIZE


int checkMagic(char* data);
int checkSource(char* data);
int checkDestination(char *data);
int checkCocoaChino(char *source);
unsigned int calcDataLength(char *dataLength);
int validOrderBrand(char *data);
int invalidOrderBrand(char *data);

// 引用した関数
int strcmp_ignorecase(const char *s1, const char *s2);


int main(int argc, char* argv[]){
    
    printf("Start RH Protocol analyzer\n");

    FILE* fp;
    
    if ((fp = fopen("pyonpyon.rh", "rb")) == NULL) {
        printf("file cannot open!\n");
        exit(EXIT_FAILURE);
    }

    int i = 1;   
    
    while(1) {
        char header_buf[BUF_SIZE];
        char data_buf[BUF_SIZE];
        int flag = 0;

        int n = fread(header_buf,sizeof(char), HEADER_SIZE, fp);
        //printf("n = %d\n", n);
        if (n < HEADER_SIZE) {
            printf("[INFO] file reading is finish!\n");
            break;
        }

        if (checkMagic(header_buf) != 1) {
            printf("[INFO] %d REJECTED in Magic\n", i);
        } else if (checkSource(header_buf + MAGIC_SIZE) != 1) {
            printf("[INFO] %d REJECTED in Source\n", i);
        } else if (checkDestination(header_buf + MAGIC_SIZE + SOURCE_SIZE) != 1) {
            printf("[INFO] %d REJECTED in Destination\n", i);
        } else if (checkCocoaChino(header_buf + MAGIC_SIZE) != 1) {
            printf("[INFO] %d REJECTED in Cond.4\n", i);
        } else {
            flag = 1;
        }


        unsigned int length = calcDataLength(header_buf+MAGIC_SIZE+SOURCE_SIZE+DEST_SIZE);
        //printf("length = %u\n", length);

        n = fread(data_buf, sizeof(char), length, fp);
        
        if (n < length) {
            printf("[INFO] file reading is finish!\n");
            break;
        }
        
        if (invalidOrderBrand(data_buf) != 1) {
            printf("[INFO] %d REJECTED in invalid order\n", i);
        } else if (validOrderBrand(data_buf) != 1) {
            printf("[INFO] %d REJECTED in valid order\n", i);
        } else {
            flag += 1;
        }
    
        if (flag == 2) 
            printf("[INFO] %d PASS!\n", i);

        i++;
    }
    
    fclose(fp);
    printf("Finish RH Protocol analyzer\n");
    
    return 0;  
}



int checkMagic(char *magic) {

    if (magic[0] == 'R' && magic[1] == 'H') {
        return 1;
    } else {
        return 0;
    }
}

int checkSource(char *source) {
   
    if (strcmp_ignorecase(source, "rise-san") == 0) {
        return 1;
    } 

    if (strcmp_ignorecase(source, "cocoa-san") == 0) {
        return 1;
    } 
    return 0;
}

int checkDestination(char *dest) {
   
    if (strcmp_ignorecase(dest, "chino") == 0) 
        return 1;

    if (strcmp_ignorecase(dest, "chino-chan") == 0) 
        return 1;
    
    return 0;
}

unsigned int calcDataLength(char *dataLength) {
   
    unsigned int length = 0;
    int i;

    for (i = 0; i < LENGTH_SIZE; i++) {
        length = length << 8;
        length += (unsigned)dataLength[i];
    }
    
    return length;
}


int checkCocoaChino(char *header) {
   
    char* source = header;
    char* dest = header + SOURCE_SIZE;

    //if ((strcmp(source, "cocoa-san") == 0) && (strcmp(dest, "Chino") == 0)) 
    if ((strcmp_ignorecase(source, "cocoa-san") == 0) && (strcmp_ignorecase(dest, "Chino") == 0)) 
        return 0;
    
    return 1;
}


int validOrderBrand(char *data) {
   
    if (strstr(data, "BlueMountain") != NULL ) 
        return 1;
    
    if (strstr(data, "Columbia") != NULL ) 
        return 1;
    
    if (strstr(data, "OriginalBlend" ) != NULL ) 
        return 1;

    return 0;
}


int invalidOrderBrand(char *data) {
    
    if (strstr(data, "DandySoda") != NULL ) 
        return 0;

    if (strstr(data, "FrozenEvergreen") != NULL ) 
        return 0;
    
    return 1;
}

// 以下のURLから引用
// http://www.c-tipsref.com/tips/string/o_strncmp_ignorecase.html
int strcmp_ignorecase(const char *s1, const char *s2) {
        int i = 0;

            /* 文字が等しい間繰り返す */
            while (toupper((unsigned char)s1[i]) == toupper((unsigned char)s2[i])) {
                        if (s1[i] == '\0') {
                                        return 0;
                                                }
                                i++;
                                    }

                return toupper((unsigned char)s1[i]) - toupper((unsigned char)s2[i]);
}

実行結果

Start RH Protocol analyzer
[INFO] 1 PASS!
[INFO] 2 PASS!
[INFO] 3 REJECTED in Cond.4
[INFO] 4 PASS!
[INFO] 5 REJECTED in Cond.4
[INFO] 6 PASS!
[INFO] 7 PASS!
[INFO] 8 REJECTED in Cond.4
[INFO] 9 PASS!
[INFO] 10 REJECTED in Destination
[INFO] 11 PASS!
[INFO] 12 REJECTED in Cond.4
[INFO] 13 PASS!
[INFO] 14 REJECTED in Destination
[INFO] 15 REJECTED in Magic
[INFO] 16 PASS!
[INFO] 17 REJECTED in Cond.4
[INFO] 18 PASS!
[INFO] 19 REJECTED in Destination
[INFO] 20 REJECTED in Magic
[INFO] 21 REJECTED in Magic
[INFO] 21 REJECTED in invalid order
[INFO] 22 PASS!
[INFO] 23 REJECTED in Cond.4
[INFO] 24 PASS!
[INFO] 25 REJECTED in Destination
[INFO] 26 REJECTED in Magic
[INFO] 27 REJECTED in Magic
[INFO] 27 REJECTED in invalid order
[INFO] 28 REJECTED in Magic
[INFO] 28 REJECTED in invalid order
[INFO] 29 PASS!
[INFO] 30 REJECTED in Cond.4
[INFO] 31 PASS!
[INFO] 32 REJECTED in Destination
[INFO] 33 REJECTED in Magic
[INFO] 34 REJECTED in Magic
[INFO] 34 REJECTED in invalid order
[INFO] 35 REJECTED in Magic
[INFO] 35 REJECTED in invalid order
[INFO] 36 REJECTED in Magic
[INFO] 37 PASS!
[INFO] 38 REJECTED in Cond.4
[INFO] 39 PASS!
[INFO] 40 REJECTED in Destination
[INFO] 41 REJECTED in Magic
[INFO] 42 REJECTED in Magic
[INFO] 42 REJECTED in invalid order
[INFO] 43 REJECTED in Magic
[INFO] 43 REJECTED in invalid order
[INFO] 44 REJECTED in Magic
[INFO] 45 REJECTED in Magic
[INFO] 45 REJECTED in invalid order
[INFO] file reading is finish!