Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

CTFのreversing問ではFLAGを実行ファイル内に隠すものがありますが,平文でFLAGを置くわけにはいきません.

作問時にFLAGをどうやって難読化するかで悩まないよう,簡単なメモを作っておきます.

入れ替え

文字列のインデックスを入れ替える.逆順は普通に目grepでばれる.
最低限FLAGが平文にならないように.

void shuffleStr(char *input, char *output) {
    size_t len = strlen(input);
    for (size_t i = 0; i < len; ++i) {
        output[(i * 7) % len] = input[i];
    }
    output[len] = '\0';
}

XOR

Ghidraで見れば普通に分かる.

void xor(char *input, char *output, char key) {
    size_t len = strlen(input);
    for (size_t i = 0; i < len; ++i) {
        output[i] = input[i] ^ key;
    }
    output[len] = '\0';
}
size_t len = strlen(input);
size_t keyLen = strlen(key);
for (size_t i = 0; i < len; ++i) {
    output[i] = input[i] ^ key[i % keyLen];
}

シーザー

FLAGのROT13がSYNTなのはよく見る.

void caesar(char *input, char *output, int shift) {
    size_t len = strlen(input);
    for (size_t i = 0; i < len; ++i) {
        if (input[i] >= 'a' && input[i] <= 'z') {
            output[i] = (input[i] - 'a' + shift) % 26 + 'a';
        } else if (input[i] >= 'A' && input[i] <= 'Z') {
            output[i] = (input[i] - 'A' + shift) % 26 + 'A';
        } else {
            output[i] = input[i];
        }
    }
    output[len] = '\0';
}

文字コードシフト

Ghidraで見れば分かる.

void shiftChar(char *str, int shift) {
    for (int i = 0; str[i] != '\0'; i++) {
        str[i] += shift;
    }
}

OpenSSL

opensslに入ってる物を色々使う.
aes, sha, des, rsa ...

#include <openssl/aes.h>
#include <openssl/sha.h>
void aesEncrypt(const unsigned char *key, const unsigned char *input, unsigned char *output) {
    AES_KEY aesKey;
    AES_set_encrypt_key(key, 128, &aesKey);
    AES_encrypt(input, output, &aesKey);
}

void aesDecrypt(const unsigned char *key, const unsigned char *input, unsigned char *output) {
    AES_KEY aesKey;
    AES_set_decrypt_key(key, 128, &aesKey);
    AES_decrypt(input, output, &aesKey);
}
void sha256Hash(const unsigned char *input, unsigned char *output) {
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, input, strlen((char *)input));
    SHA256_Final(output, &sha256);
}

One-Time

keyをランダム生成する.
このコードは多分使わないが,キーをランダム生成するのはたまによくやる

void generateKey(char *key, size_t len) {
    srand(time(NULL));
    for (size_t i = 0; i < len; ++i) {
        key[i] = rand() % 256;
    }
    key[len] = '\0';
}

Obfuscator-LLVM

しっかり難読化して,読ませたくないときに.

FLAGを構築する単純な関数などを,このツールで難読化する.

無駄な if や while がたくさん挿入され,Ghidraでデコンパイルしてもまともに読む気を無くすようなコードになる.

build/bin/clang -c flag.c -fPIE
-mllvm -sub
-mllvm -bcf
-mllvm -fla

難読化のオプションを3種類つけられる.論文ではオプションの違いやその比較をしているが,使う側としては全部載せでいい……はず.

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?