热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

GDB动态调试攻防世界SimpleCheck100

文章目录题目IDA静态分析gdb动态调试gdb基本使用gdbpeda插件函数校验绕过总结题目攻防世界Reverse高手区题目链接simple-check-100,如

文章目录

  • 题目
  • IDA静态分析
  • gdb动态调试
    • gdb 基本使用
    • gdb peda插件
    • 函数校验绕过
  • 总结


题目

攻防世界 Reverse 高手区题目链接 simple-check-100,如下:
在这里插入图片描述解压缩得到三个文件:
在这里插入图片描述三个文件依次是一个 32 位 elf,一个 64 位 elf 和一个 32 位 exe。

ELF 文件 (Executable Linkable Format) 是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。Linux 下的目标文件和可执行文件都按照该格式进行存储,它是 Linux 的主要可执行文件格式。


IDA静态分析

1、查壳发现未加壳:
在这里插入图片描述
2、这 3 个文件拖进 IDA 后的反汇编结果是大体一致的,以 64 位 elf 文件为例进行分析,定位到 main 函数:
在这里插入图片描述3、按 F5 查看反汇编结果的的 C 语言伪代码:
在这里插入图片描述完整代码如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{void *v3; // rspconst char **v5; // [rsp+0h] [rbp-60h] BYREFint v6; // [rsp+Ch] [rbp-54h]char v7[28]; // [rsp+1Ch] [rbp-44h] BYREF__int64 v8; // [rsp+38h] [rbp-28h]const char ***v9; // [rsp+40h] [rbp-20h]unsigned __int64 v10; // [rsp+48h] [rbp-18h]v6 = argc;v5 = argv;v10 = __readfsqword(0x28u);v7[0] = 84;v7[1] = -56;v7[2] = 126;v7[3] = -29;v7[4] = 100;v7[5] = -57;v7[6] = 22;v7[7] = -102;v7[8] = -51;v7[9] = 17;v7[10] = 101;v7[11] = 50;v7[12] = 45;v7[13] = -29;v7[14] = -45;v7[15] = 67;v7[16] = -110;v7[17] = -87;v7[18] = -99;v7[19] = -46;v7[20] = -26;v7[21] = 109;v7[22] = 44;v7[23] = -45;v7[24] = -74;v7[25] = -67;v7[26] = -2;v7[27] = 106;v8 = 19LL;v3 = alloca(32LL);v9 = &v5;printf("Key: ");__isoc99_scanf("%s", v9);if ( (unsigned int)check_key(v9) )interesting_function(v7);elseputs("Wrong");return 0;
}

可以看到,程序的核心是让输入一个字符串,然后使用 check_key 函数进行判断,如果返回非 0(为真),则执行 interesting_fuction 函数。

4、双击跟进查看 interesting_fuction 函数伪代码:
在这里插入图片描述该函数对输入的 v7(未知)进行加密处理,最后 putchar 输出。

5、check_key 函数是一个计算校验和与正确的校验和对比的一个函数:
在这里插入图片描述
解题思路

只要让程序绕过 check_key 函数的检查,强行执行 interesting_function 函数,就能获得目标 Flag。故可以对程序进行动态调试,将 check_key 的返回结果改为 1,就能调用 interesting_function 函数并得到正确的 key。

gdb动态调试

GDB (GNU Debugger)是一个由 GNU 开源组织发布的、UNIX/LINUX 操作系统下的、基于命令行的、功能强大的程序调试工具。像所有的调试器一样,GDB 可以让你调试一个程序,包括让程序在你希望的地方停下,此时你可以查看变量、寄存器、内存及堆栈,更进一步你可以修改变量及内存值。对于一名 Linux 下工作的 C/C++ 程序员或逆向工作者,gdb 是必不可少的工具。

基础使用教程:linux下gdb调试方法与技巧整理、CTF 竞赛入门指南(CTF All In One)。


gdb 基本使用

gdb 的常用命令如下:
在这里插入图片描述
本人在自己的 VPS 服务器(Centos8)上安装 gdb,步骤如下:

#安装C++编译器
yum install gcc gcc-c++
#下载源码包
wget http://ftp.gnu.org/gnu/gdb/gdb-10.2.tar.gz
#编译安装
tar -zxvf gdb-10.2.tar.gz
cd gdb-10.2
./configure --with-python=/usr/bin/python --enable-targets=all
make
sudo make install
#查看是否安装成功
gdb -v

注意防坑】编译 gdb 时必须加上--with-python参数指定本地的 Python 路径,否则后续使用 gdb 插件时将各种报错(为此我浪费了整整一天……最终参照 博文 找到了该解决的办法)。

如下已成功安装 gdb 工具:
在这里插入图片描述
GDB基础用法演示

下面给出一个具有 test.c 的程序:

#include
int getSum(int n) {int sum&#61;0,i;for (i&#61;1;i<&#61;n;i&#43;&#43;)sum&#43;&#61;i;return sum;
}
int main(){int res&#61;getSum(100);printf("1&#43;2&#43;...&#43;100&#61;%d\n",res);
}

1、使用 gcc 编译 C 语言程序&#xff1a;
在这里插入图片描述
【注意】如果要调试程序&#xff0c;则在进行 gcc 编译的时候要加上 -g 参数&#xff08;表示 debug 模式&#xff09;&#xff0c;即gcc -g test.c -o test (如果是 C&#43;&#43; 程序的话则是g&#43;&#43; -g test.cpp -o test&#xff09;。如果没有 -g 参数&#xff0c;你将看不见程序的函数名、变量名&#xff0c;所代替的全是运行时的内存地址。

2、执行命令 gdb test&#xff0c;开始使用 GDB 对生成的 test 可执行程序进行调试&#xff08;GDB 会显示自己的提示符 gbd&#xff0c;提示并等待你输入调试命令&#xff09;&#xff1a;
在这里插入图片描述3、输入l命令&#xff08;相当于 list&#xff09;&#xff0c;gdb 将从第一行开始列出源码&#xff08;默认前 10 行&#xff09;&#xff1a;
在这里插入图片描述
直接回车表示&#xff0c;重复上一次命令&#xff08;继续输出第 10-20 行的源码&#xff09;&#xff1a;
在这里插入图片描述
4、执行命令break 9break getSum&#xff0c;表示在第 9 行处、getSum 函数处设置断点&#xff0c;同时执行命令info break可查看设置的断点信息&#xff1a;
在这里插入图片描述
5、执行命令run(简写 r) &#xff0c;开始从头运行程序&#xff0c;直到程序结束或者遇到断点并等待下一个命令&#xff1a;
在这里插入图片描述
6、执行命令 continue&#xff08;简写 c&#xff09;&#xff0c;表示从暂停处继续运行程序&#xff1a;
在这里插入图片描述
7、执行 step 命令&#xff0c;表示向前执行一步&#xff08;可进入被调用函数中&#xff09;&#xff0c;进一步可利用 print i&#xff08;变量名&#xff09;来查看变量的值&#xff1a;
在这里插入图片描述
8、执行命令 backtrace&#xff08;简写 bt&#xff09;&#xff0c;可查询当前函数调用栈&#xff0c;执行命令 finish&#xff0c;可退出当前函数并返回到上层函数中&#xff08;本例为 main 主函数&#xff09;&#xff1a;
在这里插入图片描述
9、执行命令set res &#61; 6666&#xff0c;可改变程序中指定变量的值&#xff1a;
在这里插入图片描述
10、info reg 命令可查看寄存器使用情况&#xff0c;info stack命令可查看堆栈使用情况&#xff1a;
在这里插入图片描述
最后执行命令 quit&#xff08;简写 q&#xff09;&#xff0c;即可退出 gdb&#xff1a;
在这里插入图片描述
而未被篡改变量值的程序正常的运行输出应当如下&#xff1a;
在这里插入图片描述

gdb peda插件

从上面的演示实例中也可以看出&#xff0c;gdb 非常强大&#xff0c;但是在调试过程中对于需要查看的辅助信息&#xff08;如寄存器信息&#xff09;都要手动输入命令&#xff0c;未免有点麻烦&#xff0c;所以就出现了插件&#xff0c;把某一些经常要查看的信息每一步都自动帮你显示出来&#xff0c;方便调试。一般来说有常用的 3 个 GDB 插件&#xff1a;peda、gef、gdbinit。
&#xff0c;完整介绍可参见&#xff1a;GDB的三个插件&#xff08;gef gdbinit peda&#xff09;。Github 上已经有人把这 3 个插件的项目合成了一个&#xff0c;使得插件的安装使用很方便&#xff1a;

# 从 Github 将汇聚了 gdb 的 3 个插件的项目拷贝到本地
git clone https://github.com/gatieme/GdbPlugins.git ~/GdbPlugin
# GdbPlugins 文件夹包含的 3 个插件对应启动命令&#xff1a;
echo "source ~/GdbPlugins/peda/peda.py" > ~/.gdbinit
echo "source ~/GdbPlugins/gef/gef.py" > ~/.gdbinit
echo "source ~/GdbPlugins/gdbinit/gdbinit" > ~/.gdbinit

成功克隆到本地后可以看到包含 3 个插件的文件夹&#xff1a;
在这里插入图片描述
下文将介绍其中的 peda 插件——peda 是 gdb 调试工具的插件&#xff0c;用于增强 gdb 的调试能力&#xff0c;同时增强 gdb 的显示&#xff1a;在调试过程中着色并显示反汇编代码&#xff0c;寄存器和内存信息&#xff08;单纯的 gdb 在内存信息、汇编信息的显示和查看上的不方便&#xff09;。

1、设置 gdb 以 peda 插件的执行形式启动&#xff0c;并调试上面编译好的 test 程序&#xff1a;
在这里插入图片描述
2、输入 start 命令开始调试程序&#xff0c;从下图中可以看到寄存器 (registers)&#xff0c;汇编代码 (code)&#xff0c;栈空间数据 (stack) 等信息&#xff1a;
在这里插入图片描述

在前面的文章 浅析缓冲区溢出漏洞的利用与Shellcode编写 中曾经介绍了函数调用过程中的内存堆栈变化&#xff0c;建议读者同步阅读博文 基于GDB-peda汇编调试理解函数调用栈 &#xff0c;作者利用 peda 插件来汇编调试一段程序&#xff0c;帮助深入理解函数调用栈。

函数校验绕过

返回到 CTF 题目中&#xff0c;在 Linux 中正常运行程序如下&#xff1a;
在这里插入图片描述
下面开始借助 gdb 对程序进行动态调试&#xff0c;将 check_key 函数的返回结果改为真即可正确的 key。

1、启动 gdb 调试程序&#xff0c;执行命令 break main 在 main 函数设置断点&#xff08;Breakpoint 1 at 0x4007c0&#xff09;&#xff0c;然后执行命令 run 开始运行程序&#xff1a;
在这里插入图片描述程序暂停在断点处&#xff1a;
在这里插入图片描述

2、上述程序暂停在 main 函数断点处&#xff0c;执行命令 next 开始一步步单步执行程序&#xff08;一直按回车键重复执行 next 命令即可&#xff09;&#xff0c;直到运行至 check_key 函数所在位置&#xff0c;随意输入 key 之后会有判断函数&#xff0c;所以注意看 check_key 所在位置&#xff1a;
在这里插入图片描述3、当判断函数执行完之后&#xff0c;再次跳到test eax, eax时候&#xff0c;可以用printi $eax查看寄存器的值&#xff0c;发现是 0&#xff1a;
在这里插入图片描述4、这样的话不会跳转藏有 flag 函数的位置&#xff0c;所以执行命令 set $eax&#61;1&#xff0c;手动篡改寄存器 eax 的值&#xff0c;最后执行命令 continue&#xff0c;运行程序直至程序终止&#xff0c;可获得 flag 值如下&#xff1a;
在这里插入图片描述提交 flag&#xff0c;over&#xff01;
在这里插入图片描述

总结

本文通过一道 CTF 题目&#xff0c;学习记录了 GDB 调试工具及其 peda 插件的使用&#xff0c;实现了对二进制程序的内存数值进行篡改并成功绕过程序的逻辑校验的目的&#xff0c;这有点类似于 Android 中使用 Frida 对 APP 的函数返回值进行 hook 拦截和篡改。


推荐阅读
  • 本报告记录了嵌入式软件设计课程中的第二次实验,主要探讨了使用KEIL V5开发环境和ST固件库进行GPIO控制及按键响应编程的方法。通过实际操作,加深了对嵌入式系统硬件接口编程的理解。 ... [详细]
  • Gradle 是 Android Studio 中默认的构建工具,了解其基本配置对于开发效率的提升至关重要。本文将详细介绍如何在 Gradle 中定义和使用共享变量,以确保项目的一致性和可维护性。 ... [详细]
  • 视觉Transformer综述
    本文综述了视觉Transformer在计算机视觉领域的应用,从原始Transformer出发,详细介绍了其在图像分类、目标检测和图像分割等任务中的最新进展。文章不仅涵盖了基础的Transformer架构,还深入探讨了各类增强版Transformer模型的设计思路和技术细节。 ... [详细]
  • binlog2sql,你该知道的数据恢复工具
    binlog2sql,你该知道的数据恢复工具 ... [详细]
  • 本文详细介绍了如何在CentOS 6.5系统上安装和配置Redis 3.0.6,包括必要的环境准备、软件包下载、编译安装及基本功能测试。 ... [详细]
  • 本文探讨了如何在PHP与MySQL环境中实现高效的分页查询,包括基本的分页实现、性能优化技巧以及高级的分页策略。 ... [详细]
  • 如何高效学习鸿蒙操作系统:开发者指南
    本文探讨了开发者如何更有效地学习鸿蒙操作系统,提供了来自行业专家的建议,包括系统化学习方法、职业规划建议以及具体的开发技巧。 ... [详细]
  • Excel技巧:单元格中显示公式而非结果的解决方法
    本文探讨了在Excel中如何通过简单的方法解决单元格显示公式而非计算结果的问题,包括使用快捷键和调整单元格格式两种方法。 ... [详细]
  • 本文探讨了如何使用Scrapy框架构建高效的数据采集系统,以及如何通过异步处理技术提升数据存储的效率。同时,文章还介绍了针对不同网站采用的不同采集策略。 ... [详细]
  • 本文详细介绍了MySQL InnoDB存储引擎中的Redo Log和Undo Log,探讨了它们的工作原理、存储方式及其在事务处理中的关键作用。 ... [详细]
  • 本文介绍了如何使用 Python 的 Pyglet 库加载并显示图像。Pyglet 是一个用于开发图形用户界面应用的强大工具,特别适用于游戏和多媒体项目。 ... [详细]
  • 本文探讨了Linux环境下线程私有数据(Thread-Specific Data, TSD)的概念及其重要性,介绍了如何通过TSD技术避免多线程间全局变量冲突的问题,并提供了具体的实现方法和示例代码。 ... [详细]
  • 汇总了2023年7月7日最新的网络安全新闻和技术更新,包括最新的漏洞披露、工具发布及安全事件。 ... [详细]
  • Fiddler 安装与配置指南
    本文详细介绍了Fiddler的安装步骤及配置方法,旨在帮助用户顺利抓取用户Token。文章还涵盖了一些常见问题的解决方案,以确保安装过程顺利。 ... [详细]
  • td{border:1pxsolid#808080;}参考:和FMX相关的类(表)TFmxObjectIFreeNotification ... [详细]
author-avatar
陈怡伶翰纬
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有