New crash exploit part III (17.11.2012)
Re: New crash exploit part III (17.11.2012)
Nice job, Grabbi on capturing those packets.
From observing the wireshark the server normally updates the clients(@ 33Hz?)
with a data packet of 212 bytes.
In Grabbi's packet log, the server sends its last data packet, No. 5593, at time 10.119069.
So I assume after this time the server has hung, and is no longer updating clients
with data. Thus the hacker(50.117.78.136) probably did something bad somewhere around
time 10.119069 that is causing the problem.
battlefield42 data packets follow this general format:
[7 bytes] header
[2 bytes] size of data contents
[... bytes] data contents (of a number of bytes specified by the 2 byte field above)
So looking around server packet no. 5593, this packet sent by the hacker, looks fishy
because the 2 byte field that holds the size of the data contents is 0:
No. Time Source Destination Protocol Length Info
5597 10.120369 50.117.78.136 h1345257.stratoserver.net UDP 99 Source port: ansyslmd Destination port: 14567
Frame 5597: 99 bytes on wire (792 bits), 99 bytes captured (792 bits)
Ethernet II, Src: Cisco_a2:9c:00 (00:16:9c:a2:9c:00), Dst: TyanComp_65:10:65 (00:e0:81:65:10:65)
Internet Protocol Version 4, Src: 50.117.78.136 (50.117.78.136), Dst: h1345257.stratoserver.net (85.214.86.156)
User Datagram Protocol, Src Port: ansyslmd (1055), Dst Port: 14567 (14567)
Data (57 bytes)
0000 0c 85 fa ff ff ff ff [00 00] c3 00 00 00 00 fc df ................
0010 ff fd df ff fd df ff 01 00 00 00 fc df ff fd df ................
0020 ff fd df ff 01 00 00 00 fc df ff fd df ff fd df ................
0030 ff 01 00 00 00 04 ad b1 89 .........
;I put []'s around the word that is supposed to hold the size of the data contents,
notice how its 0! :/
From the backtrace that you posted wq_Compf, it shows that an infinite loop
is somewhere in those functions:
(gdb) bt
#0 0x0843c12b in dice::ref2::io::SWConnection::getPacketFromRecvQueue(unsigned char*, unsigned int*) ()
#1 0x0843867a in dice::ref2::io::NetServer::getRecvdPacket(int*, unsignedchar*, unsigned int*) ()
#2 0x08137913 in dice::bf::GameServer::receive(int*) ()
#3 0x08137be2 in dice::bf::GameServer::processReceivedPackets() ()
#4 0x08132995 in dice::bf::GameServer::update(int, float) ()
#5 0x080bc366 in dice::bf::Setup::mainLoop() ()
#6 0x080bb71c in dice::bf::Setup::start(std::string const&) ()
#7 0x08050775 in main ()
So I began to look at how a data packet with its size field set to 00 would affect these functions.
The problem looks to ultimately begin in dice::ref2::io::SWConnection::getPacketFromRecvQueue(
where these 2 bytes are read:
0x0843c147 <+71>: mov ax,WORD PTR [eax+edx*1] ;get the size field in the data packet
0x0843c14b <+75>: test ax,ax
0x0843c14e <+78>: jne 0x843c157 ;jump if size != 0
0x0843c150 <+80>: mov eax,0x9 ;set the return variable to 0x9
0x0843c155 <+85>: jmp 0x843c11a ;jump to ret
Normally, getPacketFromRecvQueue() would have popped this packet from the Receive Queue but because
of the 0 data field it has returned early, leaving the bad packet still in its queue.
From this point on, functions return and processing ends up back in GameServer::processReceivedPackets().
Now, GameServer::processReceivedPackets() checks the value returned by GameServer::receive(), which is
in the eax register:
0x08137bdd <+61>: call 0x81378d0 <dice::bf::GameServer::receive(int*)>
0x08137be2 <+66>: add esp,0x10
0x08137be5 <+69>: mov edi,eax ;retval, eax = 9 set in SWConnection::getPacketFromRecvQueue
0x08137be7 <+71>: cmp eax,0x1
0x08137bea <+74>: je 0x81382f0
0x08137bf0 <+80>: cmp eax,0x1
0x08137bf3 <+83>: jle 0x8137f80
0x08137bf9 <+89>: cmp eax,0xa
0x08137bfc <+92>: je 0x8137f10
0x08137c02 <+98>: cmp eax,0xd
0x08137c05 <+101>: je 0x8137e90
0x08137c0b <+107>: cmp edi,0x8
0x08137c0e <+110>: jne 0x8137bd0 ;a retval of 0x9 loops back, and the bad packet remains!
This shows that with a return value of 0x9 the jne @ 0x08137c0e gets
executed looping back causing the infinite loop.
To check this using a bf42 server process, I used GDB. At instruction 0x843c147 in SWConnection::getPacketFromRecvQueue,
I set the data field of any of battlefield data packet to 00:
//$hobo is just a variable name i made up
(gdb) x/i $eip
=> 0x843c147 <_ZN4dice4ref22io12SWConnection22getPacketFromRecvQueueEPhPj+71>:mov ax,WORD PTR [eax+edx*1]
(gdb) x/x $eax+$edx
0xb08d6ff: 0x58c1002d
(gdb) set variable $hobo=0xb08d6ff
(gdb) p/x $hobo
$9 = 0xb08d6ff
(gdb) set *(char*)$hobo=0x0
(gdb) x/x $eax+$edx
0xb08d6ff: 0x58c10000
(gdb) continue
I noticed that the server no longer responds, but I change the data field
back to what it was (normally it is 0x2d), the server starts working again
because it can start handling packets out of its recv queue again.
I am not sure how this is all effected if the bad client sends good
packets again, if the server just pops & processes those and then hangs
on the bad packet.
I hope that with the ability to re-create the problem in GDB, tuia, s[sk] and other
talented individuals can help get this patched
I also wonder if this is the only trick the hacker is using, or if there are bad
things in the packet log.
From observing the wireshark the server normally updates the clients(@ 33Hz?)
with a data packet of 212 bytes.
In Grabbi's packet log, the server sends its last data packet, No. 5593, at time 10.119069.
So I assume after this time the server has hung, and is no longer updating clients
with data. Thus the hacker(50.117.78.136) probably did something bad somewhere around
time 10.119069 that is causing the problem.
battlefield42 data packets follow this general format:
[7 bytes] header
[2 bytes] size of data contents
[... bytes] data contents (of a number of bytes specified by the 2 byte field above)
So looking around server packet no. 5593, this packet sent by the hacker, looks fishy
because the 2 byte field that holds the size of the data contents is 0:
No. Time Source Destination Protocol Length Info
5597 10.120369 50.117.78.136 h1345257.stratoserver.net UDP 99 Source port: ansyslmd Destination port: 14567
Frame 5597: 99 bytes on wire (792 bits), 99 bytes captured (792 bits)
Ethernet II, Src: Cisco_a2:9c:00 (00:16:9c:a2:9c:00), Dst: TyanComp_65:10:65 (00:e0:81:65:10:65)
Internet Protocol Version 4, Src: 50.117.78.136 (50.117.78.136), Dst: h1345257.stratoserver.net (85.214.86.156)
User Datagram Protocol, Src Port: ansyslmd (1055), Dst Port: 14567 (14567)
Data (57 bytes)
0000 0c 85 fa ff ff ff ff [00 00] c3 00 00 00 00 fc df ................
0010 ff fd df ff fd df ff 01 00 00 00 fc df ff fd df ................
0020 ff fd df ff 01 00 00 00 fc df ff fd df ff fd df ................
0030 ff 01 00 00 00 04 ad b1 89 .........
;I put []'s around the word that is supposed to hold the size of the data contents,
notice how its 0! :/
From the backtrace that you posted wq_Compf, it shows that an infinite loop
is somewhere in those functions:
(gdb) bt
#0 0x0843c12b in dice::ref2::io::SWConnection::getPacketFromRecvQueue(unsigned char*, unsigned int*) ()
#1 0x0843867a in dice::ref2::io::NetServer::getRecvdPacket(int*, unsignedchar*, unsigned int*) ()
#2 0x08137913 in dice::bf::GameServer::receive(int*) ()
#3 0x08137be2 in dice::bf::GameServer::processReceivedPackets() ()
#4 0x08132995 in dice::bf::GameServer::update(int, float) ()
#5 0x080bc366 in dice::bf::Setup::mainLoop() ()
#6 0x080bb71c in dice::bf::Setup::start(std::string const&) ()
#7 0x08050775 in main ()
So I began to look at how a data packet with its size field set to 00 would affect these functions.
The problem looks to ultimately begin in dice::ref2::io::SWConnection::getPacketFromRecvQueue(
where these 2 bytes are read:
0x0843c147 <+71>: mov ax,WORD PTR [eax+edx*1] ;get the size field in the data packet
0x0843c14b <+75>: test ax,ax
0x0843c14e <+78>: jne 0x843c157 ;jump if size != 0
0x0843c150 <+80>: mov eax,0x9 ;set the return variable to 0x9
0x0843c155 <+85>: jmp 0x843c11a ;jump to ret
Normally, getPacketFromRecvQueue() would have popped this packet from the Receive Queue but because
of the 0 data field it has returned early, leaving the bad packet still in its queue.
From this point on, functions return and processing ends up back in GameServer::processReceivedPackets().
Now, GameServer::processReceivedPackets() checks the value returned by GameServer::receive(), which is
in the eax register:
0x08137bdd <+61>: call 0x81378d0 <dice::bf::GameServer::receive(int*)>
0x08137be2 <+66>: add esp,0x10
0x08137be5 <+69>: mov edi,eax ;retval, eax = 9 set in SWConnection::getPacketFromRecvQueue
0x08137be7 <+71>: cmp eax,0x1
0x08137bea <+74>: je 0x81382f0
0x08137bf0 <+80>: cmp eax,0x1
0x08137bf3 <+83>: jle 0x8137f80
0x08137bf9 <+89>: cmp eax,0xa
0x08137bfc <+92>: je 0x8137f10
0x08137c02 <+98>: cmp eax,0xd
0x08137c05 <+101>: je 0x8137e90
0x08137c0b <+107>: cmp edi,0x8
0x08137c0e <+110>: jne 0x8137bd0 ;a retval of 0x9 loops back, and the bad packet remains!
This shows that with a return value of 0x9 the jne @ 0x08137c0e gets
executed looping back causing the infinite loop.
To check this using a bf42 server process, I used GDB. At instruction 0x843c147 in SWConnection::getPacketFromRecvQueue,
I set the data field of any of battlefield data packet to 00:
//$hobo is just a variable name i made up
(gdb) x/i $eip
=> 0x843c147 <_ZN4dice4ref22io12SWConnection22getPacketFromRecvQueueEPhPj+71>:mov ax,WORD PTR [eax+edx*1]
(gdb) x/x $eax+$edx
0xb08d6ff: 0x58c1002d
(gdb) set variable $hobo=0xb08d6ff
(gdb) p/x $hobo
$9 = 0xb08d6ff
(gdb) set *(char*)$hobo=0x0
(gdb) x/x $eax+$edx
0xb08d6ff: 0x58c10000
(gdb) continue
I noticed that the server no longer responds, but I change the data field
back to what it was (normally it is 0x2d), the server starts working again
because it can start handling packets out of its recv queue again.
I am not sure how this is all effected if the bad client sends good
packets again, if the server just pops & processes those and then hangs
on the bad packet.
I hope that with the ability to re-create the problem in GDB, tuia, s[sk] and other
talented individuals can help get this patched
I also wonder if this is the only trick the hacker is using, or if there are bad
things in the packet log.
Re: New crash exploit part III (17.11.2012)
first of all, great analysis, we're not worthy!
mov ebx, 0x9
jmp 0x0843C195
to pop that message out of the queue and still return 9
quick and limited test showed that now it disconnects that client and doesn't hang, can't test it on a populated server right now so no idea whether there are any side effects
bf1942_lnxded.static:
003F4150: B8 -> BB
003F4156: C3 -> 3E
let me know what you think
i've tested it by injecting udp packet with that size being 0 into client-server communication, it does hang the serverdierighty wrote: So looking around server packet no. 5593, this packet sent by the hacker, looks fishy
because the 2 byte field that holds the size of the data contents is 0:
the first thing that was screaming "try me!" was0x0843c147 <+71>: mov ax,WORD PTR [eax+edx*1] ;get the size field in the data packet
0x0843c14b <+75>: test ax,ax
0x0843c14e <+78>: jne 0x843c157 ;jump if size != 0
0x0843c150 <+80>: mov eax,0x9 ;set the return variable to 0x9
0x0843c155 <+85>: jmp 0x843c11a ;jump to ret
mov ebx, 0x9
jmp 0x0843C195
to pop that message out of the queue and still return 9
quick and limited test showed that now it disconnects that client and doesn't hang, can't test it on a populated server right now so no idea whether there are any side effects
bf1942_lnxded.static:
003F4150: B8 -> BB
003F4156: C3 -> 3E
let me know what you think
Last edited by s[sk] on Sun Dec 09, 2012 2:34 pm, edited 1 time in total.
Re: New crash exploit part III (17.11.2012)
You can test on my server if you like, its getting crashed alot anyway so if it can help solve the problem just go ahead and do whatever it takes.
Re: New crash exploit part III (17.11.2012)
without having much clue of these datas I thought already, that the attacker now has found an effective way to stall a server without leaving an exception message behind which easily could lead to a fix, and it could be the search for a needle in the haystack.
respect !
Hope you guys will find the needle
Greetings
Grabbi
well I think the nice job is on your side dierighty analyzing the captured data protocol with such a precision.dierighty wrote:Nice job, Grabbi on capturing those packets.
respect !
Hope you guys will find the needle
Greetings
Grabbi
[url=bf1942://85.214.226.169:14567][/url]
Re: New crash exploit part III (17.11.2012)
Very good analysis dierighty!
s[sk], your fix seems fine to me, pop from the queue the "bad" packet with data size 0 and return the same value 9 to the caller function, so it doesn't get processed.
s[sk], your fix seems fine to me, pop from the queue the "bad" packet with data size 0 and return the same value 9 to the caller function, so it doesn't get processed.
Re: New crash exploit part III (17.11.2012)
i've looked into windows binary, i can't easily test it so i just tried to blindpatch it, it's 50:50 i got it right, anyway someone will correct me if i'm wrong
1f75eb8b55ab5bb4d6782dd6f3be2e45 BF1942_w32ded.exe
001B360F: 5E B8 -> 90 BB
001B3615: 5B 59 -> EB E8
edit: fixed that extra pop
1f75eb8b55ab5bb4d6782dd6f3be2e45 BF1942_w32ded.exe
001B360F: 5E B8 -> 90 BB
001B3615: 5B 59 -> EB E8
edit: fixed that extra pop
Last edited by s[sk] on Sun Dec 09, 2012 10:31 pm, edited 1 time in total.
Re: New crash exploit part III (17.11.2012)
It's there, but there is a previous pop esi instruction which should be nop'd, because the stack pointer will be changed. Or it can be modified to:
001B360F: 6A 09 5B EB EB
This is for BF1942_w32ded.exe v1.61.
I've tested s[sk] fixes on both Linux and Windows BF1942 servers and they seem to patch it correctly.
001B360F: 6A 09 5B EB EB
This is for BF1942_w32ded.exe v1.61.
I've tested s[sk] fixes on both Linux and Windows BF1942 servers and they seem to patch it correctly.
Re: New crash exploit part III (17.11.2012)
yes, of course, i'm blindtuia wrote:It's there, but there is a previous pop esi instruction which should be nop'd, because the stack pointer will be changed.
thanks
Re: New crash exploit part III (17.11.2012)
I would test this as well on my server I just need to know how to patch the Linux server files. I am using the 1.62 patched version. I don't need a guide just give me a kick in the right direction and a link to the needed tools
http://www.battlefield1942.net Frag On!
Re: New crash exploit part III (17.11.2012)
i suggest using vbindiff for hexediting in linuxViral wrote:I would test this as well on my server I just need to know how to patch the Linux server files. I am using the 1.62 patched version. I don't need a guide just give me a kick in the right direction and a link to the needed tools
just be sure you are not editing a binary that's in use (running)