المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : تغيير قيمة معينة فى ملف عن طريق دالة معينة


hanipino
05-04-2010, 02:19 AM
السلام عليكم

اخوانى كيف اغيير قيمة معينة فى ملف تنفيدى لاكن بشرط ... استعمال هده الدالة .
المشكل هو كيف الحصول على BaseAddress لهده القيمة (برمجيا).

procedure MemoryPatch(sExecutableFilePath :string; Patch: Byte; BaseAddress: Integer; nSize, BytesCount: Cardinal);
var
ProcessInfo: TProcessInformation;
StpInfo: TStartupInfo;
buf: PChar;
begin
FillChar(StpInfo,SizeOf(TStartupInfo), #0);
FillChar(ProcessInfo,SizeOf(TProcessInformation), #0);

if not CreateProcess(PChar(sExecutableFilePath),
Nil, Nil, Nil, False, CREATE_SUSPENDED,
Nil, Nil, StpInfo, ProcessInfo)
then
MessageBox(0, 'Program not found!', '', MB_OK + MB_ICONWARNING)
else
begin
GetMem(buf, 1);
buf^ := Chr(Patch);
WriteProcessMemory(ProcessInfo.hProcess, Ptr(BaseAddress), buf, nSize, BytesCount);
FreeMem(buf);
ResumeThread(ProcessInfo.hThread);
end;
end;


--- يوجد فى المنتدى كيفية استثمار هده الدالة ---

مثلا هده القيمة .
http://ups.imagup.com/09/1270473925.jpg

TF6M
05-04-2010, 08:29 AM
و عليكم السلام و رحمة الله و بركاته

- أخي hanipino , الدالة عبارة عن Loader أي أنها تقوم بتحميل sExecutableFilePath
الى الذاكرة بواسطة CreateProcess .
الهدف منها تغير Byte من البرنامج المحمل (أي عمل Patching) بواسطة WriteProcessMemory
في الذاكرة (يعني نتعامل مع العناوين كـ VA = virtual address) .

مواضيع ذات صلة :

1- Api Hook مثال بسيط, Hook للدالة TerminateProcess (http://delphi4arab.com/forum/showthread.php?t=949) , مثال رائع WriteProcessMemory
2- رفع اللبس عن Rva,Va و الأوفسيت (http://www.at4re.com/f/showthread.php?t=1318)

- BaseAddress # ImageBase , راجع Image_Nt_Headers المهم يجب أن تعرف بنية PE Header
3- ستجد كتاب بالمرفقات , مفيد جدا ! .

مثال توضيحي :

ستجد أن RegMe , يطلب كود التسجيل , الأن نفذ الـ Loder , ثم قم بإدخال أي User Name
و أي Pass Word (عشوائيا) , الأن أصبح البرنامج مسجل:tong: .

http://img62.imageshack.us/img62/3117/4564545.gif

ملاحظة : الـ Loder , للـ الأخ Kachwahed , فقط قمت بتبديل موضع القفزات .

بالتوفيق ,,

kachwahed
05-04-2010, 01:05 PM
وعليكم السلام ورحمة الله
المشكل هو كيف الحصول على BaseAddress لهده القيمة (برمجيا).
تم الحصول على BaseAddress من هنا:
http://i40.tinypic.com/2yugapg.jpg
القيمة التي أصبحت 74 هي PokeValue. وهي قيمة واحدة لذلك NumberOfBytes =1
ملاحظة: تغيرت العناوين بعد الـ Compile بدلفي 7 كما في الصورة.
برمجيا
ممم... لكن على أساس ماذا؟
ربما يساعدك هذا:
مثال للحصول على EP برمجيا:
const
// PE header constants
CENEWHDR = $003C; // offset of new EXE header
CEMAGIC = $5A4D; // old EXE magic id: 'MZ'
CPEMAGIC = $4550; // NT portable executable

function GetImageNtHeaders(module: dword) : PImageNtHeaders;
begin
result := nil;
try
if word(pointer(module)^) = CEMAGIC then begin
result := pointer(module + dword(pointer(module + CENEWHDR)^));
if result^.signature <> CPEMAGIC then
result := nil;
end;
except result := nil end;
end;

function GetEntryPoint(module: dword) : pointer;
var nh : PImageNtHeaders;
begin
nh := GetImageNtHeaders(module);
if (nh <> nil) and (nh^.OptionalHeader.AddressOfEntryPoint <> 0) then
dword(result) := module + nh^.OptionalHeader.AddressOfEntryPoint
else
result := nil;
end;
بالتوفيق.

TF6M
05-04-2010, 01:37 PM
...
الأن أوضحت الكود , كنت أظن أن Base Address هي Image Base ؟؟؟ في المثال الذي وضعته أنت ,
لكن أخي kachwahed أليس العنوان المشار إليه Va ؟؟ أم أن له تسمية أخرى (Base Address).
بالتوفيق ,,

hanipino
05-04-2010, 05:35 PM
سلام عليكم

لكن أخي kachwahed أليس العنوان المشار إليه Va ؟؟ أم أن له تسمية أخرى (Base Address).


نعم هى Va لاكن اخدت اسم Base Address فى الدالة MemoryPatch لانها استعملت فى البرمتر الثانى للدالة
WriteProcessMemory الدى يحمل نفس الاسم ... فقط .

http://ups.imagup.com/09/1270527017.jpg


تم الحصول على BaseAddress من هنا:


والله اعلم يمكن الحصول عليها من خلال موقع البايت فى الملف التنفيدى

مثلا فى المثال الدى الرفقته اخى كاش واحد المسمى PatchMe.exe عند تنفيد الدالة RvaToOffset عليه ستعطى موقع البايت التى تؤشر عيه VA و هو 327165
الان افتح الملف PatchMe.exe بمحرر هكس و دهب الى هدا الموقع ستجد تلك القيمة تغيرت

http://ups.imagup.com/09/1270528990.jpg

و بالتالى بطريقة عكسية يمكن الحصول على VA من موقع البايت مثلا


Edit1.text := InttoHex(327165, 8) ;


ثم نستعمل القيمة المخزة فى EDIT1 فى الدالة offset2rva فنحصل على VA
اى يمكن الحصول على VA من موقع البايت و الله اعلم .
لاكن المشكل الدى واجهنى هو ادا كان موقع هدا البايت اصغر من 18954 ... لا احصل على VA الصحيح

kachwahed
05-04-2010, 08:06 PM
الـ VA هي العنوان الافتراضي، تستخدم عند إنشاء Loader ، وهي التي تظهر في Disassembler
الـ Offset هي عنوان البايت على القرص وهي التي تستخدم عند الـ Patch، وهي التي تستخدم في محررات الـ Hex

الـ Relative Virtual Address (أو RVA) هي عنوان VA بعد تحميله في الذاكرة (أي بزيادة ImageBase)

لتسهيل التحويل بين VA و RVA و Offset استخدم بريمج LordPE كما يلي:
للتحويل من VA إلى غيره:
http://i43.tinypic.com/13ygw0h.jpg
أنقر على زر آخر لتحويل باتجاه آخر :)


اقتباس:
لكن أخي kachwahed أليس العنوان المشار إليه Va ؟؟ أم أن له تسمية أخرى (Base Address).
نعم هى Va لاكن اخدت اسم Base Address فى الدالة MemoryPatch لانها استعملت فى البرمتر الثانى للدالة
WriteProcessMemory الدى يحمل نفس الاسم ... فقط .
تماما كان علي اختيار اسم آخر للمتغير :D
بالتوفيق.

TF6M
05-04-2010, 11:14 PM
نعم صحيح يمكن القول أن Virtual Address = Base Address , إستنتجتها من VirtualAllocEx .
بالتوفيق ,,

hanipino
05-04-2010, 11:47 PM
نعم اخوانى
اختلطت على الامور ... :)

1- نريد الحصول على va برمجيا اى (va ل بايت معين على اساس موقعه مثلا البايت الاول .. 2 .. 3 .. 4 )
اولا نحسب offset ثم نحول هدا offset الى va

---
حساب offset سهل جدا

مثلا
offset ل البايت الاول
Edit1.text := InttoHex(1, 8) ;
offset ل البايت الثانى
Edit1.text := InttoHex(2, 8) ;


ثم نحول هدا offset الى va ... انا استعملت هده الدالة Offset2Rva من اسمها يتضح انها تحول الى Rva لكنها تعطى نتائج va (لا علينا المهم اننا نحتاج va)

function Offset2Rva (pAddrOfFile: Pointer; dwRva : dword ):dword;
type
IMAGE_SECTION_HEADER = packed record
Name : packed array [0..IMAGE_SIZEOF_SHORT_NAME-1] of Char;
PhysicalAddress : DWORD;
VirtualAddress : DWORD;
SizeOfRawData : DWORD;
PointerToRawData : DWORD;
PointerToRelocations : DWORD;
PointerToLinenumbers : DWORD;
NumberOfRelocations : WORD;
NumberOfLinenumbers : WORD;
Characteristics : DWORD;
end;
PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS;
PIMAGE_SECTION_HEADER = ^IMAGE_SECTION_HEADER;

var
i : byte;
sectionh : PIMAGE_SECTION_HEADER;
dosh : PIMAGE_DOS_HEADER;
peh : PIMAGE_NT_HEADERS;
begin
if dwRva = 0 then
begin
result:=dwRva;
exit;
end;
dosh := PIMAGE_DOS_HEADER(pAddrOfFile);
peh := PIMAGE_NT_HEADERS(Longword(dosh) + Longword(dosh._lfanew));
Sectionh := PIMAGE_SECTION_HEADER(peh);
inc(pimage_nt_headers(Sectionh));
// dwRva := dwRva - peh.OptionalHeader.ImageBase;
for i:=peh.FileHeader.NumberOfSections Downto 1 do
begin
if (dwRva >= Sectionh.VirtualAddress) and
(dwRva < (Sectionh.VirtualAddress + Sectionh.PhysicalAddress))
then break;
inc(sectionh);
end;
Result := dwRva + peh.OptionalHeader.ImageBase + sectionh.VirtualAddress - sectionh.PointerToRawData;
end;


الان المشكل الدى يقع هو ادا اردنا الحصول على va لبايت موقعه قبل 4096 النتائج تكون خاطئة فى غير دالك النتائج صحيحة ... للمقارنة نستعمل البرنامج الدى اشار اليه اخى كاش واحد بارك الله فيه .
مثلا الحصول على va للبايت الاول نقوم بحساب

InttoHex(1, 8) ;

ونسجله فى حانة ال offset لبرنامج LordPE ونقارن مع نتائج هدا الرفق .

:bye1:

TF6M
06-04-2010, 12:36 AM
أخي hanipino , بغض النظر عن من&إلى التحويل Offset&RVA , لكن كيف عرفت الـ Target Offset ؟
هل تستعمل منقح يعمل بالـ Offset ؟, نقوم بدراسة الملف بـ OllyDbg (أشهر debugger) عند معرفة مكان
تغير القفزة مثلا ؟؟ ... ستكون بالـ VA , لديك قاعدة بسيطة :


VA = RVA + ImageBase
Target_OFFSET = Targer_RVA – Section_RVA + Section_OFFSET
Target_OFFSET = Targer_VA – Section_VA + Section_OFFSET

كل ما قلته لك , موجود في المشاركة رقم #2 .

بالتوفيق ,,

hanipino
06-04-2010, 03:18 AM
:) لم افهمك اخى tf6m

المهم ...

نفترض انه لديك ملف تنفيدى و انت تعلم لو غيرت البايت العاشر مثلا سيصبح البرنامج Registred
هل تستطيع تحميل هدا الملف للداكرة وتغير دالك البايت فى الداكرة

بشرط دون استعمال OllyDbg او اى برنامج اخر من هدا النوع .اى (عندك ملف تنفيدى و محرر هكس و دالفى ).

TF6M
06-04-2010, 02:06 PM
مستحيل أن يكون البايت 10 , لماذا ؟ لأننا نتعامل مع Code Section ,هل قرأت Pe Files
الذي أرفقته ؟؟؟ المهم تابع الشكل العام :


Entete :
* Offset_PE_Header
---------------------------------------------------------
PE-Header :
* Nombre de Sections : n
* EntryPoint : Offset_EntryPoint
* Taille de l'Image : TailleImage
---------------------------------------------------------
Section Header
* Entrée Section 1
* Entrée Section 2
* [...]
* Entrée Section n
---------------------------------------------------------
Section 1
---------------------------------------------------------
Section 2
---------------------------------------------------------
[...]
---------------------------------------------------------
Section n
---------------------------------------------------------ستستنتج أن البايت 10 ينتمي للـ Dos Header , ممكن تقوم بتصليح الـ Pe (بعد العبث به) كما وضع
في Home Work1 , فلا تستطيع أصلا تحميله للذاكرة لكي تعدل فيه أصلا ! .

hanipino
06-04-2010, 06:38 PM
هل قرأت Pe Files
الذي أرفقته ؟؟؟ المهم تابع الشكل العام :

ليس بعد ... لا يحتاج الى قرائة فقط بل الى قرائة و اهم شىء الفهم :) عند توفر الوقت ان شاء الله ساغوص فيه .

فلا تستطيع أصلا تحميله للذاكرة لكي تعدل فيه أصلا ! .


ساتعبك معى قليلا اخى tf6 :kick:
فى المشاركة رقم 2 ارفقت ملف تنفيدى اسمه RegMe.exe ... لو غيرنا بايتين فى هدا الملف سيصبح
registred موقع هادين البايتين هما على التوالى (326837, 326808)

---
الان هل يمكن ان نحمل RegMe.exe للداكرة ونغير هادين البايتين ... دون الاستعانة ب OllyDbg اى ليست غندنا va عندنا فقط موقع بايتين فى الملف (326837, 326808)

B.M.AbdelAziZ
06-04-2010, 08:49 PM
مستحيل أن يكون البايت 10 , لماذا ؟...
البايت 10 ينتمي للـ Dos Header
لا شيئ مستحيل شرط ان يكون منطقي
تا بع معي (ساتحدث مع نفسي!)
ما فائدة Dos Header ؟
تحتوي معلومات لتنفيذ البرنامج في DOS
هل برامجنا تنفذ في DOS ؟
لا
اذن يمكن الاستغناء عنها ؟
نعم
كليا ؟
لا، على الاقل يجب وجود اول حرفين MZ وبدونهما يعتبر النظام الملف غير تنفيذي
تقصد حذف كليا DOS Header مع الابقاء على MZ
نعم
إذن كيف ينفذ النظام الملف مع ان المعلومات حذفت ؟
PE header هي التي يحتاجها النظام لتنفيذ ملف Win32PE
اها!
نعم
هل لدبك دليل ؟ او مثال حي
نعم، برامج ضغط كثيرة منها uPack/WinUpack رابط تحميله بموضوع سابق
http://www.delphi4arab.com/forum/showthread.php?t=1530

موقع هادين البايتين هما على التوالى (326837, 326808)
تلك offset
اي موضعها بالملف التنفيذي الخام وهو بالقرص
عندما يتم تحميله للذاكرة قد يتغير شكله
والoffset لا تنفع الى بعد تحويلها RVA
لا وقت لشرح الامر
انصحك بقرائة موضوع لZool@nder بمنتدى AT4RE

هناك طريقة ثانية للتعديل هي Search & Replace البحث ثم التعديل
وبالتوفيق

kachwahed
06-04-2010, 09:08 PM
لا أدري إن كنت طرحتها أم لا. العكس Rva2Offset:
//Convert Rva2Offset & Offset2Rva

IMAGE_SECTION_HEADER = packed record
Name : packed array [0..IMAGE_SIZEOF_SHORT_NAME-1] of Char;
PhysicalAddress : DWORD;
VirtualAddress : DWORD;
SizeOfRawData : DWORD;
PointerToRawData : DWORD;
PointerToRelocations : DWORD;
PointerToLinenumbers : DWORD;
NumberOfRelocations : WORD;
NumberOfLinenumbers : WORD;
Characteristics : DWORD;
end;

PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;

PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS;

PIMAGE_SECTION_HEADER = ^IMAGE_SECTION_HEADER;

function rva2offset( pAddrOfFile: Pointer; dwRva : dword ):dword;
var i : byte;
sectionh : PIMAGE_SECTION_HEADER;
dosh : PIMAGE_DOS_HEADER;
peh : PIMAGE_NT_HEADERS;
begin
if dwRva = 0 then begin
result:=dwRva;
exit;
end;
dosh := PIMAGE_DOS_HEADER(pAddrOfFile);
peh := PIMAGE_NT_HEADERS(Longword(dosh) + Longword(dosh._lfanew));
Sectionh := PIMAGE_SECTION_HEADER(peh);
inc(pimage_nt_headers(Sectionh));
dwRva := dwRva - peh.OptionalHeader.ImageBase;
for i:=1 to peh.FileHeader.NumberOfSections do begin
if (dwRva >= Sectionh.VirtualAddress) and
(dwRva < (Sectionh.VirtualAddress + Sectionh.PhysicalAddress)) then break;
inc(sectionh);
end;
result:=dwRva - sectionh.VirtualAddress + sectionh.PointerToRawData;
end;


function offset2rva (pAddrOfFile: Pointer; dwRva : dword ):dword;
var i : byte;
sectionh : PIMAGE_SECTION_HEADER;
dosh : PIMAGE_DOS_HEADER;
peh : PIMAGE_NT_HEADERS;
temp: dword;
begin
if dwRva = 0 then begin
result:=dwRva;
exit;
end;
dosh := PIMAGE_DOS_HEADER(pAddrOfFile);
peh := PIMAGE_NT_HEADERS(Longword(dosh) + Longword(dosh.e_lfanew));
Sectionh := PIMAGE_SECTION_HEADER(peh);
inc(pimage_nt_headers(Sectionh));
inc (sectionh, peh.FileHeader.NumberOfSections);
for i:=peh.FileHeader.NumberOfSections downto 1 do begin
temp := dwRva + sectionh.VirtualAddress - sectionh.PointerToRawData;
if (temp >= Sectionh.VirtualAddress) and
(temp < (Sectionh.VirtualAddress + Sectionh.PhysicalAddress)) then break;
dec(sectionh);
end;
dwRva := temp + peh.OptionalHeader.ImageBase;
Result := dwRva;
end
بالتوفيق.

hanipino
06-04-2010, 09:13 PM
والoffset لا تنفع الى بعد تحويلها rva


هل تقصد شىء مثل هدا .

TF6M
06-04-2010, 09:39 PM
"مستحيل أن يكون البايت 10 " هذا على أساس التساؤل الذي أراد معرفته الاخ هاني .