有点新意的就是, 在线程函数里调用 VirtualFree
函数时, 不是用 call 指令, 而是 jmp, 这样, 当 VirtualFree 函数返回后,
就会直接进入到 ExitThread 函数, 因为此前已经将这个函数的地址压入栈了.
我们知道, call 指令其实就是两个操作:
1. 将 call 指令返回后的紧接着的下一条指令的地址压栈,
2. 跳转到 call 指令代表的函数的首地址.
函数执行完毕后,
1. ret 指令就将从栈上读取返回地址,
2. 跳转到那个地址继续执行,
我们其实是在这里人为的将其执行流程给改了. 我们这么做的意图很负责任: 释放这块指令所处的内存, 避免内存泄漏,
因为注入代码的进程已经退出, 没有机会清理这块内存, 咱们就自力更生了.
这么干也很安全, 因为 ExitThread
不会返回了, EIP 就不会跑飞了(也就是说, 换成别的函数会造成目标进程崩溃的, 特此说明.).
线程函数的最后的平衡堆栈的指令和返回指令是没有意义的, 放这里是为了让反汇编器不会少见多怪.
接下来废话少说, 贴代码:
#include <windows.h>
#include <tchar.h>
#include <TLHELP32.H>
#include <stddef.h>
void EnablePrivilege(void)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp = { 0 };
HANDLE hProcess = GetCurrentProcess();
if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
return;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid))
{
CloseHandle(hToken);
return;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
NULL, NULL);
CloseHandle(hToken);
}
DWORD FindTarget(LPCTSTR lpszProcess)
{
DWORD dwRet = 0;
PROCESSENTRY32 pe32 = { sizeof( PROCESSENTRY32 ) };
HANDLE hSnapshot = NULL;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Process32First(hSnapshot, &pe32);
do
{
if (0 == lstrcmpi(pe32.szExeFile, lpszProcess))
{
dwRet = pe32.th32ProcessID;
break;
}
} while (Process32Next(hSnapshot, &pe32));
CloseHandle(hSnapshot);
return dwRet;
}
static DWORD WINAPI DelProc(LPVOID lpParam)
{
Sleep(50);
DeleteFileA((LPCSTR)lpParam);
VirtualFree((PVOID)0x10000000, 0, MEM_RELEASE);
ExitThread(0);
return 0;
}
//==============================================================================
PUCHAR FindDWordFromBuffer(PUCHAR lpBuffer, UINT cchMax, DWORD dwValue)
{
PUCHAR pResult = NULL;
UINT nIter = 0;
for (nIter=0; nIter<cchMax; nIter++)
{
if ( *(DWORD *)(lpBuffer + nIter) == dwValue ) {
pResult = lpBuffer + nIter;
break;
}
}
return pResult;
}
//==============================================================================
#define Sleep_addr 0xBBBBBBBB
#define DeleteFileA_addr 0xDDDDDDDD
#define ExitThread_addr 0xFFFFFFFF
#define VirtualFree_addr 0xEEEEEEEE
#define _DelProc_addr 0xCCCCCCCC
static __declspec(naked) DWORD WINAPI _DelProc(LPVOID lpParam)
{
__asm {
; // __this_addr:
push ebp ;
mov ebp, esp ;
push 0x32 ; // dwMilliseconds
mov eax, Sleep_addr ;
call eax ; // ds:__imp__Sleep@4 ; Sleep(x)
mov eax, [ebp+8] ;
push eax ; // lpFileName
mov eax, DeleteFileA_addr ;
call eax ; // ds:__imp__DeleteFileA@4 ; DeleteFileA(x)
push 0 ; // dwExitCode, ExitThread 函数的参数
push 8000h ; // dwFreeType
push 0 ; // dwSize
mov eax, _DelProc_addr ; // __this_addr
push eax ; // lpAddress
mov eax, ExitThread_addr ; // ds:ExitThread
push eax ; // 将 ExitThread
函数的地址压栈, 这样, VirtualFree 函数返回后就会马上执行 ExitThread
函数
mov eax, VirtualFree_addr ;
jmp eax ; // ds:__imp__VirtualFree@12 ; VirtualFree(x,x,x)
mov esp, ebp ; // 以下 3 条指令不会被执行的.
pop ebp ;
ret 4 ;
}
}
static __declspec(naked) DWORD WINAPI _DelProc_end(LPVOID lpParam)
{
__asm {
ret 4 ;
}
}
BOOL BuildRemoteThreadCode(OUT PUCHAR lpCode, UINT cchMax, DWORD dwRemoteBegin)
{
UINT nCodeLen = 0;
PUCHAR pIter = NULL;
DWORD dwFnAddr = 0;
if (NULL==lpCode || 0==cchMax) {
return FALSE;
}
nCodeLen = (PUCHAR) &_DelProc_end - (PUCHAR) &_DelProc;
if (nCodeLen > cchMax) {
return FALSE;
}
memcpy((void *)lpCode, (void *) &_DelProc, nCodeLen);
{
pIter = FindDWordFromBuffer(lpCode, nCodeLen, Sleep_addr);
if (NULL == pIter) {
return FALSE;
}
dwFnAddr = (DWORD) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "Sleep");
if (0 == dwFnAddr) {
return FALSE;
}
*(DWORD *)pIter = dwFnAddr;
}
{
pIter = FindDWordFromBuffer(lpCode, nCodeLen, DeleteFileA_addr);
if (NULL == pIter) {
return FALSE;
}
dwFnAddr = (DWORD) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "DeleteFileA");
if (0 == dwFnAddr) {
return FALSE;
}
*(DWORD *)pIter = dwFnAddr;
}
{
pIter = FindDWordFromBuffer(lpCode, nCodeLen, ExitThread_addr);
if (NULL == pIter) {
return FALSE;
}
dwFnAddr = (DWORD) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "ExitThread");
if (0 == dwFnAddr) {
return FALSE;
}
*(DWORD *)pIter = dwFnAddr;
}
{
pIter = FindDWordFromBuffer(lpCode, nCodeLen, VirtualFree_addr);
if (NULL == pIter) {
return FALSE;
}
dwFnAddr = (DWORD) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "VirtualFree");
if (0 == dwFnAddr) {
return FALSE;
}
*(DWORD *)pIter = dwFnAddr;
}
{
pIter = FindDWordFromBuffer(lpCode, nCodeLen, _DelProc_addr);
if (NULL == pIter) {
return FALSE;
}
dwFnAddr = (DWORD) dwRemoteBegin;
if (0 == dwFnAddr) {
return FALSE;
}
*(DWORD *)pIter = dwFnAddr;
}
return TRUE;
}
BOOL RemoteDel(DWORD dwProcessID, LPCSTR lpszFileName, DWORD dwTime)
{
CHAR szFileName[MAX_PATH] = { 0 };
HANDLE hProcess = NULL;
DWORD dwCodeLen = 0;
DWORD dwSize = 0;
LPVOID lpRemoteBuf = NULL;
PUCHAR pBuff = NULL;
DWORD dwWritten = 0;
DWORD dwID = 0;
HANDLE hThread = NULL;
// 打开目标进程
hProcess = OpenProcess(
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE,
dwProcessID);
if (NULL == hProcess)
return FALSE;
GetModuleFileNameA(NULL, szFileName, MAX_PATH);
dwCodeLen = (DWORD)&_DelProc_end - (DWORD)&_DelProc;
dwSize = dwCodeLen + sizeof(szFileName);
lpRemoteBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (NULL == lpRemoteBuf)
{
CloseHandle(hProcess);
return FALSE;
}
pBuff = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(pBuff, &_DelProc, dwSize);
BuildRemoteThreadCode(pBuff, dwCodeLen, (DWORD)lpRemoteBuf);
memcpy(pBuff+dwCodeLen, szFileName, strlen(szFileName) + 1);
WriteProcessMemory(hProcess, lpRemoteBuf, (LPVOID)pBuff, dwSize, &dwWritten);
hThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)lpRemoteBuf,
(LPVOID)((DWORD)lpRemoteBuf + dwCodeLen), 0, &dwID);
CloseHandle(hThread);
CloseHandle(hProcess);
VirtualFree(pBuff, 0, MEM_RELEASE);
return TRUE;
}
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPTSTR lpCmdLine, int nShowCmd)
{
CHAR szMe[MAX_PATH] = { 0 };
DWORD dwId = 0;
EnablePrivilege();
GetModuleFileNameA(NULL, szMe, MAX_PATH);
dwId = FindTarget(_T("explorer.exe"));
RemoteDel(dwId, szMe, 50);
return 0;
}
posted on 2008-06-21 22:24
free2000fly 阅读(1864)
评论(11) 编辑 收藏 引用