问题描述
我想通过挂钩修改ELF文件的二进制的.text功能,我的意思是更换一个指令,如BL XXXX与BL YYYY中,YYYY被点到的ELF文件中的填充区域。跳转后,我保存寄存器和调用的dlopen&安培;对dlsym获得新功能的地址另一个LIB的,调用它,然后恢复寄存器和跳回XXXX。
I want to hook a function by modify elf file's .text binary, my mean is replace an instruction like 'bl xxxx' with 'bl yyyy', the 'yyyy' is point to an padding area in elf file. After jump, I save the registers and call dlopen&dlsym to get new function's addr of another lib, call it, then restore the registers and jump back to 'xxxx'.
这是不是很辛苦,我也只是一个问题几乎是成功的:我不能在我的钩子函数使用64位的变种。 int类型是没有问题的,但是当我的printf 的int64_t 变种,它总是显示了一个错误的号码。
It is not very hard, and I have almost successful except for a problem: I cannot use 64-bits var in my hook function. The int type is no problem, but when I printf int64_t var, it's always shows a wrong number.
1这是SRC code:结果
test_ori
// test_ori.c
#include <stdio.h>
#include <dlfcn.h>
// I will hook sub and jump to myfn
void sub() {
printf("sub called...\n");
}
// The purpose of sub2 is just for let me know the addr of dlopen&dlsym
void (*func)();
void sub2() {
void *p = dlopen("/system/lib/libyyy.so", RTLD_NOW);
func = (void (*)())dlsym(p,"myfn2");
func();
}
int main(){
sub();
sub2();
return 0;
}
libyyy.so
// yyy.c
#include <stdio.h>
void myfn() {
int x = 1;
uint32_t y = 2;
uint64_t z = 3;
printf("x=%d, y=%u, z=%llu\n", x, y, z);
}
void myfn2() {}
2使用objump对发现的dlopen和放大器的addrs的;对dlsym
// dlopen is 0x8440, dlsym is 0x844c
84a8: f7ff efca blx 8440 <dlopen@plt>
...
84b2: f7ff efcc blx 844c <dlsym@plt>
// sub is 0x84d4
84e0: 003c movs r4, r7
84e2: 0000 movs r0, r0
84e4: b510 push {r4, lr}
84e6: f7ff fff5 bl 84d4 <puts@plt+0x7c>
84ea: f7ff ffd9 bl 84a0 <puts@plt+0x48>
3找到填充区域,并修改ELF文件
// I use the offset 0x550(it's padding area) as my jump destination, the addr is 0x8550
// by the way, I also modify the segment's size field(0x580->0x600) so my new code can be loaded
ori -> 84e6: f7ff fff5 bl 84d4
new -> 84e6: f000 f833 bl 8550
4的钩子过程从0x8550,由ASM:
1. push {r0-r7} // save registers
2. push {lr} // save lr
3. mov r1, #0 // param2 of dlopen(RTLD_NOW)
4. mov r0, pc
5. add r0, #xx // param1 of dlopen(addr of "libyyy.so")
6. blx xxxx // call dlopen
7. mov r1, pc
8. add r1, #xx // param2 of dlsym(addr of "myfn")
9. blx xxxx // call dlsym
10. blx r0 // call myfn
11. pop {r3} //
12. mov lr, r3 // restore lr
13. pop {r0-r7} // restore registers
14. b xxxx // jump back
5修改ELF文件:写code将填充区域
// I convert the asm above to machine code and write it(and strings "libyyy.so" & "myfn") to file
// then I check it in gdb:
(gdb) x/20i 0x8550
0x8550: push {r0, r1, r2, r3, r4, r5, r6, r7}
0x8552: push {lr}
0x8554: movs r1, #0
0x8556: mov r0, pc
0x8558: adds r0, #24
0x855a: blx 0x8440
0x855e: mov r1, pc
0x8560: adds r1, #26
0x8562: blx 0x844c
0x8566: blx r0
0x8568: pop {r3}
0x856a: mov lr, r3
0x856c: pop {r0, r1, r2, r3, r4, r5, r6, r7}
0x856e: b.w 0x84d4
6的结果
# ./test_new
x=1, y=2, z=12884901888
sub called...
正如你看到的,x和y是正常的,但是Z(uint64_t中)是错误的。它shoule是3,但我得到的 12884901888(0x300000000)在这里。
这似乎针对z的高/低寄存器是不正确的,但你能告诉我为什么,以及如何解决呢?
感谢您的关注!
As you see, the x and y is normal, but z(uint64_t) is wrong. It shoule be 3, but I get 12884901888(0x300000000) here.It seems the high/low register for z is incorrect, but can you tell me why and how to fix it?Thanks for your attention!
推荐答案
在回答这个问题是在的。
The answer to this question is in the ARM Procedure call standard.
printf("x=%d, y=%u, z=%llu\n", x, y, z);
这有四个参数。该的格式的字符串,32位 X
和是
和3 以Z
值。由于前三个参数着陆以Z
奇地址,编译器垫一个空间,使 LDRD
和 STRD
指令可以正常工作;如果叠未对齐这些64位的负载不工作。
This has four arguments. The format string, the 32bit x
and y
and the 3 z
value. As the first three arguments land z
at an odd address, the compiler pads a space so that ldrd
and strd
instruction can work; these 64-bit loads do not work if the stack is not aligned.
您是否显示为的 C 的$ C $汇编c您编译或如果你正在试图修改生成的code目前尚不清楚。最有可能你不能确保为的变参的必须放在堆栈上。
It is not clear whether you are showing assembler for the C code you compiled or if you are trying to modify the generated code. Most likely you do not ensure that the stack is eight byte aligned as var args must be put on the stack.
诗:有一个关于ARM 8字节对齐了良好的堆栈溢出的问题,但现在我找不到它。随意编辑我的问题或发表评论。
Ps: There is a good stack-overflow question about ARM 8-byte alignment, but I can not find it now. Feel free to edit my question or leave a comment.
这篇关于关于钩臂功能的一个难题,通过修改ELF文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!