Assembly ASM-在“运行”期间修改寄存器;函数调用";
我尝试钩住一些函数,不管是x86上的stdcall还是cdecl 我想做以下事情:Assembly ASM-在“运行”期间修改寄存器;函数调用";,assembly,call,cpu-registers,Assembly,Call,Cpu Registers,我尝试钩住一些函数,不管是x86上的stdcall还是cdecl 我想做以下事情: 1.保存堆栈 2.保留反寄存器 3.做我的事 4.恢复寄存器 5.恢复堆栈 我的堆栈没有问题,但我的寄存器备份确实有一些问题:我无法在不修改某些寄存器的情况下备份寄存器(我无法使用堆栈,因为我无法以这种方式备份堆栈) 我可以将它们备份到堆上(我使用一个包含一些.EAX、.EBX等成员的结构),我从ASM访问该结构,这就是问题所在。。。我必须修改一些寄存器才能做到这一点 然而,这是我的故事。我真正想了解的是以下问题
1.保存堆栈
2.保留反寄存器
3.做我的事
4.恢复寄存器
5.恢复堆栈 我的堆栈没有问题,但我的寄存器备份确实有一些问题:我无法在不修改某些寄存器的情况下备份寄存器(我无法使用堆栈,因为我无法以这种方式备份堆栈) 我可以将它们备份到堆上(我使用一个包含一些.EAX、.EBX等成员的结构),我从ASM访问该结构,这就是问题所在。。。我必须修改一些寄存器才能做到这一点 然而,这是我的故事。我真正想了解的是以下问题的答案: 关于函数调用期间可以修改的寄存器和不修改的寄存器,是否有任何“规则” 我用调试器检查了一些函数调用。我在“调用某个函数”处添加了一个断点,按F8键“跳过函数调用”,然后检查修改的寄存器。我可以看到这样的情况: 1.ESP/EBP可以根据呼叫约定进行修改(cdecl与stdcall) 2.EAX、EBX、EDX-几乎总是经过修改! 3.EBX、EDI、ESI似乎总是保留着 所以我的“伪解决方案”来了:如果我只保留那些寄存器(EBX、EDI、ESI),可以吗?我不会弄乱堆栈,因此EBP和ESP不是问题。但我必须修改一些寄存器(EAX、ECX、EDX) 我在一些编译器优化方面会有问题吗?是否有可能通过修改那些“无辜”寄存器(EAX、ECX、EDX)来搞乱代码
谢谢不清楚除了保存寄存器的标准技术之外,为什么还需要其他技术。通常的方案是:
; call site: push args into stack, move to registers as required for callee
push arg1
push arg2
mov reg, arg3
call subroutine
lea esp, sizeof(arg1)+sizeof(arg2)[esp] ; pop arg1 and arg2
...
subroutine:
push ebp
push reg1 ; save the registers that subroutine is documented to preserve
...
push regn ; if you insist, save *all* the registers
mov ebp, esp ; now ebp points to stacked args/saved registers no matter what you do next
; note: we have not saved the ESP, but we do know how much we pushed on ESP
...
body of subroutine, move ESP up and down
...
subroutine_exit:
mov esp, ebp ; now points to saved registers
pop regn
...
pop reg1
pop ebp
ret
是的,调用约定允许您关闭
EAX
、ECX
和EDX
。我相信微软C++ >代码> ECX < /C> >用于<代码> < <代码>指针。注:这仅适用于遵循约定的功能。如果您试图钩住一个内部函数,而该函数可能已经优化为不使用标准约定,那么它将不起作用
您只需将内容保存在数据部分,如果适用,请特别注意可重入性和并发性。是的,我会做以下事情:
1.跳转到而不是前5个函数字节(经典挂钩)
2.跳转到仅我的裸体asm功能
3.在我的函数中,我需要调用一些函数(memcpy-还原原始字节,flushintruction缓存)并使用一个结构,因此这里我需要修改一些寄存器
4.我在堆栈上添加了内容,但在堆栈的末尾与“调用”时刻相同
5.我跳转到具有正确堆栈的回调函数(jmp EAX)!我无法回到这里,因为在回调函数中,我需要调用原始函数并返回“call function+5”(返回调用时放在堆栈上的EIP)。我必须跳转到正确的堆栈,因为参数在堆栈上,钩子是通用的,我不知道有多少参数 所以,在回调函数中,我做我的工作,调用原始函数并恢复钩子。我需要的正是:我需要恢复寄存器,或者确保不修改它们,但正如我所说的,我必须这样做 目前,我正试图避免使用EBX、EDI和ESI。我希望它能工作,我不会有优化问题。如果它不起作用,我将尝试在我的结构中备份它们,并在回调函数中恢复它们
谢谢大家! 保留堆栈是什么意思?您并没有真正保留它,只需在完成后恢复SP。是的,我不修改EBP,我只修改恢复ESP。问题比我描述的更复杂。我只需要知道是否可以只保留那些寄存器:EBX、EDI、ESI。@但必须保留所有寄存器。但我不明白你的问题,这听起来很简单;调用函数;调用在堆栈上推送下一个EIP并转到该函数。1.在该函数上,我跳转到我的代码(仅asm函数,裸体)2。我必须调用一些函数并跳转到另一个函数(回调)3。回调函数必须具有与调用之前相同的堆栈(相同的原型)4。执行回调函数后,我必须有未修改的寄存器和stack@lonut对不起,我还是不明白。你想做些定制的还是什么?Wny不是吗?你只是遵循调用约定并保持简单?我假设他在做一个通用钩子,而不知道参数占用了多少空间。我的代码示例不关心他推了多少参数,或者它们是否在寄存器中。但它也不是钩子,或者至少我不明白它是怎么回事。钩子只是一个看起来很有趣的子例程,它保留了寄存器。这样说似乎很奇怪,但子例程只是保留它们使用的寄存器。钩子也一样。