۴. پچ کردن باینری (Runtime Patching)
گاهی هوک کردن کافی نیست؛ شما میخواهید دستورات اسمبلی را تغییر دهید. مثلا یک دستور شرطی JE (پرش اگر برابر بود) را به JMP (پرش بیقید و شرط) تبدیل کنید، یا یک دستور را با NOP (پوچ) جایگزین کنید تا اجرا نشود.
برای نوشتن در حافظه کد (که معمولا Read-Only است)، اول باید محافظت حافظه را با Memory.protect بردارید.
کد فریدا (تغییر دستورات اسمبلی):
javascript
var base = Module.findBaseAddress("libgame.so")
/* آفست دستوری که میخواهیم تغییر دهیم */
var offset = 0x5500
var targetPtr = base.add(offset)
console.log("[*] Patching instruction at: " + targetPtr)
/* 1. تغییر دسترسی حافظه به RWX (خواندن، نوشتن، اجرا) */
/* چون کدها معمولا Read-Only هستند و نوشتن در آنها ارور میدهد */
Memory.protect(targetPtr, 4, 'rwx')
/* 2. نوشتن بایتهای جدید */
/* مثلا تبدیل دستور (C0 03 5F D6) که معادل RET است به (1F 20 03 D5) که معادل NOP است */
/* یا هر تغییری که مد نظر شماست */
Memory.writeByteArray(targetPtr, [0x1F, 0x20, 0x03, 0xD5])
console.log("[+] Patch applied successfully.")خلاصه ابزارهای Module و Memory
| دستور | کاربرد |
|---|---|
Module.findBaseAddress("lib.so") | پیدا کردن آدرس شروع ماژول (برای دور زدن ASLR) |
base.add(0x123) | اضافه کردن آفست به آدرس پایه |
Module.enumerateExports("lib.so") | لیست کردن توابع موجود در ماژول |
Memory.scan(ptr, size, pattern) | جستجوی الگوی Hex در حافظه |
Memory.protect(ptr, size, 'rwx') | تغییر سطح دسترسی حافظه (برای نوشتن) |
Memory.writeByteArray(ptr, bytes) | نوشتن بایتهای جدید در آدرس مشخص |