目标文件: ciscn_2019_ne_5。

来源 :https://buuoj.cn/challenges

保护情况:保护是没有保护的

主要伪代码:

int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // [esp+0h] [ebp-100h]
char src[4]; // [esp+4h] [ebp-FCh]
char v5; // [esp+8h] [ebp-F8h]
char s1[4]; // [esp+84h] [ebp-7Ch]
char v7; // [esp+88h] [ebp-78h]
int *v8; // [esp+F4h] [ebp-Ch] v8 = &argc;
setbuf(stdin, 0);
setbuf(stdout, 0);
setbuf(stderr, 0);
fflush(stdout);
*(_DWORD *)s1 = 48;
memset(&v7, 0, 0x60u);
*(_DWORD *)src = 48;
memset(&v5, 0, 0x7Cu);
puts("Welcome to use LFS.");
printf("Please input admin password:");
__isoc99_scanf("%100s", s1); // 输入密码: administrator
if ( strcmp(s1, "administrator") )
{
puts("Password Error!");
exit(0);
}
puts("Welcome!");
while ( 1 )
{
puts("Input your operation:");
puts("1.Add a log.");
puts("2.Display all logs.");
puts("3.Print all logs.");
printf("0.Exit\n:");
__isoc99_scanf("%d", &v3);
switch ( v3 )
{
case 0:
exit(0); // 退出
return;
case 1:
AddLog((int)src); // 输入
break;
case 2:
Display(src); // 删除输入的
break;
case 3:
Print();
break;
case 4:
GetFlag(src); // 将输入的输出
break;
default:
continue;
}
}
}
int __cdecl AddLog(int a1)
{
printf("Please input new log info:");
return __isoc99_scanf("%128s", a1);
}
int __cdecl GetFlag(char *src)
{
char dest[4]; // [esp+0h] [ebp-48h]
char v3; // [esp+4h] [ebp-44h] *(_DWORD *)dest = 48;
memset(&v3, 0, 0x3Cu);
strcpy(dest, src);
return printf("The flag is your log:%s\n", dest);
}

GetFlag的栈结构示意

其它信息:

或者这个 "sh" 字符串也可以用其他方式找到:

调试目标 :构造GetFlag函数的栈溢出并借此开启一个shell。

先打上至少一个断点,不然待会干啥的白瞎

也可以直接对函数名下断点(如果程序没开PIE的话)

我将程序的执行断在了call进GetFlag前:

很明显,0xFFFFD3FC就是输入字符串的保存地,0x804891B是这个call的返回值。

用 "s"命令跟进这个call,直到抬栈完毕。( 想步过这个call的话用  "n"就好。)

先看看栈:

GetFlag函数中有个字符拷贝的行为,从GetFlag函数的栈顶开始写入0xFFFFD3FC之后的内容直到被 0 截断为止。

GetFlag函数的栈容量只有0x48个字节,再往后就是原 EBP 和返回值

思路:将GetFlag函数的返回值覆盖为system函数的地址 ,并在其后写入字符串 "sh"的地址 0x80482EA

接下来是利用 set 命令修改内存,但 set 命令一修改就是四个字节,有时候并不算太方便。

改原 EBP 到没什么讲究,只要四字节中没有为零的就好。

然后是覆盖返回值

这个不重要,占位子的,四字节中没有为零的就好

写入参数地址

至此,GetFlag的栈已经构造完成:

下面就是放飞自我的时候了( "go" 命令 :直接执行的下一个断点(但在这里是不可能的了)):

可以看到程序已经崩溃,并且如愿开启了shell。

记一次GDB调试的更多相关文章

  1. 用gdb调试python多线程代码-记一次死锁的发现

    | 版权:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.如有问题,可以邮件:wangxu198709@gmail.com 前言 相信很多人都有 ...

  2. Linux学习----gdb调试(指针的指针)

    昨天遇到一个很奇怪的问题,如下: 按照理论,最后*p的值应该是99,不知为什么是15了,所以今天记录用gdb调试的过程,并熟悉gdb的使用. (调试过程参考:http://www.cnblogs.co ...

  3. GDB调试实用命令

    个人感觉从windows平台转到linux平台一个不适应的地方就是调试器的使用.因为windows下调试器基本上都依赖快捷键和图像界面来完成操作,就算是windbg这种伪命令行的工具,命令也很简单比较 ...

  4. GDB调试命令小结

    1.启动调试 前置条件:编译生成执行码时带上 -g,如果使用Makefile,通过给CFLAGS指定-g选项,否则调试时没有符号信息.gdb program //最常用的用gdb启动程序,开始调试的方 ...

  5. GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 分析过程 这是我的C源文件:click here 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb ...

  6. gdb调试器的使用

    想要使用gdb调试程序的话,首先需要gcc -g main.c -o test 然后运行gdb test对程序进行调试 l (小写的l,是list的首字母),用以列出程序 回车    是运行上一个命令 ...

  7. 20145212——GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 测试代码 #include <stdio.h> short val = 1; int vv = 2; int g(int xxx) { return xxx + ...

  8. gdb调试PHP扩展错误

    有时候,使用PHP的第三方扩展之后,可能会发生一些错误,这个时候,可能就需要更底层的方式追踪调试程序发生错误的地方和原因,熟悉linux下C编程的肯定不陌生gdb 首先,使用ulimit -c命令,查 ...

  9. gdb调试汇编堆栈过程的学习

    gdb调试汇编堆栈过程的学习 以下为C源文件 使用gcc - g code.c -o code -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器: 进入之 ...

随机推荐

  1. 《Head First 设计模式》:外观模式

    正文 一.定义 外观模式提供了一个统一的接口,用来访问子系统中的一群接口.外观定义了一个高层接口,让子系统更容易使用. 要点: 外观模式将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外 ...

  2. 区块链入门到实战(32)之Solidity – 代码注释

    Solidity 支持c风格和c++风格的注释. //之后到行尾的文本,都被看作注释,编译器忽略此内容 /* 与 */ 之间的文本被看作注释, 编译器忽略此内容 示例 注释示例. function g ...

  3. 前端 的一些css的写法

    攒一下小技巧 1.select 默认提示但是不显示在选择列表中 <option selected="selected" disabled="disabled&quo ...

  4. Mac包管理神器:Home-brew

    最近看到一个大神修改的Homebrew国内脚本,安装非常方便,以前使用国外的经常下载不下来,这个感觉是非常快的. Homebrew 国内自动安装脚本 ,修改原脚本中的 clone 操作为“浅拷贝”(- ...

  5. idea 执行maven打包命令时,修改war包名称

  6. 正则表达式断言精讲 Java语法实现

    目录 断言 1.2.3.1 情景导入 什么是断言 断言的语法规则 零宽断言为什么叫零宽断言 零宽 前行 负向 断言DEMO 断言的基础应用和实际用处 验证不包含 验证开头包含 验证开头包含且匹配到的数 ...

  7. Unity坑之 传递默认枚举类型参数

    今天在编写一个通用模块的时候,遇到一个奇怪的问题,vs编译时没有任何问题,但是轮到unity编译时,却报错: error CS0103: The name `PrintInt' does not ex ...

  8. Java垃圾回收略略观

    本文主要介绍Java垃圾回收(Garbage Collection),90%干货,文字颇多,需要耐心一点看. [对象判断状态算法] ------引用计数法 在创建对象时,为对象创建一个伴生的引用计数器 ...

  9. 转载:记录一次MySQL两千万数据的大表优化解决过程

    地址:https://database.51cto.com/art/201902/592522.htm 虽然是广告文,但整体可读性尚可.

  10. java 将本地文件或网络文件与base64互相转换

    一:将网络文件转为Base64 将文件转为base64 public static String fileToBase64(String url){ int byteread = 0; String ...