Arsip: EXE/PE File Protector


by reev in Articles more 16 years ago 7305
Banyak kita melihat virus-virus yang menyerang file EXE/PE, seperti varian Alman, Virut dan berbagai virus lainnya. Banyak juga yang membuat aplikasi-aplikasi untuk memproteksi komputer dari tangan jahil atau bahkan virus. Pertanyaan, jika kedua jenis software di atas bisa kita buat, yang mana yang akan kita buat?
Saya pribadi akan membuat virus. Sayang, saya tidak bisa membuat virus yang bauk, jadi "terpaksa" saya pilih yang kedua, aplikasi untuk kepentingan sekuriti.
Software : Delphi 6, PE Inject API oleh Michal Strahovsky
Tingkat Kemahiran: 80%
Kategori: Sekuriti & WIN32API

Pengantar

Banyak kita melihat virus-virus yang menyerang file EXE/PE, seperti varian Alman, Virut dan berbagai virus lainnya. Banyak juga yang membuat aplikasi-aplikasi untuk memproteksi komputer dari tangan jahil atau bahkan virus. Pertanyaan, jika kedua jenis software di atas bisa kita buat, yang mana yang akan kita buat?
Saya pribadi akan membuat virus. Sayang, saya tidak bisa membuat virus yang bauk, jadi "terpaksa" saya pilih yang kedua, aplikasi untuk kepentingan sekuriti.

Virus-virus yang menyerang file PE/EXE, sebagaimana juga software sekuriti dimaksud di atas, setidaknya memiliki dua opsi untuk mengerjakan tugasnya - menurut sepengetahuan saya, harap diingat - itu. Seperti ini:

1. Sebagai stub dengan embbeded data. Ini mirip dengan aplikasi installer pada umumnya, di mana sebuah aplikasi membuat/mengkopi file EXE/PE dan kemudian menambahkan data tambahan di akhirnya, dan di bagian paling akhir (atau di bagian mana saja yang aman), ditambahkan beberapa parameter untuk digunakan oleh stub nantinya, seperti CRC check signature, besar data yang diembed, jumlah file/data yang diembed, dsb. Jika, misalnya, cara ini dipakai untuk kepentingan distribusi data melalui sebuah file (Self Extractor) atau SFX, jadilah dia sebuah aplikasi instalasi. Namun jika dipakai untuk menyebarkan "sesuatu", maka jadilah dia dalam golongan virus. Sebagai catatan, jika ada yang membuat virus dengan cara ini, sebaiknya kedua tugas di atas - membuat stub dan mengandung embedded data - dikerjakan oleh sebuah EXE saja, sehingga bisa menyebar tanpa software bantu lainnya. Dan sebaiknya jangan memilih tool yang menggunakan shared depencies seperti VB :-)
Di Tanah Air Indonesia ini, saya melihat kecenderungan membuat trojan atau virus - atau apa kek- dengan metode ini. Namun ada kelemahannya, icon aplikasi (stub/target) yang sudah dihinggapi (bukan diinfeksi) akan berubah sesuai icon stub yang sebenarnya, jadi user yang menjadi korban, jika cukup teliti, akan tahu bahwa dia sedang disantet.
Ini sebanya (barangkali), beberapa waktu lalu saya acap menerima e-mail atau membaca posting di milis-milis tentang bagaimana mengubah icon sebuah aplikasi. Tapi sebagaimana Anda, saya juga tidak menjawab sebuah pertanyaan yang mempunyai tendensi negatif, apalagi yang ditanyakan oleh seorang Delphier. Bukankah akan memalukan?
2. Ini yang seru. Sebagai stub yang menjadi bagian dari file yang ditumpangi. Varian Alman dan Virut di atas masuk kategori ini. Sebuah aplikasi, katakan A, akan menyuntik kode-kode tertentu, katakan B, (seperti DLL Injection) yang residen dalam file target. Jika cara ini dipakai oleh virus, maka virus itu akan masuk kategori sulit dibasmi, kecuali dengan mempertaruhkan keselamatan file terinfeksi (bukan dihinggapi, silahkan bandingkan dengan metode pertama di atas) :-)
Seperti juga di atas, jika sebuah program mampu menjadi kode yang iinject sekaligus penginjectnya, pastikan program ini sudah menjadi sebuah virus yang tangguh. Tinggal ditambahkan sebuah rutin untuk mencari file PE/EXE di harddisk target, trus jalankan injeksi ke tiap PE/EXE yang mungkin untuk diinject.

Baik. Sampai di sini, saya menunggu koreksi jika Anda menemukan ketidak sesuaian.

Sesuai judul, kita hanya akan membahas metode nomor dua, dengan batasan positif, membuat sebuah aplikasi sekuriti untuk memproteksi file-file PE/EXE dengan password. Berikut kita lihat beberapa gambar screenshot dari demo aplikasi yang sudah saya buat:


Ini tampilan depan.


Ini tampilan pesan yang menyatakan bahwa proses injeksi berlangsung sempurna.


Ini tampilan jika PE/EXE yang telah dinjeksi dijalankan :-)

Proses Pembuatan

Proses pembuatan aplikasi proteksi ini kita bagi dua. Yang pertama kode yang akan diinject ke file target (yang harus merupakan PE/EXE), dan yang kedua aplikasi untuk menginjeksi. Kita tidak membuat virus, jadi tugas aplikasi ini kita pisahkan, tidak dilakukan oleh sebuah aplikasi tunggal.

Untuk menjalankan proses, kita butuh PE Inject Library oleh Michal Strahovsky, yang mana bukan saya pembuatnya :-). Silahkan download di websitenya http://migeel.sk. Selanjutnya , kita buat sebuah projek baru di Delphi (saya menggunakan Delphi 6), dengan target Dynamic Link Library. Ini untuk mempermudah, karena Michal Strahovsky memilih menggunakan DLL sebagai kode yang akan diinject, sehingga dengan mudah kita buat, tanpa harus pusing menentukan batasan-batasan kode yang akan kita inject. Plus, kita bisa sertakan form (dengan WinAPI) tentunya.

Michal Strahovsky membagi kode dalam DLL kita atas dua, berupa fungsi BeforeHandler dan AfterHandler, yang akan dijalankan sebelum kode PE/EXE sesungguhnya dari file target, kemudian masuk ke entry point PE/EXE target, dan setelah berakhir, outpoint akan melompat ke awal fungsi AfterHandler dan menjalankan kode kita. Agar bisa diload oleh PEInject, kedua fungsi ini harus diekspor.

Saya tidak menggunakan AfterHandler (opsional) karena yang saya butuhkan hanya Beforehandler sebelum masuk entry point PE/EXE target - yang disebut Original Entry Point, selanjutnya akan saya sebut OEP saja. Kemudian saya tambahkan sebuah fungsi WindowPorc untuk memproses pesan. Funsgi ini perlu untuk menangani message yang datanng dari Windows. Ingat, untuk meminta password kita butuh form dan minimal sebuah EditBox. Untuk membuat form, kita butuh WindowProc.

Perbedaan mendasar DLL ini dari DLL lainnya adalah, entry pointnya berada pada fungsi BeforeHandler, bukan Begin & End. Jadi proses pembuatan form harus ditempatkan dalam fungsi ini.

Agar tidak membosankan, saya langsung saja dengan kodenya, yang terbagi atas dua: Entry Point BeforeHandler dan WindowProc.


Library pelock;

uses
Windows,Messages, InjectionTypes;

const
ClassName='PELOCKER_Plugin';

var
sLen:cardinal;
form1,
lblPassword,
edtPassword,
BtnOK:hwnd;
s, pass:string;
wc:TWNDClassEx;
msg:Tmsg;
Font:HFont;
p:PChar;
Adata:PextData;

truePass:Boolean;

//define window proc:
function WndProc(handle:hwnd; wmsg:cardinal;wparam:WParam;lparam:LParam):longint;stdcall;
begin
result:=defWindowProc(handle,wmsg,wparam,lparam);
case wmsg of
wm_Destroy:
begin
halt;
end;
wm_command:
begin
if lparam=BtnOK then //user click send button:
begin
slen:=GetWindowTextLength(edtPassword);
if slen=0 then begin //no message, boom!
Messagebox(handle,'There is no password entered.','Cannot Run',MB_ICONHAND);
SetWindowText(edtPassword, nil);
SetFocus(edtPassword);
end
else
begin
//is it true password?
Pass:=Adata^.Password;
//DEBUG_ONLY:-> MessageBox(Form1, PChar(pass), 'Test',MB_OK);
getmem(p, slen+1);
GetWindowText(edtPassword, p, slen+1);
s:=String(p);
FreeMem(p);
if s=pass then
begin
truePass:=True;
end
else
begin
MessageBox(Form1, 'Invalid password!','Cannot Run',MB_ICONHAND);
SetWindowText(edtPassword, nil);
SetFocus(edtPassword);
end;
end;
end;
end;
//case...
{
other message
}
end;
end;

function BeforeHandlers(Config: PStubConfiguration): DWORD; stdcall;
begin
Adata:=PExtData(Config.ImageBase+Config.ExtraDataRVA);
truepass:=False;

//define main window's class:
wc.cbSize:=sizeof(wc);
wc.style:=0;
wc.lpfnWndProc:=@WndProc;
wc.cbClsExtra:=0;
wc.cbWndExtra:=0;
wc.hInstance:=Hinstance;
wc.hIcon:=LoadIcon(hinstance,'MAINICON');
wc.hCursor:=LoadCursor(hinstance,IDC_ARROW);
wc.hbrBackground:=color_btnface+1;
wc.lpszMenuName:=nil;
wc.lpszClassName:=ClassName;
wc.hIconSm:=0;
//register class:
registerclassex(wc);
//Create main window:
form1:=CreateWindowEx(WS_EX_STATICEDGE,
pchar(ClassName),'PE Lock - JokoRB',
WS_DLGFRAME+WS_VISIBLE+WS_SYSMENU,
253,191,245,60,
0,0,
hinstance,nil);
//show it
ShowWindow(form1,SW_SHOW);
updateWindow(form1);
lblPassword:=CreateWindow(
'Static','Password',WS_VISIBLE+WS_CHILD,
2
,6,
50,
13,
form1,
0,
hinstance,nil);

edtPassword:=CreateWindow(
'Edit',
nil,
WS_VISIBLE+WS_CHILD+WS_BORDER+ES_AUTOHSCROLL+ES_PASSWORD,
63,
2,
121,
21,
form1,0,hinstance,nil);

BtnOK:=CreateWindow('Button',
'Run!',
WS_CHILD+WS_VISIBLE+BS_PUSHLIKE,
187,
2,
46,
21,
form1,
0,hinstance,nil);
//Create Default font:
font:=CreateFont(14,5,0,0,0,0,0,0,0,0,0,0,0,'Arial');
//set Control's font:
SendMessage(lblPassword,WM_SETFONT,font,0);
SendMessage(edtPassword,WM_SETFONT,font,0);
SendMessage(BtnOK,WM_SETFONT,font,0);
//limit entry text for hostname and message to 200 character
SendMessage(edtPassword,EM_LIMITTEXT,30,0);
SetFocus(edtPassword);
//Then Create Message Processing Looping:
while getmessage(msg,0,0,0) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
if truepass then
begin
ShowWindow(Form1, SW_HIDE);
exit;
end;
end;

Result:=1; // the result is not checked, so this could be anything
end;

exports BeforeHandlers;
begin
end.



OK. Kita lanjut ke program penginjeknya.

Kita butuh sebuah resource yang berisi DLL di atas. Ini supaya DLL nantinya tidak perlu diload dari harddisk.
Jadi kita buat sebuah file Resource Script dan isikann dengan skrip berikut

lockplugin RCDATA pelock.dll

Script ini bisa dikompilasi dengan BRCC32 - terdapat dalam %DelphiFolder%\Bin - untuk mendapatkan file Compiled Resource-nya. Ingat, pelock.dll adalah hasil kompilasi kode DLL di atas. Selanjutnya kita buat sebuah projek baru lagi dan tambahkan resource hasil kompilasi skrip di atas ke project source atau ke unit1 (unit utama).



//......................

PE_LOCK_DLL = 'pelocklugin.dll';

var
Form1: TForm1;

implementation

{$R .dfm}

//tambahkan baris berikut, dengan memisalkan nama file resource adalah
// plugin.res

{$R plugin.RES}
//..........................................




Kemudian, kita lihat prosedur untuk melakukan proses injeksi:



procedure TForm1.SpeedButton2Click(Sender: TObject);
var
cback:Boolean;
ExtData:PExtData;
PHost, PDll:Pointer;
szHost, szDll:Cardinal;
mslSize:DWORD;
msldata, PEData:Pointer;
TestSize:DWORD;
begin
cback:=CheckBox1.Checked;
if not FileExists(edit1.Text) then
begin
MessageBox(handle, 'File doesn''t exist!', 'Error',MB_ICONHAND);
Edit1.SetFocus;
Edit1.SelectAll;
exit;
end;
if Edit2.Text<>Edit3.Text then
begin
MessageBox(handle, 'Passwords don''t match!', 'Error',MB_ICONHAND);
Edit2.SetFocus;
Edit2.SelectAll;
exit;
end;

if Edit2.Text='' then
begin
MessageBox(handle, 'Passwords are empty!', 'Error',MB_ICONHAND);
Edit2.SetFocus;
Edit2.SelectAll;
exit;
end;

TestSize:=TakeFileSize(Edit1.Text);
if testsize > (100
10241024) {100MB} then
begin
MessageBox(handle, 'Target PE''size exceeds limit (100MB)!', 'Error',MB_ICONHAND);
Edit1.SetFocus;
Edit1.SelectAll;
exit;
end;

with TMemoryStream.Create() do
begin
LoadFromFile(Edit1.Text);
szHost:=size;
GetMem(PHost, szHost);
Read(pHost^, szHost);
Free;
end;

with TResourceStream.Create(hInstance, 'lockplugin', RT_RCDATA) do
begin
szDll:=Size;

GetMem(pDll, szDll);
Read(pDll^, szDll);
Free;
end;

//get dll as MSL:
mslSize:=szDLL;
mslData:=MappedDllToMsl(pDLL, @mslSize);
FreeMem(pdll);

New(ExtData);
ExtData^.PasswordLength:=Length(Edit2.Text);
ExtData^.Password:=Edit2.Text;

if CBack then
CopyFile(PChar(edit1.text), Pchar(Edit1.Text+'.bak'), False);

PEData:=injectMappedFile(PHost, @szHost, MSLDATA, MslSize, ExtData, sizeof(TExtData),
INJECT_FLAG_DOIMPORTS or
INJECT_FLAG_JUMPTOOEP or
INJECT_FLAG_HANDLERELOC or
INJECT_FLAG_STRIPRELOCS or
INJECT_FLAG_COMPRESSDLL or
INJECT_FLAG_BACKUPTLS
);
if PEData<>nil
{
if 0 = InjectFile(Pchar(edit1.text),
Pchar(edit1.text),
PChar(fn),
ExtData,
SizeOf(TextData),
INJECT_FLAG_DOIMPORTS or
INJECT_FLAG_JUMPTOOEP or
INJECT_FLAG_HANDLERELOC or
INJECT_FLAG_STRIPRELOCS or
INJECT_FLAG_COMPRESSDLL or
INJECT_FLAG_BACKUPTLS
)
}
then
begin
SaveFile(PEData, szHost, Edit1.Text);
FreeMem(PHost, szHost);
FreeMem(MSLDATA, mslSize);
FreeMem(peData);
MessageBox(handle, 'PE was injected successfully.', 'Information',MB_ICONInformation);
end
else
begin
MessageBox(handle, 'PE Injection failed.', 'Error',MB_ICONHAND);
end;
DispoSe(extData);
end;



Sampai di situ. Beberapa fungsi pendukung seperti TakeFileSize dan System dir tidak perlu saya tulis. Yang pertama untuk mengambil ukuran sebuah file dan yang kedua untuk mengambil path tempa System32 berada. Kenyataanya, kedua fungsi ini tidak dipakai :-)

Dan berikut kode selengkapnya:



unit uMMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, jpeg, StdCtrls, Buttons, InjectionTypes, InjectionEngine, msl, PEUtils;

type

TForm1 = class(TForm)
Panel1: TPanel;
Label1: TLabel;
Label2: TLabel;
imgOn: TImage;
Bevel1: TBevel;
Label3: TLabel;
Edit1: TEdit;
SpeedButton1: TSpeedButton;
OpenDialog1: TOpenDialog;
Bevel2: TBevel;
Label4: TLabel;
Label5: TLabel;
Edit2: TEdit;
Label6: TLabel;
Edit3: TEdit;
CheckBox1: TCheckBox;
Bevel3: TBevel;
SpeedButton2: TSpeedButton;
SpeedButton3: TSpeedButton;
Label7: TLabel;
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure SpeedButton3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
function TakeFileSize(const AFile:String):DWORD;
function SystemDir:String;
end;

const
PE_LOCK_DLL = 'pelocklugin.dll';

var
Form1: TForm1;

implementation

{$R
.dfm}
{$R plugin.RES}

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
if OpenDIalog1.Execute then
begin
edit1.Text:=openDialog1.FileName;
end;
end;

procedure TForm1.SpeedButton2Click(Sender: TObject);
var
cback:Boolean;
ExtData:PExtData;
PHost, PDll:Pointer;
szHost, szDll:Cardinal;
mslSize:DWORD;
msldata, PEData:Pointer;
TestSize:DWORD;
begin
cback:=CheckBox1.Checked;
if not FileExists(edit1.Text) then
begin
MessageBox(handle, 'File doesn''t exist!', 'Error',MB_ICONHAND);
Edit1.SetFocus;
Edit1.SelectAll;
exit;
end;
if Edit2.Text<>Edit3.Text then
begin
MessageBox(handle, 'Passwords don''t match!', 'Error',MB_ICONHAND);
Edit2.SetFocus;
Edit2.SelectAll;
exit;
end;

if Edit2.Text='' then
begin
MessageBox(handle, 'Passwords are empty!', 'Error',MB_ICONHAND);
Edit2.SetFocus;
Edit2.SelectAll;
exit;
end;

TestSize:=TakeFileSize(Edit1.Text);
if testsize > (1001024 1024) {100MB} then
begin
MessageBox(handle, 'Target PE''size exceeds limit (100MB)!', 'Error',MB_ICONHAND);
Edit1.SetFocus;
Edit1.SelectAll;
exit;
end;

with TMemoryStream.Create() do
begin
LoadFromFile(Edit1.Text);
szHost:=size;
GetMem(PHost, szHost);
Read(pHost^, szHost);
Free;
end;

with TResourceStream.Create(hInstance, 'lockplugin', RT_RCDATA) do
begin
szDll:=Size;

GetMem(pDll, szDll);
Read(pDll^, szDll);
Free;
end;

//get dll as MSL:
mslSize:=szDLL;
mslData:=MappedDllToMsl(pDLL, @mslSize);
FreeMem(pdll);

New(ExtData);
ExtData^.PasswordLength:=Length(Edit2.Text);
ExtData^.Password:=Edit2.Text;

if CBack then
CopyFile(PChar(edit1.text), Pchar(Edit1.Text+'.bak'), False);

PEData:=injectMappedFile(PHost, @szHost, MSLDATA, MslSize, ExtData, sizeof(TExtData),
INJECT_FLAG_DOIMPORTS or
INJECT_FLAG_JUMPTOOEP or
INJECT_FLAG_HANDLERELOC or
INJECT_FLAG_STRIPRELOCS or
INJECT_FLAG_COMPRESSDLL or
INJECT_FLAG_BACKUPTLS
);
if PEData<>nil
{
if 0 = InjectFile(Pchar(edit1.text),
Pchar(edit1.text),
PChar(fn),
ExtData,
SizeOf(TextData),
INJECT_FLAG_DOIMPORTS or
INJECT_FLAG_JUMPTOOEP or
INJECT_FLAG_HANDLERELOC or
INJECT_FLAG_STRIPRELOCS or
INJECT_FLAG_COMPRESSDLL or
INJECT_FLAG_BACKUPTLS
)
}
then
begin
SaveFile(PEData, szHost, Edit1.Text);
FreeMem(PHost, szHost);
FreeMem(MSLDATA, mslSize);
FreeMem(peData);
MessageBox(handle, 'PE was injected successfully.', 'Information',MB_ICONInformation);
end
else
begin
MessageBox(handle, 'PE Injection failed.', 'Error',MB_ICONHAND);
end;
DispoSe(extData);
end;

function TForm1.TakeFileSize(const AFile: String): DWORD;

begin
With TFileStream.Create(AFile, fmOpenRead or FMShareDenyNone) do
begin
try
Result:=Size;
finally
Free;
End;
end;
end;

procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
Messagebox(handle, 'PE Executable Locker by JokoRB.'#13'Find more at htt://jokorb.wordpress.com!','About',MB_ICONINFORMATION or MB_OK);
end;

function TForm1.SystemDir: String;
var
p:PChar;
begin
GetMem(p, MAX_PATH+1);
GetSystemDirectory(p, MAX_PATH);
Result:=String(p);
FreeMem(p, MAX_PATH+1);
if Result[Length(Result)]='' then
Delete(Result, Length(Result),1);
end;

end.




Download

Berikut demo dari posting ini beserta source kodenya dan PEInject Library:
Demo + Source
PE Inject Library
Dan jangan lupa, ekstensi ppt harus diubah ke zip, dan scan dulu file hasil download dengan antivirus :-)

Local Business Directory, Search Engine Submission & SEO Tools FreeWebSubmission.com SonicRun.com