首页 > 代码库 > CSAPP 六个重要实验 lab3

CSAPP 六个重要实验 lab3

CSAPP && lab3


level2 & leve3未完,待更新! : )


               In this lab, you will gain firsthand experience with one of the methods commonly used to exploit security weaknesses in operating systems and network servers. Our purpose is to help you learn about the runtime operation of programs and to understand the nature of this form of security weakness so that you can avoid it when you write system code. We do not condone the use of these or any other form of attack to gain unauthorized access to any system resources. There are criminal statutes governing such activities.



实验指导说明:

http://download.csdn.net/detail/u011368821/7920313

实验材料:

http://download.csdn.net/detail/u011368821/7920335












The Exploits


               There are three functions that you must exploit for this lab. The exploits increase in difficulty. For those of you looking for a challenge, there is a fourth function you can exploit for extra credit.


Level 0: Candle


              When getbuf() executes its return statement, the program ordinarily resumes execution within function test(). Within the file bufbomb, there is a function smoke():

void smoke()
{
entry_check(0); /* Make sure entered this function properly */
printf("Smoke!: You called smoke()\n");
validate(0);
exit(0);
}


             Your task is to get bufbomb to execute the code for smoke() when getbuf() executes its return statement, rather than returning to test().You can do this by supplying an exploit string that overwrites the stored return pointer in the stack frame for getbuf() with the address of the first instruction in smoke. Note that your exploit string may also corrupt other parts of the stack state, but this will not cause a problem, because smoke() causes the program to exit directly.


Advice:


      • All the information you need to devise your exploit string for this level can be determined by examining a disassembled version of bufbomb.

      • Be careful about byte ordering.
      • You might want to use gdb to step the program through the last few instructions of getbuf() to make sure it is doing the right thing.
      • The placement of buf within the stack frame for getbuf() depends on which version of gcc was used to compile bufbomb. You will need to pad the beginning of your exploit string with the proper number of bytes to overwrite the return pointer. The values of these bytes can be arbitrary.
      • Check the line endings if your smoke.txt with hexdump -C smoke.txt.




我了个大X,调了几天才搞明白怎么用“溢出缓冲区攻击"



利用先构建一个输入文本,记录要数据的字符(溢出用)

我这里是 

exploit.txt

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 01 02 03 04 01 02 03 04 05 06 07 08 c0 10 40 00 00 00 00 00

这里一定不要有换行符号(如果有也没关系,去生成的文件里,用vim打开编辑了之后去掉就是了)

这里一共0x30byte+8byte+8byte == 0x40byte

第一个0x30byte 是由于64bits的机器字节对齐导致的36byte的数组被扩展到0x30byte!

而后的8byte是之前 push %rbp 寄存器的value

最后的8byte是return address,也就是我们要”攻击“的地方!

考虑到机器的大小端.

smoke的地址是

00 00 00 00 00 40 10 c0

写入的时候应该是

 c0 10 40 00 00 00 00 00



这里把生成的数据记录到exploit.byte里面

接着把该文件作为输入就是啦~ : )




Level 1: Sparkler

问题解决基础:




/* $begin fizz-c */
void fizz(int arg1, char arg2, long arg3, char* arg4, short arg5, short arg6, unsigned long long val)
{
  entry_check(1);  /* Make sure entered this function properly */
  if (val == cookie) {
	printf("Fizz!: You called fizz(0x%llx)\n", val);
	validate(1);
  } else {
	printf("Misfire: You called fizz(0x%llx)\n", val);
  }
  exit(0);
}
/* $end fizz-c */



               Similar to Level 0, your task is to get bufbomb to execute the code for fizz() rather than returning to test.In this case, however, you must make it appear to fizz as if you have passed your cookie as its argument. You can do this by encoding your cookie in the appropriate place within your exploit string.


Advice:

Note that in x86--64, the first six arguments are passed into registers and additional arguments are passed through the stack. Your exploit code needs to write to the appropriate place within the stack.


You can use gdb to get the information you need to construct your exploit string. Set a breakpoint within getbuf() and run to this breakpoint. Determine parameters such as the address of global_value and the location of the buffer.





在破坏原来test()调用getbuf push的return address之后,跳转到fizz,此时看到题目要求是要把cookie作为fizz的参数输入,根据反汇编得到的信息,我们可以看见这里

cmp 0x201296(%rip) %rsi

如果相等就会跳转到0x40109f接着顺利退出.

由于之前rsp寄存器的值没有被破坏,于是我们反推,如果”攻击rsp“的值,使得0x10(%rsp)指向 cookie

那么就可以顺利退出了!


由于最后leaveq的时候会把保存好的%rbp重新赋值给%rsp,于是

我们这里可以转而攻击保存好的%rbp,来实现间接改变%rsp



cmp 0x201296(%rip) %rsi

死死的扣住这句不放,这里吧0x201296(%rip) 地址处的值和%rsi的值比较

0x201296(%rip)

就是cookie的地址,然后这里%rsi是参数val的地址

cmp把cookie地址处的值!注意是cookie地址处的值,和%rsi比较

如果想等才能正确返回否则你看到的永远是missfire!


这里给出我的解

首先查看cookie地址处的值然后输入



exploit_for_level1.txt

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 01 02 03 04 20 23 60 00 00 00 00 00 70 10 40 00 00 00 00 00 00 00 00 00 00 00 00 00 c2 46 c1 21 48 ca 33 39

             细心的人会发现,我这里在return address之上还多填了8byte的空间,接着才填充我们的答案.

这是因为return addres之上还有什么我这里确实不清楚,不过我这里这么做是根据反汇编的结果测试并计算出来的.

有心人可以一起讨论这里跳转到fizz之后之前寄存器的变化 : ) jasonleaster@gmail.com





然后把exploit_for_level1.byte作为输入即可




Level 2: Firecracker

 

                A much more sophisticated form of buffer attack involves supplying a string that encodes actual machine instructions. The exploit string then overwrites the return pointer with the starting address of these instructions. When the calling function (in this case getbuf) executes its ret instruction, the program will start executing the instructions on the stack rather than returning. With this form of attack, you can get the program to do almost anything. The code you place on the stack is called the exploit code. This style of attack is tricky, though, because you must get machine code onto the stack and set the return pointer to the start of this code.

              For level 2, you will need to run your exploit within gdb for it to succeed. (attu has special memory protection that prevents execution of memory locations in the stack. Since gdb works a little differently, it will allow the exploit to succeed.)


             Similar to Levels 0 and 1, your task is to get bufbomb to execute the code for bang() rather than returning to test(). Before this, however, you must set global variable global_value to your cookie. Your exploit code should set global_value, push the address of bang() on the stack, and then execute a retq instruction to cause a jump to the code for bang().


Advice:
            Determining the byte encoding of instruction sequences by hand is tedious and prone to errors. You can let tools do all of the work by writing an assembly code file containing the instructions and data you want to put on the stack. Assemble this file with gcc and disassemble it with objdump. You should be able to get the exact byte sequence that you will type at the prompt. (A brief example of how to do this is included in the Generating Byte Codes section above.)

            Keep in mind that your exploit string depends on your machine, your compiler, and even your cookie. Make sure your exploit string works on attu or your VM, and make sure you include your UWNetID on the command line to bufbomb.


           Watch your use of address modes when writing assembly code. Note that movq $0x4, %rax moves the value
0x0000000000000004 into register %rax; whereas movq 0x4, %rax moves the value at memory location
0x0000000000000004 into %rax. Because that memory location is usually undefined, the second instruction will
cause a segmentation fault!

           Do not attempt to use either a jmp or a call instruction to jump to the code for bang(). These instructions use PC- relative addressing, which is very tricky to set up correctly. Instead, push an address on the stack and use the retq instruction.


这里我跳转到buffer地址的时候有问题...segment fault   


我的尝试:

首先观察发现这里cmp 相等就会跳转并安全结束.

比较的两个对象是0x602320指向的value,而%rsi是global_value.

cookie的值在我们输入的时候就定了. 这里能改的就是global_value处(即0x602308处)的值了。

普通的做法是搞不定的.




这里必须自己写一段攻击代码——汇编形式的

然后在这段代码里面把cookie的值赋值给global_value,就成功了一半了,

接着把这段代码gcc -c 编译成obj。然后objdump去看相应的机器码


mov 0x602330,%rax 就对应的机器码就是

48 8b 04 25 20 23 60

不解释了

值得一提的是这里有


pushq $0x401020

和retq操作(稍后解释用途)


然后把这些机器码写到buffer里面去!

试想一下这里如果我覆盖的reture address是只想buffer头的,那么在buffer处的这些指令就得以执行.

接着当这些指令执行到最后的时候

pushq $0x401020

retq

这步就可以跳转到0x401020(bang函数头)。执行 bang函数,我们已经在攻击代码里面修改了global_value,那么cmp的结构就是0,je跳转,程序安全结束.

这仅仅是我的理论分析,我遇到的问题就是这里跳转到buffer头的时候会出现segment fault...


路过高手可以指教一下 : )








CSAPP 六个重要实验 lab3