Unikanie sieci

https://chacker.pl/

Po ustanowieniu kanału C2 musimy być w stanie uniknąć wykrycia w sieci. Istnieją dwa obszary kontroli, których zazwyczaj musimy unikać. Pierwszy to IDS/IPS, a drugi to wykrywanie proxy. Większość organizacji nie odszyfrowuje danych TLS wewnętrznie, ale mogą odszyfrować dane TLS wychodzące poza organizację. Wiedząc o tym, mamy wiele obszarów, w których można zastosować szyfrowanie i unikanie zabezpieczeń.

 

Kompilowanie i testowanie launcherów Nim

https://chacker.pl/

W laboratorium Nim będziemy używać tej samej konfiguracji, co w poprzednich dwóch laboratoriach, z naszym modułem obsługi Metasploit Meterpreter nasłuchującym i budującym nasz kod na maszynie Kali. Aby skonfigurować nasze moduły dla naszego kodu Nim, musimy zainstalować moduł. Nimble jest menedżerem modułów Nimble, więc z naszego katalogu Shells instalujemy moduł winim za pomocą Nimble, w następujący sposób:

Pakiet winim zawiera moduły systemu Windows i definicje potrzebne do uruchomienia naszego kodu powłoki. Nie jest instalowany domyślnie, więc musimy go zainstalować. Następnie rzucimy okiem na nasz kod Nim w pliku nim.template w katalogu powłoki. Ten kod jest oparty na wielu przykładach OffensiveNim autorstwa Byt3bl33der. Wyeliminujemy wiele sprawdzania błędów i przesyłania wiadomości, aby zaoszczędzić miejsce:

Funkcja Patchntdll zastępuje funkcjonalność funkcji EtwEventWrite kodem powrotu, dzięki czemu nie wykona żadnego zawartego w niej kodu. Funkcja EtwEventWrite rejestruje zdarzenia Event Tracing for Windows (ETW), więc zapobiegnie zapisaniu żadnego z nich, ukrywając w ten sposób nasz kod przed jakąkolwiek instrumentacją, która go używa. Aby to zrobić, zaczynamy od uzyskania informacji o funkcji, dzięki czemu wiemy, co musimy nadpisać. Funkcja LoadLib (1) ładuje bibliotekę ntdll.dll do naszego kodu. Funkcja symAddr (2) pobiera adres funkcji EtwEventWrite. Funkcja VirtualProtect (3) ustawia lokalizację pamięci, którą nadpisujemy, na Odczyt/Zapis/Wykonanie, abyśmy mogli (4) zastosować nadpisane bajty do tej pamięci. Na koniec przywracamy pierwotny tryb ochrony do pamięci zapisanej w zmiennej origProtect za pomocą funkcji VirtualProtect (5) . Po wyłączeniu ETW musimy wstrzyknąć nasz kod powłoki. Aby to zrobić, użyjemy funkcji injectCreateRemoteThread do wstrzyknięcia naszego kodu powłoki w nowy proces:

Część tego kodu widzieliśmy już wcześniej, a wzór wygląda znajomo. W tym przykładzie uruchamiamy nowy proces (1) (w tym przypadku notepad.exe), w którym wstrzykniemy nasz kod. Musimy zawiesić proces, aby nie był widoczny i nie dawał użytkownikowi kontroli. Zamiast tego otworzymy nasz proces (2), abyśmy mogli nim manipulować i zapisać w nim nasz kod powłoki (3). Resetujemy (4) ustawienia ochrony pamięci, aby nie wyglądała dziwnie, a następnie tworzymy (5) wątek. Wątek będzie nadal działał, a nasz kod powłoki zostanie wykonany, podczas gdy normalna funkcjonalność procesu będzie nadal zawieszona i niewidoczna dla użytkownika. Na koniec musimy powiązać te informacje w jedną całość. Robimy to w odpowiedniku funkcji main dla Nim:

Oznacza to, że jeśli nie dołączymy tego kodu jako biblioteki, a jest to główny moduł projektu, to załata bibliotekę DLL, a następnie wstrzyknie kod powłoki. Możemy zbudować kod powłoki za pomocą polecenia build_nim.sh. Plik binarny /tmp/nim_dropper64.exe powinien teraz znajdować się w katalogu /tmp, a kiedy uruchomimy go w systemie Windows, nie powinniśmy zobaczyć żadnych wyników, ale powinniśmy zobaczyć powrót sesji w Metasploit:

Tworzenie wyrzutni Nim

https://chacker.pl/

Nim to kolejny skompilowany język, który obsługuje wiele systemów operacyjnych i wykorzystuje niektóre popularne części Pythona i innych języków, aby stworzyć bardziej przyjazny dla użytkownika język, który kompiluje się do C, C++, Objective-C i JavaScript. Dzięki temu kod można skompilować do jednego z języków pośrednich i włączyć do innych projektów, a także sam skompilować do formatu binarnego. Elastyczność Nim jest częścią jego popularności, podobnie jak fakt, że sygnatury plików binarnych będą na tyle różne, aby ominąć wiele tradycyjnych wykryć AV. Obecnie nie ma zbyt wielu repozytoriów korzystających z Nim, ale przyciągnęło to uwagę zarówno podmiotów zagrażających, jak i etycznych hakerów. Jedną z osób, która przeprowadziła świetne badania na temat ofensywnego Nima, jest Marcello Salvati, znany w Internecie jako Byt3bl33der. Jego repozytorium Offensive Nim pod adresem https://github.com/byt3bl33d3r/OffensiveNim zawiera próbki implementacji wielu technik uruchamiania i unikania kodu powłoki.

Kompilowanie i testowanie programów uruchamiających Go

https://chacker.pl/

Pliki binarne systemu Windows w Go można skompilować krzyżowo z Kali Linux przy użyciu pakietów mingw. Po zainstalowaniu pakietów golang i mingw wystarczy, że określimy architekturę i system operacyjny, a Go zajmie się za nas większością instrukcji kompilacji. W tym laboratorium będziemy nadal używać naszego detektora Meterpretera i będziemy używać plików build_go.sh i go.template w katalogu Shells. Kod Go w tym laboratorium wykorzystuje nieco inną technikę niż w poprzednim laboratorium. Zamiast wątków używamy światłowodu do uruchomienia naszego kodu. Włókno jest podobne do nici. Jest to strumień wykonania oddzielony od głównej części kodu. Jednak wątki są planowane przez aplikację. Dwa wątki nie muszą robić nic specjalnego, aby oba działały w tym samym czasie. Światłowody wymagają harmonogramu do obsługi wielozadaniowości. W rezultacie, kiedy uruchomimy nasze włókno, będzie ono działać aż do zakończenia działania lub do chwili, gdy nasz kod zrzeknie się kontroli nad resztą aplikacji. Ponieważ nasz kod powłoki nie wie, że znajduje się we włóknie, efektem końcowym jest to, że nasz kod będzie zawieszony do momentu zakończenia działania kodu powłoki. Kod Go będzie wyglądał podobnie do tego, co zrobiliśmy w C#, ponieważ używa również bibliotek Windows kernel32.dll i ntdll.dll. Kod ten jest modyfikowany na podstawie przykładów światłowodów ired.team, a także kodu z repozytorium Ne0nd0g wspomnianego wcześniej. W tym przykładzie będziemy kodować nasz kod powłoki w base64, co pozwala nam łatwo umieścić go w składni Go:

Tutaj używamy biblioteki base64 i dekodujemy ciąg znaków, który ustawiliśmy za pomocą naszego kodu powłoki, sc i zapisujemy go w zmiennej kodu powłoki. Jeśli zwrócone zostaną jakiekolwiek kody błędów, zostaną one zapisane w zmiennej err. Operator := służy do jednoczesnego tworzenia i przypisywania zmiennych, gdzie = służy do przypisania wartości już utworzonej zmiennej:

Aby wykonać nasz kod powłoki, musimy wykonać kilka kroków. Pierwszym krokiem jest przekształcenie naszej głównej nici w włókno. Robimy to za pomocą funkcji ConvertThreadToFiber (1) , która, jeśli zostanie określona bez opcji, pobiera bieżący wątek i konwertuje go na włókno. Musimy to zrobić, ponieważ tylko włókna mogą tworzyć dodatkowe włókna. Następnym krokiem jest przydzielenie pamięci dla naszego kodu powłoki za pomocą funkcji VirtualAlloc (2). Tutaj tworzymy pamięć jako Odczyt/Zapis/Wykonanie w jednym kroku. Może to być postrzegane jako szkodliwe dla niektórych produktów obronnych, dlatego zawsze możemy umożliwić zapis, kopiując kod powłoki, a następnie usuwając bity zapisu za pomocą programu VirtualProtect, aby wyglądało to mniej podejrzanie. Teraz, gdy mamy już pamięć, możemy skopiować do niej kod powłoki za pomocą wywołania RtlCopyMemory (3). Jedną z rzeczy, na które warto zwrócić uwagę w przypadku Go, jest to, że stara się chronić Cię przed niektórymi konwersjami typów, które mogą być niebezpieczne, więc użycie niebezpiecznej biblioteki ominie te zabezpieczenia. Następnym krokiem jest utworzenie nowego włókna do harmonogramowania za pomocą funkcji CreateFiber (4). Zauważ, że na potrzeby tego wywołania tworzymy nowe włókno wskazujące lokalizację pamięci naszego kodu powłoki, które zwraca adres nowego włókna. Mając ten adres możemy ustawić wykonanie na nowym włóknie za pomocą wywołania SwitchToFiber (5). Od tego momentu nasz kod będzie wykonywany aż do zakończenia światłowodu lub kodu z powrotem do głównego włókna. Teraz, gdy rozumiemy, co robi nasz kod, możemy uruchomić skrypt build_go.sh z katalogu powłoki w naszym hostowanym Kali. Spowoduje to utworzenie pliku /tmp/CreateFiber.exe, który możemy uruchomić z naszego okna Windows. Linia kompilacji samego pliku binarnego Go określa architekturę i system operacyjny w wierszu poleceń ze zmienną środowiskową, którą można ustawić w środowisku użytkownika lub w samym wierszu poleceń:

Teraz, gdy działa nasz słuchacz msfconsole, możemy uruchomić kod w systemie Windows:

W naszej sesji Linux Meterpreter powinniśmy teraz zobaczyć nową sesję, z którą możemy wchodzić w interakcję i używać jej do wykonywania poleceń:

Nasz plik binarny w systemie Windows będzie nadal wykonywany, dopóki nie wyjdziemy z sesji Meterpretera, a następnie powinien zakończyć się. Możesz sprawdzić dodatkowe przykłady w katalogu go-shellcode w swojej instancji Kali i możesz spróbować zmodyfikować inne przykłady, aby działały również w polu docelowym.

Tworzenie programów uruchamiających Go

https://chacker.pl/

Popularność Go rośnie ze względu na możliwości pracy na wielu platformach. Go można skompilować na mobilne i tradycyjne platformy komputerowe, w tym iOS, Linux, Windows, macOS, Solaris, a nawet z/OS. Ponieważ Go jest skompilowany, jest to dobry sposób na wprowadzenie programów uruchamiających, których tradycyjne podpisy mogą nie przechwycić. Go może używać wbudowanych bibliotek i konstrukcji systemu Windows i innych systemów operacyjnych do wykonywania kodu powłoki bez stosowania tradycyjnych wzorców, których mogą szukać wykrycia oparte na sygnaturach. Jednym z projektów GitHub, który ma dobre przykłady dla Windows, jest repozytorium go-shellcode Russela Van Tuyla (https://github.com/Ne0nd0g/goshellcode), które ma różne wzorce wykonywania napisane w Go. Są to dobre odniesienia do tworzenia własnego programu uruchamiającego Go, a także do przenoszenia tych wzorców na inne języki.