当前位置: 首页 > news >正文

【C语言】SCU安全项目2-BufBomb

目录

关键代码解读:

getxs()

getbuf()

test()

核心思路

具体操作1

具体操作2


前段时间忙于强网杯、英语4级和一些其他支线,有点摸不清头绪了,特别是qwb只有一个输出,太过坐牢,决定这个安全项目做完后就继续投身web的修炼,向C语言暂时说拜拜!!!

前置知识:

C语言函数调用栈

贴出源码:

/* bufbomb.c** Bomb program that is solved using a buffer overflow attack** program for CS:APP problem 3.38** used for CS 202 HW 8 part 2** compile using*   gcc -g -O2 -Os -o bufbomb bufbomb.c*/#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>/* Like gets, except that characters are typed as pairs of hex digits.Nondigit characters are ignored.  Stops when encounters newline */
char* getxs(char* dest)
{int c;int even = 1; /* Have read even number of digits */int otherd = 0; /* Other hex digit of pair */char* sp = dest;while ((c = getchar()) != EOF && c != '\n') {if (isxdigit(c)) {int val;if ('0' <= c && c <= '9')val = c - '0';else if ('A' <= c && c <= 'F')val = c - 'A' + 10;elseval = c - 'a' + 10;if (even) {otherd = val;even = 0;}else {*sp++ = otherd * 16 + val;even = 1;}}}*sp++ = '\0';return dest;
}int getbuf()
{char buf[16];getxs(buf);return 1;
}void test()
{int val;printf("Type Hex string:");val = getbuf();printf("getbuf returned 0x%x\n", val);
}int main()
{int buf[16];/* This little hack is an attempt to get the stack to be in astable position*/int offset = (((int)buf) & 0xFFF);int* space = (int*)malloc(offset);*space = 0; /* So that don't get complaint of unused variable */test();return 0;
}

关键代码解读:

getxs()

这段代码定义了一个函数 getxs,它接受一个参数 dest,类型为 char*。函数的作用是从标准输入中读取一串十六进制数字,并将其转换为对应的字符序列,最后将结果存储在 dest 指向的内存空间中。

代码中使用了一个 while 循环来逐个读取输入的字符,直到遇到文件结束符(EOF)或换行符('\n')为止。在循环体内部,首先判断当前字符是否是一个十六进制数字,这由 isxdigit 函数来判断。

如果是十六进制数字,根据其值计算出对应的十进制数。如果当前已经读取了偶数个数字,则将该数字保存在 otherd 变量中,并将 even 标志位设置为 0,表示下一个数字是一个新的十六进制数字的开始。如果当前已经读取了奇数个数字,则将 otherd 乘以 16 并加上当前数字的值,将结果存储在 sp指向的内存空间中,sp指向地址增加一个字节,并将 even 标志位设置为 1。

循环结束后,将字符串的终止符 '\0' 存储在sp 指向的内存空间中,并返回指向 dest 的指针作为函数的返回值。

总而言之,这段代码实现了将输入的十六进制数字转换为字符序列的功能。

比如想输入deadbeef,则要输入efbeadde(小端存储,不解释)

getbuf()

 先是定义一个16个字节长度的字符型数组,讲数组首地址传入getxs函数,最后返回一个1。

这里就存在一些栈溢出的手段,暂按不表。

test()

定义了一个整形变量val,打印"Type Hex string",将val赋值为getbuf()的返回值(这里为1),最后将val的16进制型打印出。如果我们放任不管的话,无论输入什么值,因为无法改变getbuf()的返回值,所以回显一定如下。

但实验要求是让我们输出getbuf returned 0xdeadbeef,我们该怎么入手呢?

核心思路

以我浅薄的C语言能力应该无法修改getbuf的返回值为deadbeef,所以想到可以利用栈溢出的方式跳过val的赋值语句,直接运行第二个printf函数,而val的值也通过溢出覆盖为期望的deadbeef。

而buf[16]和getxs函数的配合恰好可以满足我们搞破坏的需求。

一行输入的内容超过了16字节,getxs并不会停止读入,此时的读入已经超出了数组范围(数组访问越界),从而实现覆写改变高地址处内容。

具体修改什么内容呢?

主要有两个部分:getbuf()函数的返回地址(从而直接跳转到第二个printf,不执行赋值操作)和val的初始值

具体操作1

设个断点开始调试,进入test函数

看寄存器状态,得知EBP地址为0019FDB4

看一眼 EBP地址里存的内容为0019FEE8(原原EBP地址,即test函数栈帧的原EBP地址——main函数的EBP地址,这里其实不太严谨,但为了后续方便表述所以用了两个原)

再看内存中val的地址,为0019FDAC

(内容是cccccccc说明val变量还未初始化)

看汇编代码得知val赋值语句和第二个printf的地址分别为004119D7,004119DA

 到此为止我们可以先用表格做个总结

 

具体操作2

跟进调试,进入getbuf函数,栈帧切换为getbuf

 看一眼寄存器,发现新EBP地址为0019FCD4

在内存里查看新BEP地址里存的值,发现为原EBP地址(即test函数栈帧EBP地址)0019FDB4

 看一下0019FDB8和0019FDBC里存的值,发现分别是val赋值语句的函数返回地址(004119D7)和原原EBP地址(0019FEE8)。

这里凡是相关EBP地址的内容我们都不能改,不然会报错,但是函数返回值可以任由我们操纵。

我们可以把0019FDB8的值由004119D7改为004119DA,这样就可以跳过赋值语句直接printf。

最后再看一眼buf数组的首地址为0019FCC0,因为是16个char,所以占四字节

 我们可以用表格模拟当前栈的分布情况

最终payload:

12345678 12345678 12345678 12345678 12345678 B4FD1900 DA194100 E8FE1900 12345678 12345678 12345678 12345679 12345680 12345681 12345682 12345683 12345684 12345685 12345686 12345687 12345688 12345689 12345690 12345691 12345692 12345693 12345694 12345695 12345696 12345697 12345698 12345699 12345700 12345701 12345702 12345703 12345704 12345705 12345706 12345707 12345708 12345709 12345710 12345711 12345712 12345713 12345714 12345715 12345716 12345717 12345718 12345719 12345720 12345721 12345722 12345723 12345724 12345725 12345726 efbeadde

 

没学过几天C语言的我都能做出,相信优秀的你们一定也没问题!!!!

再见,安全项目QWQ

http://www.lryc.cn/news/263739.html

相关文章:

  • C++第一讲之初入C++
  • 如何实现公网访问本地内网搭建的WBO白板远程协作办公【内网穿透】
  • js知识点1:防抖节流
  • 虚拟机下Ubuntu上网设置
  • Unity3d C#利用Editor编辑器拓展实现配置UI背景样式一键设置UI背景样式功能(含源码)
  • 【微服务】服务间调用
  • 一句话分清C/C++声明和定义
  • 《哥德尔证明》阅读笔记——初等命题逻辑的一致性证明过程
  • 迪文屏开发保姆级教程—弹出键盘录入ASCII字符
  • Java,处理字符串的案例()
  • 微信小程序更新机制
  • CentOS 7 部署 Nacos-2.3.0 (单机版)
  • Springboot优雅实现对接口返回统一封装
  • Kafka 安装与部署
  • 计算 N*4*4 位姿形状的逆变换,在N*3*4位姿后补充 [0,0,0,1]
  • 人工智能可以战胜人类智慧大脑么?
  • 【数据结构和算法】 K 和数对的最大数目
  • 基于ssm高校推免报名系统源码和论文
  • 算法设计与分析2023秋-头歌实验-实验七 动态规划
  • 复杂 SQL 实现分组分情况分页查询
  • JavaScript---如何完美的判断返回对象是否有值
  • kafka offset sasl加密连接
  • Android studio矩形背景颜色以及弧度的设置
  • Acrel-1000DP分布式光伏系统在某重工企业18MW分布式光伏中应用——安科瑞 顾烊宇
  • 3 python基本语法 - Dict 字典
  • Magnific AI:彻底改变 AI 生成图像的升级
  • BKP 备份寄存器 RTC 实时时钟-stm32入门
  • 1.1 数据结构-数据的表示
  • UNIX Linux系统 启动PPOCRLabel报错[已放弃 (核心已转储)]
  • 前端开发中的webpack打包工具