【pwn入门】用gdb调试32位程序

声明

本文是B站你想有多PWN学习的笔记,包含一些视频外的扩展知识。

问题源码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char sh[]="/bin/sh";
int func(char *cmd){
	system(cmd);
	return 0;
}

int main(){
    char a[8] = {};
    char b[8] = {};
	puts("input:");
	gets(a);  // gets函数可以读取超过8个字节的数据,然后写入a,造成越界写b
	printf(a);
	if(b[0]=='a'){ // b数组出现'a',即进入获取shell的分支
		func(sh);
	}
    return 0;
}

编译调试

编译32位的程序

说明:默认64位系统编译64位的程序,如果要编译32位需要添加-m参数,同时需要安装32位的编译支持,参考【pwn入门】基础知识

gcc -m32 question_1.c -o question_1_x86

在这里插入图片描述

直接hack

在这里插入图片描述

用gdb调试理解这个过程

  1. 反汇编main函数
    disassemble main
    可以看到32位的地址长度只有64位的一半
    在这里插入图片描述
    注意这里的0x00001362是反汇编出来的地址偏移,并不是内存中的实际地址。
  2. 获取可以打断点的内存地址
    要获取内存实际的地址,可以用x命令

在这里插入图片描述

x/40i $eip

在这里插入图片描述

  1. 打断点
b *0x56556379

在这里插入图片描述

  1. 输入8个b,一个a

在这里插入图片描述
5. 查看内存中的值
在这里插入图片描述
6. eax赋值前查看寄存器的值

没有执行赋值之前,查看eax寄存器的值
在这里插入图片描述
7. 查看执行赋值后eax的值
在这里插入图片描述
在这里插入图片描述
8. 查看程序的执行流程在这里插入图片描述9. 验证
多次执行ni命令
在这里插入图片描述

32位跟64位的区别

1.地址长度不一样
2.寄存器的名字不一样
32位中以e开头,64位中以r开头。
32位寄存器
eax:通常用来存放函数调用的返回值
esp:栈顶指针,指向栈的顶部
ebp:栈底指针,指向栈的底部,通常用ebp+偏移量的形式来定位函数存放在栈中的局部变量
eip:指针寄存器(instruction pointer) 这个寄存器保持着下一条要执行的指令的地址

64位寄存器
rax:通常用于存储函数调用返回值
rsp:栈顶指针,指向栈的顶部
rbp:存放当前栈帧的栈底地址
rip:指针寄存器(instruction pointer) 这个寄存器保持着下一条要执行的指令的地址
3.同一个源码,编译出的汇编指令不一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值