PWN-整数溢出

一、特殊数字

0x8000000000000000 # int64 8字节 所以是 16个字符,int32等同理

在计算机中

-0x8000000000000000 = 0x8000000000000000

我们可以利用这一特性绕过计算机部分检测

如:

char *sub_4009A0()
{
  __int64 v1; // [rsp+0h] [rbp-A0h]
  char s; // [rsp+10h] [rbp-90h]

  puts("Tell me the size of your story:");
  v1 = get_size("Tell me the size of your story:");
  if ( v1 < 0 )
    v1 = -v1;
  if ( v1 > 128 )
    v1 = 0x400LL;
  puts("You can speak your story:");
  sub_400ABE(&s, (unsigned __int64) v1);
  return strdup(&s);
}

因为 v1为 int64类型,我们可以设置v1为:0x8000000000000000

在计算机中0x8000000000000000 是一个负数

在执行 v1 = -v1 时, v1仍是一个负数,根据此特性,我们可以绕过 v1 > 128 的判断,

而在 sub_400ABE 函数中,计算机将v1强转成一个无符号的整型,这就导致我们可以传入一个很大的正整数,来实现溢出。

原理分析:

假设我们的程序是16位程序,我们数字最大程度为16位,换算为16进制,那么我们可以输入一个0x8000,实现上述绕过逻辑。

0x8000,用2进制表现为

1000 0000 0000 0000

计算机取反,其实就是将位“变反加一”,举个例子,在16为程序中,我们将0x0800取反,即得到-0x800,那么计算机是这么运行的

0000 1000 0000 0000 # 2048
# 取反
1111 0111 1111 1111
# 加1
1111 1000 0000 0000 ​​​​​​​# -2048

由于0x8000,他的最高位已经是计算机的最高位,所以运算如下

1000 0000 0000 0000 
# 取反 
0111 1111 1111 1111 
# 加1 
1000 0000 0000 0000

二、整数字节对照表

类型

字节

范围

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

负:

unsigned long int

8byte(qword)

0~0xffffffffffffffff

三、溢出类漏洞

计算机中有 4 种溢出情况,以 32 位整数为例。

① 无符号上溢:无符号数 0xffffffff 加 1 会变成 0。

② 无符号下溢:无符号数 0 减去 1 会变成 0xffffffff,即-1。

③ 有符号上溢:有符号正数 0x7fffffff 加 1 变成 0x80000000, 即从 2147483647 变成了-2147483648。

④ 有符号下溢:有符号负数 0x80000000 减去 1 变成 0x7fffffff,即从-2147483648 变成了 2147483647。

一个经典的整数溢出例子就是 c 语言的 abs 函数,int abs(int x),该函数返回 x 的绝对值。但当 abs()函数的参数是 0x80000000 即-2147483648 的时候,它本来应该返回2147483648,但正整数的范围是 0-2147483647,所以他返回的仍然是个负数,即本身-2147483648。

四、符号转换类漏洞

符号转换类漏洞通常出在把范围大的变量赋值给范围小的变量,64 位下 long -> int,会造成截断,只把长整型的低 4byte 的值传给整型变量,比如把 long 类型的0x100000010 赋值给 int 类型的变量就会变成 0x10。

符号转换类漏洞也会出现在把signed变量赋值给unsigned变量,如下表2-6代码。如下就是 符号转换类漏洞 demo 代码。

#include<stdio.h>
void main()
{
    char buf[32];
    int len;
    puts("give your len:");
    scanf("%d",&len);
    if(len>32)
    len=32;
    puts("give your data:");
    read(0,buf,len);
    return;
}

len 变量是 signed int 类型该代码没有对 len 进行完善的约束,导致 len 可以是负数。比如我们输入-1,此时传入 read 参数的 size 就会是-1,read 的第三个参数 size 是size_t 类型,也就是 unsigned int 类型,它会将-1 解析成 0xffffffff,这就间接导致了栈溢出。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值