Извикване на функции в DLL, зареден от друг процес

Имам DLL, който инжектирам в друг процес, но искам да мога да извикам експортите на този DLL от моето приложение. Четох другаде, че трябва да използвате API на SendMessage, но нямам представа какво да правя. Има ли примерен код за това как се прави това?


person 123    schedule 08.07.2011    source източник
comment
Можете да използвате експортиранията директно от вашето приложение, без да е необходимо нищо, освен свързване към или зареждане на този DLL. Ето как наистина работят DLL файловете. Може да има различен адрес в адресното пространство на вашия процес, но това ще бъдат абсолютно същите страници. Това е причината DLL също да има своя собствена купчина (вместо просто да използва купчината на приложението).   -  person Damon    schedule 09.07.2011


Отговори (3)


По принцип не можете директно да извиквате функции в друг процес. Има обаче някои заобиколни решения, които можете да използвате.

Първо, ако знаете адреса на експорта (което не е така през повечето време) и функцията, която извиквате, използва конвенцията за извикване __stdcall, приема цяло число с размер на указател като аргумент и връща DWORD, можете да използвате CreateRemoteThread, за да го изпълните в нишка в отдалечения процес. Това често се използва за стартиране на LoadLibrary за инжектиране на DLL в целеви процес, тъй като LoadLibrary се зарежда на един и същ адрес на всички процеси на даден компютър.

В противен случай DLL, който инжектирате, ще трябва да направи някакъв вид RPC с процеса, който го е извикал. Например, можете да накарате вашата инжектирана DLL да създаде нишка в нейния манипулатор на DLL_PROCESS_ATTACH, който от своя страна се свързва с наименуван канал или се свързва през COM или нещо подобно с главния процес.

person bdonlan    schedule 08.07.2011
comment
Току-що погледнах именувани тръби и това ще направи това, което търся. Благодаря! - person 123; 09.07.2011

Въпреки че не е възможно директно да извикате функция в друг процес, можете да го направите индиректно доста лесно с няколко стъпки и API на Windows.

  1. Вземете адресите на LoadLibrary и GetProcAddress от вашия собствен процес. kernel32.dll трябва да се зареждат на един и същ адрес във всеки процес, така че можете да разчитате, че присъстват в процеса, в който инжектирате
  2. Създайте struct, който ще съдържа всички аргументи, които искате да предадете на вашата функция, която ще извика функциите в другия процес (тъй като CreateRemoteThread може да предаде само един аргумент на функция, така че ще го използваме, за да предадем указател към структурата ), който съдържа най-малко указатели на членски функции за задържане на адресите на LoadLibrary и GetProcAddress
  3. Разпределете достатъчно памет за структура в отдалечения процес чрез VirtualAllocEx, след което я попълнете с правилната информация с WriteProcessMemory
  4. Напишете функция, като вземете указател към struct, който сте написали, която използва LoadLibrary/GetProcAddress, за да извика функцията, която искате. Не забравяйте да използвате указателите към тези функции в структурата, която предавате на функцията, а не имената.
  5. Разпределете достатъчно памет в отдалечения процес, за да задържите функцията с VirtualAllocEx, като се уверите, че сте предали VAX флага PAGE_EXECUTE_READWRITE, така че да може да задържи изпълним код
  6. Прочетете и напишете кода на функцията от вашия процес в другия процес чрез Read/WriteProcessMemory
  7. Извикайте функцията в отдалечения процес (който е на адреса, върнат от VirtualAllocEx), като използвате CreateRemoteThread.

Уверете се, че всички данни, които предавате на функцията, се съхраняват в структурата и/или се намират в адресното пространство на отдалечения процес (вземете ги там с VirtualAllocEx/WriteProcessMemory.

Може да изглежда малко намесено, но всъщност не е толкова сложно. Ако имате нужда от помощ с него, не се колебайте да попитате в коментар.

person Seth Carnegie    schedule 08.07.2011
comment
Какво ще кажете за случая, когато този процес и другият са с различна битовост (32/64 бита)? Има ли начин да разберете от върнатата стойност на GetProcAddress() в този процес какво би било в друг процес, който е с различна битовост? - person tml; 26.04.2018

SendMessage ще се нуждае от манипулатор на прозорец (скрит или видим) и помпа за съобщения, свързана с него, която може да обработва персонализираното съобщение. Както при UAC/Windows-7, нивата на интегритет на приложенията може да попречат на други приложения да изпращат/публикуват съобщения от други процеси с ниска интегритет.

По-добре е да имате друга нишка, която изчаква за тези персонализирани съобщения. За това можете да използвате канали (наименувани или ненаименувани), сокети, пощенски слотове, споделена памет (заедно с mutex/събитие за задействане). Другите процеси биха изпратили съобщението, използвайки същия протокол.

Но преди да приложите този персонализиран механизъм за съобщения/протокол/IPC, ви предлагам първо да определите точната нужда.

person Ajay    schedule 09.07.2011