pwn学习日记Day9 基础知识积累

知识杂项

  • libc是Linux下的ANSI C的函数库。
  • LOOKUP函数
    数组形式:公式为= LOOKUP(lookup_value,array)
    式中 array—包含文本、数字或逻辑值的单元格区域或数组它的值用于与 lookup_value 进行比较。
  • str.ljust(width[, fillchar])
    1.width -- 指定字符串长度。
    2.fillchar -- 填充字符,默认为空格。
    返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串。如果指定的长度小于原字符串的长度则返回原字符串。

利用漏洞获取libc

  • 我们知道,不同版本的libc,函数首地址相对于文件开头的偏移和函数间的偏移不一定一致。所以如果题目不提供libc,通过泄露任意一个库函数地址计算出system函数地址的方法就不好使
    了。这就要求我们想办法获取目标系统的libc。
  • 关于远程获取libc,pwntools在早期版本就提供了一个解决方案——DynELF类。
  • DynELF类使用条件:
    1.目标程序存在可以泄露libc空间信息的漏洞,如read@got就指向libc地址空间内;
    2.目标程序中存在的信息泄露漏洞能够反复触发,从而可以不断泄露libc地址空间内的信息。
  • DynELF通过程序漏洞泄露出任意地址内容,结合ELF文件的结构特征获取对应版本文件并计算比对出目标符号在内存中的地址。
  • 使用DynELF时,我们需要使用一个leak函数作为必选参数,指向ELF文件的指针或者使用ELF类加载的目标文件至少提供一个作为可选参数,以初始化一个DynELF类的实例d。然后就可以通过这个实例d的方法lookup来搜寻libc库函数了。其中,leak函数需要使用目标程序本身的漏洞泄露出由DynELF类传入的int型参数addr对应的内存地址中的数据。且由于DynELF会多次调用leak函数,这个函数必须能任意次使用,即不能泄露几个地址之后就导致程序崩溃。由于需要泄露数据,payload中必然包含着打印函数,如write, puts, printf等。

write函数

  • write函数的特点在于其输出完全由其参数size决定,只要目标地址可读,size填多少就输出多少,不会受到诸如‘’, ‘ ’之类的字符影响。
  • 如果没有libc,got表里没有system,也没有int 80h/syscall,我们可以使用DynELF来leaklibc,进而获取system函数在内存中的地址。
  • 在我们需要让这个payload可以被重复使用。首先我们需要改掉write函数返回的地址,以免执行完write后程序崩溃。那么改成什么好呢?继续改成write是不行的,因为参数显然没办法继续传递。如果使用pop清除栈又会导致栈顶下降,多执行几次就会耗尽栈空间。这里我们可以把返回地址改成start段的地址,,执行完相应的代码后会跳转到程序的入口函数main运行程序代码。因此,在执行完write函数泄露数据后,我们可以返回到这里刷新一遍程序的环境,相当于是重新执行了一遍程序。

其他输出函数

  • puts的原型是puts(addr),即将addr作为起始地址输出字符串,直到遇到“x00”字符为止。也就是说,puts函数输出的数据长度是不受控的,只要我们输出的信息中包含x00截断符,输出就会终止,且会自动将“n”追加到输出字符串的末尾,这是puts函数的缺点,而优点就是需要的参数少,只有1个,无论在x32还是x64环境下,都容易调用。
  • 为了克服输入不受控这一缺点,我们考虑利用puts函数输出:的字符串最后一位为“n“这一特点,分两种情况来解决。
    1.puts输出完后就没有其他输出:
  if up == 'n' and c == "":  #接收到的上一个字符为回车符,而当前接收不到新字符,则
      buf = buf[:-1]             #删除puts函数输出的末尾回车符
      buf += "x00"
      break
  1. puts输出完后还有其他输出:
 if up == 'n' and c == "x":  #一定要找到泄漏信息的字符串特征
      data = buf[:-1]                     
      data += "x00"
      break

其他获取libc的方法

1.libcdb.com
这是一个用来在线查询libc版本的网站。这个网站的使用相当简单,只需要我们泄露出两个函数的内存地址。只要程序存在可以用来泄露内存的漏洞。
2.https://libc.blukat.me
这个网站同样可以通过泄露的地址来查询libc。我们通过给出__libc_start_main和read的地址后三位可以查到libc版本,并且查询结果还以__libc_start_main为基准给出了常用符号和所有符号的偏移。
3.在比赛中使用其他题目的libc。
如果一个题目无法获取到libc,通常可以尝试一下使用其他题目获取到的libc做题,有时候可能所有同平台的题目都部署在同一个版本的系统中。

内容来源

【技术分享】借助DynELF实现无libc的漏洞利用小结
Python ljust()方法
i春秋月刊第六期——Linux pwn零基础入门

原文地址:https://www.cnblogs.com/luoleqi/p/10809663.html