windows在域名解析上,为了效率,弄了个dns缓存的服务dnschace
dnsapi.dll负责解析且管理缓存.
CE附加到dnscache进程,查看该DLL导出函数,看哪个不顺眼,就下个断点.
随便ping个域名,最后找到Query_Main可以准确的拦截到域名地址
返回地址在dnsrslvr.dll模块里,所以这里直接iathook dnsrslvr.dll的Query_Main函数就行了.
代码:
效果:
当然,dnsapi.dll最终也事调用sendto解析域名,所以也可以hook sendto()函数拦截解析.原理都差不多.
/
/
直接GetServicePid(
"dnscache"
)返回dnscache服务进程
ID
,然后进行注入就行了
DWORD GetServicePid(LPCSTR lpSrvName)
{
sizeof(HOOKDATA);
SC_HANDLE hSrv;
SERVICE_STATUS_PROCESS InfoLevel;
DWORD dwBytesNeed;
SC_HANDLE hSCManager
=
OpenSCManagerA(
0
,
0
, SC_MANAGER_ALL_ACCESS);
if
((INT64)hSCManager <
=
0
)
return
0
;
hSrv
=
OpenServiceA(hSCManager, lpSrvName, SERVICE_QUERY_STATUS);
if
(hSrv
=
=
NULL)
{
return
0
;
}
if
(!QueryServiceStatusEx(hSrv, SC_STATUS_PROCESS_INFO, (LPBYTE)&InfoLevel, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeed))
{
CloseServiceHandle(hSrv);
return
0
;
}
CloseServiceHandle(hSrv);
CloseServiceHandle(hSCManager);
return
InfoLevel.dwProcessId;
}
typedef ULONG64 (WINAPI
*
Query_MainT)(PULONG64 a1, ULONG64 a2, ULONG64 a3, ULONG64 a4);
Query_MainT oldQuery_Main;
ULONG64 WINAPI NewQuery_Main(PULONG64 a1
/
*
rcx
*
/
, ULONG64 a2, ULONG64 a3, ULONG64 a4)
{
const wchar_t
*
url
=
L
"baidu.com"
;
const wchar_t
*
newurl
=
L
"pediy.com"
;
if
(wcsstr((wchar_t
*
)a1[
0
], url))
{
/
/
RCX传进来的参数,有三个一样的指针数据,就是指向的网址
/
/
WIN7系统在
+
0
,系统不一样,偏移不一样
a1[
0
]
=
(ULONG64)newurl ;
a1[
1
]
=
(ULONG64)newurl ;
a1[
2
]
=
(ULONG64)newurl ;
return
0
;
}
return
oldQuery_Main(a1, a2, a3, a4);
}
void HOOK_Query_Main()
{
HMODULE dnsapi
=
GetModuleHandleA(
"dnsapi.dll"
);
PULONG64 dnsrslvr
=
(PULONG64) GetModuleHandleA(
"dnsrslvr.DLL"
);
oldQuery_Main
=
(Query_MainT) GetProcAddress(dnsapi,
"Query_Main"
);
for
(size_t i
=
0
; i <
0x1000000
; i
+
+
)
/
/
直接遍历整个dnsrslvr模块
{
if
(IsBadReadPtr(dnsrslvr
+
i,
8
))
{
break
;
}
if
(dnsrslvr[i]
=
=
(ULONG64)oldQuery_Main)
/
/
如果找到oldQuery_Main,直接替换,会有兼容性问题,能用就行
{
ULONG oldProtect
=
0
;
VirtualProtect(dnsrslvr
+
i,
100
, PAGE_READWRITE, &oldProtect);
dnsrslvr[i]
=
(ULONG64)NewQuery_Main;
break
;
}
}
}
/
/
直接GetServicePid(
"dnscache"
)返回dnscache服务进程
ID
,然后进行注入就行了
DWORD GetServicePid(LPCSTR lpSrvName)
{
sizeof(HOOKDATA);
SC_HANDLE hSrv;
SERVICE_STATUS_PROCESS InfoLevel;
DWORD dwBytesNeed;
SC_HANDLE hSCManager
=
OpenSCManagerA(
0
,
0
, SC_MANAGER_ALL_ACCESS);
if
((INT64)hSCManager <
=
0
)
return
0
;
hSrv
=
OpenServiceA(hSCManager, lpSrvName, SERVICE_QUERY_STATUS);
if
(hSrv
=
=
NULL)
{
return
0
;
}
if
(!QueryServiceStatusEx(hSrv, SC_STATUS_PROCESS_INFO, (LPBYTE)&InfoLevel, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeed))
{
CloseServiceHandle(hSrv);
return
0
;
}
CloseServiceHandle(hSrv);
CloseServiceHandle(hSCManager);
return
InfoLevel.dwProcessId;
}
typedef ULONG64 (WINAPI
*
Query_MainT)(PULONG64 a1, ULONG64 a2, ULONG64 a3, ULONG64 a4);
Query_MainT oldQuery_Main;
ULONG64 WINAPI NewQuery_Main(PULONG64 a1
/
*
rcx
*
/
, ULONG64 a2, ULONG64 a3, ULONG64 a4)
{
const wchar_t
*
url
=
L
"baidu.com"
;
const wchar_t
*
newurl
=
L
"pediy.com"
;
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2021-2-4 03:10
被游乐娃子编辑
,原因: