Имам DLL, който инжектирам в друг процес, но искам да мога да извикам експортите на този DLL от моето приложение. Четох другаде, че трябва да използвате API на SendMessage, но нямам представа какво да правя. Има ли примерен код за това как се прави това?
Извикване на функции в DLL, зареден от друг процес
Отговори (3)
По принцип не можете директно да извиквате функции в друг процес. Има обаче някои заобиколни решения, които можете да използвате.
Първо, ако знаете адреса на експорта (което не е така през повечето време) и функцията, която извиквате, използва конвенцията за извикване __stdcall
, приема цяло число с размер на указател като аргумент и връща DWORD, можете да използвате CreateRemoteThread
, за да го изпълните в нишка в отдалечения процес. Това често се използва за стартиране на LoadLibrary
за инжектиране на DLL в целеви процес, тъй като LoadLibrary
се зарежда на един и същ адрес на всички процеси на даден компютър.
В противен случай DLL, който инжектирате, ще трябва да направи някакъв вид RPC с процеса, който го е извикал. Например, можете да накарате вашата инжектирана DLL да създаде нишка в нейния манипулатор на DLL_PROCESS_ATTACH, който от своя страна се свързва с наименуван канал или се свързва през COM или нещо подобно с главния процес.
Въпреки че не е възможно директно да извикате функция в друг процес, можете да го направите индиректно доста лесно с няколко стъпки и API на Windows.
- Вземете адресите на
LoadLibrary
иGetProcAddress
от вашия собствен процес.kernel32.dll
трябва да се зареждат на един и същ адрес във всеки процес, така че можете да разчитате, че присъстват в процеса, в който инжектирате - Създайте
struct
, който ще съдържа всички аргументи, които искате да предадете на вашата функция, която ще извика функциите в другия процес (тъй катоCreateRemoteThread
може да предаде само един аргумент на функция, така че ще го използваме, за да предадем указател към структурата ), който съдържа най-малко указатели на членски функции за задържане на адресите наLoadLibrary
иGetProcAddress
- Разпределете достатъчно памет за структура в отдалечения процес чрез
VirtualAllocEx
, след което я попълнете с правилната информация сWriteProcessMemory
- Напишете функция, като вземете указател към
struct
, който сте написали, която използваLoadLibrary
/GetProcAddress
, за да извика функцията, която искате. Не забравяйте да използвате указателите към тези функции в структурата, която предавате на функцията, а не имената. - Разпределете достатъчно памет в отдалечения процес, за да задържите функцията с
VirtualAllocEx
, като се уверите, че сте предалиVAX
флагаPAGE_EXECUTE_READWRITE
, така че да може да задържи изпълним код - Прочетете и напишете кода на функцията от вашия процес в другия процес чрез
Read/WriteProcessMemory
- Извикайте функцията в отдалечения процес (който е на адреса, върнат от
VirtualAllocEx
), като използватеCreateRemoteThread
.
Уверете се, че всички данни, които предавате на функцията, се съхраняват в структурата и/или се намират в адресното пространство на отдалечения процес (вземете ги там с VirtualAllocEx
/WriteProcessMemory
.
Може да изглежда малко намесено, но всъщност не е толкова сложно. Ако имате нужда от помощ с него, не се колебайте да попитате в коментар.
SendMessage
ще се нуждае от манипулатор на прозорец (скрит или видим) и помпа за съобщения, свързана с него, която може да обработва персонализираното съобщение. Както при UAC/Windows-7, нивата на интегритет на приложенията може да попречат на други приложения да изпращат/публикуват съобщения от други процеси с ниска интегритет.
По-добре е да имате друга нишка, която изчаква за тези персонализирани съобщения. За това можете да използвате канали (наименувани или ненаименувани), сокети, пощенски слотове, споделена памет (заедно с mutex/събитие за задействане). Другите процеси биха изпратили съобщението, използвайки същия протокол.
Но преди да приложите този персонализиран механизъм за съобщения/протокол/IPC, ви предлагам първо да определите точната нужда.