最長2解散MWS Cup 2022
最適2年担当O株式会社サイバーディフェンス研究所中島将太O間題作成委員o O o o学生、若手募集中！株式会社エヌ・エフ・ラポラトリーズ皆川諒株式会社サイバーディフェンス研究所森瑞穂21
マルウェアを正しく理解するO o課題を通して解析のポイントを学習するO最新情報を得るo最近のin-the-wildなマルウェアを扱うO長務に近い作業o静的解析による復号スクリプトの作成W O積極的に変数名や型変更する名前を付けて読みやすくしていくoデフォルトで民型情報がないことが多いo Oデコンパイラを冒用しすぎないアセンブリを確認して整合性を確認するo手動で修正するo 。順番に回答する必要はないので解けそうな問題から解く
初のELFマルウェア!
2020/11/10攻撃グループBlackTechが使用するLinux版マルウエア(ELF_PLEAD) BOOKTOCH 2022/08/30攻撃グループLazarusが使用するマルウェアYamaBotレウェアは、Urux OSをターグットにしており、CPUアーキテクチャーがARM社よび×64に対応した2つのタイプが確認されています。これのマルウェアは、どのようなデバイス上で動作を想定されて作成されたものなのかは不明ですが、loT線器上での動作を想定している可能性もあ6んなクーケットにしたマルク
MWS Cup 2022 6
O Gキーで開くGo Toダイアログにアドレスやlabelを入力任意の場所に簡単に移動o問題ではアドレスが指定されていることが多いので必須! o security init cookie 7
O Bytesウィンドウでコピーする
20
●　コピーしたい範囲を選択コンテキストメニューからCopy Special =>好きなフォーマットを選択o
0041e450 7d
Etri+V OK Cancel 9
Filter: mws x  0101  Defined Strings   × / Bookmarks × } Python × 10
swi(software interrupt)がある場合は、Listingウィンドウを見るDecompile: FUN 080685d0 - 0 2 uint FUN 080635d0(void) 3 4 5 code *pcVarl; 6 7 uint uVar2, int *in GS OFFSET; 8 9 0.0 pcVarl = (code *)swi(0x80); uVar2 = (*pcVar1)();
11
main()関数の前には何があるのか（7) Linuxカーネルに見る、システムコール番号と引数、システムコール・ラッパーとは(1/2ページ) C霊語の「Hello World！」ブログラムで使われる、「printf()」「main()」関数の中身を、デバッカによる解析と逆アセンブル、ソースコード諸解などのさまざまな側面から探る連載。前回から、printf()内のwrite()やint $0x80の呼び出しについてLinuxカーネルのソースコード側から探ってきた。今回は、さらに気政通知  B! 9 Sックアップして紹介する本シリーズ。今回は、奏World" OSと標準ライブラリの※福集部注：前回記事「Linuxカーネルのソースコードを読んで、システムコールを探る」はこちらhttps://atmarkit.itmedia.co.jp/ait/articles/1703/01/news172.html Hint!!
project logo Chromium OS Docs Home    214m2s　George Started　Developer Guide　Contact　Busi　Glorisary　Zode Guide Markdown]　GM46,Markdown Expression
Linux System Call Table
Warning: This document is old & has moved. Please update arry links: https://chromium.googlesource.com/chromiumos/docs/+/HEAD/constants/syscalis.md These are the system call numbers (NR) and their corresponding symbolic names. These vary significantly across architectures/ABIs, both in mappings and in actual name. This is a quick reference for people debugging things (e.g. seccomp failures). For more details on syscalls in general, see the syscall(2) man page
Contents
●   Random Names ■ Kernel Implimations ● Calling Conventions • Tebles 00_116_64 (64-bit) to harm (32-billeably no) arm64 (64-bit) (0) ×86 (32-bit) ● Cross-arch Numbers
x86 (32-bit)

Compiled from Linux 4.14.0 headers.
https://chromium.googlesource.com/chromiumos/docs/+/master/constants/ MWS Cup 2022 13
MWS Cup 2022 14
Challenge X 1-1.コンフィグサイズ課題2はマルウェアの静的解析に関する問題です。問題ファイルsample.gzfをダウンロードし、Ghidraで解析して回答してください。このマルウェアは複数のIPアドレスとポートをコンフィグとして持つことができる。1つのコンフィグのサイズを10進数で答えよ。 ___ 15
o O FUN 0804851の引数に利用FUN_0804851内のループで操作
17
引数で受け取ったアドレスを0x3e(62)毎に進めるO for (: DAT 080d4b00 < 10: DAT if ((*(char *)(DAT 080d4b00 (*(short *)(DAT 080d4b00 DAT 080d4b00 = 0; if (On< local lc) { FUN_0804ed10(local_lc); = DAT 080d4b00 + 1) { param_l) == '\0'). [l paramel + 0x3c) == 0)) 29 30 33 34 35 return -1; 18
The Answer is: 62 MWS Cup 2022 19
Challenge X 1-2.コンフィグ数2このマルウェアが保有できるIPアドレスとポートの組の最大数を10進数で答えよ。
o 10回ループする10組のIPアドレスとポート情報を保持可能o for (; DAT 080d4b0) < 10; IAT 080d4b00 = DAT 080d4b00 + 1) { f ((*(char *)(DAT_080d4500 * 0x3e + param_1) == '\0') || (*(short *)(DAT_080d4b00 * 0x3e + param_1 + 0x3c) == 0)) { DAT_080d4b00 = 0; if (On< local_lc) { FUN_0804ed10(local_lc); return -1;
The Answer is: 10 MWS Cup 2022 22
Challenge X 1-3.通信先3本検体の通信先(C2サーバ)を"IPアドレス:ポート番号"の形式で答えよ。複数存在する場合はカンマ(,)区切りで連続させて、IPアドレスの第4オクテットが小さい順に並べること。例: 192.168.2.2:80,192.168.2.150:8080
28
for (; DAT 080d4b00 < 10; DAT 080d4b00 = DAT 080d4b00 + 1) { if ((*(char *)(DAT_080d4b00 * 0x3e + param_1) == '\0') [] (*(short *)(DAT_080d4b00 * 0x3e + param_1 + 0x3c) == 0))
FUN 0804ed10(local lc); 2 1-3.新昌先0x1BB → 443 o
MWS Cup 2022 1-3.連信先The Answer is: 172.16.123.133:443 MWS Cup 2022
Challenge 2.コマンド数2 FUN_0804b79eはC2サーバから受信したコマンドをもとに処理を決定する関数である。コマンド数を答えよ。 27
FUN_0804b79e内のコマンドIDを使った分岐処理を数えるCy Decompile: FUN_0804b79e -  (sample) undefined4buVarl; undefined4 local_c; byte and_id; if ((param_1 == 0) Il (param_1 == -1)) { local_c = 0; else if (param_2 == (byte *)0x0) { local_c = 0; else if (param_3 < 1) { local_c = 50; else { cnd_id = "param_2; if (cmd_id == 0x89) { local_c = FUN_08049e65(param_1,param_2,param_3); else { if (cmd_id < 0x8a) { if (cmd_id == 0x84) { uVarl = FUN_080493e5(param_1,param_2,param_3); return uVarl; if (cmd_id < 0x85) { if (cmd_id == 0x82) { uVarl = FUN_08048e74(param_1,param_2,param_3); return uVarl; if (0x82 < cmd_id) { 2.コマント教The Answer is: 15 MWS Cup 2022
Challenge 3.コマンド処理1 2コマンド0x85の処理はどれか。以下から選択せよ。 ※1度しか回答できません。注意して回答してください。 ○ファイル読み込み○ファイル書き込み○ファイル削除○ファイルの名前変更0/1 attempt X 30
else { if (bVarl == 0x86) { uVar2 = FUN_08049747(param_1,param_2,param_3); return uVar2; iVar2 = FUN 08049626(param 1,param 2,param 3); return uVar2 , if (bVarl)== 0x07)={ uVar2 = FUN_08049c69(param_1,param_2,param_3); return uVar2; undefined FUN_08049626(int param_1,int param_2,int param_3) undefined uVarl; undefined local_e [2]; int fd; int local 8; if ((param_l == -1) || (param_l == 0)) { uVarl = 0; else if (param_2 == 0) { uVarl = 0; else if (param_3 < 1) { uVarl = 60; else Id if open(sDAT_080d8780,0x442,0x1f8); uVarl = 0; else { FUN_080 local_8 FUN_0804
uint open(void) code *pcVarl; uint uVar2; undefined4 uVar3; int *in GS OFFSET; 👍 8 9 10 D ■ 12 13 D 1.4 15 else { 	 D uVar3 = FUN 0804e8e0(); pcVarl = (code *)swi(0x80); uVar2 = (*pcVar1)(uVar3); if (in GS_OFFSET[3] == 0) { pcVarl = (code *)swi(0x80); uVar2 = (*pcVar1) (); if (uVar2 < Oxfffff001) { return uVar2; swi関数。中身はopenシステム書MWS Cup 2022
uint write(void) code *pcVarl; uint uVar2; → undefined4 uVar3; int *in GS OFFSET; 😍 ■ 10 0 II if (in GS OFFSET[3] == 0) { pcVarl = (code *) swi(0x80); uVar2 = (*pcVar1)(); if (uVar2 < Oxfffff001) { return uVar2; ■ 14 15 16 else { 18 C 19 D uVar3 = FUN 0804e8e0(); pcVarl=2(code *)swi(0x80); uVar2 = (*pcVar1)(uVar3); 20 👍 FUN 0804e8a0(); if (uVar2 < Oxfffff001) { MWS Cup 2022 swi日数。writeシス3.コマンド処理1
MWS Cup 2022
Challenge 4.コマンド処理2 3コマンドID 0xF6の動作を説明せよ。 X MWS Cup 2022 35
iVarl = FUN 080553b0(PTR DAT 080d47fc,0,1,0); if (iVarl == 0) { FUN_08062910("/bin/sh","/bin/sh",0);
EBP ECX,dword ptr [EBP + param 2] EBX k,dword ptr [EBP + param]31 ptr: [EBP + param 1] MOV 00 00 08087762 cd 80 INT 0x80 int *in GS OFFSET, pcVarlu= (code *)swi(0x80); uVar2 = (*pcVar1)(); if (Oxfffff000 < uVar2) { *(uint *)(*in GS OFFSET + -0x30) = -uVar2; uVar2 = Oxfffffff; return uVar2; /bin/shという文字列からシェルを開くこを接続定システムコールはexecveである。 MWS Cup 2022
iVarl = FUN 080553b0(PTR DAT 080d47fc,0,1,0); if (iVarl == 0) { FUN 08062910("/bin/sh","/bin/sh",0); int *in GS OFFSET, 08087750 55 PUSH EBP .080 080 execve 080 080
ht $)($in.gs_offset_+ -ux30) = -uvar2; uVar2 = Oxfffffff; return uVar2; 0808775a 8b 5d 08 0808775d b8: 0b 00 00 00 08087762 cd 80
EAX 0xb ptr [EBP + param 1] /bin/shという文字列からシェルを開くことな概定システムコールEtexecye (をある。 MWS  Cup  2022 INT 0x80 4.コマンド処理2:コマンドID 0xF6の動作を説明せよThe Answer is:気事ないたマシンのリモートシェルを開くexecve("/bin/sh", "/bin/sh", [0]);
Challenge 5.コマンド処理3 2ファイル名の変更をするコマンドIDを16進数で答えよ。例えば、コマンドIDが0x1234ABCDだと判明した場合、 0x1234ABCDの形式で回答せよ。 ※回答回数が制限されています。注意して回答してください。 X 0/3 attempts
ま本方針: RATのみイン関数FUN_0804b79eに真理をしているヨマンドを全て読み、   undefined4 run_0804b79e(int_param_1,byte_*param_2,int_param_3) byte bVarl; undefineds uvar2; undefined4 local c; if ((param 1 == 0) [] (param 1 == -1))){ local c = 0; else if (paran_2 == (byte *)0x0} { local c = 0; else if (paran 3 < 1) { local_c = 0; 6110 { bVarl = *paran_21 if (bVarl == 0x89) { local_c = FUN_08049e65(param_1,param_2,param_3); else ( if (bVarl < 0x8a) { if [bVar1 == 0x04] { uVar2 = FUN_080493a5(param_1,param_2,param_3); return uVar2; if (bvar1 < 0x85) { if (byan1 == 0x82) { uVar2 = FUN_08048e74(paran_1,paran_2,paran_3); return uVar2; if (0x82 < bVar1 ) { uVar2 = FUN_08048ef8(paran_1,paran_2,paran_3); return uVar2; MWS Cup 2022
FUN_0804a456で使用されているsystem call “38”が最もそれらしい
else { if (bVarl == 0xc6) { return 2; if (bVarl < 199) { if (bVarl == 0x8b) { uVar2 = FUN_0804a2fa(param_1,param_2,param_3); return uVar2; if (bVar1 < 0x8b) { uVar2 = FUN_08049fca(param_1,param_2,param_3); return uVar2; if (bVarl == 0x8f) { uVar2 = FUN_0804a456(param_1,param_2,param_3); return uVar2; 42
5.コマント処理3
MWS Cup 2022
6-1.暗号アルゴリズム2 FUN_080482c5はマルウェアが通信の暗号化のために使用する関数である。暗号のベースとなっているアルゴリズムを以下から選択せL o ※1度しか回答できません。注意して回答してください。 ○ RC4 ○ xor ○ AES O XXTEA 0/1 attempt 45
2020年: AESラウンド処理部分を探す2021年: XOR 2-1.エンコード[loader_x86] Answer ● XORでデコードするループMXS Cup 2021
o指定された関数を読み、暗号アルゴリズムの特徴と一数する部分がないかを探す冒頭に0x100 (= 256)バイトのo配列を作り、0 ~ 256の値で初期化する処理が入っているさらにこの配列は、初期化処理後o関数の第3月数の値を使いながら値がスワップされるam 1.int param 2.int param 3.int param local 14 < 0x100; local 14 - local 14 + 1) { = 0; local 14 < 0x100; local 14 - local 14 + param 4) { (local 10 = 0; ((int)local 10 < param 4 && ((int)(local 10 + local 1 cal 10 = local 10 + 1) { 32[local 14 + local 10] = *(byte *)(local 10 + param 3); = 0; local 14 < 0x100; local 14 = local 14 + 1) { abstack276[loca], 141 : bStack532[local_14]; ocal 5 + local 10 + (uint)abStack532[local 14] & Oxff; abStack276[local][0]: 141 0= abStack276[loral, 10];
RC4と特定するための特徴ぱっと見でRC4だと特定するための特徴と思われるものをまとめてみます。 • 256バイトのSという状態を持つ•最初に鍵を元にKSAによってSの状態が初期化される（初回のみ呼ばれる） • Sの状態変化はswapで行われる•データの暗号化はPRGAから出力された1パイト値をXORによって暗号化する• KSAとPRGAの計算は似ている（けど鍵の計算がないので少し違う） •暗号化と復号が同じ処理（送信と受信で同じ関数を使っている場合） 『アセンブリで書かれたRC4は見た瞬間分かるか』, yasulib memo, https://vasulib.hatenablog.jp/entry/20180127/151704182
The Answer is: RC4 MWS Cup 2022 49 6-2.復号鍵3マルウェアが暗号化で使用する鍵を16進数で答えよ。例えば、鍵が文字列“ABCD”だった場合、 \x41\x42\x43\x44の形式で回答せよ。 50
o 6-1で暗号アルゴリズムがRC4だとわかれば、この関数の第3引数として使われたデータが鍵である可能性が高いo暗号関数の参照を辿る。使用されているのはアドレス0x030482be void FUN 080982c5(int param 1,int param 2,int param 3,int param 4,byte param 5)
アドレス0x080482beへいくとFUN_08048294というwrapper関数らしき関数へo形ないo FUN_080482c5の第3引数はFUN_08048294の第1引数として使われているので、次はFUN_08048294の参照を辿り第1引数として使われている個差殺す。 6-2.復長後O参照されているアドレスのいずれかを確認すると、FUN  08048294の第1引数にはlxa3 ~ lx00華3016バイトが使用されていることがわかる。 ⇒これがRC4で使用される雑else { local, Ac = 0xa3; local 4b = 0x78; local, 4a =10x26r local, 49 - 40x35; local 48 =10x57; local,475-60x32, local 46 = 0x2d; local,45 - 0x60; local 44 = 0xb4; local 43 m 0x3c; local, 42 m 0x2a, local 41 = 0x5e; local, 40 -- 0x33; local 3f = 0x34; local 3e = 0x72; local 3d = 0; pivar2 = (int *) FUN 0005d000(para if (piVar2)== {int *}0x0} { local_e4 = 0; else ( local 3cl = piVar2; if (DAT 080d4b1c == 1) { iVar3 = FUN 08048256(param 3); *piVar2 = iVar3; else if (DAT 080d4b1c (==)0} ( *piVar2 = paran_3; pivar2 = local 3c + 1; for (iVar3 = param_3; iVar3 != 0; iVar3 = iVar3 + -1) { *(undefined *)piVar2 = *param 2; param_21= param_21+ 1; piVar2 = (int *)((int)piVar2 + 1); JN 08048294(&local 4c,local 3c + 1,param 3); W References to FUN 08048294 - 2 locations (CodeBrow
TIPs:鍵の最さの予想。 0x00はNull終端であって鍵として使用していないのではないかと考えた人がいるかもしれないので補足FUN 080482c5の第3号数が鍵の本体ならば、 o第4月数には数の長さが使われるているのではないかという予想ができる(これは、FUN_080482c5を解析しても確認できる)本検体の場合、第4引数は0x10 (= 16)固定。そのため、鍵としては1xa3から始oまる16バイト分が距離ned4 param 1.undefined4 param 2.undefined4 para am 2,param 3,param 1,0x10,0x16); 6-2.復与鑑民の引越を紹介の年長6-2.復与後The Answer is: lxa3lx78lx26lx35lx57lx32lx2dlx60lxb4lx3clx2alx5elx33lx34lx72lx00
6-3.復号処理FUN_080482c5のアルゴリズムで暗号化されたファイルをencrypted.binとして取得した。解析結果をもとにファイルを復号し、得られた平文を答えデなお、ベースとなっている暗号アルゴリズムのコードはencrypt_hint.pyとして実装されている。必要なチームは本コードをベースに復号コードを書いてもよい。 - - encrypt hint.... 57
天年度後与問題解けたテームU 商品をので、今年民復与に使えるペースのコミ経理意しました!!
def encrypt(data: bytes, key: bytes) -> bytearray: result: list[int] = [] S: list[int] = [0] * 0x100 for i in range(0, 0x100, 1): S(i) = i j: int = 0 for i in range(0, 0x100, 1): S_i_tmp: int = S[i] k: int = key[i % len(key)] j = (S_i_tmp + j + k) & 0xFF S[i] = S[j] S[j] = S_i_tmp j: int = 0 for i in range(0, len(data), 1): S_i_tmp: int = S[(i + 1) & 0xFF] j = (S[(i + 1) & 0xFF] + j) & 0xFF S[(i + 1) & 0xFF] = S[j] S[j] = S_i_tmp index: int = (S[(i + 1) & 0xFF] + S[j]) & 0xFF xor_key: int = S[index] calc: int = data[i] ^ xor_key result.append(calc) return bytearray(result) return; else C local_70= local_7 ^ *(byte *)(local_14 * param_1); * Dyte *){local_1d + param_1} = {char}local_c + local_7; local c)=0 (uint)param 5; focal 10 = 0; for (local 14 = 0; local 14)< param 2r local 14 = local 14 + 1) [ local_7 = sabStack276[local_14 + 1U & Oxffl; local 10 = abstack276[local 14 + ives Oxff] + local 10 & Oxff; abStack276[local_14 + 1U & Oxifl = abStack276[local_10]; abstack276[local_10] = local_7; local_6 = abstack27611ocal_14 + 1U & Oxffl + local_7; local_? = abstack276[{byte}[abstack276[local_14 + iv & Oxff] + local_?)]; it [[local c 4 0x80] == 0] { *(char *){local_14 + param_1} = *{char *){local_14 + param_1} + {char}local_c; * Dyte *){local_14 + param_1} = *{byte *){local_14 + param_1} * local_7; local 10 = 0; for (local 14 = 0r_local_14 < 0x100r_local_14 = local_14 + 1) { local 5 = abitack276[local 14]; local 6 = ab8tack532[local 14]] local 10 = local 5 + local 10 + (uint)abStack332[local 14] & Oxff; local 6:= rab8tack276[local 10]; abStack276[local_14] = abStack276[local_10]; abstack276[local_10] = local_5; local 14 = 0; local 14 < 0x100; local 14 = local 14 + param 4) } for (local 10 = 0; ((int)local 10 < param 4 ss [{int)(local 10 + local 14) < 0x100}} local 10 = local 10 + 1) [ abStack532[local_14 + local_10] = * [byte *) {local_10 + param_3} r for (local 14 = 0; local 14 < 0x100; local 14 = local 14 + 1) + abstack276[local 14] = [byte]local 14;
def encrypt(data: bytes, key: bytes) -> bytearray: result: list[int] = [] S: list[int] = [0] * 0x100 for i in range(0, 0x100, 1): S[i] = i j: int = 0 for i in range(0, 0x100, 1): S_i_tmp: int = S[i] k: int = key[i % len(key)] j = (S_i_tmp + j + k) & 0xFF S[i] = S[j] S[j] = S_i_tmp j: int = 0 for i in range(0, len(data), 1): S_i_tmp: int = S[(i + 1) & 0xFF] j = (S[(i + 1) & 0xFF] + j) & 0xFF S[(i + 1) & 0xFF] = S[j] S[j] = S_i_tmp index: int = (S[(i + 1) & 0xFF] + S[j]) & 0xFF xor_key: int = S[index] calc: int = data[i] ^ xor_key result.append(calc) a1:14n</0x100; local:14n="local " forni 5 + forni 10 + {uint}abStack}}2[local 14] & Oxff ck276[local_14] = abdtack276[loc #独自のアルゴリズムで作成したreturn bytearray(result)
def encrypt(data: bytes, key: bytes) -> bytearray: result: list[int] = [] S: list[int] = [0] * 0x100 for i in range(0, 0x100, 1): S(i) = i j: int = 0 for i in range(0, 0x100, 1): S_i_tmp: int = S[i] k: int = key[i % len(key)] j = (S_i_tmp + j + k) & 0xFF S[i] = S[j] S[j] = S_i_tmp j: int = 0 for i in range(0, len(data), 1): S_i_tmp: int = S[(i + 1) & 0xFF] j = (S[(i + 1) & 0xFF] + j) & 0xFF S[(i + 1) & 0xFF] = S[j] S[j] = S_i_tmp index: int = (S[(i + 1) & 0xFF] + S[j]) & 0xFF xor_key: int = S[index] calc: int = data[i] ^ xor_key result.append(calc)第55|数の価が- 0x80 (=128)未満で"加算"=> XOR" '- 0x80 (=128)以上で"XOR =>加算" RC4にシーザー暗号のような処理追加されているbstack276flocal 14 + situs Oxffl + lo {local 14}+ 1U & Oxffl = abStack276[1 ick276[local_10] = local_7] local 6 = vabitack276[local :14 +c]II k forfil +c lo local_7 = rabstack276[(byte)[abstack276[local_14] it (Hlocal c é 0x60) == 0) { *(char *){local 14 */param 1}) = *(char *){local 14 *forter*\{local:ld_toparam:l} = *{hyter*}{local:ld cal_70^ *(byte *){local_14}+ param_1}; *Dyte *){local_14 + param_1} = {char}local_c + local_7; return bytearray(result) return;
FUN 08043294(undefined4 param 1,undefined4 param 2,undefined4 param 3) FUN_080482c5(param_2,param_3,param_1,0x10,0x16); return; 0x16 (= 22)なので加算=>  X
解析編現を元に、コードを加筆・修正する● 修正点1: S-boxの追加修正点2: KSA処理の変更o ●  修正点3:沅算処理の追加暗与化コードが加算”なのでo ”減算”処理をしないと復号できない点に注意
武器専例def RC4_custom(data: bytes, key: bytes, shift: int) -> bytearray: result: list[int] = [] # KSA S: list[int] = [0] * 0x100 S_extend: list[int] = [0] * 0x100 for i in range(0, 0x100, 1): S[i] = i for i in range(0, 0x100, 16): for i2 in range(0, 16, 1): S-box追加if i + 12 > 0x100: break S_extend[i + i2] = key[i2] j: int = 0 for i in range(0, 0x100, 1): S_tmp: int = S[i] KSAのおスマS_extend_tmp: int = S_extend[i] j = (S_tmp + S_extend_tmp + j) & 0xFF S[i] = S[j] S[j] = S_tmp # PRGA j: int = 0 for i in range(0, len(data), 1): S_i_tmp: int = S[(i + 1) & 0xFF] j = (S[(i + 1) & 0xFF] + j) & 0xFF S[(i + 1) & 0xFF] = S[j] S[j] = S_i_tmp index: int = (S[(i + 1) & 0xFF] + S_i_tmp) & 0xFF xor_key: int = S[index]無して正確の仕事のcalc: int = 0 if shift & 0x80 == 0: calc = ((data[i] ^ xor_key) - shift) & 0xFF else: calc = ((data[i] - shift) ^ xor_key) & 0xFF result.append(calc) return bytearray(result)
長行結果~/Documents/work viaこv3.9.0 》 python bifrose_rc4.py encrypted.bin bytearray(b'MWS{W3lc0m3_t0_d33p_1n_th3_rc4_c1ph3r!!}') def RC4_custom(data: bytes, key: bytes, shift: int) -> bytearray: result: list[int] = [] # KSA S: list[int] = [0] * 0x100 S_extend: list[int] = [0] * 0x100 for i in range(0, 0x100, 1): S[i] = i for i in range(0, 0x100, 16): for i2 in range(0, 16, 1): S-box非加if i + 12 > 0x100: break S_extend[i + i2] = key[i2] j: int = 0 for i in range(0, 0x100, 1): S_tmp: int = S[i] KSAのおスコS_extend_tmp: int = S_extend[i] j = (S_tmp + S_extend_tmp + j) & 0xFF S[i] = S[j] S[j] = S_tmp # PRGA j: int = 0 for i in range(0, len(data), 1): S_i_tmp: int = S[(i + 1) & 0xFF] j = (S[(i + 1) & 0xFF] + j) & 0xFF S[(i + 1) & 0xFF] = S[j] S[j] = S_i_tmp index: int = (S[(i + 1) & 0xFF] + S_i_tmp) & 0xFF xor_key: int = S[index]馬力 1975年の日本の日本のcalc: int = 0 if shift & 0x80 == 0: calc = ((data[i] ^ xor_key) - shift) & 0xFF else: calc = ((data[i] - shift) ^ xor_key) & 0xFF result.append(calc) return bytearray(result) 6-3.須号処理The Answeris: MWS{W3lc0m3_t0_d33p_1n_th3_rc4_c1ph3r!!} MWS Cup 2022
o ELF bifrose o BlackTechが利用2020年以降Linux環境も狙うoおわりに攻撃グループBlackTechは、引き続き活動を続けており、今後も注意が必要です。今回解説した検体の通信先に関しては、Appendix Cに記載していますので、アクセスしている端末がないかご確認ください。なお、今回紹介したマルウェアが発見されたサーバー上では、その他のマルウェア（ダウンローダー、バックドア、ELF Bitrose）や、攻撃ツールを確認しています。次にサーバー上で保存されている攻撃ツールを列挙します。これらのツールは、攻撃グループBlackTechによって利用されている可能性があることにご注意ください。 https://blogs.jpcert.or.jp/ja/2021/09/gh0sttimes.html https://teamt5.org/jp/posts/technical-analysis-on-backdoor -bifrost-of-the-Chinese-apt-group-huapi/ Linux飯のBifroseマルウエアです。過去の分析記事[14]に記載されている検体と大きく機能は変わっておりませんが、私たちが確認した検休について紹介します。静的リンクされており、攻撃者は環境依存の問題を減らしたいものhttps://p.security.ntt/resources/BlackTech_2021.pdf