-
-
[原创] 关于不同版本glibc强行加载的方法(附上代码)
-
2018-4-10 15:13
34338
-
[原创] 关于不同版本glibc强行加载的方法(附上代码)
2018/6/11 更新:https://github.com/matrix1001/welpwn 已集成
各路大佬看到这题目就知道我说的是个困扰pwn选手多年的问题,不知道大家有没有解决这个问题,反正我是强行解决了。
TODO:
1. 自行下载glibc 2.23/2.24/2.25/2.26 源码并编译
2. 将所需要使用到版本的ld.so放在pwn题目录下
3. 跑这个代码
def change_ld(binary, ld):
"""
Force to use assigned new ld.so by changing the binary
"""
if not os.access(ld, os.R_OK):
log.failure("Invalid path {} to ld".format(ld))
return None
if not isinstance(binary, ELF):
if not os.access(binary, os.R_OK):
log.failure("Invalid path {} to binary".format(binary))
return None
binary = ELF(binary)
for segment in binary.segments:
if segment.header['p_type'] == 'PT_INTERP':
size = segment.header['p_memsz']
addr = segment.header['p_paddr']
data = segment.data()
if size <= len(ld):
log.failure("Failed to change PT_INTERP from {} to {}".format(data, ld))
return None
binary.write(addr, ld.ljust(size, '\0'))
if not os.access('/tmp/pwn', os.F_OK): os.mkdir('/tmp/pwn')
path = '/tmp/pwn/{}_debug'.format(os.path.basename(binary.path))
if os.access(path, os.F_OK):
os.remove(path)
info("Removing exist file {}".format(path))
binary.save(path)
os.chmod(path, 0b111000000) #rwx------
success("PT_INTERP has changed from {} to {}. Using temp file {}".format(data, ld, path))
return ELF(path)
#example
elf = change_ld('./pwn', './ld.so')
p = elf.process(env={'LD_PRELOAD':'./libc.so.6'})
用法很简单,参数第一个可以是ELF,可以是路径,第二个必须是ld.so的路径(最好放在当前文件夹,原因后面讲)。返回值我自己方便用所以是ELF,不喜欢的自己改成path,这个不会改变你原来的文件,只是建立一个修改的副本放在/tmp/pwn里面
4. 不用LD_PRELOAD则加载 源码级 libc(调libc=调源码? 存在的) 或者 使用LD_PRELOAD加载给定的libc
原理:
PT_INTERP这是个神秘的东西,这个是编译的时候就硬编码好的东西,值是'/lib/ld-linux.so.2' ,其实这个就是万恶的ld了,程序加载的时候,首先进去的不是_start处的代码,而是先加载执行PT_INTERP指向的程序,ld在加载后会给程序加载libc,最后再执行程序的代码。
但是在改的时候,是有长度限制的,代码已经写好了,所以将ld.so放当前文件夹就不会出错。
所以说,利用LD_PRELOAD直接加载不同版本的libc,会由于libc和ld匹配不上而出错。
望各路大佬指正。
议题征集启动!看雪·第七届安全开发者峰会
最后于 2018-6-11 11:52
被matrixIOOI编辑
,原因: