Closed ghost closed 6 years ago
Thanks for the issue. I will look into it. It is important for the library to allocate memory that is within 2GB offset of the target function if the replaced instructions are RIP-relative, but I cannot find a good way to make the OS to allocate a chunk of memory as near as possible to a given address. Any idea?
As is discussed in this, one way is to parse the mapping info file. Another way is to check if pages are mapped one by one. Either way is complicated.
why not alloc the func in heap for alloc patch for exe,and mmap to alloc func for shared library patch
the heap seems to be always mapped after the address where the exe mapped.and the shared library is always mapped at 0x7ffff...(64bit address),when i called mmap.it always create a mapping at 0x7ffff...(64bit address)
heap每次似乎都会在elf映射地址之后映射,所以在heap里分配patch似乎是最佳方案。共享库每次都在0x7ffff....装入,每次mmap如果不指定地址,好像会在0x7ffff...创建映射,而且每次映射的起始地址抵减
不知道我的理解对不对,您的意思是用malloc来申请func的空间?用heap的话会依赖于malloc(glibc),有几个问题: 第一,把用于malloc的堆内存改为executable属性似乎不是很好,也许会存在安全问题? 第二,如果用户hook了malloc和它内部的函数,而pfishhook又调用了malloc,会不会出现无限递归?这个库目前只依赖于mmap 第三,用堆malloc也就无法控制分配内存的地址?
谢谢您提出的意见!
您的意思是不是heap的地址和executable image的地址相近;而mmap默认地址和shared lib的地址相近?这样似乎可以用brk来分配空间?
您的意思是不是heap的地址和executable image的地址相近;而mmap默认地址和shared lib的地址相近?这样似乎可以用brk来分配空间?
是的
heap总是会映射到executable image地址之后,对于executable image的话,最简单的方法应该是在堆上分配,直接brk可能会破坏程序堆结构?
我这里大多数程序都在0x555555554000处开始映射,也许可以在其之前来分配
如果要读取/proc/self/maps的话又要依赖read,,,
user_desc sb; syscall(SYS_modify_ldt,0,&sb,sizeof(sb)); printf("%p\n",sb.base_addr); 这个应该是可以读取起始地址的
似乎只能brk了,malloc分配的内存既可能在brk分配的页中,也可能在mmap分配的页中,具体在哪里是基于malloc库实现的
PR里有一个不依赖malloc和brk的实现
你手头是什么系统啊?为什么我的程序text段都是加载在低32位地址的?你的PR似乎在我的系统Ubuntu16.04/Linux 4.13.0-37-generic 没有获得正确的.text地址。详见PR里的comment
Ubuntu18 4.15.0-33-generic 我的都加载在高位,而且奇怪的是我现在也无法获得.text,直接读取失败
现在最稳妥的是读/proc/self/maps,但是依赖又太多,或许可以直接syscall来绕过glibc的包装
谢谢bug fix了,我在你的基础上commit了一些fix 另外我比较好奇,你是用这个库开发其他软件还是至是单纯做研究呀?你是第一个给我提bug issue的人,蛮开心的
给一个游戏服务器搞hook实现mod,这个主要是别人在搞,我也研究了一下
😆这个库有人用了,蛮开心的
感觉可以直接在ELF装入地址前256MB或者后2GB-256MB,0x7ffff..各映射一个256MB的页面,一个放ELF补丁,一个放库的,可以省了memchunk的逻辑和mmap调用次数。 因为linux的lazy机制,似乎mmap的256MB内存,只要不写入,就不会实际占用内存空间
但是似乎灵活性上会有欠缺吧?
比如?
或者给为elf或lib的patch映射这两个区域 如果遇到了最特殊的情况(比如给jit生成的机器码打patch,两块区域都不符合要求)再单独mmap。但是因为suggest address的问题 mmap的实际地址还是会成为0x7fffff..(因为指定地址已经被映射),然后回退到尝试在elf之前映射,事实上,和在elf前先映射256MB是一样的
这样应该可以
意思是说 这样的效果实际上是和不改是一样的,但是减少了mmap次数,可以不用memchunk的逻辑
或者给为elf或lib的patch映射这两个区域 如果遇到了最特殊的情况(比如给jit生成的机器码打patch,两块区域都不符合要求)再单独mmap。但是因为suggest address的问题 mmap的实际地址还是会成为0x7fffff..(因为指定地址已经被映射),然后回退到尝试在elf之前映射,事实上,和在elf前先映射256MB是一样的
如果mmap的hint地址被占用,理论上linux会选择最近的地址,而并不是如你所说直接忽略的。但是实际运行的时候好像对于低地址之类的地址会忽略hint。我的意思是预先分配两块区域ok,但是原有的单独mmap的逻辑还是要有,就是如果hooked function离两块区域都很远的话要fallback到单独mmap,多一次尝试机会。
mmap(addr, ALLOC_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS... When addr is in a mapped address range, addr will seem to be ignored. For example,call mmap(0x55555555f6df,4096,7,34,-1,0)=(void *) 0x7ffff7ff6000 because address 0x555555554000-0x5555555ae000 has mapped. then AddressDiff(chunk, addr) >= ((1ULL << 31) - 1) and cause a AllocError