BHO 透过IE9 保护模式 反IE9保护模式动态库导入表注入 当然反注入不是只能应用到这里,根据不同的注入方案反注入也不同

BHO插件工作虽然权限已经足够过,不过很多时候还会因为IE9本身影响BHO运行,比如BHO启动外部进程,或者BHO中访问网络,都同样受到保护模式的限制,

前段时间对于保护模式工作特征进行了DEBUG追踪发现,保护模式主要是由IEShims.dll完成。

IE进程首先加载IEShims.dll,然后注册NTDLL.dll提供的LibraryLoad通知,然后在其余任何动态库进行加载的时候注入动态库的导入表,然后接核心函数,比如GetProcAddress然后再IEShims.dll实现的GetProcAddress函数内进行了部分功能屏蔽,做到限制其他动态库反注入。以及接管一些IO函数和进程线程相关的核心函数,以便于在合时时候选择弹出提示让用户确认是否运行,不过很多时候这个确实很烦人。

GetProcAddress对于注入来说非常重要,虽然保护模式接管了它,但是我们也可以自己实现他的功能,动态库的句柄(动态库在内存影射的起始地址),既然句柄为起始地址,完全可以通过这个起始地址根据PE文件结构找到动态库的导入表, 同样也可以找到导出表。

这个时候完全可以获得kernel32.dll的句柄计算出GetProcAddress函数的导出地址,然后找到自己动态库的的导入表中GetProcAddress函数修改掉被保护模式注入的地址。恢复GetProcAddress函数,那么后续可以在使用GetProcAddress函数恢复其他函数的地址。就可以完成反注入。即刻在让你的BHO插件在保护模式下自由工作。

 1 DWORD MySimpleGetProcAddress(HANDLE hIns,LPSTR funcName)
2 {
3 LPBYTE imageBase=NULL;
4 DWORD result=NULL;
5
6 PIMAGE_DOS_HEADER tmpdosHead=NULL;//PE DOS头
7 PIMAGE_NT_HEADERS tmpntHead=NULL;//PE NT头
8 PIMAGE_EXPORT_DIRECTORY tmpExport;//导出表
9 LPDWORD tmpFirstExport=NULL;
10 LPDWORD tmpFirstName=NULL;
11 LPWORD tmpFirstOrder=NULL;
12
13 LPSTR libName=NULL;
14 HANDLE tmphInst=NULL;
15 LPVOID tmpPoint=NULL;
16 tmphInst=hIns;
17 tmpdosHead=(PIMAGE_DOS_HEADER)tmphInst;//PE DOS头
18 tmpntHead=(PIMAGE_NT_HEADERS)((LPBYTE)tmphInst+tmpdosHead->e_lfanew);//PE NT头
19 tmpExport=(PIMAGE_EXPORT_DIRECTORY)((LPBYTE)tmphInst+tmpntHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);//导出表
20 tmpFirstExport=(LPDWORD)(tmpntHead->OptionalHeader.ImageBase+tmpExport->AddressOfFunctions);
21 tmpFirstOrder=(LPWORD)(tmpntHead->OptionalHeader.ImageBase+tmpExport->AddressOfNameOrdinals);
22 tmpFirstName=(LPDWORD)(tmpntHead->OptionalHeader.ImageBase+tmpExport->AddressOfNames);
23
24 for(DWORD count=0;count<tmpExport->NumberOfNames;count++)
25 {
26
27 if(strcmp( (LPSTR)(tmpntHead->OptionalHeader.ImageBase+*(tmpFirstName+count)),funcName)==0)
28 {
29 tmpPoint=(LPVOID)(tmpntHead->OptionalHeader.ImageBase+tmpFirstExport[tmpFirstOrder[count]]);
30 if(tmpPoint!=NULL)
31 {
32 result=(DWORD)tmpPoint;
33 break;
34 }
35 }
36 }
37 return result;
38 }
if(hIns==NULL)
{
hIns=GetModuleHandleA("NFIEPlugin");//获取当前模块句柄
}
LPBYTE imageBase=NULL;
PIMAGE_DOS_HEADER dosHead=NULL;//PE DOS头
PIMAGE_NT_HEADERS ntHead=NULL;//PE NT头
PIMAGE_DATA_DIRECTORY importTableDataDir=NULL;//导入表
PIMAGE_IMPORT_DESCRIPTOR importDesc=NULL;//导入描述(单个动态库相关)
PIMAGE_THUNK_DATA32 funPointThunk=NULL;//函数地址链
PIMAGE_THUNK_DATA32 funNameThunk=NULL;//函数名称链
PIMAGE_IMPORT_BY_NAME funName=NULL;


PIMAGE_DOS_HEADER tmpdosHead=NULL;//PE DOS头
PIMAGE_NT_HEADERS tmpntHead=NULL;//PE NT头
PIMAGE_EXPORT_DIRECTORY tmpExport;//导出表
LPDWORD tmpFirstExport=NULL;
LPDWORD tmpFirstName=NULL;
LPWORD tmpFirstOrder=NULL;

LPSTR libName=NULL;
HANDLE tmphInst=NULL;
LPVOID tmpPoint=NULL;
DWORD oldProtect=0;
if(IsBadReadPtr(hIns,sizeof(IMAGE_DOS_HEADER)))//检测地址有效性
return FALSE;
dosHead=(PIMAGE_DOS_HEADER)hIns;
ntHead=(PIMAGE_NT_HEADERS)((LPBYTE)hIns+dosHead->e_lfanew);
if(IsBadReadPtr(ntHead,sizeof(IMAGE_NT_HEADERS)))//检测地址有效性
return FALSE;
if(ntHead->FileHeader.Machine!=IMAGE_FILE_MACHINE_I386&&ntHead->FileHeader.Machine!=IMAGE_FILE_MACHINE_AMD64)
{
return FALSE;//不支持
}
if(ntHead->FileHeader.SizeOfOptionalHeader<=0)
{
return FALSE;//无可选头则不包含导入表
}
*(LPDWORD)&Kernel32GetProcAddress=(DWORD)MySimpleGetProcAddress(LoadLibraryA("kernel32.dll"),"GetProcAddress");
imageBase=(LPBYTE)ntHead->OptionalHeader.ImageBase;
PIMAGE_DATA_DIRECTORY dataDir=&ntHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; //获取导入表
importDesc=(PIMAGE_IMPORT_DESCRIPTOR)(imageBase+dataDir->VirtualAddress);

while(importDesc->Characteristics!=0)
{
libName=(LPSTR)(imageBase+importDesc->Name);
if(strlen(libName)==0)
{
continue;
}
//获取句柄
tmphInst=GetModuleHandleA(libName);
if(tmphInst==NULL)
tmphInst=LoadLibraryA(libName);
if(libName==NULL)
continue;

tmpdosHead=(PIMAGE_DOS_HEADER)tmphInst;//PE DOS头
tmpntHead=(PIMAGE_NT_HEADERS)((LPBYTE)tmphInst+tmpdosHead->e_lfanew);//PE NT头
tmpExport=(PIMAGE_EXPORT_DIRECTORY)((LPBYTE)tmphInst+tmpntHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);//导出表
tmpFirstExport=(LPDWORD)(tmpntHead->OptionalHeader.ImageBase+tmpExport->AddressOfFunctions);
tmpFirstOrder=(LPWORD)(tmpntHead->OptionalHeader.ImageBase+tmpExport->AddressOfNameOrdinals);
tmpFirstName=(LPDWORD)(tmpntHead->OptionalHeader.ImageBase+tmpExport->AddressOfNames);

for(DWORD count=0;count<tmpExport->NumberOfNames;count++)
{
//得到名称指针和函数地址指针
funPointThunk=(PIMAGE_THUNK_DATA32)(imageBase+importDesc->FirstThunk);
funNameThunk=(PIMAGE_THUNK_DATA32)(imageBase+importDesc->OriginalFirstThunk);
while(funPointThunk->u1.AddressOfData!=0&&funNameThunk->u1.AddressOfData!=0)
{

funName=(PIMAGE_IMPORT_BY_NAME)(imageBase+funNameThunk->u1.AddressOfData);
if(IsBadReadPtr(funName,4))
break;
if(strcmp( (LPSTR)(tmpntHead->OptionalHeader.ImageBase+*(tmpFirstName+count)),(LPSTR)&funName->Name[0])==0)
{
/*if(funName->Hint+tmpExport->Base<tmpExport->NumberOfNames)
{
*/
tmpPoint=(LPVOID)(tmpntHead->OptionalHeader.ImageBase+tmpFirstExport[tmpFirstOrder[count]]);
/* }
else
{
tmpPoint=(LPVOID)(tmpntHead->OptionalHeader.ImageBase+tmpFirstExport[tmpFirstOrder[funName->Hint]]);
}
*/
if(tmpPoint!=NULL)
{
VirtualProtect(funPointThunk,4,PAGE_EXECUTE_WRITECOPY,&oldProtect);
funPointThunk->u1.AddressOfData=(DWORD)Kernel32GetProcAddress(tmphInst,(LPSTR)funName->Name);;
VirtualProtect(funPointThunk,4,oldProtect,&oldProtect);
}
}

funPointThunk=funPointThunk+1;
funNameThunk=funNameThunk+1;
}
}
importDesc=importDesc+1;
}
}

首先恢复GetProcAddress函数,因为上边我自己写的获取导出地址的函数存在BUG不能保证每个函数都能获取正确,不过GetProcAddress肯定会获取对的,也没有精神研究具体的原因,因为恢复GetProcAddress后我就可以不用那个函数了。


 

原文地址:https://www.cnblogs.com/a185771876/p/2350844.html