PDA

View Full Version : سوال: نحوه دستیابی به پروسه های یک فایل اجرایی



farzad93
چهارشنبه 26 آبان 1389, 11:04 صبح
با سلام خدمت دوستان عزیز.
من میخوام یه فایل exe که در حال اجرا هست رو توش یه سری تغییرات بدم.
یعنی مقدار(value) یه آدرس یا پروسه رو در اون فایل تغییر بدم.
یه چیزی مثل ترینر برای بازی ها.
کسی میتونه کمکم کنه؟

xxxxx_xxxxx
چهارشنبه 26 آبان 1389, 19:29 عصر
API های لازم برای این کار GetProcessMemoryInfo و CopyMemory و FillMemory هستند.

farzad93
پنج شنبه 27 آبان 1389, 20:28 عصر
API های لازم برای این کار GetProcessMemoryInfo و CopyMemory و FillMemory هستند.
یه توضیح کوچیک بدید ممنون میشم!

xxxxx_xxxxx
جمعه 28 آبان 1389, 16:59 عصر
سلام،
ابتدا عذرخواهی می کنم که در پست قبل، منظورتون رو دقیق متوجه نشده بودم (به خاطر کم دقتی خودم) و به همین خاطر توابع کار با حافظه (RAM) بدون توجه به ناحیه کاری یک پروسس رو معرفی کردم. هرچند کاملاً بی ارتباط با موضوع تاپیک نیست و میتونه برای کسی که میخواد با حافظه به طور مستقیم کار کنه مفید باشه.

اما برای این منظور، یعنی عمل نوشتن در ناحیه کاری یک پروسس تابعی با نام WriteProcessMemory وجود داره و در مقابل اون تابع ReadProcessMemory. که از اسمشون مشخص هست هر کدوم چه کاری انجام میدن.

باید توجه داشته باشید که پروسسی که میخواید در حافظه اختصاص داده شده بهش چیزی بنویسید، دسترسی لازم برای نوشتن در پروسس رو داشته باشید، یعنی اون پروسس نباید Protect شده باشه.

چون تو پست قبل دقیق جواب ندادم و شاید برای شما گمراه کننده بود، سعی می کنم اینجا یک مثال با تابع WriteProcessMemory بزنم که جبران کرده باشم.
خب، فرض کنید ما یک برنامه ساده نوشتیم با این دستورات:


Private Sub Command1_Click()
Dim x As Long, y As Long, z As Long
x = 1
Print x
y = 2
Print y
z = x + y
Print z
End Sub
همونطور که مشخص هست خروجی این برنامه به ترتیب اعداد 1 و 2 و 3 هست. قصد داریم در روند اجرای همین برنامه تغییراتی ایجاد کنیم تا بجای عدد 3 که حاصلجمع 1 و 2 است، یک عدد دیگه چاپ بشه. (مثلاً 4)

خب، پس ابتدا فایل اجرایی برنامه رو میسازیم. (من ساختم میتونید از ضمیمه همین پست دانلود کنید.) این برنامه در حالت عادی اعداد 1 و 2 و 3 رو چاپ میکنه. (امتحان کنید)

حالا میخوایم توسط یک پروژه دیگه، پروسس این برنامه رو دستکاری کنیم تا بجای عدد 3، عدد 4 چاپ بشه. با استفاده از تابع WriteProcessMemory
شکل کلی این تابع به این صورت است:


Private Declare Function WriteProcessMemory Lib "kernel32" _
(ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, _
ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
پارامتر اول که واضح هست (Handle پروسسی که میخوایم دستکاریش کنیم).
پارامتر دوم مشخص میکنه که در کدام خانه از حافظه این پروسس میخواید چیزی بنویسید (آدرس خانه شروع برای دستکاری)
پارامتر سوم، همون داده ای هست که میخوایم در اون آدرس نوشته بشه.
پارامتر چهارم، طول داده ای هست که میخوایم در اون آدرس نوشته بشه. (خروجی تابع Len روی داده مون)
پارامتر آخر هم بهش توجه نکنید، به کار ما نمیاد. ولی جهت اطلاع، این پارامتر، یک پارامتر خروجی هست که بعد از اجرای موفقیت آمیز تابع به ما میگه که چند بایت در حافظه نوشته است.

خب، اولین قدم، بدست آوردن Handle پروسس موردنظرمون هست. ما اینجا برای اینکه Handle رو داشته باشیم، با استفاده از تابع CreateProcess فایل اجرایی رو اجرا میکنیم تا Handle رو از طریق همین تابع بدست بیاریم. نمی دونم چقدر با این تابع آشنایی دارید، ولی این تابع به این شکل عمل میکنه که آدرس یک فایل اجرایی رو بهش میدیم و یک سری خصوصیات دیگه در مورد Process و Thread. بعد، این تابع فایل موردنظرمون رو با توجه به خصوصیاتی که درخواست می کنیم اجرا میکنه و اطلاعاتی در مورد پروسس رو بهمون برمیگردونه. این اطلاعات در Type هایی که توسط برنامه نویس تعریف میشن قرار میگیره. ما به همه این اطلاعات نیازی نداریم، فقط Handle پروسس رو میخوایم. ولی با اینحال، Type ها رو باید تعریف کنیم.
این دو Type به شکل زیر هستند:


Private Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Byte
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type

Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End Type

Private pInfo As PROCESS_INFORMATION
Private sInfo As STARTUPINFO
در آخر دو متغیر pInfo و sInfo رو از همین Type ها تعریف میکنیم. (pInfo و sInfo از پارامترهای تابع CreateProcess هستند که بعد از اجرای موفقیت آمیز، همه فیلدهاشون مقداردهی میشه)

تابع CreateProcess هم به این شکل تعریف میکنیم:


Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" _
(ByVal lpApplicationName As String, ByVal _
lpCommandLine As String, lpProcessAttributes As Any, _
lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal _
dwCreationFlags As Any, lpEnvironment As Any, ByVal _
lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION) As Long
خب، تابع رو به این شکل فراخوانی میکنیم تا برنامه مون اجرا بشه:

Dim Result As Long
Result = CreateProcess(vbNullString, "project1.exe", ByVal 0&, ByVal 0&, 1&, CREATE_NEW_PROCESS_GROUP, ByVal 0&, vbNullString, sInfo, pInfo)
project1.exe همون برنامه ای هست که گفتیم دو عدد 1 و 2 رو با هم جمع میکنه و 1 و 2 و 3 رو به ترتیب چاپ میکنه.

ثابت CREATE_NEW_PROCESS_GROUP رو قبل از این تعریف کنید:


Private Const CREATE_NEW_PROCESS_GROUP = &H200&
این مشخص میکنه که وضعیت پروسس برای اجرا باید به چه نحو باشه. (برای اطلاعات بیشتر در MSDN جستجو کنید)
بعدش Handle پروسس رو از Type ای که تعریف کردیم استخراج میکنیم:


Dim pHandle As Long
pHandle = pInfo.hProcess
حالا از اینجا به بعد کار اصلیمون شروع میشه. (یعنی دستکاری در ناحیه حافظه پروسس مورد نظرمون)
شما باید قبلاً محل موردنظرتون رو در حافظه برای دستکاری پیدا کنید (با برنامه های Debugger). من این رو نگاه کردم و آدرس H401A0A رو به عنوان نقطه شروع برای دستکاری انتخاب کردم. (جایی که عدد 3 چاپ میشه) و قصد دارم این داده ها رو در اون آدرس تزریق کنم:


Chr(&HB8) & Chr(&H4)
H4 عدد 4 برای چاپ هست که روی عدد 3 در حافظه نوشته میشه.
پس به این شکل ترتیبش رو میدیم:


Dim Buffer As String
Buffer = Chr(&HB8) & Chr(&H4)
Result = WriteProcessMemory(pHandle, &H401A0A, Buffer, Len(Buffer), 0&)
یک بار دیگه در برنامه Project1.exe که اجرا شده، امتحان کنید، میبینید که بجای اعداد 1 و 2 و 3، اعداد 1 و 2 و 4 چاپ میشه.

سورس برنامه به همراه فایل project1.exe ضمیمه شده.

موفق باشید/

farzad93
شنبه 29 آبان 1389, 20:27 عصر
چرا من هر کاری میکنم نتیجه نمیگیرم؟
هر کاری کردم بازم 3 چاپ میشه هیچ تغییری هم نمیکنه!!
مشکل چیه به نظر شما؟

xxxxx_xxxxx
شنبه 29 آبان 1389, 21:14 عصر
اگر فایل اجرایی رو دستی اجرا کنید، نتیجه 1و2و3 هست. اگر فایل با برنامه اجرا بشه، نتیجه 1و2و4 هست. در واقع تا زمانی که تابع WriteProcessMemory اجرا نشده، نتیجه همون 1و2و3 هست، اما بعد از اجرای تابع، نتیجه 1و2و4 میشه.
برای درک بهتر قضیه، برنامه رو با F8 خط به خط اجرا کنید. زمانی که تابع CreateProcess اجرا بشه، فایل project1.exe اجرا میشه. وقتی project1.exe اجرا شد، روی Command1 کلیک کنید، نتیجه 1و2و3 هست. بعدش دوباره با F8 جلو برید تا تابع WriteProcessMemory هم اجرا بشه. حالا دوباره روی Command1 کلیک کنید. می بینید که نتیجه 1و2و4 هست.

ویدئو ضمیمه رو ببینید.

farzad93
یک شنبه 30 آبان 1389, 13:55 عصر
زمانی که تابع CreateProcess اجرا میشه بجای اینکه project1.exe اجرا بشه، یه فرم باز میشه که روش یه عکس هست.
عکس ضمیمه رو ببینید متوجه میشید.

farzad93
یک شنبه 30 آبان 1389, 14:03 عصر
زمانی که تابع CreateProcess اجرا میشه بجای اینکه project1.exe اجرا بشه، یه فرم باز میشه که روش یه عکس هست.
.
اشکال رو خودم فهمیدم.
اشکال از یه dll بود که درستش کردم!
حالا یه سوال: نمیشه توی برنامه ای که قبلا توسط کاربر اجرا شده باشه رو نفوذ کرد؟؟

xxxxx_xxxxx
یک شنبه 30 آبان 1389, 18:30 عصر
حالا یه سوال: نمیشه توی برنامه ای که قبلا توسط کاربر اجرا شده باشه رو نفوذ کرد؟؟
شاید اگر هدفتون از این کار رو بگید بشه راهکار بهتر و ساده تری رو معرفی کرد.

farzad93
یک شنبه 30 آبان 1389, 19:44 عصر
میخوام یک ترینر واسه یه بازی بنویسم یا یک چیزی مثل برنامه ی Artmoney یا cheat engine

xxxxx_xxxxx
دوشنبه 01 آذر 1389, 00:45 صبح
تا جایی که اطلاع دارم، Cheat Engine خودش debugger هم داره و حافظه اختصاص یافته به پروسس ها رو میتونه رصد کنه.
برای این کار فکر میکنم بشه با ReadProcessMemory یک کارهایی کرد.