📜 ⬆️ ⬇️

Dll injection

DLL injection allows you to execute your code in the address space of an already running process. Many use infections to write cheats for games, perform malicious actions for the system, etc. But this technique does not necessarily apply to the implementation of cunning plans, but for example, to update your application.

The operation algorithm is very simple, we need to create a thread in the process and embed our code execution in it. For example, we infect explorer.exe and display a message about it.

We describe the structure through which we obtain the data we need:
typedef FARPROC (WINAPI *LPMessageBox)(HWND, LPCWSTR, LPCWSTR, UINT);

typedef struct _InjectData {
char title[50];
char msg[50];
LPMessageBox MessageB;
} InjectData, *PInjectData;

InjectData injectData = {
"Test" ,
"" ,
NULL
};

Now we describe the entry point of our stream:
static DWORD WINAPI InjectionMain(LPVOID lpParams) {

PInjectData info = (PInjectData)lpParams;

info->MessageB(NULL, (LPCWSTR)info->msg, (LPCWSTR)info->title, MB_OK);
return 0;
}

In our example, it is pretty simple. In it, we do not load the DLL, although for most tasks you may need it, for this you need to pass pointers to the LoadLibrary and GetProcAddress functions, as well as we have to do for MessageBoxA, and with the help of them load the DLLs you need.
')
Now we need to access explorer.exe, write our code, the data in the address space of the process and create a thread in the process to execute our code.

We describe a function that returns the process ID:
DWORD getProcessID() {
DWORD processID = 0;
HANDLE snapHandle;
PROCESSENTRY32 processEntry = {0};

if ( (snapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE ) {
return 0;
}

processEntry.dwSize = sizeof (PROCESSENTRY32);
Process32First(snapHandle, &processEntry);
do {
if ( wcscmp(processEntry.szExeFile, PROCESSNAME) == 0 ) {
return processEntry.th32ProcessID;
}
} while (Process32Next(snapHandle,&processEntry));

if ( snapHandle != INVALID_HANDLE_VALUE ) {
CloseHandle(snapHandle);
}

return 0;
}

CreateToolhelp32Snapshot - returns us actually a list of processes and their threads. We go around the entire list and if our process is found, then we return its identifier or 0. Now that we have an identifier, we can access the process using OpenProcess, but we cannot write anything to its memory. In order for our application to get the rights, we need the following function:
BOOL setPrivilege(HANDLE hToken, LPCTSTR szPrivName, BOOL fEnable) {
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, szPrivName, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof (tp), NULL, NULL);
return ((GetLastError() == ERROR_SUCCESS));
}

You can read more about rights here . Despite the fact that the answer for 1998 is still relevant for XP SP3 and as far as I know, for Windows 7, although I personally have not tested it yet.

Now we have everything to access the process:
DWORD processID = getProcessID();
HANDLE hCurrentProc = GetCurrentProcess();

if (!OpenProcessToken(hCurrentProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {
addLogMessage( "OpenProcessToken Error" , GetLastError());
return 0;
} else {
if (!setPrivilege(hToken, SE_DEBUG_NAME, TRUE)) {
addLogMessage( "SetPrivlegesSE_DEBUG_NAME Error" , GetLastError());
return 0;
}
}

if (processID == 0) {
MessageBox(NULL, _T( "Process not found!" ), _T( "Error" ), MB_OK | MB_ICONERROR);
return 0;
}

processHandel = OpenProcess(PROCESS_ALL_ACCESS, false , processID);

We lack a pointer to the function MessageBoxA, which is located in user32.dll:
HINSTANCE userHinstance = LoadLibrary(_T( "user32.dll" ));
injectData.MessageB = (LPMessageBox) GetProcAddress(userHinstance, "MessageBoxA" );

Well, now let's move on to the most interesting, actually to infection, write our data and code into memory and create a thread that starts all this. To modify the memory, we need two functions: VirtualAllocEx and WriteProcessMemory.
LPVOID lpProc = VirtualAllocEx(processHandel, NULL, ProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
LPVOID lpParams = VirtualAllocEx(processHandel, NULL, 1024, MEM_COMMIT, PAGE_READWRITE );
DWORD dwWritten;
if (WriteProcessMemory(processHandel, lpProc, InjectionMain, ProcSize, &dwWritten ) == 0) {
addLogMessage( "WriteProcessMemory error" , GetLastError());
return 0;
}
if (WriteProcessMemory( processHandel, lpParams, &injectData, sizeof (injectData), &dwWritten ) == 0) {
addLogMessage( "WriteProcessMemory error" , GetLastError());
return 0;
}

VirtualAllocEx - provides physical memory in the virtual address space of the process, and WriteProcessMemory writes our data to the process memory.

Now we will create a thread in a process that will bring our cunning plan to life:
DWORD ThreadID;
HANDLE hThread = CreateRemoteThread(processHandel, NULL, 0, (LPTHREAD_START_ROUTINE)lpProc, lpParams, 0, &ThreadID);
if (hThread == NULL) {
sprintf_s(buffer, "Error creating thread" );
addLogMessage(buffer, 1001);
}

Here is the source for the full image, I repeat that I did not test for Window 7, but I am sure that it should work too. The truth is interesting, as their new firewall will behave, in Windows XP it did not detect changes in memory. Antivirus programs are not afraid of this method, its enemy is only a firewall, since they notify about attempts to change memory. But as practice shows, many people hammer on such messages, if they give the name to the application that infects to give normal, then even advanced users will skip, unless of course the firewall is in paranoiac mode.

Source: https://habr.com/ru/post/73324/


All Articles