الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

Checksum

بدأه C++er في 30 ديسمبر 2009 · 4 رد · 787 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

اغلب الأوقات اقوم بحفظ بيانات داخل ملفات ثنائية و لمعرفة اذا كان تم تعديلها ام لا اقوم بحفظ الهاش الخاص بالملف داخل مكان معين (فى الأغلب الـ header) و عندما اوقم بالتحقق من صحة بيانات الملف اقوم بتخطى الـ header و حساب الهاش لباقى البيانات.

هذه الطريقه هى التى اعرفها و لا اعرف غيرها، و لكن اثناء تصفحى للكود الخاص بويندوز وجدت الكود الذى يستخدم لحساب الـ checksum للملفات التنفيذيه و من باب حب الإستطلاع قمت بإستخلاص الكود فى مشروع خارجى و قمت بتجربته على العديد من الملفات التنفيذيه و قد عمل بكفائه. الغريب فى الموضوع ان الطريقه المستخدمه لا تقوم بتخطى اى جزء من الملف و لكن تتعامل مع ماللف من اوله لأخره و النتيجه تكون متطابقه مع المخزنه فى الملف و هذا يعنى ان الرقم تم حسابه على الملف ثم تم حفظه داخله و لكن ان تم هذا الأمر فالملف تم تعديله و الهاش بذلك يتغير، فكيف تمت هذه العمليه و اقصد حساب الهاش لملف ثم حفظه داخله و عند حسابه لا يتغير.

و الله ولى التوفيق

مدونتي: C++ Tips and Tricks

#2

الويندوز Checksum يتم على الملف كله ثم يتم طرح الـChecksum الخاص بالـNtHeader مرة اخرى :)

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#3
GamingMasteR كتب:

الويندوز Checksum يتم على الملف كله ثم يتم طرح الـChecksum الخاص بالـNtHeader مرة اخرى :)

بإعتبار اننى سأقوم بإنشاء ملف تنفيذى جديد.

1 - قمت بملء الـ headers بالبيانات المناسبه (بالطبع دون وجود الـ checksum فهى بصفر الأن).

2 - قمت بحساب الـ checksum للمره الأولى على المحتويات السابق ذكرها.

3 - قمت بوضع قيمة الـ checksum داخل مكانها (و بالتالى اصبحت الـ checksum الحقيقية غير مطابقه لما تم حفظها داخل الملف التنفيذى).

4 - قمت بحساب الـ checksum للملف مره اخرة بعد تعديله و قمت بتنفيذ عمليه حسابيه بسيطه على الرقم الناتج و هى كالتالى

ملاحظه : القيم التاليه هى قيم حقيقيه مستخرجه من ملف shell32.dll

DWORD SavedSum = 0x0081D6E5
DWORD CalculatedSum = 0x0000904C

if ( LOWORD(CalculatedSum) >= HIWORD(SavedSum) )
    CalculatedSum -= LOWORD(SavedSum);
else
    CalculatedSum = ((LOWORD(CalculatedSum) - HIWORD(SavedSum)) & 0xFFFF) - 1;

// CalculatedSum now equal 0x0000B966

if ( LOWORD(CalculatedSum) >= HIWORD(SavedSum) )
    CalculatedSum -= HIWORD(SavedSum);
else
    CalculatedSum = ((LOWORD(CalculatedSum) - HIWORD(SavedSum)) & 0xFFFF) - 1;

// CalculatedSum now equal 0x0000B8E5

CalculatedSum += FileSize; // FileSize contain shell32.dll size in bytes

// CalculatedSum now equal 0x0081D6E5 !!!!!! DON'T UNDERSTAND HOW

اذا كان احدكم يعرف كيف حدث هذا ارجو توضيحها لى لإحتاجى لها.

سأقوم بإرفاق الكود الخاص بحساب الـ checksum للملفات التنفيذيه بأكمله بعد قليل (حيث انه مكتوب بلغة اخرى غير سى).

و الله ولى التوفيق

مدونتي: C++ Tips and Tricks

#4

هذا هو كود الـChecksum Virification الخاص بـNT :

USHORT
ChkSum(
	ULONG PartialSum,
	PUSHORT Source,
	ULONG Length
	)

/*++

Routine Description:

	Compute a partial checksum on a portion of an imagefile.

Arguments:

	PartialSum - Supplies the initial checksum value.

	Sources - Supplies a pointer to the array of words for which the
 	checksum is computed.

	Length - Supplies the length of the array in words.

Return Value:

	The computed checksum value is returned as the function value.

--*/

{

	RTL_PAGED_CODE();

	//
	// Compute the word wise checksum allowing carries to occur into the
	// high order half of the checksum longword.
	//

	while (Length--) {
 	PartialSum += *Source++;
 	PartialSum = (PartialSum >> 16) + (PartialSum & 0xffff);
	}

	//
	// Fold final carry into a single word result and return the resultant
	// value.
	//

	return (USHORT)(((PartialSum >> 16) + PartialSum) & 0xffff);
}


BOOLEAN
LdrVerifyMappedImageMatchesChecksum (
	IN PVOID BaseAddress,
	IN ULONG FileLength
	)

/*++

Routine Description:

	This functions computes the checksum of an image mapped as a data file.

Arguments:

	BaseAddress - Supplies a pointer to the base of the mapped file.

	FileLength - Supplies the length of the file in bytes.

Return Value:

	TRUE - The checksum stored in the image matches the checksum of the data.

	FALSE - The checksum in the image is not correct.

--*/

{

	PUSHORT AdjustSum;
	PIMAGE_NT_HEADERS NtHeaders;
	USHORT PartialSum;
	ULONG HeaderSum;
	ULONG CheckSum;

	RTL_PAGED_CODE();

	//
	// Compute the checksum of the file and zero the header checksum value.
	//

	HeaderSum = 0;
	PartialSum = ChkSum(0, (PUSHORT)BaseAddress, (FileLength + 1) >> 1);

	//
	// If the file is an image file, then subtract the two checksum words
	// in the optional header from the computed checksum before adding
	// the file length, and set the value of the header checksum.
	//

	NtHeaders = RtlImageNtHeader(BaseAddress);
	if (NtHeaders != NULL) {
 	HeaderSum = NtHeaders->OptionalHeader.CheckSum;

#ifndef NTOS_KERNEL_RUNTIME
 	//
 	// On Nt 3.1 and 3.5, we allowed printer drivers with 0 checksums into
 	// csrss unintentionally. This means that we must allow this forever.
 	// I don't want to allow this for kernel mode drivers, so I will only
 	// allow 0 checksums of the high order bit is clear ?
 	//


 	if ( HeaderSum == 0 ) {
 	return TRUE;
 	}
#endif // NTOS_KERNEL_RUNTIME

 	AdjustSum = (PUSHORT)(&NtHeaders->OptionalHeader.CheckSum);
 	PartialSum -= (PartialSum < AdjustSum[0]);
 	PartialSum -= AdjustSum[0];
 	PartialSum -= (PartialSum < AdjustSum[1]);
 	PartialSum -= AdjustSum[1];
	} else {
 	PartialSum = 0;
 	HeaderSum = FileLength;
	}

	//
	// Compute the final checksum value as the sum of the paritial checksum
	// and the file length.
	//

	CheckSum = (ULONG)PartialSum + FileLength;
	return (CheckSum == HeaderSum);
}

كما ترى فانه يتم طرح الـChecksum الخاص بالترويسة من الـChecksum الكلي للملف .

تم تعديل هذه المشاركة بواسطة GamingMasteR في 31 ديسمبر 2009 في 02:01

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#5

يبدو ان الطريقه المتبعه داخل nt4 مختلفه عن 2k فما بعده.

قرأت الكود مرات عديده و لكن يبدو ان عقلى متوقف :stop: و لا استطيع استيعابه لذا سأتركه و اقرئه فيما بعد :mad:

اقتباس
سأقوم بإرفاق الكود الخاص بحساب الـ checksum للملفات التنفيذيه بأكمله بعد قليل

الملف بالمرفقات فقط قم بتمرير اسم الملف المراد حساب الـ checksum له كـ command line سيظهر لك الهاش الموجود بالملف و الهاش الذى تم حسابه و حالة الملف (سليم ام تالف).

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

Checksum Verifier.rar

و الله ولى التوفيق

مدونتي: C++ Tips and Tricks

مواضيع مشابهة