int ImAcDeclFunc(int a,int b) { return a + b; }
如果我想从字面上创建这个函数的副本,但是完全动态,那需要什么(并记住它是带内联汇编的C)?对于初学者,我想我必须做这样的事情(或类似的解决方案):
// My main.... byte * ImAcDeclFunc = new byte[memory]; mprotect(Align(ImAcDeclFunc),pageSize,PROT_EXEC | PROT_READ | PROT_WRITE);
在此之后,我将不得不找出ImAcDeclFunc(int a,int b);的汇编代码.现在我在组装时仍然很糟糕,那么这个功能将如何用于AT& T语法?这是我的大胆尝试:
push %ebp movl %%ebp,%%esp movl 8(%ebp),%%eax movl 12(%ebp),%%edx addl edx,eax pop ebp ret
现在,如果这段代码是正确的(我非常怀疑,请纠正我)我只需要在十六进制中找到这个代码的值(例如,’jmp’是0xE9,’inc’是0xFE),并直接使用这些值C ?如果我继续以前的C代码:
*ImAcDeclFunc = 'hex value for push'; // This is 'push' from the first line *(uint)(ImAcDeclFunc + 1) = 'address to push'; // This is %ebp from the first line *(ImAcDeclFunc + 5) = 'hex value for movl' // This is movl from the second line // and so on...
在我为整个代码/缓冲区完成此操作之后,这对于完全动态的_cdecl函数是否足够(即我可以将其转换为函数指针并执行int result =((int(*)(int,int) )ImAcDeclFunc)(firstArg,secondArg)?).
而且我对使用boost :: function或类似的东西不感兴趣,我需要这个函数是完全动态的,因此我的兴趣:)
注意:这个问题是我previous one的延续,但更具体.
@H_404_21@解决方法
int ImAcDeclFunc(int a,int b) { return a + b; } int main(void) { return 0; }
你可以用gcc -Wall lala.c -o lala编译它.然后,您可以使用objdump -Dslx lala>>反汇编可执行文件. lala.txt.你会发现ImAcDeclFunc被组装到:
00000000004004c4 <ImAcDeclFunc>: ImAcDeclFunc(): 4004c4: 55 push %rbp 4004c5: 48 89 e5 mov %rsp,%rbp 4004c8: 89 7d fc mov %edi,-0x4(%rbp) 4004cb: 89 75 f8 mov %esi,-0x8(%rbp) 4004ce: 8b 45 f8 mov -0x8(%rbp),%eax 4004d1: 8b 55 fc mov -0x4(%rbp),%edx 4004d4: 8d 04 02 lea (%rdx,%rax,1),%eax 4004d7: c9 leaveq 4004d8: c3 retq
实际上这个功能相对容易复制到其他地方.在这种情况下,你完全正确地说你可以复制字节,它只会工作.
当您开始使用将相对偏移作为操作码的一部分的指令时,将出现问题.例如,相对跳转或相对呼叫.在这些情况下,您需要正确地重新定位指令,除非您碰巧能够将其复制到与最初位置相同的地址.
简而言之,要重新定位,您需要找到它最初所在的位置,并计算您将基于它的位置的差异,并重新定位每个相对指令的偏移量.这本身是可行的.你真正的困难是处理对其他函数的调用,特别是对库的函数调用.在这种情况下,您需要保证链接库,然后以您定位的可执行格式定义的方式调用它.这非常重要.如果您仍然感兴趣,我可以指出您应该阅读的方向.
在上面的简单案例中,您可以这样做:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <malloc.h> #include <sys/mman.h> #include <unistd.h> int main(void) { char func[] = {0x55,0x48,0x89,0xe5,0x7d,0xfc,0x75,0xf8,0x8b,0x45,0x55,0x8d,0x04,0x02,0xc9,0xc3}; int (* func_copy)(int,int) = mmap(NULL,sizeof(func),PROT_WRITE | PROT_READ | PROT_EXEC,MAP_PRIVATE | MAP_ANONYMOUS,0); memcpy(func_copy,func,sizeof(func)); printf("1 + 2 = %d\n",func_copy(1,2)); munmap(func_copy,sizeof(func)); return EXIT_SUCCESS; }
这在x86-64上工作正常.它打印:
1 + 2 = 3@H_404_21@ @H_404_21@