pwnable.tw-calc详解

本文深入解析ROP链构造技术,通过具体实例演示如何利用ROP技术在受限环境下实现代码执行。文章详细介绍了ROP的基础概念,包括栈中ebp和esp的变换,以及如何在不使用shellcode的情况下,通过精心构造的ROP链绕过Canary和NX保护机制。

重点需要的知识:ROP链的构造、栈中ebp和esp的变换

这题颠覆了我原本以为pwn都是各种套路的思想,和pwn只需要关注危险函数的思想,栈溢出并不是只有各种ret技术,恐怕堆溢出也不仅仅局限于各种heap of技术,那些只是基础。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  ssignal(14, timeout);
  alarm(60);
  puts("=== Welcome to SECPROG calculator ===");
  fflush(stdout);
  calc();
  return puts("Merry Christmas!");
}

主函数没什么特别的,ssignal()和alarm()应该只是让程序时间长了不交互就自动退出。

unsigned int calc()
{
  int pool; // [esp+18h] [ebp-5A0h]
  int v2[100]; // [esp+1Ch] [ebp-59Ch]
  char s; // [esp+1ACh] [ebp-40Ch]
  unsigned int v4; // [esp+5ACh] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  while ( 1 )
  {
    bzero(&s, 0x400u);//对s字符数组置零
    if ( !get_expr((int)&s, 1024) )//get_expr是对函数进行字符过滤
      break;
    init_pool(&pool);//init_pool是对数组进行置零
    if ( parse_expr((int)&s, &pool) )//parse_expr是对表达式进行运算,溢出点就在这里
    {
      printf((const char *)&unk_80BF804, v2[pool - 1]);
      fflush(stdout);
    }
  }
  return __readgsdword(0x14u) ^ v4;
}

这里s虽然只是一个字符变量,但是进了get_expr就能知道s其实存储的是我们输入的字符串

int __cdecl get_expr(int s, int a2)
{
  int v2; // eax
  char v4; // [esp+1Bh] [ebp-Dh]
  int v5; // [esp+1Ch] [ebp-Ch]

  v5 = 0;
  while ( v5 < a2 && read(0, &v4, 1) != -1 && v4 != 10 )//read负责读取一个字符,然后放入if检查
  {
    if ( v4 == 43 || v4 == 45 || v4 == 42 || v4 == 47 || v4 == 37 || v4 > 47 && v4 <= 57 )
    {
      v2 = v5++;
      *(_BYTE *)(s + v2) = v4;//如果符合条件就加入s数组
    }
  }
  *(_BYTE *)(v5 + s) = 0;//添加终止符
  return v5;
}

get_expr中的while循环就是只要字符串超过1024,或者读到终止符或者读不到字符就终止,然后只有字符等于+-*/%1234567890时才会存入s字符数组(v2和v5就是偏移量,因为s传入get_expr的是int型的首地址值),最后s末尾加上终止符

_DWORD *__cdecl init_pool(_DWORD *a1)
{
  _DWORD *result; // eax
  signed int i; // [esp+Ch] [e
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值