标签:csapp
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
实验材料:
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.
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); }
Advice:
我了个大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
这里一共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里面
接着把该文件作为输入就是啦~ : )
问题解决基础:
/* $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 addres之上还有什么我这里确实不清楚,不过我这里这么做是根据反汇编的结果测试并计算出来的.
有心人可以一起讨论这里跳转到fizz之后之前寄存器的变化 : ) jasonleaster@gmail.com
然后把exploit_for_level1.byte作为输入即可
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
原文地址:http://blog.csdn.net/cinmyheart/article/details/39228441