cal System的Window,他也有办法提升权限:他可以利用Tool Help函数得到属于 Local System的进程及其Thread,只要其中任何一个Thread能处理Window的Message,用户就可以用函数PostThreadMessage()向这个属于Local System的Thread发送Message,然后就。。。如此这般。。。地提升权限。不过我没有时间 亲手试验过这种方法。
这两篇文章引起了很大的反响,其中最引人注意的是Microsoft的答复,Micorsoft说这种方法老早就有人提出来了,Nothing New!又说根本就不应该在普通用户的Desktop上创建属于Local System的Window,编程序的人应该避免这样的设计。但实际上隐藏式的窗口"NetDDE Agent"就出自于Microsoft的设计,它属于Local System但是却运行在登录用户的Desktop上,看来Microsoft是知法犯法啊! 我觉得这个缺陷就象不安全的函数strcpy一样,C语言在实现strcpy函数时有漏洞(函数返回地址、函数堆栈栈底地址等系统管理信息与缓冲区分配在一块,缓冲区的溢出就会覆盖系统管理信息),於是大家寄希望于程序员能够避免使用函数strcpy。现在Microsoft也承认在普通用户的Desktop上创建一个Window是危险的,所以它也寄希望于大家编程时避免使用这样的设计。
下面我专门编写了一个服务进程“SimpleService”来演示一下Microsoft的这个设计缺陷。SimpleService以Local System的权限运行,它打开一个Named Pipe然后等待Named Pipe Client与它联络;普通用户接着登录计算机并运行程序“Client”,“Client”是一个Named Pipe Client;它向SimpleService的Named Pipe随便写一些字节,於是SimpleService就在登录用户的Desktop上产生一个对话窗口(Dialog Box)。普通用户最后利用FOON的攻击程序Shatter攻击这个对话窗口来获得“Local System”的权限。
因为SimpleService程序太长,所以我只节选了关键的部分让大家参考:
<====================SimpleService====================>
#define SZAPPNAME _T("Simple")
#define SZSERVICENAME _T("SimpleService")
#define SZSERVICEDISPLAYNAME _T("Simple Service")
#define SZDEPENDENCIES _T("")
typedef struct DLGPARAM{
UINT numOfHit;
TCHAR *msg;
} DlgParam;
// internal function prototypes
static BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// SimpleService.cpp : Defines the entry point for the
application.
//
HINSTANCE hAppInstance;
DlgParam m_dlgParam;
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
......
}
void WINAPI service_main()
{
......
}
VOID WINAPI service_ctrl(DWORD dwCtrlCode)
{
......
}
BOOL WINAPI ControlHandler ( DWORD dwCtrlType )
{
......
}
HANDLE hServerStopEvent = NULL;
VOID ServiceStart ()
{
......
......
hPipe = CreateNamedPipe(
lpszPipeName , // name of pipe
FILE_FLAG_OVERLAPPED
PIPE_ACCESS_DUPLEX, // pipe open mode
PIPE_TYPE_MESSAGE
PIPE_READMODE_MESSAGE
PIPE_WAIT, // pipe IO type
1, // number of instances
0, // size of outbuf
file://(0 == allocate as necessary)
0, // size of inbuf
1000, // default time-out value
&sa); // security attributes
......
......
while ( 1 )
{
......
......
ConnectNamedPipe(hPipe, &os);
......
......
bRet = ReadFile(
hPipe, // file to read from
szIn, // address of input buffer
sizeof(szIn), // number of bytes to read
&cbRead, // number of bytes read
&os); // overlapped stuff, not needed
......
......
_stprintf(szOut, _T("Please check the Dialog Box"));
_stprintf(szOut1, _T("Eacho Back! [%s]"), szIn);
......
......
bRet = WriteFile(
hPipe, // file to write to
szOut, // address of output buffer
sizeof(szOut), // number of bytes to write
&cbWritten, // number of bytes written
&os); // overlapped stuff, not needed
......
......
DisconnectNamedPipe(hPipe);
m_dlgParam.numOfHit++;
m_dlgParam.msg = szOut1;
/*
在登录用户的Desktop上创建一个窗口
*/
int result = DialogBoxParam(hAppInstance,
MAKEINTRESOURCE(IDD_SVCMSG),
NULL,
(DLGPROC) DialogProc,
(LPARAM) &m_dlgParam);
}
cleanup:
......
......
}
VOID ServiceStop()
{
if ( hServerStopEvent )
SetEvent(hServerStopEvent);
}
#define SIZEOFBUF 40
/*
Window的Message Handler
*/
BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DlgParam* l_pDlgParam = (DlgParam*) lParam;
CHAR tempBuf[SIZEOFBUF];
switch (uMsg)
{
case WM_INITDIALOG:
{
HWND hNumVisit = GetDlgItem(hwnd, IDC_NUMHIT); /*限定Edit Control的尺寸(Size)为3*/
SendMessage( hNumVisit, EM_LIMITTEXT, (WPARAM) 3,
(LPARAM)0);
_itoa(l_pDlgParam->numOfHit, tempBuf,10);
SendMessage(hNumVisit, WM_SETTEXT, (WPARAM)
0,(LPARAM)tempBuf);
HWND hMsg = GetDlgItem(hwnd, IDC_MSG);
/*限定Edit Control的尺寸(Size)为40*/
SendMessage( hMsg, EM_L
·上一篇: 暂时空缺
·下一篇: Win2K系统几个攻击实例成败心得(四)
|