Malware/malware analysis

[Qakbot ๋ถ„์„ (4)] ๋ฆฌ์†Œ์Šค ๋ณตํ˜ธํ™” ๋ฃจํ‹ด ํŒŒ์•… ๋ฐ ์ •๋ณด ์ถ”์ถœ

์œค์ •_ 2025. 2. 12. 17:53

์ง€๋‚œ ํฌ์ŠคํŒ…์— ์ด์–ด Qakbot ์•…์„ฑ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ์•…์„ฑ์ฝ”๋“œ์˜ ๋ฆฌ์†Œ์Šค ๋ณตํ˜ธํ™” ๋ฃจํ‹ด์„ ํŒŒ์•…ํ•˜๊ณ  ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์—์„œ ์–ด๋–ค ์ •๋ณด๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ƒ˜ํ”Œ ํ•ด์‹œ(SHA256)๋Š” 73e4969db4253f9aeb2cbc7462376fb7e26cc4bb5bd23b82e2af0eaaf5ae66a8์ž…๋‹ˆ๋‹ค.

 

 

 

๊ณ„์† ๋ถ„์„ํ•˜๊ธฐ ์œ„ํ•ด sub_1000FB74 ์„œ๋ธŒ๋ฃจํ‹ด์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ž์—ด ํ…Œ์ด๋ธ” ๋””์ฝ”๋”(mw_decode_string_table_2)๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ง€๋‚œ๋ฒˆ ์ž‘์„ฑํ•œ IDA Python ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด์„ ๋ณตํ˜ธํ™”ํ•˜์—ฌ ์ฃผ์„์œผ๋กœ ์ถ”๊ฐ€ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

(์Šคํฌ๋ฆฝํŠธ ๋‚ด์šฉ์€ '๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ์•”ํ˜ธํ™”๋œ ๋ฌธ์ž์—ด ์ถ”์ถœ(๋ณตํ˜ธํ™”)ํ•˜๊ธฐ'์— ์ž์„ธํžˆ ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.)

 

์ฃผ์„์œผ๋กœ ์ถ”๊ฐ€๋œ ๋ณตํ˜ธํ™”๋œ ๋ฌธ์ž์—ด

 

 

sub_1000FABA (mw_manipulate_persistence) ์„œ๋ธŒ๋ฃจํ‹ด ๋˜ํ•œ ๋‚ด๋ถ€์— ๋ณตํ˜ธํ™”๋œ ๋ฌธ์ž์—ด์ด ์ฃผ์„์œผ๋กœ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ž์—ด ๋ฐ ํ˜ธ์ถœ๋˜๋Š” API๋ฅผ ํ†ตํ•ด ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์™€ ์ž‘์—… ์˜ˆ์•ฝ์„ ํ†ตํ•ด ์ง€์†์„ฑ์„ ์„ค์ •ํ•จ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

Capa ๋ถ„์„์„ ํ†ตํ•ด HTTP ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜๋Š” ์„œ๋ธŒ๋ฃจํ‹ด์ด ์กด์žฌํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

ํ•ด๋‹น ์„œ๋ธŒ๋ฃจํ‹ด sub_1000E815 (mw_HTTP_stuff)๋ฅผ ์‚ดํŽด๋ณด๋ฉด

WinINet API๋“ค์„ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์•…์„ฑ์ฝ”๋“œ๊ฐ€ WinINet API๋ฅผ ์ด์šฉํ•˜์—ฌ ํŠน์ • IP ์ฃผ์†Œ์ธ C2์™€ ํ†ต์‹ ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๋” ์ž์„ธํžˆ ๋ถ„์„ํ•ด๋ณด๊ธฐ ์œ„ํ•ด์„œ sub_1000E815 (mw_HTTP_stuff) ์„œ๋ธŒ๋ฃจํ‹ด์˜ ๊ต์ฐจ ์ฐธ์กฐ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

(mw_HTTP_stuff → sub_1000EBE2 → sub_1000EBE1 → sub_1000729B → sub_1000719F)

sub_1000EBE2 ์„œ๋ธŒ๋ฃจํ‹ด์€ HttpQueryInfoA, InternetReadFile ๋“ฑ์„ ํ†ตํ•ด C2 ํ†ต์‹ ์„ ์ˆ˜ํ–‰ํ•˜๊ณ 

sub_1000EBE2

 

sub_1000EBE1์€ sleepEx ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด sub_1000EBE2์˜ ํ˜ธ์ถœ ๊ฐ„๊ฒฉ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

sub_1000EBE1

 

sub_1000729B ์„œ๋ธŒ๋ฃจํ‹ด์—์„œ ํ˜ธ์ถœํ•˜๋Š” sub_1000719F๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

sub_1000729B

 

 

sub_1000719F (mw_SHA_RC4)

mw_SHA_RC4 (sub_1000719F)

 

์ง€๋‚œ ๋ฒˆ ๋ดค๋˜ mersenne twister ํ•จ์ˆ˜๋„ ์žˆ๊ณ , SHA1 ๊ด€๋ จ ํ•จ์ˆ˜์ธ mw_w_SHA1 (sub_10007118)๋„ ๋ณด์ž…๋‹ˆ๋‹ค.

mw_w_SHA1๋กœ ๋“ค์–ด๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

mw_w_SHA1

 

16๋ฒˆ์งธ ์ค„ mw_SHA1 (sub_1000F681) ์„œ๋ธŒ๋ฃจํ‹ด ๋‚ด๋ถ€ ์ดˆ๋ฐ˜ ์ฝ”๋“œ ๋ถ€๋ถ„์—์„œ ์•”ํ˜ธํ™” ์ƒ์ˆ˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

mw_SHA1

 

mw_w_SHA1 ์„œ๋ธŒ๋ฃจํ‹ด์˜ ๋ฐ˜ํ™˜๊ฐ’์ธ mw_RC4_init (sub_1000F353) ์„œ๋ธŒ๋ฃจํ‹ด์—์„œ๋Š” ์•ฝ๊ฐ„ ์ˆ˜์ •๋œ KSA(Key-scheduling algorithm) ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

mw_RC4_init

S-Box(S_array) ์ดˆ๊ธฐํ™” ๋ฐ ์„ž๊ธฐ(์žฌ๋ฐฐ์—ด) ๊ณผ์ •์ด ์ž˜ ๋‚˜ํƒ€๋‚˜์žˆ์Šต๋‹ˆ๋‹ค.

 

  • KSA (Key-scheduling algorithm)
    • RC4 ๊ฐ™์€ ์ŠคํŠธ๋ฆผ ์•”ํ˜ธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ‚ค ์Šค์ผ€์ค„๋ง ์•Œ๊ณ ๋ฆฌ์ฆ˜

 

 

๋‹ค์‹œ mw_SHA_RC4๋กœ ๋Œ์•„์™€์„œ 18๋ฒˆ์งธ ์ค„์˜ mw_RC4_ PRGA ์„œ๋ธŒ๋ฃจํ‹ด์„ ๋ณด๋ฉด,

mw_w_SHA1์—์„œ ๋ฐ˜ํ™˜๋œ ํ‚ค ์ŠคํŠธ๋ฆผ key_stream์„ ๋‹ค์‹œ mw_RC4_ PRGA (sub_1000F3C5)ํ•จ์ˆ˜ ํ˜ธ์ถœ์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์“ฐ์ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

mw_RC4_PRGA

์ด๋ฅผ ํ†ตํ•ด mw_RC4_PRGA๊ฐ€ RC4์˜ PRGA ๋ฃจํ‹ด์ธ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  • PRGA (Pseudorandom Generation Algorithm)
    • ์˜์‚ฌ๋‚œ์ˆ˜ ์ƒ์„ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜
    • RC4 ๊ฐ™์€ ์ŠคํŠธ๋ฆผ ์•”ํ˜ธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ•„์š”ํ•œ ์˜์‚ฌ๋‚œ์ˆ˜๋ฅผ ์ƒ์„ฑ

 

 

RC4 ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด์„œ ์•…์„ฑ์ฝ”๋“œ๊ฐ€ ๋ฌด์Šจ ์ผ์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•˜๋‹ˆ ๊ต์ฐจ ์ฐธ์กฐ๋ฅผ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœ๋˜๊ณ  ์žˆ๊ณ  ๊ทธ์ค‘ sub_10008F17 ์„œ๋ธŒ๋ฃจํ‹ด์œผ๋กœ ์ด๋™ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

mw_w_RC4

 

sub_10008F17 (mw_w_RC4)์˜ ๊ต์ฐจ ์ฐธ์กฐ๋ฅผ ํ™•์ธํ•˜๋ฉด sub_100089C6 ์„œ๋ธŒ๋ฃจํ‹ด์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

sub_100089C6 (mw_ww_RC4)

 

sub_100089C6 (mw_ww_RC4) ๋‚ด๋ถ€์—๋Š” mw_SHA์™€ mw_w_RC4 ํ˜ธ์ถœ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

๊ทธ๋ฆฌ๊ณ  mw_ww_RC4์˜ ๊ต์ฐจ ์ฐธ์กฐ๋ฅผ ํ™•์ธํ–ˆ์„ ๋•Œ ๋ฐœ๊ฒฌํ•œ sub_10008AC1 ์„œ๋ธŒ๋ฃจํ‹ด์— ๋“ค์–ด๊ฐ€์„œ,

sub_10008AC1 ์„œ๋ธŒ๋ฃจํ‹ด์— ๋Œ€ํ•œ ๊ต์ฐจ ์ฐธ์กฐ ์ค‘ sub_10002783๋ฅผ ์„ ํƒํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

sub_10002783 ์„œ๋ธŒ๋ฃจํ‹ด์„ ์ž์„ธํžˆ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

sub_10002783

 

sub_10002783 ์„œ๋ธŒ๋ฃจํ‹ด ๋‚ด๋ถ€์—๋Š” resource๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” sub_1000A6CA (mw_get_resources) ์„œ๋ธŒ๋ฃจํ‹ด๊ณผ
์ด๋ฏธ ๋ถ„์„ํ–ˆ๋˜ ๋ฌธ์ž์—ด ๋ณตํ˜ธํ™” ๋ฃจํ‹ด mw_w_decode_string_table_0 (sub_10001080),
๋˜๋‹ค๋ฅธ resource ๊ด€๋ จ sub_10008AC1 (mw_w_resource_crypto) ์„œ๋ธŒ๋ฃจํ‹ด์„ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ sub_10008AC1 (mw_w_resource_crypto) ์„œ๋ธŒ๋ฃจํ‹ด์€ mw_ww_RC4์˜ ๊ต์ฐจ ์ฐธ์กฐ๋ฅผ ํ™•์ธํ–ˆ์„ ๋•Œ ๋ฐœ๊ฒฌํ•œ, ์ฒ˜์Œ์— ์™”๋˜ ๊ทธ ์„œ๋ธŒ๋ฃจํ‹ด์ž…๋‹ˆ๋‹ค.

sub_10002783 ์„œ๋ธŒ๋ฃจํ‹ด ๋‚ด๋ถ€ ๋ณ€์ˆ˜/์„œ๋ธŒ๋ฃจํ‹ด๋ช…์„ ์ˆ˜์ •ํ•˜์—ฌ ์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

mw_get_resources (sub_1000A6CA) ์„œ๋ธŒ๋ฃจํ‹ด์œผ๋กœ ๋“ค์–ด๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

mw_get_resoucres

ํ•ด๋‹น ์„œ๋ธŒ๋ฃจํ‹ด์€ ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ .rsrc ์„น์…˜์—์„œ ๋ฆฌ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์•„ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

 

  • FindResourceA
    • ๋ฆฌ์†Œ์Šค ํŒŒ์ผ์—์„œ ํŠน์ • ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณต

    • FindResourceA ํ•จ์ˆ˜ ๊ตฌ์กฐ
HRSRC FindResourceA(
  HMODULE hModule,    // ๋ฆฌ์†Œ์Šค๊ฐ€ ํฌํ•จ๋œ ๋ชจ๋“ˆ์˜ ํ•ธ๋“ค
  LPCSTR lpName,      // ์ฐพ๊ณ ์ž ํ•˜๋Š” ๋ฆฌ์†Œ์Šค์˜ ์ด๋ฆ„
  LPCSTR lpType       // ๋ฆฌ์†Œ์Šค์˜ ์œ ํ˜• (์˜ˆ: RT_ICON, RT_STRING ๋“ฑ)
);

 

  • SizeofResource
    • ๋ฆฌ์†Œ์Šค ํฌ๊ธฐ ๋ฐ˜ํ™˜

  • LoadResource
    • ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋กœ๋”ฉ

 

 

๋‹ค์‹œ mw_get_resources๋กœ ๋Œ์•„๊ฐ€์„œ, ๊ต์ฐจ ์ฐธ์กฐ๋ฅผ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๊ทธ์ค‘ sub_1000173B (mw_resource_decryptor)๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

mw_resource_decryptor

58๋ฒˆ์งธ ์ค„์—์„œ ๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž 3719๊ฐ€ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

59๋ฒˆ์งธ ์ค„ mw_get_resources๋ฅผ ํ†ตํ•ด ๋ฆฌ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

66๋ฒˆ์งธ ์ค„์—์„œ ํŠน์ • ๋ฌธ์ž์—ด์ด ๋ณตํ˜ธํ™”๋ฉ๋‹ˆ๋‹ค.

67๋ฒˆ์งธ ์ค„์—์„œ ๊ฐ€์ ธ์˜จ ๋ฆฌ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฅผ ๋ณตํ˜ธํ™”ํ•ฉ๋‹ˆ๋‹ค.

 

 

mw_w_resource_crypto_0๊ณผ mw_resource_decryptor ์„œ๋ธŒ๋ฃจํ‹ด์„ ํ†ตํ•ด ์•Œ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€,
๋ฆฌ์†Œ์Šค ์‹๋ณ„์ž(ID) 5812, 3719๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฆฌ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , ๊ทธ๊ฒƒ์„ ๋ณตํ˜ธํ™”ํ•˜๊ธฐ ์œ„ํ•œ mw_w_resource_crypto ํ•จ์ˆ˜, ๊ทธ๋ฆฌ๊ณ  mw_ww_RC4 ์„œ๋ธŒ๋ฃจํ‹ด์„ ํ˜ธ์ถœํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ SHA1 ๋ฐ RC4 ๊ด€๋ จ ์„œ๋ธŒ๋ฃจํ‹ด(mw_SHA, mw_w_RC4, mw_ww_RC4 ๋“ฑ)์„ ํ†ตํ•ด ์•Œ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€,
ํ‚ค๊ฐ€ SHA1 ์„œ๋ธŒ๋ฃจํ‹ด์— ์ œ๊ณต๋˜๊ณ , SHA1 ์„œ๋ธŒ๋ฃจํ‹ด์˜ ๊ฒฐ๊ณผ(key_stream)๊ฐ€ RC4 ์„œ๋ธŒ๋ฃจํ‹ด์— ์ œ๊ณต๋˜๋ฉฐ(์ด๋•Œ SHA1๋Š” KDF), RC4 ์„œ๋ธŒ๋ฃจํ‹ด์€ ๋ฆฌ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๋„ˆ๋ฌด ๊ธธ๊ณ  ๋งŽ์•„์„œ ๊นŒ๋จน์ง€ ์•Š๊ฒŒ ์ •๋ฆฌํ•ด๋ดค์Šต๋‹ˆ๋‹ค. (์œผ์œฝ;;)

 

 

 

์ด๋ฒˆ์—๋Š” mw_resource_decryptor์˜ ๊ต์ฐจ ์ฐธ์กฐ ์ค‘ sub_100019DE ์„œ๋ธŒ๋ฃจํ‹ด์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

sub_100019DE ์„œ๋ธŒ๋ฃจํ‹ด ๋‚ด๋ถ€์— inet_ntoa ํ•จ์ˆ˜๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.

sub_100019DE

 

  • inet_ntoa 
    • IPv4 ์ฃผ์†Œ๋ฅผ ๋ฌธ์ž์—ด ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜

 

inet_ntoa ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด IP์ฃผ์†Œ๋ฅผ ๋ฌธ์ž์—ด ํ˜•์‹(dotted-decimal)์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. mw_resource_decryptor๊ฐ€ .rsrc์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋‹ˆ๊น ํ•ด๋‹น ์„น์…˜์— C2 ์ฃผ์†Œ๊ฐ€ ์ €์žฅ๋˜์–ด ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

 

์ด๋ฒˆ์—๋Š” mw_resource_decryptor์˜ ๊ต์ฐจ ์ฐธ์กฐ ์ค‘ sub_1000173B ์„œ๋ธŒ๋ฃจํ‹ด์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค

 

 

๋‚ด๋ถ€์— ๋ณด๋‹ˆ ๋”ฑ ๋ด๋„ IP ์ฃผ์†Œ ํ˜•์‹์˜ ๋ฌธ์ž์—ด์ด ์žˆ์Šต๋‹ˆ๋‹ค: "%u.%u.%u.%u"%u"

sub_1000173B

 

 

์ด๋ ‡๊ฒŒ .rsrc ์„น์…˜์— ์ค‘์š”ํ•œ ์ •๋ณด๋“ค์ด ์žˆ์œผ๋‹ˆ .rsrc ์„น์…˜ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๊ณ  ๋ณตํ˜ธํ™”ํ•ด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

 

๋จผ์ € ์ฝ”๋“œ์—์„œ๋„ ํ™•์ธํ–ˆ์ง€๋งŒ Resource Hacker ํˆด๋กœ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๋ณด๋ฉด, ๋‘ ๊ฐœ์˜ ๋ฆฌ์†Œ์Šค ID๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

๋ถ„์„์„ ํ†ตํ•ด ์•Œ๊ณ  ์žˆ๋Š” ์ƒํ™ฉ์€
mw_w_RC4 ์„œ๋ธŒ๋ฃจํ‹ด์ด ๋‘ ๋ฒˆ ํ˜ธ์ถœ๋˜์–ด ๋‘ ๋ฆฌ์†Œ์Šค ID๋ฅผ ๋ณตํ˜ธํ™”ํ•˜๊ณ  ์žˆ๊ณ ,
mw_w_RC4 ํ˜ธ์ถœ ์‹œ(mw_w_RC4(0x14u, (int)key, key + 20, resource_size - 20, *arg_key_stream);) ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ 20์„ ๋”ํ•˜๋Š” ๊ฒƒ์„ ๋ณด๋ฉด ์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” 21๋ฒˆ์งธ ๋ฐ”์ดํŠธ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

SHA1์˜ ํ•ด์‹œ๊ฐ’์ด 20๋ฐ”์ดํŠธ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด์™€ ์—ฐ๊ด€์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ด ์ •๋ณด๋“ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ Python ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๋ณตํ˜ธํ™”ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ("Alexandre Borges์˜ "Malware Analysis Series(MAS) – Article 2" ์ฐธ์กฐ)

import binascii
import pefile
import ipaddress
from Crypto.Cipher import ARC4
from Crypto.Hash import SHA1

# Key found in the code (doubled slashs because the interpretation)
key = b'\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'

# SHA hash of the key
sha1_key = SHA1.new(data=key).digest()

# This routine extracts data from .rsrc section.
def extract_resource(filename, res_identification):
    
	extracted_data = b""
	pe = pefile.PE(filename)
	for resource in pe.DIRECTORY_ENTRY_RESOURCE.entries:
		if hasattr(resource, 'directory'):
			for res_id in resource.directory.entries:
				if hasattr(res_id, 'name'):
					if (str(res_id.name) == str(res_identification)):
						offset = res_id.directory.entries[0].data.struct.OffsetToData
						resid_size = res_id.directory.entries[0].data.struct.Size

	extracted_data = pe.get_memory_mapped_image()[offset:offset+resid_size]
	return extracted_data

# This routine decrypt resource data using RC4 + hashed key
def data_decryptor(key_data, data):
    
	data_cipher = ARC4.new(key_data)
	decrypted_config = data_cipher.decrypt(data)
	return decrypted_config

# Main routine used to perform all necessary calls.
def main():
    
	# Path to the malware
	filename = r"C:\Users\user\Desktop\mas2_sample_unpack\rundll32_047A0000_from_VirtualProtect.bin"

	# Extracts the second resource id (smaller) and decrypt it.
	resource_data = extract_resource(filename, 5812)
	hex_resource_data = binascii.hexlify(resource_data)

	# Remember that the useful data strat at 21th byte onward.
	decrypted_data = data_decryptor(sha1_key, resource_data)[20:]
    
	# Prints SHA1 key
	print('SHA1 KEY: ', end='')
	print(binascii.hexlify(sha1_key))
	print(60*'=')


	# Prints decrypted resource : ID=5812
	print('\nDECRYPTED BOTNET AND CAMPAIGN ID: ', end='')
	print("\n" + 34*'-')
	print(decrypted_data.decode('latin1'))


	# extracts the first resource id and decrypt it.
	resource_data = extract_resource(filename, 3719)
	decrypted_data = data_decryptor(sha1_key, resource_data)

	# Remember that the useful data start at 21th byte onward.
	resource_item = decrypted_data[21:]

	# Prints decrypted resource : ID=3719
	# The format is: [4 bytes for IP address][2 bytes of part]
	print('\nC2 IP ADDRESS LIST: ')
	print(30*'-')

	k = 0
	i = 0
	while (k < len(resource_item)):
		ip_item = resource_item[k:k+4]
		ip_port = resource_item[k+4:k+6]
		print("IP[%d]: %s" % (i, ipaddress.IPv4Address(ip_item)), end=':')
		print(int(binascii.hexlify(ip_port),16))
		k = k+7
		i = i+1

if __name__ == '__main__':
	main()

 

 

๋ฆฌ์†Œ์Šค ๋ณตํ˜ธํ™” ์Šคํฌ๋ฆฝํŠธ ๊ฒฐ๊ณผ (1)
๋ฆฌ์†Œ์Šค ๋ณตํ˜ธํ™” ์Šคํฌ๋ฆฝํŠธ ๊ฒฐ๊ณผ (2)

์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ†ตํ•ด ๋ด‡๋„ท ์ด๋ฆ„์ด obama150์ด๋ผ๋Š” ๊ฒƒ๊ณผ ์บ ํŽ˜์ธ ID๊ฐ€ 1640256791์ด๋ผ๋Š” ๊ฒƒ, ๊ทธ๋ฆฌ๊ณ  C2 IP ์ฃผ์†Œ 150๊ฐœ๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ๋Š” ์•…์„ฑ์ฝ”๋“œ๊ฐ€ Crypto API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ C2 ํ†ต์‹ ํ•˜๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•ด ๋ถ„์„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 

Ref. "Malware Analysis Series(MAS) – Article 2", Alexandre Borges