duliri123

duliri123

shell スクリプトの一種の難読化方法

インスピレーションの源:rwkgyg/sing-box-yg

現在、さまざまな PaaS、SaaS、BaaS などのプラットフォームでは、Xray、Alist などの一般的なアプリケーションをホスティングする際に、違反の警告が表示され、デプロイが許可されないことがよくあります。大量のテストを行った結果、これらのプラットフォームは主にキーワード検出を禁止の要因としていることがわかりました。したがって、ログ、ファイル名、テキストファイルの内容にこれらのキーワードが含まれていなければ、デプロイを続けて正常に使用することができます。

ほとんどの場合、このようなアプリケーションのデプロイは、機能が充実したシェルプログラムを使用して自動化されており、その中でファイル名とログを適切に処理するだけで済みます。しかし、最終的にシェルスクリプト自体の内容には、Xray、Alist などのアプリケーションのダウンロードリンクが不可避的に含まれるため、シェルスクリプト自体がプラットフォームによって検出されて禁止されることになります。もちろん、複数の変数を分割してダウンロードリンクを構築し、キーワードを回避する方法もありますが、これは間違いなくスクリプトの作成の複雑さを増します。そこで、rwkgyg/sing-box-yg を参照することでインスピレーションを得て、シェルスクリプトを難読化するための Python スクリプトを作成しました:

import os
import uuid
import base64

# スクリプトを読み込む
with open('script.sh', 'r') as f:
    script = f.read()

# スクリプトを base64 でエンコードする
encoded_script = base64.b64encode(script.encode()).decode()

# 各文字列セグメントのサイズを定義する
chunk_size = 4

# エンコードされたスクリプトを複数の小さなセグメントに分割する
chunks = [encoded_script[i:i+chunk_size]
          for i in range(0, len(encoded_script), chunk_size)]

# 最終的なスクリプトを保存する新しいファイルを作成する
with open('final_script.sh', 'w') as f:
    # 各変数の代入文を出力する
    variable_names = []
    for chunk in chunks:
        while True:
            var_name = str(uuid.uuid4()).replace('-', '')  # 変数名として UUID を生成する
            if not var_name.startswith('0') and not var_name.startswith('1') and not var_name.startswith('2') and not var_name.startswith('3') and not var_name.startswith('4') and not var_name.startswith('5') and not var_name.startswith('6') and not var_name.startswith('7') and not var_name.startswith('8') and not var_name.startswith('9'):
                break
        variable_names.append(var_name)
        f.write(f'{var_name}=\'{chunk}\'\n')

    # すべての変数を接続する文を出力する
    f.write('eval "$(echo -n "')
    for var_name in variable_names:
        f.write(f'${var_name}')
    f.write('" | base64 --decode)"')

# ファイルの権限を変更して実行可能にする
os.chmod('final_script.sh', 0o755)

この Python スクリプトの原理は非常にシンプルで、まず元のシェルスクリプトを Base64 でエンコードし、その後多くの文字列に分割し、UUID を変数名として使用して各文字列を変数に格納し、最後に UUID 変数をすべて連結して eval コマンドで実行します。

シンプルで効果的で、使用した人は皆満足しています。

第二版:
import base64
import uuid
import re

def generate_var_names():
    chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
    for first in chars:
        for second in chars:
            yield f"{first}{second}"
    while True:
        var_name = str(uuid.uuid4()).replace('-', '')
        if re.match(r'^[a-zA-Z]', var_name):
            yield var_name

with open('your_script.sh', 'r') as file:
    script_content = file.read()

first_encoded = base64.b64encode(script_content.encode('utf-8')).decode('utf-8')
first_eval_command = f'eval "$(echo -n "{first_encoded}" | base64 --decode)"'

second_encoded = base64.b64encode(first_eval_command.encode('utf-8')).decode('utf-8')

var_names = generate_var_names()
var_assignments = []
eval_parts = []
for i in range(0, len(second_encoded), 4):
    chunk = second_encoded[i:i+4]
    var_name = next(var_names)
    var_assignments.append(f'{var_name}="{chunk}"')
    eval_parts.append(f'${var_name}')

final_eval_command = f'eval "$(echo -n "{"".join(eval_parts)}" | base64 --decode)"'

var_assignment_line = ';'.join(var_assignments)

with open('obfuscated_script.sh', 'w') as file:
    file.write(var_assignment_line + '\n')
    file.write(final_eval_command + '\n')

print("元のスクリプトは obfuscated_script.sh に難読化されました")```

```
対応するデコード:
```
import os
import re

def decode_script(script_content):
    decoded_script = script_content

    while True:
        eval_match = re.search(r'eval\s*"\$\(\s*echo\s+-n\s+"([^"]+)"\s*\|\s*base64\s+--decode\s*\)"', decoded_script)
        
        if not eval_match:
            break
        
        base64_string = eval_match.group(1)
        
        modified_script = decoded_script.replace('eval', 'echo', 1)

        result = os.popen(f'bash -c \'{modified_script}\'').read()

        print("デコードされた部分:", result)

        decoded_script = re.sub(r'eval\s*"\$\(\s*echo\s+-n\s+"([^"]+)"\s*\|\s*base64\s+--decode\s*\)"', result, decoded_script, count=1)
    
    return result.strip()

with open('obfuscated_script.sh', 'r') as file:
    obfuscated_script_content = file.read()

deobfuscated_script_content = decode_script(obfuscated_script_content)

with open('deobfuscated_script.sh', 'w') as file:
    file.write(deobfuscated_script_content)

print("難読化されたスクリプトは逆生成され、deobfuscated_script.sh に保存されました")
```
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。