为什么Pwn题要注意libc版本?

2024-09-03

为什么Pwn题要注意libc版本?这个困扰了我许久的问题,今天就来解释一下

前言

之前做Pwn题目retlibc的时候,一直不懂为什么老是打不通本地。后门发现是libc版本的问题,但是为什么libc版本不同就打不通呢?今天我来解释一下

原因

libc版本不同的话,函数的偏移地址在也会不同。我们先要知道这句话。

在本地运行可执行程序的时候,默认使用的是当前系统自带的libc版本

而常常retlibc题目,会给我们一个附件libc.so.6,这是远程靶机的libc版本

在我们写exp时,我们必然会用到以下语句:

libc= ELF('./libc.so.6')
puts_libc_addr = libc.sym['puts']

libc.sym['函数']表示在是在libc中,获得指定函数的偏移地址注意这里的libc表示的是ELF(‘./libc.so.6’),也就是远程靶机的libc

而我们如果打本地的程序时,系统会使用的是本机默认的libc,函数的偏移量也是取决于本机默认libc

如果当远程靶机的libc版本和本地libc的版本不一样的时候:

由于 libc基址=函数真实地址-函数的偏移地址

一旦libc版本不同,函数的偏移地址也不同,最终求出来的libc基址也必然不同。

假设我们求通过puts函数求基址:

puts_libc_addr = libc.sym['puts'](用题目附件给的libc查找puts函数移地址)

libc_base(基址) = puts_addr(puts函数实际地址) - puts_libc_addr(puts函数偏移地址)

由于程序实际运行puts_libc_addr(puts函数偏移地址)题目附件libc.so.6查找到puts_libc_addr(puts函数偏移地址)不一样

这就使得通过exp求出来的libc基址实际运行时的libc基址不对应

换句话说,就是程序实际运行的libc基址,与远程靶机的libc基址不同

这一系列的连锁反应,也影响到后面求出的后门函数地址

如:system_addr = libc_base+system_libc_addr

后门函数在本地实际运行的地址,根本就和你通过exp求出来的后门函数地址不同,那你想打通本地,当然不可能了啊!

所以这时,就会出现远程打得通,本地打不通的情况。

结语

所以做retlibc题目出现远程打得通,本地打不通的原因,就是因为系统默认的libc版本和题目附件给的(远程靶机)libc版本不同

什么?问我这么看libc版本一不一样?

别急,马上写出来给看。